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. What a Reset Costs

Part 6 · Reset & CDC · Intermediate

What a Reset Costs

Three reset choices on one 32-bit pipeline, measured: cell counts, the load on the reset net, and why the unreset data registers are still safe.

On this page

    Why this matters

    Resetting every flop of a 32-bit, 4-stage pipeline puts 136 loads on the reset net; resetting only the valid chain and one counter puts 8, with the same output. Each reset is a bigger cell or an extra gate, and a load the reset tree must reach in time.

    After this lesson you can: decide which registers need a reset, measure the reset cost of a block from a Yosys stat report, and show in simulation that unreset data qualified by a valid bit is safe.

    Every reset pin is a load the reset tree must reach

    The same 4-stage, 32-bit pipeline was synthesised three ways. With every flop reset, the reset net rst_n drives 136 loads; with only the valid chain and one counter reset, it drives 8, and the data that comes out is identical.

    A reset is not free. Each reset flop is a larger cell or has a gate in front of it, and every one is a load on a net that has to reach the whole block within its timing window. The picture compares the three versions.

    Cell count and rst_n load for the same pipeline with every flop reset asynchronously, every flop reset synchronously, and only the control flops reset

    Read the top chart as logic size and the bottom chart as reset-tree size.

    • (a) all async and (c) control only have the same cell count. The difference is in the flop types: (a) uses 136 reset flops, (c) only 8.

    • (b) all sync adds 136 gates, one in front of every flop's D input, to force it to 0 when rst_n is low.

    • The reset net has 136 loads in (a) and (b) but 8 in (c). That is the number the reset tree has to be built and timed for.

    The block: a data pipeline with a valid chain

    A word enters with in_valid, passes four stages (capture, XOR with a key, rotate by a byte, add 1) and leaves with out_valid. The valid bits travel in a 4-bit shift register v beside the data. A 4-bit counter beats counts delivered words. Version (c), below, resets only v and beats.

    pipe_c.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
    28
    29
    30
    31
    32
    33
    // yosys: ok
    // Version (c): only control state is reset. Data registers load when valid.
    module pipe_c (
      input  logic        clk, rst_n,
      input  logic        in_valid,
      input  logic [31:0] in_data,
      input  logic [31:0] key,
      output logic        out_valid,
      output logic [31:0] out_data,
      output logic [3:0]  beats            // words delivered since reset
    );
      logic [3:0]  v;                      // valid chain: control, reset
      logic [31:0] d1, d2, d3, d4;         // datapath: no reset
    
      always_ff @(posedge clk or negedge rst_n)
        if (!rst_n) begin
          v     <= '0;
          beats <= '0;
        end else begin
          v <= {v[2:0], in_valid};
          if (v[3]) beats <= beats + 1'b1;
        end
    
      always_ff @(posedge clk) begin
        if (in_valid) d1 <= in_data;
        if (v[0])     d2 <= d1 ^ key;
        if (v[1])     d3 <= {d2[23:0], d2[31:24]};
        if (v[2])     d4 <= d3 + 32'd1;
      end
    
      assign out_valid = v[3];
      assign out_data  = d4;
    endmodule

    Version (a) keeps the same control block and puts the data registers under the same asynchronous reset:

    design.sv
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    // snippet: version (a), data block; the control block is as in pipe_c
      always_ff @(posedge clk or negedge rst_n)
        if (!rst_n) begin
          d1 <= '0; d2 <= '0; d3 <= '0; d4 <= '0;
        end else begin
          if (in_valid) d1 <= in_data;
          if (v[0])     d2 <= d1 ^ key;
          if (v[1])     d3 <= {d2[23:0], d2[31:24]};
          if (v[2])     d4 <= d3 + 32'd1;
        end

    Version (b) is version (a) with or negedge rst_n removed from both event lists, so both blocks reset on a clock edge. The three versions hold 136 flops: 128 data bits, 4 valid bits and 4 counter bits.

    Reading the stat reports

    A plain synth -top pipe_x; stat reports 236 cells for all three versions: 100 logic gates and 136 flops. Only the flop names differ.

    Version

    Flops in generic synthesis

    Logic

    Total

    (a) all async

    132 $_DFFE_PN0P_, 4 $_DFF_PN0_

    100

    236

    (b) all sync

    132 $_SDFFE_PN0P_, 4 $_SDFF_PN0_

    100

    236

    (c) control only

    128 $_DFFE_PP_, 4 $_DFFE_PN0P_, 4 $_DFF_PN0_

    100

    236

    Read the names letter by letter. DFFE has an enable, PN0 means a positive clock and an active-low reset to 0, and the S in SDFF means the reset is synchronous. The generic library has a flop for every combination, so the reset cost hides inside the cell name.

    To see it, map the flops to a smaller set: a plain flop $_DFF_P_ and an async-reset flop $_DFF_PN0_, with no enable and no synchronous reset built in. Anything else has to be built from gates in front of D:

    Diagram
    yosys -p "read_verilog -sv pipe_b.sv; synth -top pipe_b; dfflegalize -cell \$_DFF_P_ x -cell \$_DFF_PN0_ x; opt -nodffe -nosdff; stat; select -count w:rst_n %co1 w:rst_n %d"
    ...
          504 cells
           30   $_AND_
          136   $_DFF_P_
          268   $_MUX_
            2   $_NAND_
            2   $_NOT_
            2   $_XNOR_
           64   $_XOR_
    
    136 objects.

    The last line is the select -count result: the number of cells connected to rst_n, with the wire itself removed from the selection. The same two commands on all three versions give this table.

    Version

    Flops

    Reset flops

    $_MUX_

    Other logic

    Total cells

    Loads on rst_n

    (a) all async

    136 $_DFF_PN0_

    136

    132

    100

    368

    136

    (b) all sync

    136 $_DFF_P_

    0

    268

    100

    504

    136

    (c) control only

    128 $_DFF_P_, 8 $_DFF_PN0_

    8

    132

    100

    368

    8

    Read the columns one at a time.

    • 132 muxes in every version are the enables: each enabled flop now holds its value through a mux from Q back to D. They cost the same in all three.

    • (b) has 136 more muxes. Each one forces D to 0 while rst_n is low, so the synchronous reset becomes a gate in every data path, including the output of the 32-bit adder.

    • (a) and (c) have the same totals, but (a) uses 136 reset flops where (c) uses 8. In a real library a flop with a reset pin is a larger cell than a plain one, so (c) is smaller even at the same count.

    • Loads on rst_n fall from 136 to 8 only in (c). Removing the reset, not changing its style, is what shrinks the reset tree.

    The reset tree is the cost that grows with the chip. An asynchronous reset must reach every reset pin within its recovery and removal window, so the net is buffered and balanced like a clock (see Reset tree planning). A synchronous reset needs the same net, timed as data to every gate. With thousands of data registers per block, removing their resets removes most of that tree.

    Warning

    Limits. These are generic cell counts, not area or timing. The second mapping models a library with no enable flops and no synchronous-reset flops. Many real libraries offer enable flops, some offer synchronous-reset flops, and the counts change with them, but the load count on the reset net does not. Reset tree delay and buffering appear only after placement.

    Which registers need a reset

    A register needs a reset when its power-up value can change what the block does. A register whose value is always written before anyone reads it does not.

    Register

    Reset?

    Why

    FSM state

    Yes

    A random start state can do anything, including an illegal encoding.

    Valid bits, request and handshake flags

    Yes

    They decide whether other registers are read.

    Counters and pointers that gate outputs

    Yes

    A random count produces a wrong full, last or interrupt.

    Software-visible configuration

    Yes

    Software expects the documented reset values.

    Pipeline data qualified by a valid bit

    No

    It is written before it is used, and the valid bit hides it until then.

    Memories and register files

    No

    Too many bits; initialise them by protocol or mark them unwritten.

    Proof that unreset data is safe

    The bench below runs version (c) against a reference model. It prints the first nine cycles, then sends 20 cycles of traffic with a gap every third cycle and checks every word that comes out. It also checks on every cycle that out_valid is never x.

    Diagram
    cycle 1  rst_n=0 in_valid=0  d1=xxxxxxxx  out_valid=0  out_data=xxxxxxxx
    cycle 2  rst_n=0 in_valid=0  d1=xxxxxxxx  out_valid=0  out_data=xxxxxxxx
    cycle 3  rst_n=1 in_valid=0  d1=xxxxxxxx  out_valid=0  out_data=xxxxxxxx
    cycle 4  rst_n=1 in_valid=0  d1=xxxxxxxx  out_valid=0  out_data=xxxxxxxx
    cycle 5  rst_n=1 in_valid=1  d1=a0000000  out_valid=0  out_data=xxxxxxxx
    cycle 6  rst_n=1 in_valid=1  d1=a0000001  out_valid=0  out_data=xxxxxxxx
    cycle 7  rst_n=1 in_valid=0  d1=a0000001  out_valid=0  out_data=xxxxxxxx
    cycle 8  rst_n=1 in_valid=1  d1=a0000003  out_valid=1  out_data=0f0f0fb0
    cycle 9  rst_n=1 in_valid=1  d1=a0000004  out_valid=1  out_data=0f0f0eb0
    PASS: 14 words correct; out_valid never X although data registers start as X

    Each line is printed 1 ns after a rising clock edge and shows the values that edge produced.

    • Cycles 1 to 4: d1 and out_data are x, because nothing has written them. out_valid is 0 from the first cycle, because v is reset.

    • Cycle 5: the first word is captured, so d1 becomes a0000000. out_data is still x, and out_valid is still 0.

    • Cycle 7: a gap: in_valid is 0 and d1 holds its value.

    • Cycle 8: the first word arrives three edges after cycle 5, with out_valid = 1 and a known value: a0000000 XOR 0f0f0f0f, rotated by one byte, plus 1, which is 0f0f0fb0.

    The x on out_data in cycles 1 to 7 is real: those flops hold random values in silicon too. It is harmless because no one reads out_data while out_valid is 0. The trap is a consumer that does. If it adds out_data into a sum every cycle, simulation shows x and the bug is visible. If it tests if (out_data == K), an if treats x as false and simulation takes the else branch: the bug is masked. X-propagation discipline covers why that optimism hides bugs.

    Common mistakes

    Common pitfall

    Removing the reset from a register that feeds a control decision. A data register compared against a threshold to raise an interrupt, or a last flag carried in the data word, decides what the block does next. Unreset, it powers up random in silicon, and in simulation the if takes its else branch on x, so the test passes. If any branch, enable or valid depends on a register, reset it.

    Check yourself In version (c), beats only counts delivered words. Why is it reset, and what would simulation show without the reset?

    It is a software-visible output, and anything that reads it, such as a full or interrupt check, would act on a random power-up count. Without the reset, beats starts as x and x + 1 stays x, so the counter never becomes known in simulation.

    Check yourself Version (b) uses no reset flops at all. Why does it still put 136 loads on the reset net?

    The synchronous reset is a gate in front of each flop's D input, so rst_n drives 136 gate inputs instead of 136 reset pins. The tree is the same size; it is timed as a data path instead of for recovery and removal. Only removing resets, as in (c), shrinks it.

    Testbench

    The bench repeats pipe_c so the block runs on its own. A queue holds every word sent, and a reference function computes the expected output for each.

    pipe_c.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
    28
    29
    30
    31
    module pipe_c (
      input  logic        clk, rst_n,
      input  logic        in_valid,
      input  logic [31:0] in_data,
      input  logic [31:0] key,
      output logic        out_valid,
      output logic [31:0] out_data,
      output logic [3:0]  beats
    );
      logic [3:0]  v;
      logic [31:0] d1, d2, d3, d4;
    
      always_ff @(posedge clk or negedge rst_n)
        if (!rst_n) begin
          v     <= '0;
          beats <= '0;
        end else begin
          v <= {v[2:0], in_valid};
          if (v[3]) beats <= beats + 1'b1;
        end
    
      always_ff @(posedge clk) begin
        if (in_valid) d1 <= in_data;
        if (v[0])     d2 <= d1 ^ key;
        if (v[1])     d3 <= {d2[23:0], d2[31:24]};
        if (v[2])     d4 <= d3 + 32'd1;
      end
    
      assign out_valid = v[3];
      assign out_data  = d4;
    endmodule
    

    Remember

    • Reset what decides behaviour: FSM state, valid bits, counters and pointers that gate outputs, software-visible registers.

    • Data written before it is read, and qualified by a reset valid bit, needs no reset. Its x in simulation is real but unread.

    • A synchronous reset still loads the reset net: it moves from reset pins to a gate in every D path. Only removing resets shrinks the tree.

    Rule of thumb: reset what decides; let a reset valid bit guard what carries.

    How this was checked

    Tool: Yosys 0.69+post (git sha1 143eb14f9), run on 2026-10-17, on pipe_a.sv, pipe_b.sv and pipe_c.sv (the three versions on the page). Commands, for x in a b c: yosys -p "read_verilog -sv pipe_x.sv; synth -top pipe_x; stat" and yosys -p "read_verilog -sv pipe_x.sv; synth -top pipe_x; dfflegalize -cell $_DFF_P_ x -cell $_DFF_PN0_ x; opt -nodffe -nosdff; stat; select -count w:rst_n %co1 w:rst_n %d".

    Result: generic synthesis gives 236 cells for all three (100 logic, 136 flops). After the mapping: (a) 368 cells with 136 $_DFF_PN0_ and 132 $_MUX_; (b) 504 cells with 136 $_DFF_P_ and 268 $_MUX_; (c) 368 cells with 128 $_DFF_P_, 8 $_DFF_PN0_ and 132 $_MUX_. select -count reports 136, 136 and 8 objects on rst_n. The chart and tables use these numbers.

    Tool: Icarus Verilog 13.0, same date. Command: iverilog -g2012 -o tb.vvp pipe_c.sv tb_pipe_c.sv && vvp -n tb.vvp. Result: the nine trace lines and PASS line on the page (14 words checked against the reference model, out_valid never x). The same bench was also run against pipe_a and pipe_b and passed, so all three deliver the same words.

    Scope and limits: generic cells, no technology library, so counts are not area or timing; the mapping models a library without enable or synchronous-reset flops. Reset-tree buffering and recovery/removal timing need placement and STA, which were not run.

    Keep going

    • Practice: Reset strategies in RTL: sync, async and gated

    • Practice: Why reset is important in FSMs and how it is handled

    • Code lab: Build a pipeline register stage

    • Code lab: Build a D flip-flop with asynchronous reset

    • Interview: run a mock interview on this topic

    Related topics

    • Reset is a system contract

    • X-propagation discipline

    Previous

    159 / 350

    Next: Metastability and Synchronisation

    Up next

    Up nextMetastability and Synchronisation

    Sign in to save progress

    Practice this lessonReport an error

    See also

    • Reset Is a System Contract
    • Async Assert, Sync Deassert
    • Reset Tree Planning