Skip to main content

Welcome to a Grasp lesson

Create a free account to keep studying and create your own study path.

Lesson 30

Modeling a Synchronous Reset D Flip-Flop with `always @(posedge clk)`

Recommended resources

Hello! In our last lesson, we wrapped up combinational logic by building a parameterized N-bit adder. This marked a major milestone, giving you the tools to create complex logic that calculates outputs based purely on its current inputs.

Today, we transition into the exciting world of sequential logic. Unlike combinational circuits, sequential circuits have memory. Their outputs depend not just on current inputs, but also on their past state. The fundamental building block for this memory is the flip-flop.

This lesson is your first step into modeling sequential logic in Verilog. Our goal is to model the most common sequential element: an edge-triggered D-type flip-flop with a synchronous reset. We'll use the always @(posedge clk) construct, which is the cornerstone of synchronous digital design.

1. The Heart of Sequential Logic: The Clocked always Block

In previous lessons, we used assign statements or always @(*) for combinational logic. To create logic that changes its state only at specific moments in time, we need a different construct.

In synchronous systems, all state changes are synchronized to a master clock signal. We model this in Verilog using an edge-sensitive always block.

Verilog always Block

This article from ChipVerify introduces the different uses of the always block.

Read the introduction, focusing on the section that starts with the comment // Edge-sensitive: Execute always block at positive edge of signal "clk". This shows the syntax for the clocked always block. Then, scroll down and read "Mistake #4: Forgetting to Declare Outputs as 'reg' in Always Blocks" to understand a key requirement for signals assigned within these blocks.

As you just read, the syntax always @(posedge clk) tells the simulator and synthesis tools to execute the code inside the block only on the rising (positive) edge of the clk signal. This is how we ensure our circuit's state updates synchronously.

A crucial point from the reading: any signal that gets a value assigned to it inside an always block (or any other procedural block) must be declared as type reg. This is a Verilog syntax rule. It can be confusing because reg does not always mean the hardware will be a register (as we saw with always @(*)), but in an edge-triggered always block, it almost always does.


2. Modeling a Basic D Flip-Flop

Let's start with the simplest D flip-flop. Its behavior is straightforward: on the rising edge of the clock, the output q takes the value of the input d. At all other times, q holds its value.

The Verilog code for this is remarkably simple and elegant.

module d_ff (
    input clk,
    input d,
    output reg q
);

    always @(posedge clk) begin
        q <= d;
    end

endmodule

Notice the <_=_ operator. This is the non-blocking assignment. For now, just know that you should always use non-blocking assignments (<=) for sequential logic inside a clocked always block. It correctly models how real flip-flops behave—all flip-flops in a system capture their inputs at the same time (the clock edge) and then update their outputs simultaneously. We will explore this topic in much more detail in our next lesson.


3. Adding a Synchronous Reset

In any real system, we need a way to put our circuits into a known, initial state. This is done with a reset signal. A synchronous reset is a reset that only takes effect on an active clock edge.

Synchronous Reset Asynchronous Reset in Sequential design with verilog code

This video from the Explore VLSI channel clearly explains and demonstrates the concept of a synchronous reset.

First, watch the conceptual explanation of synchronous vs. asynchronous reset. The key idea is that a synchronous reset is synchronized with the clock. Next, see how this is implemented in Verilog in the code example. Pay close attention to how the if (reset) check is placed inside the always @(posedge clk) block. Finally, watch the waveform analysis to see visually how the output q only goes to zero when the reset is active and a positive clock edge arrives.

As the video demonstrated, implementing the synchronous reset is a matter of adding an if-else statement inside our clocked always block. The reset condition is given priority. If the reset signal is active, the output is forced to a known value (usually 0). If the reset is not active, the flip-flop performs its normal operation.

This coding style directly describes the hardware that will be created.

Schematic of a D Flip-Flop with Synchronous Reset
This schematic shows what a synthesis tool infers from Verilog code for a D flip-flop with synchronous reset. The `if-else` statement is synthesized into a 2:1 multiplexer that selects either the reset value (`0`) or the data input (`d`) to be fed into a basic flip-flop. The selection is controlled by the `reset` signal.

The pattern for a D flip-flop with an active-high synchronous reset is a fundamental building block in RTL design.

Structural Design with Verilog

This guide from Harvey Mudd College provides concise examples of common Verilog structures.

Please read section 4.1, "Flip-Flops." Skim the basic flop example and focus on the module defined as flopr with the comment // synchronous reset. This provides another clear example of the exact structure we are implementing.


4. Your Turn: Code the D-FF Module

Now it's time to write the code yourself. Your task is to complete the Verilog module for a single-bit D flip-flop with an active-high synchronous reset.

Specifications:

  • Module Name: dff_sync_reset
  • Ports:
    • clk (input)
    • reset (input, active-high)
    • d (input)
    • q (output)
  • Behavior:
    • On the positive edge of clk, if reset is high (1), q should be driven to 0.
    • Otherwise, on the positive edge of clk, q should capture the value of d.
  • Remember to declare q as reg and use non-blocking assignments (<=).

Fill in the always block below.

module dff_sync_reset (
    input  clk,
    input  reset,
    input  d,
    output reg q
);

    // Your always block goes here.
    // It should be sensitive to the positive edge of the clock.
    // Inside, it should check for the reset condition first.

endmodule
Solution
module dff_sync_reset (
    input  clk,
    input  reset,
    input  d,
    output reg q
);

    always @(posedge clk) begin
        if (reset) begin
            q <= 1'b0;
        end else begin
            q <= d;
        end
    end

endmodule

This is the standard, synthesizable template for a D flip-flop with a synchronous reset. It's one of the most common patterns you'll use in digital design.


Conclusion

In this lesson, we made the crucial leap from combinational to sequential logic. You learned how to model the fundamental memory element of digital design—the D-type flip-flop.

Key Takeaways:

  • Sequential logic is modeled in Verilog using clocked always blocks, most commonly always @(posedge clk).
  • This construct creates synchronous logic that only changes state on a clock edge.
  • A synchronous reset is implemented with an if statement inside the clocked always block, giving the reset condition the highest priority.
  • Signals assigned inside an always block must be declared as type reg.
  • Non-blocking assignments (<=) are essential for correctly modeling the parallel nature of hardware in sequential blocks.

We've used non-blocking assignments (<=) throughout this lesson with the simple rule "always use them for sequential logic." In our next lesson, we will dive deep into the "why." You will learn the critical differences between blocking (=) and non-blocking (<=) assignments and see why using the wrong one can lead to simulations that don't match the real hardware.