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".

rstnclkdq (next)Behavior
0xx0Reset (async: immediately; sync: at next rising edge)
1Rising edge00Capture d
1Rising edge11Capture d
1No edgexq (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 uses negedge (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.

Synthesized schematic of a D flip-flop with rstn connected to the asynchronous clear pin

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.

Synthesized schematic of a D flip-flop with an AND gate combining rstn and d in front of the D input

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 ResetSynchronous Reset
Sensitivity listposedge clk or negedge rstnposedge clk
Takes effectImmediatelyAt the next active clock edge
Needs a running clockNoYes
HardwareFlip-flop with a clear pinPlain flip-flop plus gating on D
Short reset glitchesCan reset the flop unintentionallyFiltered unless present at a clock edge
Timing checks on resetRecovery and removal at releaseSetup 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 d at the rising clock edge and holds q between edges
  • An asynchronous reset is in the sensitivity list and clears q immediately, 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 rstn with if (!rstn)
  • The reset check must be the first statement, with all normal logic in its else branch
  • Many designs assert reset asynchronously and release it through a reset synchronizer
Did you find what you were looking for?

Quiz

Test Your Knowledge

1 of 5 Score: 0 / 5