Skip to content

Verilog · Chapter 14.5 · Behavioural Modeling

Multiway Branching in Verilog — if/else, case & Latch Avoidance

Branching is how behavioural logic makes decisions, and Verilog gives you two constructs. The if and else form checks conditions in order and is inherently a priority structure, where the first true branch wins. The case form selects among the values of an expression and is inherently a parallel structure of mutually exclusive branches. Both build the multiplexers and decoders of combinational logic and the decision logic of state machines. They also share one hazard that dominates this section, which is latch inference. A combinational block must assign every output on every path, and an if without an else, or a case without a default, leaves a path where the output holds its old value, which synthesis turns into an unintended latch. This page surveys both constructs, the priority versus parallel distinction, and above all the discipline of avoiding latches.

Foundation15 min readVerilogif elsecaseLatchCombinationalRTL Design

Chapter 14 · Section 14.5 · Behavioural Modeling

1. The Engineering Problem

An engineer writes a combinational block that conditionally drives an output:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
always @(*)
    if (en) y = d;           // assigns y only when en is 1 — no else

When en is 0, y is not assigned — so it must hold its previous value, which means it needs memory. Synthesis infers an unintended latch (a storage element) in logic that was meant to be purely combinational. The block "works" (it holds the old value) but it is a latch, not a wire — a classic, silent bug that lint flags as "latch inferred."

The fix is to assign y on every path:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
always @(*)
    if (en) y = d;
    else    y = 8'h00;       // every path now assigns y → no latch  ✓

A combinational always block must assign every output on every path — an if without an else, or a case without a default, leaves an unassigned path that infers an unintended latch.

Multiway branching — if/else and case — is how behavioural logic decides, and latch avoidance is the discipline that keeps it combinational. This page surveys both constructs and the latch rule; the sub-topics drill each.

2. Mental Model — if Is Priority, case Is Parallel; Both Must Be Complete

Visual A — if (priority) vs case (parallel)

if/else vs case

data flow
if/else vs caseif / else if /elsePRIORITY — first true wins→ priority mux(cascade)conditions in ordercasePARALLEL — select on a value→ parallel mux /decodermutually exclusive cases
if/else is a priority structure — conditions checked in order, first true wins, synthesizing to a priority-mux cascade. case is a parallel structure — selecting among an expression's values with mutually-exclusive cases, synthesizing to a parallel mux/decoder. Both must assign every output on every path to avoid an inferred latch.

3. if/else — Priority Branching

if/else if/else checks conditions in order — the first true branch executes:

if-else.v
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
   always @(*)
       if      (sel_a) y = a;       // highest priority
       else if (sel_b) y = b;
       else            y = c;       // else ensures every path assigns y (no latch)
  • It is priority: sel_a is checked first; sel_b only if sel_a is false. The textual order is the priority order (like the conditional-operator chain, 10.11).
  • The else ensures y is assigned even when no condition holds — preventing a latch.
  • Use if/else when conditions have a natural priority (an error overrides normal operation, an interrupt takes precedence). (Drilled in 14.5.1.)

4. case — Parallel Branching

case selects among the values of an expression:

case.v
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
   always @(*)
       case (op)
           2'b00: y = a + b;
           2'b01: y = a - b;
           2'b10: y = a & b;
           default: y = a | b;      // default covers all other values (no latch)
       endcase
  • It is parallel: the cases are (normally) mutually exclusive, so it synthesizes to a parallel mux/decoder, not a priority cascade.
  • The default covers every value not listed explicitly — preventing a latch (and handling unexpected inputs).
  • Use case when selecting on a value: an opcode, an FSM state, a mux select. (Drilled in 14.5.2, including casez/casex.)

5. Latch Avoidance — The Core Discipline

The rule that dominates this section: in a combinational always @(*) block, assign every output on every path. A missing else or default leaves a path where an output is unassigned, so it must hold its previous value — which requires memory — and synthesis infers a latch.

latch-avoidance.v
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
   // LATCH — y not assigned when en=0:
   always @(*) if (en) y = d;
 
   // FIX 1 — complete the branches:
   always @(*) if (en) y = d; else y = 0;
 
   // FIX 2 — default assignment at the top:
   always @(*) begin
       y = 0;                       // default first
       if (en) y = d;               // override when en — y always has a value
   end

Both fixes guarantee complete assignment. The default-at-the-top pattern (Fix 2) is especially robust: assign every output a default value at the start of the block, then override in the branches — so no path can leave an output unassigned, regardless of how complex the branching gets. Latch inference is a watched bug; lint flags it, and the discipline of complete assignment eliminates it. (Sequential blocks @(posedge clk) intentionally hold state, so this is a combinational-block rule.)

6. The Sub-Topics

§Sub-topicCovers
14.5.1If / Else Statementsif/else if/else — priority branching, nesting, latch from missing else
14.5.2Case Statementscase/casez/casex — parallel branching, default, the casex x-matching hazard
14.5.3Multiway Advanced Techniquesdon't-cares, full_case/parallel_case pragmas (and their dangers), priority vs parallel

7. Common Misconceptions

"if and case are interchangeable." Partly false. Both branch, but if/else is priority (ordered) and case is parallel (mutually exclusive). The choice affects the synthesized structure (priority cascade vs parallel mux) and readability — use if for prioritized conditions, case for value selection.

"A combinational block can skip assigning an output sometimes." False. Skipping an assignment on any path infers a latch. Combinational logic assigns every output on every path.

"Latches are fine." Misleading. Unintended latches are bugs — they create timing hazards and were almost never intended in synchronous design. Synchronous design uses flip-flops (clocked), not level-sensitive latches; an inferred latch usually means a missing else/default.

8. Debugging Lab

One multiway-branching debug post-mortem

9. Interview Q&A

10. Summary

Multiway branching makes decisions in behavioural logic:

  • if/else — priority — conditions in order, first true wins; a priority-mux cascade.
  • case — parallel — select among an expression's values; a parallel mux/decoder.
  • Latch avoidance — a combinational block must assign every output on every path; a missing else/default infers an unintended latch. Fix by completing the branches or assigning defaults at the top.

The discipline this section instils: complete assignment in combinational blocks — every output, every path — and use if for priority, case for value selection.

The sub-topics drill each: Chapter 14.5.1 If / Else Statements (priority branching), 14.5.2 Case Statements (parallel branching, casez/casex), and 14.5.3 Multiway Advanced Techniques (don't-cares, synthesis pragmas). After branching, the chapter covers iteration: 14.6 Loops.