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
  • Interrupts, DMA and Peripherals15
  • Memories, Boot and Security21
  • IP Integration and Handoff21
  • Top-Level Verification and Bring-up21
    • SoC Verification Strategy
    • Integration and Connectivity Tests
      • Register Access Sweeps
      • Address-Map and Interrupt Wiring Checks
      • Reset, Clock and Power Sanity
    • Firmware Co-Simulation
    • Performance Verification
    • Gate-Level and Power-Aware Simulation
    • Emulation and FPGA Prototyping
    • Bring-Up Readiness
  • Package, Pads and I/O18
  • Chip Signoff and Tapeout18
  • SoC Interview Prep16
  • Capstone: Integrate NanoSoC14
Loading lesson

←Integration and Connectivity Tests
  1. Topics
  2. SoC Design
  3. Top-Level Verification and Bring-up
  4. Integration and Connectivity Tests
  5. Reset, Clock and Power Sanity
On this page

    Part 10 of 14, lesson 6 of 21Part 10 of 14/Top-Level Verification and Bring-up/Lesson 6 of 21All levels

    Reset, Clock and Power Sanity

    One short test that the chip is alive: release order, clock delivery, and isolation presence before anything else runs.

    Why it matters

    A chip that fails its sanity test fails everything after it with the same symptom — nothing answers — and the debug starts in the wrong place. NanoSoC has three aliveness facts to prove before the first register access: the resets released in order with the CPU last, every clock toggling with its gate open, and the isolation cells present and clamping before power moves. Its one job is that aliveness proof: three checks that gate the whole suite, the longest of them the 53.948 us hardware release sequence. A pad reset adds a fourth: a RESET_N pulse must last more than 16 clk_per cycles (666.7 ns) to count, and a longer one must set RST_CAUSE bit 1.

    The core idea

    Reset sanity replays the release table with a stopwatch: rst_per_n after the oscillator counter, rst_sys_n after the 16-cycle hold plus two synchroniser cycles, rst_cpu_n 8 system cycles plus 2 CPU cycles after that. The assertion that matters is an ordering one — rst_cpu_n must rise strictly after rst_sys_n — which is planted bug 2 with its fix stated as a check. In the faulty chip rst_cpu_n is released in the same step as rst_sys_n and passes only its own two-flop synchroniser (2 clk_cpu, 10.4 ns), so it rises about 177 ns before rst_sys_n; the failure is "CPU earlier", not "CPU equal", and the strict comparison also rejects the tied case. Software-reset sanity repeats the tail only: SWRST asserts the system and CPU nets for 16 system cycles while the peripheral net stays released, proving the documented scope. Clock sanity opens the CLK_EN gates and requires a toggle on each clock within 100 cycles of its domain, then closes them and proves the failure is bounded rather than a hang: with CLK_EN cleared, a read of DMA STATUS must complete with an error response inside the 256-cycle watchdog, which is planted bug 10 stated as a check, and the hardware must refuse to gate a block that is BUSY. Power sanity counts the isolation cells in the power intent and netlist — 114 expected across the APB bridge outputs, the SRAM0 and ROM ports and the two interrupts — and requires iso_sw_en asserted before any power transition, which is planted bug 6 with its two missing clamps named.

    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
    30
    31
    32
    33
    34
    35
    36
    # Aliveness checks as functions over traces and counts, each run on a good
    # case and on a planted-bug case. NanoSoC teaching values (reset release and isolation tables).
    T_SYS_NS, T_CPU_NS = 1e9 / 96e6, 1e9 / 192e6
    def release_times(mode="staged"):
        r5 = 18 * T_SYS_NS # rst_sys_n after the 16-cycle hold and 2-flop sync
        if mode == "staged": # correct: 8 clk_sys gap plus the clk_cpu synchroniser
            r6 = r5 + 8 * T_SYS_NS + 2 * T_CPU_NS
        elif mode == "bug2": # released in the common step: only its own 2-flop sync
            r6 = 2 * T_CPU_NS
        else: # "tied": same instant as rst_sys_n
            r6 = r5
        return {"rst_sys_n": r5, "rst_cpu_n": r6}
    def order_ok(t):
        return t["rst_cpu_n"] > t["rst_sys_n"]
    good = release_times()
    assert abs(good["rst_sys_n"] - 187.5) < 0.01
    assert abs(good["rst_cpu_n"] - good["rst_sys_n"] - 93.75) < 0.01
    assert order_ok(good)
    bug2 = release_times("bug2")
    assert not order_ok(bug2) # bug 2: the CPU comes out first
    assert abs(bug2["rst_sys_n"] - bug2["rst_cpu_n"] - 177.08) < 0.01 # 177 ns early
    assert not order_ok(release_times("tied")) # strict: equal is also a failure
    # pad reset: a pulse is a reset only if it lasts more than 16 clk_per cycles (666.7 ns)
    T_PER_NS = 1e9 / 24e6
    def pad_reset_seen(width_ns):
        return width_ns > 16 * T_PER_NS
    assert pad_reset_seen(700) and not pad_reset_seen(600)
    EXPECT_ISO = {"apb_cdc": 47, "sram0": 52, "rom": 13, "irq": 2}
    def iso_gaps(present):
        return {g: EXPECT_ISO[g] - present.get(g, 0) for g in EXPECT_ISO if present.get(g, 0) != EXPECT_ISO[g]}
    assert sum(EXPECT_ISO.values()) == 114
    assert iso_gaps(dict(EXPECT_ISO)) == {}
    assert iso_gaps({"apb_cdc": 47, "sram0": 52, "rom": 13}) == {"irq": 2} # bug 6: 112 of 114
    SW_RESET_SCOPE = {"rst_sys_n", "rst_cpu_n"} # SWRST never touches rst_per_n
    assert "rst_per_n" not in SW_RESET_SCOPE
    print("PASS: order holds, bug 2 (177 ns early) and bug 6 are caught, the SW reset scope is two nets")

    What the review looks for

    • The ordering assertion on the two CPU and system resets is bound in every test, not only in the reset test.

    • Clock sanity opens each gate and proves the toggle, and proves that a closed gate ends in an error response, not a hang; no access test assumes a clock it has not observed.

    • The isolation count is checked against the per-group table, so a missing pair shows its group.

    Verify and debug

    If sanity fails, stop: no later failure is meaningful until aliveness passes. A missing clock toggle points at CLK_EN programming, or at a gate whose enable comes from the domain it gates, which can never wake itself. A release-order violation points at the sequencer or a test that releases resets together for speed. An isolation shortfall points at the power-intent description before the RTL, because the cells are generated from it.

    Unsynchronised interrupt crossing, planted bug 5: irq_dma into the controller with no two-flop synchroniser, missed once in thousands of jobs and green in every directed test. Sanity cannot force it. Structural CDC checking is the guard: it flags the path without needing a failure to occur. RTL simulation misses it unless the bench randomises clock phase and models a violation as X, gate-level simulation with library timing checks can flag a setup or hold violation on the path, and an FPGA or silicon shows it only rarely. The fix is the synchroniser on every controller input, waiver forbidden.

    If asked what runs before anything else on a new chip, answer the aliveness triple: order, toggles, isolation. Then give the numbers: CPU 8 system cycles after sys, 16-cycle software reset, 114 cells.

    Check yourself Clock sanity passes with every gate open, but the first DMA access hangs after software wrote CLK_EN to save power. What does planted bug 10 say to check?

    Whether software wrote CLK_EN with the DMA bit cleared: with the DMA clock stopped the slave cannot drive PREADY and the bridge waits forever. The fix is a 256-cycle watchdog plus hardware that refuses to gate a BUSY block.

    Related topics

    • Address-Map and Interrupt Wiring Checks

    • Clock and Reset: Reset Sequencing and Release

    • Power: Isolation and Retention Integration

    • CDC and RDC: CDC Signoff Dashboard

    • CDC and RDC: RDC Signoff Dashboard

    • Verification First Principles: Low-Power Verification Strategy

    Previous

    198 / 289

    Next: Firmware Co-Simulation

    Up next

    Up nextFirmware Co-Simulation

    Sign in to save progress

    Practice this lessonPrevious lessonReport an error

    See also

    • Register Access Sweeps