0
0
VerilogComparisonBeginner · 4 min read

Blocking vs Nonblocking in Verilog: Key Differences and Usage

In Verilog, blocking assignments use the = operator and execute statements sequentially, pausing the next until the current finishes. Nonblocking assignments use <= and schedule updates to happen simultaneously at the end of the time step, allowing parallel execution.
⚖️

Quick Comparison

This table summarizes the main differences between blocking and nonblocking assignments in Verilog.

AspectBlocking (=)Nonblocking (<=)
Execution OrderSequential, one after anotherParallel, all updates happen together
Use CaseCombinational logic modelingSequential logic (flip-flops) modeling
TimingRight side evaluated and assigned immediatelyRight side evaluated immediately, assigned later
Effect on SimulationCan cause race conditions if misusedAvoids race conditions in sequential logic
Typical in Always Blockalways @(*) for combinationalalways @(posedge clk) for sequential
Assignment BehaviorBlocks next statement until doneDoes not block next statement
⚖️

Key Differences

Blocking assignments use the = operator and execute statements in the order they appear. Each assignment completes before the next one starts, similar to how you do tasks one by one in real life. This makes blocking assignments suitable for modeling combinational logic where outputs depend immediately on inputs.

Nonblocking assignments use the <= operator and schedule the assignment to happen at the end of the current time step. This means all right-hand sides are evaluated first, then all left-hand sides updated together. This behavior models how flip-flops update simultaneously on a clock edge, preventing race conditions and ensuring correct sequential logic simulation.

Using blocking assignments in sequential logic can cause unexpected results because statements execute one after another, potentially reading stale or intermediate values. Nonblocking assignments avoid this by updating all variables in parallel after evaluation, matching hardware behavior more closely.

⚖️

Code Comparison

Here is an example showing how blocking assignments handle a simple sequential logic task of updating two registers.

verilog
module blocking_example(input clk, input rst, output reg [3:0] a, output reg [3:0] b);
  always @(posedge clk or posedge rst) begin
    if (rst) begin
      a = 0;
      b = 0;
    end else begin
      a = b + 1;
      b = a + 1;
    end
  end
endmodule
Output
This code causes unintended behavior because 'a' is updated before 'b', so 'b' uses the new 'a' value immediately, not the old one.
↔️

Nonblocking Equivalent

The same logic rewritten with nonblocking assignments updates both registers simultaneously, avoiding the problem.

verilog
module nonblocking_example(input clk, input rst, output reg [3:0] a, output reg [3:0] b);
  always @(posedge clk or posedge rst) begin
    if (rst) begin
      a <= 0;
      b <= 0;
    end else begin
      a <= b + 1;
      b <= a + 1;
    end
  end
endmodule
Output
Both 'a' and 'b' update together at the clock edge, so 'b' uses the old 'a' value, producing correct sequential logic behavior.
🎯

When to Use Which

Choose blocking assignments when modeling combinational logic where operations must happen step-by-step and outputs depend immediately on inputs. Use nonblocking assignments for sequential logic inside clocked always blocks to correctly model flip-flop behavior and avoid race conditions. Mixing them incorrectly can cause simulation mismatches and hardware bugs.

Key Takeaways

Use blocking (=) for combinational logic to execute statements sequentially.
Use nonblocking (<=) for sequential logic to update registers simultaneously.
Nonblocking assignments prevent race conditions in clocked logic.
Blocking assignments can cause bugs if used in sequential always blocks.
Always match assignment type to the hardware behavior you want to model.