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
    • Clock Sources and PLLs
    • Dividers, Muxes and Glitch-Free Switching
    • Clock Gating Architecture
    • Clock Domain Planning
    • Top-Level Crossings
    • Always-On Domain, Wake Policy and a Timer Extension
      • Always-On Domain and Timer Clocks
      • Extension: Watchdog-to-Reset Wiring
      • Wake Sources and Reset-Versus-Interrupt Policy
    • Reset Sources and Reset Tree
    • Reset Sequencing and Release
  • Power Architecture21
  • 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

←Always-On Domain, Wake Policy and a Timer Extension
  1. Topics
  2. SoC Design
  3. Clock and Reset Architecture
  4. Always-On Domain, Wake Policy and a Timer Extension
  5. Wake Sources and Reset-Versus-Interrupt Policy
On this page

    Part 5 of 14, lesson 18 of 24Part 5 of 14/Clock and Reset Architecture/Lesson 18 of 24All levels

    Wake Sources and Reset-Versus-Interrupt Policy

    What wakes NanoSoC, what interrupts it, what resets it: one table with exactly one disposition per source.

    Why it matters

    Every event that reaches the always-on logic faces the same choice: wake the chip with a reset, interrupt it, or wait until software polls. A source with two dispositions races itself; a source with none is a dead wake pin on the package. This lesson writes the NanoSoC policy as one table and gives the audit that proves each source appears exactly once. Its one job is the policy; the placement it relies on came first.

    The core idea

    Sleep exit is a wake reset. Three sources can start it: an enabled GPIO level, UART activity, and the controller's own irq_pwr (power and PLL events). Each wakes nano_rstpwr, which runs the power-up sequence, sets RST_CAUSE bit WAKE and lets the ROM resume the retained SRAM0 image at 0x2000_0000 instead of reloading it. GPIO is a level interrupt, not an edge detector: the wake condition is a pin held high with its INT_EN bit set, so the source must stay asserted until the chip is up and software removes the condition. In run, the same sources are ordinary interrupts into the controller, with irq_pwr at priority 0. Nothing is both in the same state, and the table below is the whole policy:

    Source

    In run

    In sleep

    Disposition

    Record

    GPIO level

    Level interrupt, input 5

    Wake

    Interrupt; from sleep, wake reset

    INT_EN and DATA_IN; cleared by removing the condition

    UART activity

    TX/RX interrupt, input 3

    Wake

    Interrupt; from sleep, wake reset

    UART flags

    irq_pwr (power, PLL)

    Input 0, priority 0

    Wake

    Interrupt; from sleep, wake reset

    PWR_IRQ W1C

    Software reset (SWRST)

    Reset sys and cpu

    n/a

    Reset only

    RST_CAUSE SW

    POR, pad reset

    Reset everything

    Reset everything

    Reset only

    RST_CAUSE POR or PAD

    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
    27
    28
    29
    # Policy audit against the NanoSoC specification: three wake sources, one disposition each.
    WAKE_FACT = {"gpio", "uart", "irq_pwr"}          # sleep state table
    POLICY = {
        "gpio": ("interrupt", "wake-reset"),
        "uart": ("interrupt", "wake-reset"),
        "irq_pwr": ("interrupt", "wake-reset"),
        "swrst": ("reset", None),
        "por-pad": ("reset", "reset"),
    }
    
    def audit(policy):
        errors = []
        wakes = {s for s, (_, sleep) in policy.items() if sleep == "wake-reset"}
        if wakes != WAKE_FACT:
            errors.append("wake set differs: " + str(sorted(wakes ^ WAKE_FACT)))
        for src, (run, sleep) in policy.items():
            if run not in ("interrupt", "reset"):
                errors.append(src + ": bad run disposition")
            if sleep == "wake-reset" and run != "interrupt":
                errors.append(src + ": wakes from sleep but is not an interrupt in run")
        return errors
    
    assert audit(POLICY) == []
    # The audit can fail: SPI added as a wake source, GPIO dropped, or a wake
    # source that is a reset in run are all rejected.
    assert audit({**POLICY, "spi": ("interrupt", "wake-reset")}) != []
    assert audit({k: v for k, v in POLICY.items() if k != "gpio"}) != []
    assert audit({**POLICY, "uart": ("reset", "wake-reset")}) != []
    print("PASS: 3 wake sources (GPIO level, UART, irq_pwr); policy audit rejects 3 bad variants")

    What the review looks for

    • The table above, current, with each row's enable, priority and record named.

    • The sleep-exit path tested per row: each wake source demonstrated from sleep, not just from run.

    • The ROM's WAKE-versus-POR branch covered: retained image resumed on wake, full load on POR.

    • A watchdog or timer is not in the table: if one exists, it came from an extension and its rows carry that label.

    Verify and debug

    Drive each wake source with the chip in sleep and confirm the sequence: power-up (14.073 us), cause set, ROM resume. A wake that works in run but not in sleep points at the sleep disposition row, usually an enable that software cleared on the way down. A wake that fires again immediately after returning to sleep points at a GPIO level that was never removed.

    Wake enable cleared on the way down: software disables the GPIO or UART interrupt enable while tidying up before sleep, so the one event that should wake the chip is masked in the interrupt controller and the chip sleeps for good. Caught by a sleep-wake test per source. Fixed by writing the wake enables as the last step before the power-down request and re-checking them in the sleep-entry test.

    If asked reset or interrupt for a new event, answer with the test: does the handler need prior state. State needed means interrupt; a clean slate is acceptable means reset. Then place the event in the table.

    Check yourself A GPIO wake works in run but not in sleep. Name the two most likely rows to check.

    The GPIO enable on the sleep path, which may have been cleared with the run configuration, and the pin's level: GPIO is a level interrupt, so a pulse that ended before the controller woke is gone, and the pin must be held high with INT_EN set.

    Related topics

    • Extension: Watchdog-to-Reset Wiring

    • Reset Sources

    • Low Power: Power Domain Basics

    Previous

    108 / 289

    Next: Power Domains and States

    Up next

    Up nextPower Domains and States

    Sign in to save progress

    Practice this lessonPrevious lessonReport an error

    See also

    • Always-On Domain and Timer Clocks