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

AboutContactPrivacyTerms
Skip to lesson

Course contents

  • RTL Foundations36
  • Combinational Design25
  • Sequential Design27
  • FSM & Control27
  • Timing & Clocking39
  • Reset & CDC34
    • Reset Architecture
      • Reset Is a System Contract
      • Async Assert, Sync Deassert
      • Reset Tree Planning
      • Reset Sequencing and POR Controller
      • What a Reset Costs
    • Metastability and Synchronisation
    • Asynchronous FIFO
    • CDC Protocols
    • Reset Domain Crossing
    • CDC Verification
  • Memory & Buses57
  • Advanced RTL28
  • Senior & Interview76
  • Glossary and Notation
Loading lesson

‹Reset Architecture
  1. Topics
  2. RTL Design
  3. Reset & CDC
  4. Reset Architecture
  5. Reset Tree Planning

Part 6 · Reset & CDC · Intermediate

Reset Tree Planning

One async source feeding each clock domain through its own synchroniser, replicated for fanout.

On this page

    Why this matters

    A reset reaches every control flop on the chip, and one net with thousands of loads is slow with uncertain skew. Synchronising the raw reset twice for interacting logic can release the two parts on different cycles.

    After this lesson you can: plan a reset tree with one source, one synchroniser per clock domain, one settled reset per domain and a table of which reset drives which block.

    A reset has the same fanout problem as a clock

    A reset reaches every control flop in the chip. A single net with thousands of loads is slow and has uncertain skew.

    Large skew breaks recovery and removal margins. Plan the tree like a clock tree:

    1. One source (pin, power-on detector, watchdog), combined into a single asynchronous arst_n.

    2. One reset synchroniser per clock domain, in that domain's clock. Never share a synchroniser between clocks.

    3. Distribute one settled reset per domain through a buffered tree. Independently synchronising the raw reset twice can release interacting regions on different cycles. Any registered distribution copies must sample the same settled output and meet their timing checks.

    4. Buffer the synchronised reset like a clock net, balanced where recovery/removal need it.

    5. Document which resets drive which blocks, in one table.

    arst_n feeds two separate reset synchronisers in domain A; one drives the left branch and the other the right branch.
    Wrong: domain A has two synchronisers, so its two branches can leave reset one cycle apart
    arst_n feeds sync_a, whose output rst_a_n is buffered to the left and right branches of domain A, and sync_b, which drives domain B.
    Right: one synchroniser per clock domain; its single settled output is buffered to both branches

    Read both charts from the raw reset at the top down to the flops that use it.

    • In the wrong tree, each synchroniser can resolve a release on a different clk_a edge, so the left and right branches of one domain may start one cycle apart.

    • In the right tree, domain A makes one release decision and the buffers only copy it. This is reset_tree in the testbench below.

    • Domain B still has its own synchroniser, because it runs on a different clock.

    Design choices

    Tip

    Write the reset ownership into the module interface: input logic rst_n always means “already synchronised to this module's clock”. Raw asynchronous resets get a distinct name (arst_n) that stops at the synchroniser.

    Design choice

    Why

    Synchroniser per domain

    Release must be aligned to the clock that uses it

    Two buffered branches in domain A

    Splits the load downstream of one synchroniser

    Branches share one settled reset

    One release decision; implementation must still meet recovery/removal at every sink

    Asynchronous source goes to every synchroniser, nowhere else

    No domain sees the raw reset

    Common mistakes

    Common pitfall

    Releasing two interacting domains in the same cycle of their own clocks is not 'at the same time'. If domain A starts sending data one cycle before B is out of reset, B may miss the data. Order matters; see sequencing.

    Interview

    “How do you reset a design with three clocks?” A reset synchroniser per clock from one async source, replicated for fanout, with the order of release decided by a sequencer or by protocol (no domain transmits before its partner is ready).

    Check yourself Do two reset synchronisers using the same clock and raw reset necessarily release together?

    No. Metastability can delay one chain by a cycle. Synchronise once per interacting domain and distribute that settled result; verify the distribution tree with STA.

    Testbench

    The testbench drives two unrelated clocks through 300 random assert and release cycles.

    reset_sync.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
    `timescale 1ns/1ps
    
    module reset_sync #(parameter int STAGES = 2) (input logic clk, arst_n, output logic srst_n);
      if (STAGES < 2) begin : g_stages_check       // legal range: STAGES >= 2
        $error("reset_sync: STAGES must be at least 2");
      end
      logic [STAGES-1:0] sr;
      always_ff @(posedge clk or negedge arst_n)
        if (!arst_n) sr <= '0;
        else         sr <= {sr[STAGES-2:0], 1'b1};
      assign srst_n = sr[STAGES-1];
    endmodule
    
    // One synchroniser per clock domain; physical buffers distribute its settled output.
    module reset_tree (
      input  logic clk_a, clk_b,
      input  logic arst_n,                 // the single asynchronous source (pin, POR, watchdog...)
      output logic rst_a_left_n, rst_a_right_n,
      output logic rst_b_n
    );
      logic rst_a_n;
      reset_sync sync_a (.clk(clk_a), .arst_n, .srst_n(rst_a_n));
      assign rst_a_left_n = rst_a_n;
      assign rst_a_right_n = rst_a_n;
      reset_sync sync_b       (.clk(clk_b), .arst_n, .srst_n(rst_b_n));
    endmodule
    

    The test uses periods of 7 ns and 11 ns and checks both branches on every falling edge of clk_a. The branches share one RTL signal, so the test does not model physical reset skew; check that in implementation timing reports.

    Remember

    • One synchroniser per clock domain, in that domain's clock. Never share one between clocks.

    • Distribute one settled reset per domain through a buffered tree. Do not synchronise the raw reset twice for interacting logic.

    • Name the contract: rst_n means already synchronised to this module's clock; a raw asynchronous reset is arst_n and stops at the synchroniser.

    Rule of thumb: releasing two domains on the same cycle of their own clocks is not releasing them at the same time.

    How this was checked

    The two-clock test (7 ns and 11 ns periods, 300 random assert and release cycles) checks both branches on every falling edge of clk_a. The branches share one RTL signal, so it does not model physical reset skew or prove recovery/removal; those need implementation timing reports. Independent synchroniser chains would need a metastability model to expose unequal release latency.

    Keep going

    • Practice: FSM reset synchronisation and glitch prevention

    • Interview: run a mock interview on this topic

    Related topics

    • Sequencing and POR

    Previous

    157 / 350

    Next: Reset Sequencing and POR Controller

    Up next

    Up nextReset Sequencing and POR Controller

    Sign in to save progress

    Practice this lessonReport an error

    See also

    • Reset Is a System Contract
    • What a Reset Costs