A D flip-flop with asynchronous reset captures its data input on the rising edge of the clock and clears its output the moment reset is asserted, without waiting for a clock edge. In Verilog, you write it with an always @(posedge clk or negedge rstn) block that checks reset first.
12 min read | Beginner Level
What You'll Learn
- How a D flip-flop captures data on a clock edge, and how asynchronous and synchronous resets differ
- Write both reset styles in Verilog
- What each style synthesizes into, and when to choose one over the other
- How to verify reset behavior with a testbench and avoid common reset coding errors
What is a D Flip-Flop?
A D flip-flop is an edge-triggered storage element. At each rising edge of clk, it copies its data input d to its output q. Between edges, q holds its value no matter how d changes. This is the key difference from a level-sensitive D latch, which follows its input for as long as its enable is high.
A reset input forces q to a known value, usually 0, so the design starts in a defined state. The designs in this article use an active-low reset, rstn, where 0 means "reset".
| rstn | clk | d | q (next) | Behavior |
|---|---|---|---|---|
| 0 | x | x | 0 | Reset (async: immediately; sync: at next rising edge) |
| 1 | Rising edge | 0 | 0 | Capture d |
| 1 | Rising edge | 1 | 1 | Capture d |
| 1 | No edge | x | q (no change) | Hold |
For correct capture, d must be stable for a short setup time before the clock edge and a hold time after it. Static timing analysis checks these requirements; see Verilog Timing Checks.
Syntax
Basic Form (asynchronous active-low reset):
always @(posedge clk or negedge rstn) // Wake up on a clock edge OR on reset assertion
if (!rstn) // Reset is checked first
q <= 0; // Reset value
else
q <= d; // Normal operation: capture d
Components:
posedge clk- The clock edge that captures data (required)negedge rstn- Makes the reset asynchronous; the edge must match the reset's active level, so an active-low reset usesnegedge(required for async reset)if (!rstn)- Reset test, which must be the first statement in the block (required)<=- Non-blocking assignment, the standard for sequential logic (required)
Variations:
// 1. Synchronous reset: reset is not in the sensitivity list
always @(posedge clk)
if (!rstn) q <= 0;
else q <= d;
// 2. Asynchronous active-high reset: posedge rst, test if (rst)
always @(posedge clk or posedge rst)
if (rst) q <= 0;
else q <= d;
// 3. Multi-bit register: the same code, with vector ports
// input [7:0] d; output reg [7:0] q; -> q <= 8'h00 on reset
Design #1: With async active-low reset
With an asynchronous reset, rstn is in the sensitivity list. The block runs when rstn falls, so q clears immediately, even if the clock is stopped.
module dff (
input d, // Data input, captured on the rising clock edge
input rstn, // Active-low asynchronous reset
input clk, // Clock
output reg q // Registered output
);
// Block runs on a rising clock edge OR when rstn falls (reset asserted)
always @(posedge clk or negedge rstn)
if (!rstn) // Reset asserted: clear q immediately, no clock needed
q <= 0;
else // Reached only on a rising clock edge with reset released
q <= d;
endmodule
Synthesis result: The tool maps this block to a single D flip-flop cell with an asynchronous clear pin (often named CLR, CDN or RN). rstn connects straight to that pin, so the reset path does not pass through any logic in front of d. This pattern, an edge-triggered sensitivity list with the reset test first, is the template synthesis tools look for when inferring an async-reset flop.

Where is Asynchronous Reset Used?
At power-on, a chip's clock often is not running yet, because the PLL needs time to lock. An asynchronous reset puts control logic such as FSM state registers, bus interfaces and interrupt controllers into a known state without a clock. When the clock starts, these registers are already in their idle state.
Quick Check
Q: In Design #1, rstn falls 5 ns after a rising clock edge. When does q become 0?
Show Answer
Immediately, at the moment rstn falls. negedge rstn is in the sensitivity list, so the block runs right away and does not wait for the next clock edge.
Testbench
The testbench generates a clock with a period of 20 time units, holds reset at the start, then changes d after random delays. At the end, it asserts reset halfway between two clock edges for 10 time units. This shows the difference between the two reset styles. See Verilog Testbench for testbench structure.
module tb_dff;
reg clk;
reg d;
reg rstn;
reg [2:0] delay; // Random delay between d changes (0 to 7)
integer i;
wire q;
// Connect testbench signals to the design ports
dff dff0 ( .d (d),
.rstn (rstn),
.clk (clk),
.q (q));
// Clock: toggles every 10 time units, so rising edges at 10, 30, 50, ...
always #10 clk = ~clk;
initial begin
$monitor ("[%0t] clk=%0b rstn=%0b d=%0b q=%0b", $time, clk, rstn, d, q);
// 1. Start in reset
clk <= 0;
d <= 0;
rstn <= 0;
// 2. Change d while reset is held: q must stay 0
#15 d <= 1;
// 3. Release reset at t=25, between clock edges
#10 rstn <= 1;
// 4. Change d after random delays; d is 1 bit, so it takes bit 0 of i
for (i = 0; i < 5; i = i + 1) begin
delay = $random;
#(delay) d <= i;
end
// 5. Assert reset 5 time units after a rising edge, hold it for 10,
// and release it 5 time units before the next rising edge
@(posedge clk);
#5 rstn <= 0;
#10 rstn <= 1;
#30 $finish;
end
endmodule
When you run it, check these points in the output:
- q is 0 from time 0, and stays 0 at the rising edge at 10 and when d becomes 1 at 15, because reset is still held.
- After reset is released at 25, q changes only at rising edges (30, 50, ...), taking the value d had just before the edge.
- In step 5, q drops to 0 at the same time step that rstn falls, between clock edges.
Design #2: With sync active-low reset
With a synchronous reset, rstn is not in the sensitivity list. The block runs only on the clock edge, so reset is just another input that is sampled at the edge, like d.
module dff_sync (
input d, // Data input
input rstn, // Active-low synchronous reset
input clk, // Clock
output reg q
);
// Block runs only on the rising clock edge; rstn is sampled like data
always @(posedge clk)
if (!rstn) // Reset seen at a clock edge: clear q
q <= 0;
else
q <= d;
endmodule
Synthesis result: The tool builds a plain D flip-flop with no reset pin, plus a small gate in front of its D input. Here the next value is rstn ? d : 0, which reduces to an AND gate: D = rstn & d. Some cell libraries provide flip-flops with a built-in synchronous reset input that absorbs this gate.

To test this design, use the same testbench and change the instance to dff_sync dff0 (...). Most of the output is the same, with two differences:
- q is unknown (x) until the first rising edge at 10 ns, because a synchronous reset has no effect without a clock edge.
- In step 5, reset is held from 5 ns after one rising edge until 5 ns before the next, so no rising edge ever sees rstn = 0. The reset is missed entirely and q never clears.
A synchronous reset must be held across at least one active clock edge.
Reset pulses from external pins or other clock domains can be shorter than a clock period. Designs with synchronous resets usually stretch the reset over several clock cycles before it reaches the flip-flops.
Quick Check
Q: The clock is stopped and rstn is driven low. Which design clears q?
Show Answer
Only Design #1, the asynchronous version. Design #2 samples rstn only at a rising clock edge, so with no clock, q keeps its old value.
Asynchronous vs Synchronous Reset
| Asynchronous Reset | Synchronous Reset | |
|---|---|---|
| Sensitivity list | posedge clk or negedge rstn | posedge clk |
| Takes effect | Immediately | At the next active clock edge |
| Needs a running clock | No | Yes |
| Hardware | Flip-flop with a clear pin | Plain flip-flop plus gating on D |
| Short reset glitches | Can reset the flop unintentionally | Filtered unless present at a clock edge |
| Timing checks on reset | Recovery and removal at release | Setup and hold, like any data input |
A common industry approach combines both: assert asynchronously, release synchronously. Reset reaches the flip-flops' clear pins directly, so it works without a clock, but its release passes through a two-flop reset synchronizer. This makes all flip-flops in a clock domain leave reset on the same clock edge.
Reset Synchronizers in SoCs
An SoC with many clock domains, such as a CPU cluster, a memory controller and several peripheral buses, typically gives each domain its own reset synchronizer. The global reset asserts every domain at once. Each domain then leaves reset cleanly on its own clock, which avoids flip-flops in one domain starting a cycle earlier than others.
Which Flip-Flops Get a Reset?
Not every flip-flop needs one. Control registers, such as FSM state, valid bits and counters, must start in a known state. Wide datapath registers in pipelines and buffers are often left without reset, because their contents are ignored until a valid bit marks them as used. Leaving out the reset saves area and makes routing easier in designs with millions of flip-flops.
Common Beginner Mistakes
Mistake #1: Leaving reset out of the sensitivity list when you want an async reset
Wrong: always @(posedge clk) if (!rstn) q <= 0; else q <= d;
Right: always @(posedge clk or negedge rstn) if (!rstn) q <= 0; else q <= d;
Why? Without negedge rstn, the block never runs when reset falls, so the code describes a synchronous reset. It compiles and simulates without errors, but the reset waits for a clock edge, and does nothing at all if the clock is not running.
Mistake #2: Using an edge that doesn't match the reset's active level
Wrong: always @(posedge clk or posedge rstn) if (!rstn) q <= 0;
Right: always @(posedge clk or negedge rstn) if (!rstn) q <= 0;
Why? With posedge rstn, the block runs when reset is released, and at that moment !rstn is false, so q takes d instead of resetting. Synthesis tools usually reject this with an error about a mismatch between the edge and the condition. Active-low resets use negedge with if (!rstn); active-high resets use posedge with if (rst).
Mistake #3: Putting logic before or outside the reset check
Wrong: always @(posedge clk or negedge rstn) begin count <= count + 1; if (!rstn) q <= 0; else q <= d; end
Right: Make if (!rstn) the first and only top-level statement, and put all other assignments in its else branch
Why? Synthesis maps async-reset flops only from the template "if reset, assign reset values; else, normal logic". Any statement outside that structure would have to run on the reset edge as well, which no flip-flop cell can do. Tools either report an error or produce a netlist that doesn't match simulation.
Mistake #4: Releasing async reset close to a clock edge
Wrong: Driving the clear pins directly from an external reset pin that can be released at any time
Right: Release reset through a reset synchronizer clocked by the flip-flops' own clock
Why? If reset is released within the flop's recovery or removal window around a clock edge, the flop can become metastable, and different flops can leave reset on different cycles. RTL simulation does not model this, so the bug appears only on silicon or in gate-level timing simulation.
Practice Exercise
Challenge: 4-bit Register with Async Reset and Enable
Write a module reg4 with a 4-bit input d, a 4-bit output q, a clock clk, an active-high asynchronous reset rst that sets q to 4'hA, and an enable en. At a rising clock edge, q takes d only if en is 1; otherwise it holds.
Hint
An active-high reset uses posedge rst and if (rst). Put the enable check inside the else branch, so the reset template stays intact.
Solution
module reg4 (
input clk,
input rst, // Active-high asynchronous reset
input en, // Load enable
input [3:0] d,
output reg [3:0] q
);
always @(posedge clk or posedge rst)
if (rst) // Reset first: q is set to 4'hA immediately
q <= 4'hA;
else if (en) // On a clock edge, load d only when enabled
q <= d;
// No final else: q holds its value when en = 0
endmodule
Synthesis builds four flip-flops. Bits 1 and 3 use an asynchronous set pin and bits 0 and 2 an asynchronous clear pin, because the reset value is 4'b1010. A 2 to 1 mux in front of each D input selects d or the current q based on en. Many cell libraries provide enable flip-flops that include this mux.
Summary
In this tutorial, you learned:
- A D flip-flop captures
dat the rising clock edge and holdsqbetween edges - An asynchronous reset is in the sensitivity list and clears
qimmediately, even without a clock - A synchronous reset is sampled at the clock edge and must be held across at least one edge
- Async reset synthesizes into a flip-flop with a clear pin; sync reset becomes gating logic on the D input
- The reset edge must match its active level:
negedge rstnwithif (!rstn) - The reset check must be the first statement, with all normal logic in its
elsebranch - Many designs assert reset asynchronously and release it through a reset synchronizer