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. Extension: Watchdog-to-Reset Wiring
On this page

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

    Extension: Watchdog-to-Reset Wiring

    An extension, not in NanoSoC: how a watchdog would be added and what it changes in the reset tree, RST_CAUSE and the interrupt map.

    Why it matters

    This lesson is an extension. NanoSoC has no watchdog: no block, no RST_CAUSE bit and no interrupt input. A real chip built from it usually wants one, and adding it is a good test of whether you understand the shared tables. The block is the easy part; the three tables it touches, the reset tree, the cause register and the interrupt map, are the integrator's work. Every number below is an illustrative teaching value, not a NanoSoC fact. Its one job is the changes a watchdog forces; the wake policy for the existing chip is next.

    The core idea

    Suppose a block nano_wdt is added to PD_AON on clk_per: a 24-bit down-counter with a refresh register, in an APB slot of its own (illustrative: a slot after the existing seven). It must be on clk_per because it has to fire when software has stopped the PLL or gated the fast clocks. It changes three shared tables.

    Table

    Today in NanoSoC

    What the extension changes

    Interrupt map

    Inputs 6 and 7 reserved, tied to 0; the connectivity test flags any use

    Do not use input 6 or 7 (that breaks the check). Add the warning as bit [2] of PWR_IRQ so it shares irq_pwr, priority 0, with no map change; or make a deliberate ECO to the map and the test.

    RST_CAUSE

    Four bits: POR, PAD, SW, WAKE

    Add bit [4] WDT. A watchdog reset must not set SW: the boot code treats SW as a deliberate restart and WDT as a fault to log. The boot decoder gains a fifth row.

    Reset tree

    Four sources into three nets; sw_rst holds 16 clk_sys cycles

    A new source wdt_rst in nano_rstpwr, held 16 clk_per cycles (666.7 ns), asserting rst_sys_n and rst_cpu_n asynchronously. It cannot reuse sw_rst: that hold counts clk_sys cycles, and the fast clocks may be dead when the watchdog fires.

    The release is the subtle part. If the watchdog fired because the PLL stopped, clk_sys is not running, so the 18-cycle release R5 cannot count. The release must restart at the PLL: lock (4 + 256 clk_per), open the gates (2 clk_per), then R5 and R6 as usual. That is the wake sequence's shape, not the software reset's. Using the NanoSoC specification's cycle counts, (260 + 2) x 41.667 ns + 187.5 ns + 93.75 ns is about 11.2 us from expiry to the CPU leaving reset, an illustrative figure for this extension.

    nano_wdt_core.sv
    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
    // snippet: watchdog counter, EXTENSION (not part of NanoSoC)
    // (partial: bus writes, the window compare, the synchronised reset request
    // and cause capture live outside this fragment, in nano_rstpwr and the APB
    // register block; refresh here is already the output of a legal write).
    module nano_wdt_core (
      input  logic        clk_per,
      input  logic        rst_per_n,
      input  logic        refresh,      // pulsed by a legal bus write
      input  logic [23:0] reload,       // illustrative teaching value width
      output logic        warn_irq,     // staged interrupt when one quarter is left
      output logic        reset_req     // asserted at zero, held until reset
    );
      logic [23:0] count;
      always_ff @(posedge clk_per or negedge rst_per_n) begin
        if (!rst_per_n) begin
          count <= reload;
          reset_req <= 1'b0;
        end else if (refresh) begin
          count <= reload;
        end else if (count != 24'h0) begin
          count <= count - 24'h1;
        end else begin
          reset_req <= 1'b1;
        end
      end
      assign warn_irq = (count < (reload >> 2)) && !reset_req;
    endmodule
    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
    CLK_PER = 24e6
    WIDTH = 24
    MAX_S = (2 ** WIDTH - 1) / CLK_PER
    assert abs(MAX_S - 0.699) < 0.001, MAX_S      # about 0.7 s full range
    
    # Illustrative run-time default: reload for 0.5 s, warn when one quarter is
    # left, that is after three quarters of the timeout have elapsed.
    RELOAD = 12_000_000
    timeout_s = RELOAD / CLK_PER
    warn_left_s = (RELOAD // 4) / CLK_PER
    assert abs(timeout_s - 0.5) < 1e-9 and abs(warn_left_s - 0.125) < 1e-9
    
    # Boot: the SPI image load takes 10.928 ms (NanoSoC specification). A short BOOT
    # timeout of 5 ms (illustrative) would trip 2.2 times during the load, so
    # the ROM must refresh at least every quarter timeout: 1.25 ms -> 9 refreshes.
    SPI_LOAD_S, BOOT_TIMEOUT_S = 10.928e-3, 5e-3
    assert abs(SPI_LOAD_S / BOOT_TIMEOUT_S - 2.19) < 0.01
    import math
    refreshes = math.ceil(SPI_LOAD_S / (BOOT_TIMEOUT_S / 4))
    assert refreshes == 9, refreshes
    # The check can fail: with the 0.5 s default no refresh is needed in the load.
    assert SPI_LOAD_S < timeout_s / 4
    assert not (SPI_LOAD_S < BOOT_TIMEOUT_S / 4)
    
    # Release after expiry (PLL possibly dead): lock, gates, R5, R6.
    rel_ns = (260 + 2) * (1e9 / 24e6) + 18 * (1e9 / 96e6) + (8 * (1e9 / 96e6) + 2 * (1e9 / 192e6))
    assert abs(rel_ns - 11197.9) < 0.5, rel_ns
    print("PASS: 0.5 s default; 5 ms boot timeout needs 9 refreshes in the load; release 11.2 us")

    What the review looks for

    • The three table changes made together: interrupt map, RST_CAUSE and reset tree, with the connectivity test and the boot decoder updated in the same change.

    • The counter clock and supply traced to clk_per and PD_AON, independent of every failure the watchdog guards.

    • A release path that does not depend on a running fast clock, with its length computed.

    Verify and debug

    Stop refreshing in simulation and confirm the staged order: warning first, reset request at zero, the WDT cause bit set and SW clear, system and CPU reset, nothing else. Then repeat with the PLL disabled before expiry and confirm the release still completes. Refresh early, before a window opens, and confirm it does not count if a window is implemented: a watchdog that accepts any refresh is a loop counter, not a supervisor.

    Watchdog resets during a legitimate long operation: with the 5 ms boot timeout above, the 10.928 ms SPI load trips it 2.2 times unless the ROM refreshes inside the polling loop. Caught by boot-sequence simulation with the watchdog enabled. Fixed with bounded polling loops that refresh, never by disabling the watchdog for the operation.

    If asked to add a watchdog to an existing chip, name the three tables first: interrupt map, cause register, reset tree. Then say why its reset cannot reuse the software reset, and how the release restarts the PLL.

    Check yourself Why must the watchdog's cause bit be separate from the SW bit?

    The boot code branches on cause: SW is a deliberate restart that expects clean state, while a watchdog reset is a fault whose evidence should be logged. Sharing the bit makes every hang look like a planned restart.

    Related topics

    • Always-On Domain and Timer Clocks

    • Next: Wake Sources and Reset-Versus-Interrupt Policy

    • RTL: Watchdog Timer Example

    Previous

    107 / 289

    Next: Wake Sources and Reset-Versus-Interrupt Policy

    Up next

    Up nextWake Sources and Reset-Versus-Interrupt Policy

    Sign in to save progress

    Practice this lessonPrevious lessonReport an error