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
    • Isolation and Retention Integration
    • PMU and Power Sequencer
      • The Sequencer State Machine
      • Handshakes with the Reset Controller
      • Timeouts, Watchdogs and Refusals
    • 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

←PMU and Power Sequencer
  1. Topics
  2. SoC Design
  3. Power Architecture
  4. PMU and Power Sequencer
  5. Timeouts, Watchdogs and Refusals
On this page

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

    Timeouts, Watchdogs and Refusals

    Every wait gets a number: sizing sequencer timeouts, refusing bad requests, and what a timeout does.

    Why it matters

    A sequencer that waits forever is a hang with a nicer name: power-good never arrives because the board supply failed, the PLL never locks, the busy bit never clears because firmware crashed mid-job. Each wait needs a number after which the machine stops waiting and reports, and each number needs a reason. This lesson sizes the three hardware timeouts (ramp, power-good, relock) plus the one software timeout (quiesce), says what fires them, and says honestly what no timeout on the chip can catch.

    The core idea

    Timeouts are sized at four times the nominal wait, wide enough to absorb slow silicon and cold rails, tight enough to fail fast on a dead board. The ramp timeout covers the 64-clock switch ramp; the power-good wait covers the ramp plus the 8-clock margin; the relock wait covers the 256-clock PLL lock. The quiesce wait is software's job, not the sequencer's: the driver polls DMA and SBR idle before writing SW_OFF_REQ, with a software-side timeout of four times the longest job, 4 x 72 clk_sys = 288 clk_sys (3.0 µs, which is 72 clk_per), before it declares the DMA hung. On a hardware timeout the machine stops in the one state that is safe without a usable rail, SLEEP's state (switch open, isolation held, PD_AON running), and records the event in a sticky status bit. This is an illustrative extension: the NanoSoC PWR_IRQ register defines only LOCK_EVT and UP_DONE, so a real chip would add a timeout event bit. What no timeout can catch is a dead crystal: the sequencer and its counters run on that crystal, so with no clock nothing counts. Detect it outside the chip, with a supervisor or a watchdog on a separate clock (NanoSoC has none), or by the board-level check that por_n is released but rst_per_n never is.

    example.py
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    # Sequencer timeout sizing, NanoSoC teaching values (NanoSoC clock and power sequences).
    T_PER_NS = 41.6667   # clk_per period in ns
    T_SYS_NS = 10.4167   # clk_sys period in ns
    FACTOR = 4           # every timeout is four times nominal
    nominal = {"ramp": 64, "pgood": 64 + 8, "relock": 256}   # clk_per
    timeouts = {k: FACTOR * v for k, v in nominal.items()}
    assert timeouts == {"ramp": 256, "pgood": 288, "relock": 1024}, timeouts
    # Software quiesce timeout: longest DMA job is 72 clk_sys, also x4.
    quiesce_sys = FACTOR * 72
    quiesce_per = quiesce_sys * T_SYS_NS / T_PER_NS
    assert quiesce_sys == 288 and round(quiesce_per) == 72
    assert abs(quiesce_sys * T_SYS_NS / 1000.0 - 3.0) < 0.01     # 3.0 us
    # Each timeout must exceed its nominal wait, and the relock one is the longest.
    assert all(timeouts[k] > nominal[k] for k in nominal)
    worst_us = timeouts["relock"] * T_PER_NS / 1000.0
    assert abs(worst_us - 42.667) < 0.01, worst_us
    # A PLL that locks late (300 clk_per) still passes; one that never locks trips.
    def relock_outcome(lock_after):
        return "locked" if lock_after <= timeouts["relock"] else "timeout"
    assert relock_outcome(300) == "locked" and relock_outcome(10**9) == "timeout"
    print("PASS: HW timeouts ramp/256 pgood/288 relock/1024 clk_per; SW quiesce 288 clk_sys (3.0 us)")

    What the review looks for

    • Each wait state names its timeout in cycles and the multiple of nominal it represents; no wait is unbounded.

    • Timeout expiry always lands in a defined safe state (switch open and isolation held, or a fully powered state), never half-way through the ramp.

    • Each timeout sets a sticky status bit that firmware and the lab can both read; the dead-crystal case is listed as outside the sequencer's reach.

    Verify and debug

    Test each timeout by breaking its wait: hold power-good low, kill the lock signal, stall the ramp model, and (for the software timeout) hold the DMA busy. Each hardware timeout must end in its safe state with its status bit set within its cycle budget. If a timeout never fires, the counter is clocked by a clock that the state itself gates; sequencer counters run on the always-on peripheral clock for exactly this reason.

    A block that refuses to quiesce: the DMA stays BUSY because firmware crashed mid-job, and a naive sleep path waits forever. The NanoSoC answer is the software gate: the driver polls idle with its 288-system-clock timeout and declares the DMA hung instead of requesting sleep. Never queue a sleep behind a hung block.

    If asked to size a power timeout, give the rule first, four times nominal, safe landing, sticky status, then instantiate it: NanoSoC relock waits 256 clocks nominal and times out at 1024 peripheral clocks, about 42.7 µs. Add that a dead crystal cannot time itself out.

    Check yourself The relock timeout is a wake-path counter, not a cold-boot one. What happens if it is wired into cold boot?

    Every cold boot would pay it or trip it: the reset controller already waits for lock on its own counter (step R3 of the cold-start timeline), so a second timeout in series either duplicates the wait or false-fires. Keep the two lock waits distinct and qualify both on the lock signal.

    Related topics

    • Handshakes with the Reset Controller

    • Next: Cold-Start Power-Up Sequence

    • Protocol First Principles: Wake Signalling

    Previous

    123 / 289

    Next: Cold-Start Power-Up Sequence

    Up next

    Up nextCold-Start Power-Up Sequence

    Sign in to save progress

    Practice this lessonPrevious lessonReport an error

    See also

    • The Sequencer State Machine