A reset tested inside the clocked block clears on the next edge; a reset in the sensitivity list clears at once, with no clock needed. Both reset a 10-bit register to the same value, but they infer different generic cells, map to different library structures, and demand different timing treatment. This lesson runs both forms through inference and mapping, then prices a safe async release as the fix. The area verdict is stated once and plainly: in this library the two mapped totals are equal, and the lesson shows where the cost sits in each.
Testing reset inside the clocked block infers a synchronous reset: the reset is one more data input sampled on the edge, timed exactly like data. Adding reset to the sensitivity list beside the clock infers an asynchronous reset: the flop clears the moment reset asserts, which suits power-on and error recovery but needs its release synchronized to the clock. The first script pins both families on 10-bit registers: one $sdff cell with no $adff for the sync form, and one $adff cell with no $sdff for the async form.
Idiom | Sensitivity list | Generic cells (recorded) |
|---|---|---|
|
| 1 $sdff: reset is data-path logic. |
|
| 1 $adff: reset is a dedicated pin. |
| Either of the above | Same families with the loaded constant flipped. |
read_verilog <<EOV
module sreg10(input clk, input srst, input [9:0] d, output reg [9:0] q);
always @(posedge clk) if (srst) q <= 10'd0; else q <= d;
endmodule
EOV
hierarchy -check -top sreg10
proc
opt
select -assert-count 1 t:$sdff
select -assert-none t:$adff
select -assert-none t:$dff
select -assert-none t:$dffe
tee -o stat_sreg10_generic.txt stat
write_json net_sreg10_generic.json
design -reset
read_verilog <<EOV
module areg10(input clk, input arst, input [9:0] d, output reg [9:0] q);
always @(posedge clk or posedge arst) if (arst) q <= 10'd0; else q <= d;
endmodule
EOV
hierarchy -check -top areg10
proc
select -assert-count 1 t:$adff
select -assert-none t:$sdff
select -assert-none t:$dff
select -assert-none t:$dffe
tee -o stat_areg10_generic.txt stat
write_json net_areg10_generic.json
log PASS: sync reset infers $sdff while async reset infers $adffBoth report chip area 112: the sync form pays 80 in plain DFFs plus 32 of gating, while the async form pays 100 in reset-pin DFFRs plus 12 of glue. The totals match because the reset cost moved seats instead of changing the sum.
Generic families have no area, so the price question needs mapping. The second script maps each 10-bit register through synth, dfflegalize, dfflibmap against course.lib, then abc with -constr typical.constr and a loose -D 1000 target plus stat against course.lib. Each run asserts its storage exactly: 10 DFFs for the sync form and 10 DFFRs for the async form, with no latch in either. The cost comes from the recorded abc summaries and stat histograms, which the table and charts read directly. The companion Foundations lesson runs the same comparison on 8-bit registers and reports equal totals there too; these 10-bit designs are new widths confirming the same structure from the other side of the library.
read_verilog <<EOV
module sreg10(input clk, input srst, input [9:0] d, output reg [9:0] q);
always @(posedge clk) if (srst) q <= 10'd0; else q <= d;
endmodule
EOV
read_liberty -lib course.lib
hierarchy -check -top sreg10
synth -top sreg10 -flatten
dfflegalize -cell $_DFF_P_ 01 -cell $_DFF_PN0_ 01
dfflibmap -liberty course.lib
tee -o abc_sreg10.txt abc -liberty course.lib -constr typical.constr -D 1000
tee -o stat_sreg10.txt stat -liberty course.lib
write_json net_sreg10.json
select -assert-count 10 t:DFF
select -assert-none t:$dlatch
design -reset
read_verilog <<EOV
module areg10(input clk, input arst, input [9:0] d, output reg [9:0] q);
always @(posedge clk or posedge arst) if (arst) q <= 10'd0; else q <= d;
endmodule
EOV
read_liberty -lib course.lib
hierarchy -check -top areg10
synth -top areg10 -flatten
dfflegalize -cell $_DFF_P_ 01 -cell $_DFF_PN0_ 01
dfflibmap -liberty course.lib
tee -o abc_areg10.txt abc -liberty course.lib -constr typical.constr -D 1000
tee -o stat_areg10.txt stat -liberty course.lib
write_json net_areg10.json
select -assert-count 10 t:DFFR
select -assert-none t:$dlatch
log PASS: sync and async 10-bit registers map with recorded costs10-bit register | ABC glue area (recorded) | Chip area (stat -liberty) | Where the reset cost sits (recorded) |
|---|---|---|---|
Sync reset | 32 | 112 | DFF 80 plus 32 of data-path gating. |
Async reset | 12 | 112 | DFFR 100 plus 12 of glue. |
Both chip totals read 112: the reset cost moved seats instead of changing the sum. Read the per-bit inverters in the async row as a polarity adapter, not extra logic: the library's reset pin is active-low while the RTL reset is active-high, so each of the 10 DFFR cells takes one inverter on its reset pin, and one BUF carries the shared reset to all ten. The sync row's NOR2 plus INV pairs are the same seat in the other form: each bit's D input becomes the data AND NOT the reset. The ABC column reads 32 against 12 because it covers only this mapped glue with the flops excluded, so quoting it as the register cost misprices the sync form by more and misprices both. Quote the stat chip total whenever the design carries flops.
Library cell | Sync count | Sync area | Async count | Async area |
|---|---|---|---|---|
BUF | 1 | 2 | 1 | 2 |
DFF | 10 | 80 | 0 | 0 |
INV | 10 | 10 | 10 | 10 |
NOR2 | 10 | 20 | 0 | 0 |
DFFR | 0 | 0 | 10 | 100 |
Synchronous reset is timed like data, so it needs no special timing treatment beyond setup and hold on the reset input, provided the reset source is itself synchronous to this clock: an externally driven sync reset still needs synchronization, or its release can go metastable. Its cost is effect latency: nothing happens until the next active edge, which makes it useless for power-on before the clock runs. Asynchronous reset acts without a clock, which suits power-on and error recovery, but its release must be synchronized to the clock or some flops leave reset on different edges and the design wakes in a mixed state.
Property | Synchronous reset | Asynchronous reset |
|---|---|---|
Takes effect | On the next active clock edge | At once, with no clock |
Timing treatment | Like ordinary data | Needs recovery and removal checks at release |
Release safety | Safe if the reset source is itself synchronous to this clock | Needs a synchronized release, priced below |
Recovery and removal are the reset analogues of setup and hold: recovery asks the reset release to arrive early enough before the clock edge, removal asks it to hold long enough after. A commercial flow checks both on the async pin; the open tools here have no timing checker, so the page states the requirement as the standard semantics rather than as a recording, and prices the fix instead of the violation.
The third script keeps the async 10-bit register and derives its reset from a two-flop synchronizer: the external reset asserts both synchronizer flops at once, and the release ripples through them on the clock before reaching the register. The polarity matters: the synchronizer flops reset to 0 and shift in 1, while the register watches the falling edge of the chain (always @(posedge clk or negedge s2) if (!s2)), so the register clears while the external reset is asserted and stays in reset until the chain releases it; wiring the watched edge the other way round holds the register in reset forever. The mapped result holds 12 reset-pin DFFRs at chip area 122, 10 units over the bare async register. The two extra flops plus their glue are the recorded price of a safe release. Skipping it saves area and risks the mixed-state wake the pitfall below describes. The testbench after the script proves the assert side needs no clock: with the clock held low, asserting the external reset still clears the register.
read_verilog <<EOV
module areg10_sync(input clk, input arst_in, input [9:0] d, output reg [9:0] q);
reg s1, s2;
always @(posedge clk or posedge arst_in) begin
if (arst_in) begin s1 <= 1'b0; s2 <= 1'b0; end
else begin s1 <= 1'b1; s2 <= s1; end
end
always @(posedge clk or negedge s2) if (!s2) q <= 10'd0; else q <= d;
endmodule
EOV
read_liberty -lib course.lib
hierarchy -check -top areg10_sync
synth -top areg10_sync -flatten
dfflegalize -cell $_DFF_P_ 01 -cell $_DFF_PN0_ 01
dfflibmap -liberty course.lib
tee -o abc_areg10_sync.txt abc -liberty course.lib -constr typical.constr -D 1000
tee -o stat_areg10_sync.txt stat -liberty course.lib
write_json net_areg10_sync.json
select -assert-count 12 t:DFFR
select -assert-none t:$dlatch
log PASS: synchronized async release maps with recorded cells// engine: icarus
module areg10_sync_tb (
input logic clk, input logic arst_in, input logic [9:0] d, output logic [9:0] q
);
logic s1, s2;
always @(posedge clk or posedge arst_in) begin
if (arst_in) begin s1 <= 1'b0; s2 <= 1'b0; end
else begin s1 <= 1'b1; s2 <= s1; end
end
always @(posedge clk or negedge s2) if (!s2) q <= 10'd0; else q <= d;
endmodule
module tb_sync_release;
logic clk = 0, arst_in = 0;
logic [9:0] d = 10'h2AA, q;
areg10_sync_tb dut (.*);
int errors = 0;
initial begin
arst_in = 1; #1;
if (q !== 10'd0) begin $display("FAIL: q not cleared while arst asserted, clk idle"); errors++; end
repeat (2) begin #5 clk = 1; #5 clk = 0; end
if (q !== 10'd0) begin $display("FAIL: q not held under reset"); errors++; end
#2; arst_in = 0; #3;
repeat (2) begin clk = 1; #5; clk = 0; #5; end
if (q !== 10'd0) begin $display("FAIL: q released before 2 sync edges"); errors++; end
clk = 1; #5; clk = 0; #1;
if (q !== 10'h2AA) begin $display("FAIL: q did not load after release"); errors++; end
if (errors == 0) $display("PASS: async assert clears with no clock, release takes 2 edges");
$finish;
end
endmodulePricing a sync-reset register with the async cell's area. In this library a sync reset is a plain DFF plus gates on D, not a DFFR, and the two 10-bit totals come out equal. Pricing either form with ABC's glue-only area makes the same mistake against the recordings: the flops are excluded from that line.
The asynchronous idiom with reset in the sensitivity list. It infers $adff, recorded as one such cell beside no $sdff on this page.
Neither costs more in total: both report the same total in the recorded stat reports. The sync form pays in data-path gating around plain flops while the async form concentrates the reset into reset-pin flops, so any ABC-only gap measures excluded flops, never a cheaper reset.
Every number and picture on this page comes from three Yosys 0.70 runs recorded by the course checker (scripts/tools/run-rtl-testbenches.mjs with COURSE=synth): 10-bit sync and async registers through proc (plus opt on the sync form) for the family proof, both through synth, dfflegalize, dfflibmap -liberty course.lib, abc -liberty course.lib -constr typical.constr -D 1000 and stat -liberty course.lib with exact DFF and DFFR count assertions, and an async register with a two-flop release synchronizer through the same flow. An Icarus sim proves the assert clears the register with the clock held low. Recovery and removal are stated as standard timing semantics, not measured here. The library is fictional, so absolute areas are teaching units.