Module 68 min

if, case, and Avoiding Latches

Clean decision logic that never builds an accidental latch

Most combinational logic is a set of decisions: if this, do that. Verilog gives you if/else and case. The trick is writing them so they describe clean logic and never an accidental latch.

The default-first pattern (your safety net)

Set every output to a safe default at the very top of the block. Then override it in the branches. Because there is always a default, no branch can ever leave an output undefined - so no latch can be inferred.

verilog
always @(*) begin
  y = 1'b0;        // default first - this is the safety net
  if (enable)
    y = a & b;     // override only when needed
end

case - the clean way to handle many options

When one signal selects among several outcomes, case is clearer than a stack of if/else.

verilog
// A 4-to-1 multiplexer
always @(*) begin
  y = 1'b0;              // default first
  case (sel)            // sel is 2 bits wide
    2'b00: y = in0;
    2'b01: y = in1;
    2'b10: y = in2;
    2'b11: y = in3;
    default: y = 1'b0;  // covers any leftover, including x
  endcase
end
Pro tip

Always add a default branch to a case, even when you think you listed every value. It protects you when a select line is x in simulation, and it tells the synthesis tool you really meant to cover everything. Combined with the default-first assignment, your combinational logic will be latch-free every time.

SymptomLikely causeFix
Tool warning: "inferred latch"An output not assigned in some pathAdd default-first assignment
Output stuck at old valueMissing else or defaultCover every branch
Works in sim, breaks in chipLatch behaving differently in real timingRemove the latch with defaults
Watch out

Inside a combinational always @(*), stick to blocking assignment (=). Save the non-blocking arrow (<=) for clocked blocks in the next lessons. Mixing them up is the second most common beginner bug after inferred latches.