Skip to content
DenseChip
Learn
PracticeCode labInterview

DenseChip

Navigate

Menu

LearnPracticeCode labInterview

Tools

All toolsSV editorCode repoResume
DenseChip

Practice, courses, and chip-design tools in one focused workspace.

LearnPracticeCode labInterviewToolsLearning paths

© 2026 DenseChip

AboutRoadmapCareersInternshipsFAQContactPrivacyTerms
Skip to lesson

Course contents

  • How to Use This Course
  • The NanoSoC Tour
  • Reading Path
  • SoC Glossary10
  • SoC Metrics Reference
  • SoC Cheatsheet
  • What SoC Integration Is12
  • Architecture and Budgets21
  • Memory Maps and Address Decode26
  • Interconnect and Bus Fabrics26
  • Clock and Reset Architecture24
  • Power Architecture21
    • Power Domains and States
      • Always On Versus Switchable
      • RUN, IDLE and SLEEP
      • What Is Retained and What It Costs
    • Isolation and Retention Integration
    • PMU and Power Sequencer
    • Cold-Start Power-Up Sequence
    • Supply Sequencing and PMIC
    • Thermal and Power Envelope
    • DVFS Integration
  • Interrupts, DMA and Peripherals15
  • Memories, Boot and Security21
  • IP Integration and Handoff21
  • Top-Level Verification and Bring-up21
  • Package, Pads and I/O18
  • Chip Signoff and Tapeout18
  • SoC Interview Prep16
  • Capstone: Integrate NanoSoC14
Loading lesson

←Power Domains and States
  1. Topics
  2. SoC Design
  3. Power Architecture
  4. Power Domains and States
  5. RUN, IDLE and SLEEP
On this page

    Part 6 of 14, lesson 2 of 21Part 6 of 14/Power Architecture/Lesson 2 of 21All levels

    RUN, IDLE and SLEEP

    The three-state contract: what is on, what is clocked, entry and exit, and the milliwatt cost of each state.

    Why it matters

    Software on NanoSoC knows three words, RUN, IDLE and SLEEP, and each word is a promise about latency, power and survival. IDLE must wake on any enabled interrupt with the PLL still locked; SLEEP may take 14.073 µs to wake but must burn barely a milliwatt. If the hardware's state table and the driver's idea of it disagree, the chip either never sleeps or never wakes. This lesson writes the table once, with the NanoSoC numbers attached.

    The core idea

    RUN is everything on and clocked. IDLE keeps both domains powered with the PLL on, but the CPU clock is gated after a wait-for-interrupt and the DMA and stream-bridge clocks are gated by their enable bits, so any enabled interrupt resumes in a few cycles. SLEEP powers PD_SW off entirely, stops the PLL, keeps only the peripheral clock running, and holds SRAM0 in retention at 60 percent of its normal leakage. Entry to SLEEP is a software write to PWR_CTRL.SW_OFF_REQ followed by the hardware sequence; exit is a wake interrupt into nano_rstpwr, which sets RST_CAUSE bit 3 and resumes from the retained SRAM0 image instead of reloading.

    State

    PD_AON

    PD_SW

    PLL

    Clocks

    Entry

    Exit

    RUN

    On

    On

    On

    All on

    Boot or wake

    CPU wait-for-interrupt, or software writes SW_OFF_REQ

    IDLE

    On

    On, CPU clock gated

    On

    clk_cpu gated, rest on

    CPU wait-for-interrupt

    Any enabled interrupt

    SLEEP

    On, SRAM0 in retention

    Off, outputs isolated

    Off

    Only clk_per on

    PWR_CTRL.SW_OFF_REQ

    Enabled GPIO, UART or power interrupt wakes nano_rstpwr

    The power roll-up below recomputes the NanoSoC totals from the per-block table: 82.74 mW in RUN, 16.89 mW in IDLE and 1.40 mW in SLEEP. Two ratios are worth memorising. IDLE costs about a fifth of RUN: 5.64 mW is leakage, 6.00 mW is the PLL, and the remaining 5.25 mW is the still-clocked PD_AON peripherals plus the gated CPU and fabric residue; gating the CPU still saves its 38.00 mW dynamic. SLEEP costs about one sixtieth of RUN: PD_SW leakage collapses to 0.06 mW through the switch, and PD_AON is dominated by the retained SRAM0 at 0.72 mW.

    example.py
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    # NanoSoC state power roll-up, NanoSoC teaching values (NanoSoC power table).
    # Dynamic power in mW per block: (RUN, IDLE, SLEEP); leakage handled below.
    DYN = {
        "cpu": (38.00, 1.90, 0.00), "icache": (4.00, 0.20, 0.00),
        "axi_cdc": (3.00, 0.30, 0.00), "xbar": (5.00, 0.50, 0.00),
        "dma": (3.00, 0.00, 0.00), "sbr": (2.00, 0.00, 0.00),
        "axi2apb": (1.00, 0.10, 0.00), "apb_cdc": (0.50, 0.05, 0.00),
        "sram1": (6.00, 0.30, 0.00), "switches": (0.00, 0.00, 0.00),
        "sram0": (6.00, 0.30, 0.00), "rom": (1.00, 0.00, 0.00),
        "uart": (0.30, 0.30, 0.03), "spi": (0.40, 0.40, 0.04),
        "gpio": (0.20, 0.20, 0.02), "intc": (0.20, 0.20, 0.02),
        "rstpwr": (0.50, 0.50, 0.05), "pll": (6.00, 6.00, 0.00),
    }
    LEAK = {"RUN": 5.64, "IDLE": 5.64, "SLEEP": 1.24}
    dyn_run = sum(v[0] for v in DYN.values())
    dyn_idle = sum(v[1] for v in DYN.values())
    dyn_sleep = sum(v[2] for v in DYN.values())
    assert abs(dyn_run - 77.10) < 0.005, dyn_run
    assert abs(dyn_idle - 11.25) < 0.005, dyn_idle
    assert abs(dyn_sleep - 0.16) < 0.005, dyn_sleep
    tot = {s: round(d + LEAK[s], 2) for s, d in
           [("RUN", dyn_run), ("IDLE", dyn_idle), ("SLEEP", dyn_sleep)]}
    assert tot == {"RUN": 82.74, "IDLE": 16.89, "SLEEP": 1.40}, tot
    assert tot["IDLE"] / tot["RUN"] < 0.25
    assert tot["RUN"] / tot["SLEEP"] > 50.0
    print("PASS: RUN 82.74 mW, IDLE 16.89 mW, SLEEP 1.40 mW; ratios hold")

    What the review looks for

    • The state table names the entry trigger, the exit trigger and the wake latency class for every state.

    • The milliwatt totals reconcile with the per-block budget to the second decimal; IDLE and SLEEP carry the duty assumptions they were computed with.

    • Software's power driver handles exactly these three states, no hidden fourth mode.

    Verify and debug

    Measure each state on the bench or in power-aware simulation with a fixed workload: RUN streaming one DMA job, IDLE in wait-for-interrupt with the DMA idle, SLEEP after SW_OFF_REQ with a GPIO wake armed. If IDLE reads near RUN, a clock enable is stuck on, usually the DMA or bridge bit in CLK_EN; if SLEEP reads high, the switch never opened or the PLL never stopped. The script above is the oracle for all three readings.

    Debug access lost in a low-power state: a debug port in a gated domain disconnects on sleep. NanoSoC as documented has no debug port; a real chip must decide which domain holds it, and the answer is the always-on island or a power-request handshake, before first sleep.

    If asked to compare IDLE and SLEEP, answer with the two numbers and the two prices: 16.89 mW with cycle-fast wake against 1.40 mW with a 14.073 µs wake and a dead PD_SW. Then say which workloads earn SLEEP.

    Check yourself Software writes SW_OFF_REQ but the measured power stays near IDLE. Name the two most likely causes.

    Either the sequence never ran because the request was never accepted (a secure-only RSTPWR write from the wrong security state), or the switch opened but the PLL kept running. Check PWR_STATUS.SW_ON first: if it never cleared, the request path is the suspect; if it cleared but power is high, the PLL or a CLK_EN bit is the leak.

    Related topics

    • Always On Versus Switchable

    • Next: What Is Retained and What It Costs

    • Low Power: Supply Sets and Power States

    Previous

    110 / 289

    Next: What Is Retained and What It Costs

    Up next

    Up nextWhat Is Retained and What It Costs

    Sign in to save progress

    Practice this lessonPrevious lessonReport an error