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
    • Reset Sources and Reset Tree
    • Reset Sequencing and Release
      • Release Order and Timing
      • Asynchronous Assert, Synchronous Release
      • Release-Order Failure Modes
  • 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

←Reset Sequencing and Release
  1. Topics
  2. SoC Design
  3. Clock and Reset Architecture
  4. Reset Sequencing and Release
  5. Asynchronous Assert, Synchronous Release
On this page

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

    Asynchronous Assert, Synchronous Release

    The two-flop release synchroniser per domain: async assert, sync release, recovery and removal, with a waveform.

    Why it matters

    Release is the dangerous edge. Assertion can be asynchronous because forcing flops into reset needs no clock, but release near a clock edge violates recovery and removal on some flops and not others, leaving the domain half reset. The fix is a synchroniser per domain: assert everywhere at once, release on a clock edge. This lesson builds that cell, proves it with a waveform, and states the timing that signs it off. Its one job is the release circuit; the order it serves is the previous lesson.

    The core idea

    The circuit is taught in Async Assert, Sync Deassert; this lesson shows the NanoSoC instances and what the integrator signs off. NanoSoC has three reset nets, rst_per_n, rst_sys_n and rst_cpu_n, and each leaves nano_rstpwr through its own nano_rst_sync (two flops) in its own domain, so three instances on three clocks. Assertion is asynchronous and reaches every endpoint without a clock. On release the first flop may violate its own recovery and removal against arst_n: that is the metastability the second flop absorbs. The output rst_out_n always changes shortly after a clock edge, so the destination flops' recovery and removal are an ordinary timing check on the reset tree: clk-to-q plus buffering must fit inside one period, which is 5.208 ns in clk_cpu, 10.417 ns in clk_sys and 41.667 ns in clk_per (see Reset Tree Timing). The minimum assertion width of 16 domain cycles guarantees the reset is seen by the slowest clock in the domain.

    nano_rst_sync.sv
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    // NanoSoC teaching values: per-domain reset synchroniser, async assert,
    // two-flop synchronised release. One instance per reset net per domain.
    module nano_rst_sync (
      input  logic clk,       // domain clock
      input  logic arst_n,    // raw reset in, active low, async assert
      output logic rst_out_n  // released reset out, active low, sync release
    );
      logic q1, q2;
    
      always_ff @(posedge clk or negedge arst_n) begin
        if (!arst_n) begin
          q1 <= 1'b0;
          q2 <= 1'b0;
        end else begin
          q1 <= 1'b1;
          q2 <= q1;
        end
      end
    
      assign rst_out_n = q2;
    endmodule

    Simulation: assert and release

    The waveform below is simulation output for the wave source of this topic: an asynchronous assertion that clears both flops at once, a release near a clock edge that emerges two cycles later, and a second assert-release pair. One slot is one domain-clock cycle.

    How to read it: arst_n starts asserted and releases just before the edge at slot 3, so q1 rises in slot 3 and q2 in slot 4: the two-cycle synchronised release. arst_n falls again just before an edge and both flops clear together in slot 10, which is the asynchronous assert: no clock edge was needed. The second release puts q1 in slot 14 and q2 in slot 15, one slot apart as before, proving the cell re-arms. q2 only ever changes right after a clock edge, never in between, so every flop downstream sees the release aligned to its own clock: that is what recovery and removal need.

    example.py
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    # Release latency of the three nano_rst_sync instances, plus the R5 hold.
    # All NanoSoC NanoSoC-specification values.
    T = {"cpu": 1e9 / 192e6, "sys": 1e9 / 96e6, "per": 1e9 / 24e6}
    EXPECT = {"cpu": 10.417, "sys": 20.833, "per": 83.333}
    for dom, period in T.items():
        sync_ns = 2 * period
        print(dom, f"sync release {sync_ns:.3f} ns")
        assert abs(sync_ns - EXPECT[dom]) < 0.01
    # R5 check: 16-cycle hold + 2-flop sync = 18 sys cycles = 187.5 ns.
    assert abs(16 * T["sys"] + 2 * T["sys"] - 187.5) < 0.01
    # The assertion width is 16 cycles of each domain's OWN clock: the slowest
    # clock (clk_per) needs the longest time, 666.7 ns; clk_cpu only 83.3 ns.
    assert abs(16 * T["per"] - 666.7) < 0.1
    assert abs(16 * T["cpu"] - 83.333) < 0.01
    assert max(16 * p for p in T.values()) == 16 * T["per"]
    print("PASS: per-domain sync release 2 cycles; R5 hold-plus-sync 187.5 ns")

    What the review looks for

    • One synchroniser instance per reset net per domain, three in NanoSoC, named in the netlist, never a shared release across clocks.

    • Recovery and removal checked on the reset tree behind each synchroniser (clk-to-q plus buffering inside one period of that domain).

    • Assertion width proven at 16 cycles of each domain's own clock, so the slowest clock, clk_per at 666.7 ns, sets the longest requirement.

    Verify and debug

    Release reset at every phase against the domain clock in simulation, including just before the edge: the output must always move right after an edge, never in between. A domain that wakes half-reset, some flops live and some dead, points at a release that bypassed the synchroniser, often a test-mode mux that was never switched back. For the bug classes see the hardware-debug reset-domain lessons.

    Asynchronous deassertion not synchronised, with its siblings reset-tree skew and too-shallow synchroniser depth. Symptom: some flops reset and others not, a rare start-up bug. Caught by reset lint, recovery and removal checks, and reset-domain analysis. Fixed by the cell above on every net.

    If asked why assertion may be asynchronous but release must be synchronous, answer with recovery and removal: assertion forces state regardless of the clock, while release near an edge is a timing violation on a random subset of flops. Then draw the two flops.

    Check yourself The synchroniser depth is questioned: would three flops be safer than two?

    Marginally, at the cost of a cycle: each extra stage adds about a clock period to the resolving time and multiplies the MTBF. Two flops with met timing is the standard choice; depth beyond two needs an MTBF argument, not a feeling.

    Related topics

    • Release Order and Timing

    • Next: Release-Order Failure Modes

    • RTL: Async Assert, Sync Deassert

    Previous

    119 / 289

    Next: Release-Order Failure Modes

    Up next

    Up nextRelease-Order Failure Modes

    Sign in to save progress

    Practice this lessonPrevious lessonReport an error
    clkarst_nq1q2
    Simulation output: asynchronous assert with two-flop synchronised release