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

  • Logic Synthesis Glossary
  • Logic Synthesis Cheatsheet
  • Synthesis Foundations14
  • Logic Optimisation and Mapping20
  • Constraints and Timing15
  • Sequential, FSM and Memory19
    • Flops, Resets and Enables
      • D Flop Inference
      • Enables: Mux or Clock Enable
      • Synchronous and Asynchronous Reset
      • Reset-less Flops and Initial Values
      • Mapping Flops to Library Cells
    • FSM Synthesis
    • Memory and Macro Inference
    • Retiming and Pipelining
  • Datapath Synthesis14
  • Area, Power and Test14
  • Verification, ECO and Handoff15
  • Flows and Debugging15
  • Interview and Judgment11
Loading lesson

←Flops, Resets and Enables
  1. Topics
  2. Logic Synthesis
  3. Sequential, FSM and Memory
  4. Flops, Resets and Enables
  5. Reset-less Flops and Initial Values
On this page

    Part 4 of 9, lesson 4 of 19Part 4 of 9/Sequential, FSM and Memory/Lesson 4 of 19Intermediate

    Reset-less Flops and Initial Values

    Datapath flops skip reset, initial values ride an attribute, and early reads show x.

    Resetting every flop wastes area on bits that are always rewritten, while an unreset bit read too early is a real bug. This page records both the saving and the consequence.

    After this lesson you can: decide which flops may skip reset, say what an initial value guarantees per target, and show what an early read does in simulation.

    The question

    Reset costs a pin, routing, and area on every flop that carries it, so wide datapaths reset only what correctness needs: state, valid flags, and control. This lesson mixes a 16-bit reset-less datapath with a sync-reset flag in one module, prices a 16-bit register with and without sync reset from the recorded stat reports, follows an initial value into the netlist attribute it becomes, and watches an early read spread unknown in simulation. The verdict it builds toward: a reset-less data-path flop is fine, provided nothing reads it before its first load.

    Why datapath flops skip reset

    Data registers that are always written before they are read need no reset: their first useful value comes from a load, not from power-up. What must reset is the knowledge of whether the data is meaningful: the valid flag, the state register, the pointers. The first script mixes both families in one 16-bit pipeline stage: the data vector loads unconditionally while a valid flag carries the sync reset. It asserts one $dff beside one $sdff, proving the two families coexist in one module with no async-reset or enabled cell anywhere.

    yosys
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    read_verilog <<EOV
    module pipe16(input clk, input srst, input fill, input [15:0] d, output reg [15:0] q, output reg valid);
    always @(posedge clk) q <= d;
    always @(posedge clk) if (srst) valid <= 1'b0; else valid <= fill;
    endmodule
    EOV
    hierarchy -check -top pipe16
    proc
    opt
    select -assert-count 1 t:$dff
    select -assert-count 1 t:$sdff
    select -assert-none t:$adff
    select -assert-none t:$dffe
    tee -o stat_pipe16_generic.txt stat
    write_json net_pipe16_generic.json
    log PASS: reset-less datapath infers $dff beside a sync-reset $sdff flag
    Predict first The 16-bit data vector maps with and without a sync reset. What will the two chip areas be, and which seat will the reset cost sit in?

    The reset-less form reports chip area 128 in plain DFFs, while the reset form reports 178: the same storage plus data-path gating on D. Skipping reset on the datapath saves 50 units, and the flag beside it keeps the saving safe.

    Pipeline stage piece

    Generic cells (recorded)

    Reading

    16-bit data vector

    1 $dff cell

    Reset-less: loaded before read, never cleared.

    Valid flag

    1 $sdff cell

    Sync reset: says whether the data means anything.

    Area of the choice

    The second script maps the 16-bit data vector twice: once plain and once with a sync reset, through synth, dfflegalize, dfflibmap, abc, and stat. Both runs assert their storage so the comparison is exact. The recorded totals read 128 without reset against 178 with it, so the reset costs 50 units on this width: plain DFFs plus a NOR-and-inverter gate on every D input. No DFFR appears in either row: a sync reset is a plain flop plus gates on D, never the async cell's area.

    yosys
    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
    read_verilog <<EOV
    module data16(input clk, input [15:0] d, output reg [15:0] q);
    always @(posedge clk) q <= d;
    endmodule
    EOV
    read_liberty -lib course.lib
    hierarchy -check -top data16
    synth -top data16 -flatten
    dfflegalize -cell $_DFF_P_ 01 -cell $_DFF_PN0_ 01
    dfflibmap -liberty course.lib
    tee -o abc_data16.txt abc -liberty course.lib -constr typical.constr -D 1000
    tee -o stat_data16.txt stat -liberty course.lib
    write_json net_data16.json
    select -assert-count 16 t:DFF
    design -reset
    read_verilog <<EOV
    module data16r(input clk, input srst, input [15:0] d, output reg [15:0] q);
    always @(posedge clk) if (srst) q <= 16'd0; else q <= d;
    endmodule
    EOV
    read_liberty -lib course.lib
    hierarchy -check -top data16r
    synth -top data16r -flatten
    dfflegalize -cell $_DFF_P_ 01 -cell $_DFF_PN0_ 01
    dfflibmap -liberty course.lib
    tee -o abc_data16r.txt abc -liberty course.lib -constr typical.constr -D 1000
    tee -o stat_data16r.txt stat -liberty course.lib
    write_json net_data16r.json
    select -assert-none t:$dlatch
    log PASS: reset-less and sync-reset datapaths map with recorded costs

    16-bit datapath

    Mapped library cells (recorded)

    Chip area (stat -liberty)

    Without reset

    16 DFF

    128

    With sync reset

    16 DFF + 16 NOR2 + 16 INV + 1 BUF

    178

    Recorded total chip area from the stat reports for the datapath with and without reset. The gap is the reset gating on every bit.
    The recorded generic stage: one 1 $dff vector for the data beside one 1 $sdff flag. Two families, one module.

    Initial values and X

    An initial assignment sets the simulation value at time zero. Yosys honours it during elaboration: the third script gives an 8-bit register the initial value 8'hA5, runs proc, and asserts the usual single $dff. The recorded netlist carries that value as an init attribute on the output net, reading 10100101 in binary. Whether the attribute reaches silicon depends on the target: FPGA flows such as synth_ice40 honour init values by configuring the flop state, while an ASIC flow has no such cell and the value buys nothing. The lesson states that split as standard background, not as a run: the recording stops at the init attribute, and only one mapping family is run on this page.

    yosys
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    read_verilog <<EOV
    module initreg(input clk, input [7:0] d, output reg [7:0] q);
    initial q = 8'hA5;
    always @(posedge clk) q <= d;
    endmodule
    EOV
    hierarchy -check -top initreg
    proc
    select -assert-count 1 t:$dff
    tee -o stat_initreg.txt stat
    write_json net_initreg.json
    log PASS: initial value rides along as an init attribute on the flop

    Initial-value question

    Recorded answer

    Generic family

    1 $dff: init changes no family.

    Where the value lands

    Output-net init attribute reads 10100101 (A5 in binary).

    FPGA flows

    Honour it: configuration sets the flop state.

    ASIC flows

    Ignore it: there is no such cell; add a reset if power-up matters.

    A flop with no reset reads unknown (x) in simulation until its first load. Silicon powers up to an unpredictable but resolved 0 or 1, so any bit read before its first write is still a real bug even though no simulator flag survives to the chip. The two testbenches below show both sides on Icarus, which keeps four-state values: first the safe pattern, where the consumer waits for the valid flag, then the break-it, where it reads too early.

    pipe8.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
    // engine: icarus
    module pipe8 (
      input logic clk, input logic srst, input logic fill,
      input logic [7:0] d, output logic [7:0] q, output logic valid
    );
      always @(posedge clk) q <= d;
      always @(posedge clk) if (srst) valid <= 1'b0; else valid <= fill;
    endmodule
    module tb_x;
      logic clk = 0, srst = 1, fill = 0;
      logic [7:0] d, q;
      logic valid;
      pipe8 dut (.*);
      always #5 clk = ~clk;
      int errors = 0;
      initial begin
        #3;
        if (^q !== 1'bx) begin $display("FAIL: q not x before first load"); errors++; end
        if (valid !== 1'bx) begin $display("FAIL: valid not x before first edge"); errors++; end
        @(posedge clk); #1;
        if (valid !== 1'b0) begin $display("FAIL: valid not 0 under reset"); errors++; end
        if (^q !== 1'bx) begin $display("FAIL: q resolved with no data written"); errors++; end
        srst = 0; fill = 1; d = 8'hA5;
        @(posedge clk); #1;
        @(posedge clk); #1;
        if (q !== 8'hA5) begin $display("FAIL: q did not load"); errors++; end
        if (valid !== 1'b1) begin $display("FAIL: valid did not assert"); errors++; end
        if (errors == 0) $display("PASS: reset-less q starts x, then loads beside its valid flag");
        $finish;
      end
    endmodule

    Break it: read before the first load

    The second testbench drops the valid flag and samples the data through combinational logic from time zero. Before the first edge the output is unknown, and the bench asserts exactly that: the early sample must read as x, and only the loaded value afterwards must match. The passing run proves the consequence rather than describing it: an unread-before-write window is harmless only when nothing observes it, and this consumer observes it.

    pipe8b.sv
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    // engine: icarus
    module pipe8b (
      input logic clk, input logic [7:0] d, output logic [7:0] q
    );
      always @(posedge clk) q <= d;
    endmodule
    module tb_early;
      logic clk = 0;
      logic [7:0] d = 8'hA5, q, y;
      pipe8b dut (.*);
      assign y = q & 8'hF0;
      always #5 clk = ~clk;
      int errors = 0;
      initial begin
        #3;
        if (^y !== 1'bx) begin $display("FAIL: early read not x"); errors++; end
        @(posedge clk); #1;
        if (y !== (8'hA5 & 8'hF0)) begin $display("FAIL: loaded value wrong"); errors++; end
        if (errors == 0) $display("PASS: reading before the first load spreads x downstream");
        $finish;
      end
    endmodule

    Common mistakes

    Resetting the datapath but not its valid flag leaves stale data marked valid after reset. Reset the control that says the data is meaningful, even when the data bits themselves skip reset. The twin mistake is trusting an initial value on an ASIC: simulation starts at A5 while silicon starts anywhere, so a power-up read without reset or a first load is a bug no init attribute fixes.

    An x that clears in simulation can hide a silicon bug. The simulator holds the unknown until the first load, then resolves it; the chip never held an unknown and powered up to an arbitrary but resolved 0 or 1. If any path reads the flop before the first write, silicon and simulation disagree from power-up. Gate every consumer on valid.

    Likely probes: which flops may skip reset and what initial guarantees.

    Weak answer: reset everything to be safe, and initial values power up the chip.

    Strong answer: data written before read may skip reset while state and valid flags keep it; the 16-bit datapath saves 50 recorded units that way. initial sets simulation start and the recorded net attribute reads 10100101, but it guarantees nothing about ASIC power-up, and simulation shows x until the first load.

    Follow-up: the valid flag resets but the data bus shows x for two cycles. Answer: harmless if every consumer waits for valid, and the first testbench proves the pattern; gate the consumers on valid, not on the bus settling.

    Check yourself A 16-bit pipeline register is always loaded before its output is used. What does adding a sync reset cost in recorded units?

    An extra 50 units: 178 with reset against 128 without. The saving is the reset gating on every bit, while the valid flag beside it keeps the saving safe.

    Check yourself Simulation shows x on a reset-less data bus for the first cycles, then valid data. Is the design broken?

    Not necessarily. If the consumer ignores the bus until its valid flag asserts, the x window is harmless, as the first testbench records. If anything reads it first, that read is a bug, as the break-it testbench proves by asserting the x.

    • Data written before read may skip reset; state and valid flags keep it.

    • initial sets simulation start and a net attribute; ASIC flows ignore it.

    • Simulation shows x until the first load; silicon resolves unpredictably instead.

    Rule of thumb: reset the flag that says the data is meaningful, and gate every consumer on it.

    How this was checked

    Generic families and mapped areas on this page come from three Yosys 0.70 runs recorded by the course checker (scripts/tools/run-rtl-testbenches.mjs with COURSE=synth): a mixed 16-bit stage through proc and opt, 16-bit plain and sync-reset datapaths through synth, dfflegalize, dfflibmap -liberty course.lib, abc -liberty course.lib -constr typical.constr -D 1000 and stat -liberty course.lib, and an 8-bit register with an initial value through proc with its init attribute read from the recorded netlist. The x-propagation runs are Icarus testbenches; the FPGA-against-ASIC split is standard background, not a run. The library is fictional, so absolute areas are teaching units.

    • Interview: run a mock interview on this topic

    Related topics

    • Synchronous and Asynchronous Reset

    • Mapping Flops to Library Cells

    • Retiming and Pipelining

    • Simulation-Synthesis Mismatch

    Previous

    55 / 139

    Next: Mapping Flops to Library Cells

    Up next

    Up nextMapping Flops to Library Cells

    Sign in to save progress

    Practice this lessonPrevious lessonReport an error

    See also

    • D Flop Inference
    • Enables: Mux or Clock Enable