D Flip-Flop with Async Reset - Complete Verilog Guide
The D Flip-Flop is the fundamental building block of sequential logic. This guide covers the async reset variant with theory, implementation, testbench, and synthesis considerations.
Theory
A D Flip-Flop captures the value of the D input at the rising edge of the clock and holds it until the next clock edge. The asynchronous reset clears the output immediately when asserted, regardless of the clock.
Truth Table
| rst | clk | d | q | qbar |
|---|---|---|---|---|
| 1 | X | X | 0 | 1 |
| 0 | ↑ | 0 | 0 | 1 |
| 0 | ↑ | 1 | 1 | 0 |
| 0 | 0/1 | X | Qprev | ~Qprev |
Timing Parameters
| Parameter | Description | Typical |
|---|---|---|
| tsetup | D must be stable before clock edge | 0.1-0.5ns |
| thold | D must be stable after clock edge | 0.05-0.2ns |
| tclk-q | Clock to Q propagation delay | 0.1-0.3ns |
| trecovery | Reset release to clock edge | 0.1-0.3ns |
| tremoval | Clock edge to reset release | 0.05-0.2ns |
RTL Implementation
Verilog (ANSI Style)
module dff_async_rst (
input wire clk,
input wire rst_n, // Active-low async reset
input wire d,
output reg q,
output wire qbar
);
assign qbar = ~q;
always @(posedge clk or negedge rst_n) begin
if (!rst_n)
q <= 1'b0;
else
q <= d;
end
endmodule
Active-High Reset Variant
module dff_async_rst_high (
input wire clk,
input wire rst, // Active-high async reset
input wire d,
output reg q
);
always @(posedge clk or posedge rst) begin
if (rst)
q <= 1'b0;
else
q <= d;
end
endmodule
With Enable
module dff_en_async_rst (
input wire clk,
input wire rst_n,
input wire en,
input wire d,
output reg q
);
always @(posedge clk or negedge rst_n) begin
if (!rst_n)
q <= 1'b0;
else if (en)
q <= d;
// else: q retains value (implicit)
end
endmodule
Testbench
module tb_dff;
reg clk, rst_n, d;
wire q, qbar;
// Instantiate DUT
dff_async_rst dut (
.clk (clk),
.rst_n (rst_n),
.d (d),
.q (q),
.qbar (qbar)
);
// Clock generation: 10ns period
initial clk = 0;
always #5 clk = ~clk;
// Test sequence
initial begin
$dumpfile("dff.vcd");
$dumpvars(0, tb_dff);
// Initialize
rst_n = 0; d = 0;
#12; // Assert reset for a bit
// Release reset
rst_n = 1;
#10;
// Test: D=1 should propagate on next posedge
d = 1;
#10;
assert (q == 1) else $error("Q should be 1");
// Test: D=0
d = 0;
#10;
assert (q == 0) else $error("Q should be 0");
// Test: Async reset while D=1
d = 1;
#3;
rst_n = 0; // Assert reset mid-cycle
#2;
assert (q == 0) else $error("Async reset failed");
rst_n = 1;
#20;
$display("All tests passed!");
$finish;
end
endmodule
Synthesis Considerations
Reset Polarity
- Active-low (
rst_n): Industry standard, matches most standard cell libraries - Active-high: Requires inverter at reset input, slight area overhead
Async vs Sync Reset
| Aspect | Async Reset | Sync Reset |
|---|---|---|
| Reset timing | Immediate | Next clock edge |
| Glitch sensitivity | High (can cause metastability) | Low |
| Area | Smaller (dedicated pin) | Larger (mux at D input) |
| Static timing | Needs recovery/removal checks | Standard setup/hold |
| Use case | Power-on reset, safety-critical | Normal operation resets |
Common Gotchas
Reset Glitches: Async resets are sensitive to glitches. Use a reset synchronizer for externally-sourced resets.
Recovery/Removal Violations: Reset must be released synchronously to avoid metastability. Use a 2-FF synchronizer on the reset deassertion path.
Reset Synchronizer
// Async assert, sync deassert reset synchronizer
module reset_sync (
input wire clk,
input wire rst_async_n,
output wire rst_sync_n
);
reg [1:0] sync_ff;
always @(posedge clk or negedge rst_async_n) begin
if (!rst_async_n)
sync_ff <= 2'b00;
else
sync_ff <= {sync_ff[0], 1'b1};
end
assign rst_sync_n = sync_ff[1];
endmodule
Waveform
___ ___ ___ ___ ___
clk __| |___| |___| |___| |___| |___
rst ______|XXXXX|_____________________________
d ________|XXXXXXXXX|_________|XXXXXXXX|____
q ________| |XXXXXXXXX|_____________
^ ^ ^
| | |
reset clears d=1 d=0
Comments (0)
Leave a Comment