> ## Content Index
> Fetch the complete content index at: https://fpgadesign.io/llms.txt
> Use this file to discover other available public pages before exploring further.

# Intricacies of Blocking vs Non-Blocking Assignment Statements in SystemVerilog
- URL: https://fpgadesign.io/blog/intricacies-of-blocking-vs-non-blocking-assignment-statements-in-systemverilog/
- Published: 2025-04-26T18:30:16.000Z
- Updated: 2026-05-18T00:11:49.000Z
- Description: Have you really understood the nuances of Blocking vs Non-Blocking Assignment statements in SystemVerilog?
- Author: Milind Parelkar
- Tags: SystemVerilog

This is one of the most common questions asked in RTL and FPGA design interviews. To be completely honest, I find this question pretty useless. Anyone and everyone who has prepared even a little bit for an interview and has opened a textbook on SystemVerilog should know what **blocking* and **non-blocking* statements are.  
  
If I were to venture a guess, almost 90% of interviewees are able to answer the basic question about this topic. But go one level deeper, and the success rate drops to less than 10%. Again, these are not "official" statistics, but, I am assuming you get the point.

## Let's get the simple stuff out of the way

Verilog and SystemVerilog have two types of assignment statements -

- Blocking assignments (e.g. `a = b`)
- Non-blocking assignments (e.g. `a <= b`)\*

Blocking assignments model the behavior of combinatorial logic in hardware. The order of operations is important.  
Non-blocking assignments model the behavior of sequential elements in hardware, with clock-to-Q propagation delay.

An example of combinatorial logic.

```verilog
always_comb
begin
	a = b + c;
	d = a + b;
end
```

Combinatorial Logic Block

We have two blocking assignments. First, the sum of `b` and `c` is computed and assigned to `a`. Then next statement in the sequence is executed. `d` gets the value of `a` that was computed in the previous statement, plus the value of `b`. So in short, the value of `d` is `2*b+c`.

![](https://substackcdn.com/image/fetch/w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc625b44b-ce39-4c46-a517-0fc05a335e64_1780x963.png)

Figure 1: Waveform for Blocking Assignment Code Example

Now let's take a look how things differ when we use non-blocking assignments.

```verilog
always_ff @(posedge clk)
begin
	a <= b + c;
	d <= a + b;
end
```

Sequential Logic Block

The above snippet of code models two separate adders followed by a flip-flop each. Since non-blocking assignments are used, both statements get executed in parallel. The current values of `b` and `c` are added and assigned to `a`, which will only be updated on the next clock edge (after the clock-to-Q delay). At the same time, the current value of `a` is added to the current value of `b` and assigned to `d` at the next clock edge. In this case, the value of `d` is not equal to `2*b+c`, as in the earlier example.

![](https://substackcdn.com/image/fetch/w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb6290c41-8151-4c8e-8890-55e400860488_1781x963.png)

Figure 2: Waveform for Non-Blocking Assignment Code Example

## Now for the more tricky stuff

> I have asked this question to many candidates, right from recent graduates to some more experienced candidates.

"What happens if you use a blocking assignment inside an `always_ff` block?"

Here are some of the answers that I have come across. Think through and figure out which one of these is correct.

- \[Answer 1\] That's a syntax error. The compiler will not allow it.
- \[Answer 2\] Why would you ever want to do that? (By the way, that wasn't the essence of the question)
- \[Answer 3\] It makes no difference. I use it all the time.

By the way, the answers are either incorrect or trying to skirt the essence of the question completely.

> It is not syntactically incorrect to have a blocking statement inside a sequential block.  
> It will just not produce the output you are looking for.

Let's take an example of a simple shift register, written **incorrectly** with blocking assignments.

```verilog
always_ff (posedge clk)     // This is **NOT** how you write a Shift Register
begin
	ff0_q = d;          // Load d     into ff0_q without clock-to-Q delay
	ff1_q = ff0_q;      // Load ff0_q into ff1_q without clock-to-Q delay
end
```

Shift Register Example (with an error)

If we were to describe a shift register properly, what we really want is for `ff0_q` and `ff1_q` to be positive edge triggered flip-flops. On the appropriate clock edge, `d` should get transferred to `ff0_q` and the previous value of `ff0_q` should get transferred to `ff1_q`.

Since we have used blocking assignments, the described hardware doesn't quite work like a shift register. The blocking assignment of `d` to `ff0_q` **blocks** the evaluation of the statement that follows, until the value of `ff0_q` has been updated. Thinking through this, you can see that the value of `d` gets passed on to `ff1_q` on the first clock edge, rather than getting shifted through in two clock cycles (like a shift register).

> The synthesis tool will recognize that `ff0_q` is just a temporary variable and optimize it out.

The question then is,

> **Why are blocking statements even allowed inside a sequential block?**

The practical reason is to **allow the use of a temporary variable** within the sequential block. Let's say a complex math equation has to be computed and assigned to a sequential output. For code readability purposes, it might be practical to break down the equation into multiple parts. That is when the sequential block should use a blocking assignment to compute intermediate values. In synthesis, the extra assignment will be optimized out and the *blocking feature* will be removed.

A secondary and a more obscure, philosophical reason is that a Hardware Description Language used for synthesis and verification purposes must correctly model the hardware and must be able to prove what will work (and not work) correctly in hardware.

## Takeaways

Get into good coding habits. In most cases, you should use blocking assignments only to describe combinatorial logic (`always_comb` blocks), and non-blocking assignments to describe sequential logic (`always_ff` blocks). There are always exceptions to the rule, but I have not really ever come across the need to use these somewhat arcane exceptions.

**Practice interview questions on this topic →** [SystemVerilog Questions](https://fpgadesign.io/sv-interview-questions/)