
Latch-Free Design (Why Waste Silicon?)
How incomplete combinational HDL accidentally creates latches — and how to avoid it.
Description
An unintended latch appears when a combinational block fails to assign an output on every path, forcing the tool to 'remember' the old value. Latch-free design assigns every output on every branch — via default assignments, complete if/else, or full case — so only intended flip-flops exist.
- A combinational block leaves an output unassigned on some path.
- The tool keeps the previous value → infers a latch.
- Common cause: if without else, or case without default.
- Latches are level-sensitive and timing-hazard-prone.
- They are almost never intended in synchronous design.
- Give every output a default at the top of the block.
- Make every if have an else (or rely on the default).
- Add a default to every case.
- Use always @(*) / always_comb (tools warn on latches).
- Assign all outputs on all paths — no exceptions.
At a glance
What
Avoiding inferred latches from incompletely specified combinational logic.
Why
Stray latches cause timing problems, hazards, and wasted area.
How
Assign every output on every path: defaults, else, default case, full case.
Where
All combinational always blocks.
When
Whenever writing combinational HDL.
Think of it like…
It's like a form with blank fields kept from last time: leave a box empty and the system 'remembers' the old answer (a latch) instead of recomputing.
How a latch sneaks in
- A combinational block leaves an output unassigned on some path.
- The tool keeps the previous value → infers a latch.
- Common cause: if without else, or case without default.
- Latches are level-sensitive and timing-hazard-prone.
- They are almost never intended in synchronous design.
Avoiding latches
- Give every output a default at the top of the block.
- Make every if have an else (or rely on the default).
- Add a default to every case.
- Use always @(*) / always_comb (tools warn on latches).
- Assign all outputs on all paths — no exceptions.
Latch causes & fixes
| Cause | Fix |
|---|---|
| if without else | add else / default |
| case without default | add default |
| unassigned output | default assignment |
HDL — Verilog · VHDL · SystemVerilog
always @(*) begin
y = 1'b0; // default — no latch
case (sel)
2'b00: y = a;
2'b01: y = b;
default: y = 1'b0; // full case
endcase
endDefault assignment prevents an inferred latch.
Real-world applications
The 5 Whys
- 1
Why latches appear? Unassigned outputs keep old values.
- 2
Why bad? Level-sensitive, hazard-prone, wasteful.
- 3
Why defaults fix it? Every path now assigns.
- 4
Why always_comb? Tool flags accidental latches.
- 5
Root cause: complete assignment guarantees pure combinational logic.
Cheat sheet
Working principle
- Assign every output on every path: defaults, else, default case, full case.
- Avoiding inferred latches from incompletely specified combinational logic.
Formulas & Boolean expressions
- if without else = add else / default
- case without default = add default
- unassigned output = default assignment
Key facts
- A combinational block leaves an output unassigned on some path.
- Give every output a default at the top of the block.
Why it exists
- Root cause: complete assignment guarantees pure combinational logic.