0
0
Verilogprogramming~15 mins

When to use blocking (combinational) in Verilog - Deep Dive

Choose your learning style9 modes available
Overview - When to use blocking (combinational)
What is it?
Blocking assignments in Verilog use the '=' operator and execute statements in order, one after another. They are typically used to model combinational logic, where outputs depend immediately on inputs without memory. This means the code runs like a recipe, step-by-step, updating values instantly. Blocking assignments contrast with non-blocking assignments, which are used for sequential logic and update values later.
Why it matters
Using blocking assignments correctly ensures your combinational logic behaves as expected, producing immediate and correct outputs. Without this, your hardware design might have delays, glitches, or incorrect signals, causing chips to malfunction. If you confuse blocking with non-blocking assignments, your design can become unpredictable and hard to debug, leading to costly errors in real hardware.
Where it fits
Before learning this, you should understand basic Verilog syntax, data types, and the difference between combinational and sequential logic. After mastering blocking assignments, you will learn non-blocking assignments and how to write synchronous sequential circuits. This topic is a foundation for writing correct and efficient hardware descriptions.
Mental Model
Core Idea
Blocking assignments execute statements in order, updating values immediately, making them ideal for modeling combinational logic where outputs depend directly on current inputs.
Think of it like...
It's like following a cooking recipe step-by-step: you add ingredients one after another, and each step changes the mixture immediately before moving on to the next.
Combinational block with blocking assignments:

┌─────────────────────────────┐
│ input A, input B            │
│                             │
│ temp = A & B;  // step 1    │
│ out = temp | A; // step 2   │
│                             │
│ Outputs update immediately   │
└─────────────────────────────┘
Build-Up - 7 Steps
1
FoundationUnderstanding Blocking Assignments Basics
🤔
Concept: Introduce the '=' operator and how blocking assignments execute sequentially.
In Verilog, blocking assignments use '=' and run statements one after another in the order written. For example: always @(*) begin a = b; c = a; end Here, 'a' gets the value of 'b' immediately, then 'c' gets the updated 'a'.
Result
Variables update immediately in the order of statements.
Understanding that blocking assignments run sequentially like normal programming helps you predict how values change step-by-step.
2
FoundationCombinational Logic and Blocking Assignments
🤔
Concept: Show how blocking assignments model combinational logic where outputs depend instantly on inputs.
Combinational logic means outputs change immediately when inputs change. Using blocking assignments inside always @(*) blocks models this behavior: always @(*) begin out = in1 & in2; end The output 'out' updates as soon as 'in1' or 'in2' changes.
Result
Output reflects input changes instantly, matching combinational logic behavior.
Blocking assignments naturally fit combinational logic because they update values immediately, just like real hardware gates.
3
IntermediateSequential Execution Order Matters
🤔Before reading on: Do you think changing the order of blocking assignments affects the final output? Commit to your answer.
Concept: Explain that the order of blocking assignments affects intermediate values and final results.
Because blocking assignments update variables immediately, changing the order changes the values used in later statements: always @(*) begin a = b; c = a; end vs always @(*) begin c = a; a = b; end In the first, 'c' gets updated 'a'; in the second, 'c' gets old 'a'.
Result
Order changes the output values, so statement sequence is critical.
Knowing that blocking assignments run step-by-step means you must carefully order statements to get correct combinational logic.
4
IntermediateAvoiding Latches with Blocking Assignments
🤔Before reading on: Do you think missing an assignment in some conditions causes a latch or a combinational block? Commit to your answer.
Concept: Show how incomplete assignments in blocking code can create unintended latches.
If you don't assign a value to a variable in every possible condition, Verilog infers a latch to hold the old value: always @(*) begin if (sel) out = in1; // missing else end This causes 'out' to remember its old value when 'sel' is false, creating a latch.
Result
Unintended latches cause hardware to store values, breaking pure combinational logic.
Understanding that blocking assignments must assign all outputs in every path prevents accidental latches in combinational logic.
5
IntermediateUsing Blocking Assignments for Combinational FSM Outputs
🤔
Concept: Explain how blocking assignments help compute outputs based on current state and inputs in combinational parts of FSMs.
In finite state machines (FSMs), outputs often depend combinationally on state and inputs: always @(*) begin case(state) S0: out = in1 & in2; S1: out = in1 | in2; default: out = 0; endcase end Blocking assignments ensure outputs update immediately based on inputs and state.
Result
Outputs reflect current inputs and state without delay.
Using blocking assignments in combinational output logic of FSMs keeps outputs responsive and predictable.
6
AdvancedWhy Blocking Assignments Fail in Sequential Logic
🤔Before reading on: Do you think blocking assignments are safe to use in clocked always blocks? Commit to your answer.
Concept: Explain why blocking assignments cause problems in sequential (clocked) logic.
In clocked always blocks, using blocking assignments can cause race conditions and incorrect behavior because all statements execute immediately, not in parallel with the clock edge: always @(posedge clk) begin q = d; q2 = q; end Here, 'q2' gets the new 'q' value immediately, not the old one, breaking expected flip-flop behavior.
Result
Sequential logic behaves incorrectly, causing simulation and synthesis mismatches.
Knowing blocking assignments update immediately explains why non-blocking assignments are needed for correct sequential logic.
7
ExpertSubtle Timing Effects in Complex Combinational Blocks
🤔Before reading on: Do you think blocking assignments always produce glitch-free combinational outputs? Commit to your answer.
Concept: Discuss how blocking assignments can model combinational logic but may hide real hardware glitches or delays.
Blocking assignments simulate combinational logic as if all gates update instantly. However, real hardware has delays and glitches. Complex blocking code can mask these effects in simulation, leading to surprises in silicon: always @(*) begin a = in1 & in2; b = a | in3; out = b ^ in4; end Simulation shows clean outputs, but hardware may glitch due to gate delays.
Result
Simulation may not reveal all timing hazards, requiring careful design and timing analysis.
Understanding that blocking assignments model ideal combinational logic helps experts anticipate real hardware timing issues.
Under the Hood
Blocking assignments execute statements sequentially within an always block, updating the left-hand variable immediately before moving to the next statement. This means the right-hand side of later statements sees the updated values from earlier statements. The simulator processes these assignments in order, mimicking combinational logic where outputs depend instantly on inputs without memory.
Why designed this way?
Blocking assignments were designed to model combinational logic naturally and intuitively, reflecting how hardware gates compute outputs immediately from inputs. The sequential execution order allows designers to write code that resembles step-by-step logic calculations. Alternatives like non-blocking assignments were introduced later to handle sequential logic where updates happen on clock edges, avoiding race conditions.
┌─────────────────────────────┐
│ always @(*) block starts     │
├─────────────────────────────┤
│ Statement 1: a = b;          │
│   └─> 'a' updated immediately│
│ Statement 2: c = a;          │
│   └─> uses updated 'a'       │
│ ...                         │
│ Outputs reflect all updates  │
└─────────────────────────────┘
Myth Busters - 4 Common Misconceptions
Quick: Do blocking assignments delay updates until the end of the always block? Commit yes or no.
Common Belief:Blocking assignments wait until the always block finishes before updating variables.
Tap to reveal reality
Reality:Blocking assignments update variables immediately as each statement executes, not at the end.
Why it matters:Believing updates are delayed causes confusion about signal values during simulation and leads to incorrect code ordering.
Quick: Can blocking assignments be safely used in clocked always blocks without issues? Commit yes or no.
Common Belief:Blocking assignments work fine in sequential (clocked) always blocks.
Tap to reveal reality
Reality:Using blocking assignments in clocked blocks can cause race conditions and simulation-synthesis mismatches; non-blocking assignments are preferred.
Why it matters:Misusing blocking assignments in sequential logic leads to bugs that are hard to find and fix in hardware.
Quick: Does missing an else branch in blocking assignments always create combinational logic? Commit yes or no.
Common Belief:If you omit an else branch, the logic remains purely combinational without side effects.
Tap to reveal reality
Reality:Omitting else causes inferred latches, which store values and break combinational behavior.
Why it matters:Unintended latches cause hardware to hold old values, leading to incorrect and unpredictable circuits.
Quick: Do blocking assignments always perfectly model real hardware timing? Commit yes or no.
Common Belief:Blocking assignments simulate hardware timing exactly, including glitches and delays.
Tap to reveal reality
Reality:Blocking assignments model ideal combinational logic without real gate delays or glitches.
Why it matters:Assuming perfect timing can hide real hardware hazards, causing unexpected behavior after synthesis.
Expert Zone
1
Blocking assignments inside combinational always blocks must assign all outputs in every possible path to avoid unintended latches, a subtlety often missed.
2
The order of blocking assignments can be used deliberately to create intermediate signals that simplify complex combinational logic, improving readability and synthesis.
3
In mixed combinational and sequential designs, careful separation of blocking and non-blocking assignments prevents subtle bugs and simulation mismatches.
When NOT to use
Avoid blocking assignments in clocked (sequential) always blocks; use non-blocking assignments instead to model flip-flops and registers correctly. For asynchronous resets or complex timing, consider specialized constructs or SystemVerilog features.
Production Patterns
In real hardware designs, blocking assignments are used exclusively in combinational always @(*) blocks for logic like multiplexers, decoders, and combinational outputs of FSMs. Designers carefully order statements and ensure full assignments to prevent latches. Non-blocking assignments handle all sequential logic, maintaining clear separation.
Connections
Non-blocking assignments
Complementary concept used for sequential logic versus blocking for combinational logic.
Understanding blocking assignments clarifies why non-blocking assignments are necessary for clocked logic, preventing race conditions and ensuring correct timing.
Digital logic gates
Blocking assignments model the immediate behavior of combinational gates like AND, OR, and XOR.
Knowing how blocking assignments simulate gate-level logic helps bridge the gap between code and physical hardware.
Cooking recipes
Sequential step-by-step execution in blocking assignments mirrors following a recipe in order.
This cross-domain connection helps grasp the importance of order and immediate effect in blocking assignments.
Common Pitfalls
#1Creating unintended latches by missing else branches in combinational blocking code.
Wrong approach:always @(*) begin if (sel) out = in1; // else missing end
Correct approach:always @(*) begin if (sel) out = in1; else out = in2; end
Root cause:Not assigning output in all conditions causes Verilog to infer storage (latch) to hold previous value.
#2Using blocking assignments in clocked always blocks causing race conditions.
Wrong approach:always @(posedge clk) begin q = d; q2 = q; end
Correct approach:always @(posedge clk) begin q <= d; q2 <= q; end
Root cause:Blocking assignments update immediately, breaking expected sequential timing; non-blocking delays updates until end of time step.
#3Assuming blocking assignments delay updates until block end.
Wrong approach:always @(*) begin a = b; c = a; // expecting old 'a' here end
Correct approach:always @(*) begin a = b; c = a; // 'c' gets updated 'a' immediately end
Root cause:Misunderstanding that blocking assignments update variables immediately during execution.
Key Takeaways
Blocking assignments use '=' and execute statements in order, updating variables immediately.
They are best suited for combinational logic where outputs depend directly and instantly on inputs.
The order of blocking assignments matters because later statements see updated values from earlier ones.
Missing assignments in some conditions causes unintended latches, breaking pure combinational behavior.
Blocking assignments should not be used in clocked always blocks; non-blocking assignments are required there.