Combinational logic must assign every output on every path. A missed path holds its old value, so synthesis builds a latch.
3 lessons, about 13 min
No. Latches are legitimate storage elements and are used on purpose in clock-gating cells and some high-speed designs. The bug is an unintended latch, which is why intentional ones are written with always_latch and a comment, and everything else is checked to be latch-free.
The whole topic on one page, taken from each lesson's Remember box. Read it before an interview, or print it.
Why Accidental Latches Happen
Any path that leaves an output unassigned makes the output hold, and holding needs a latch.
Four causes: if without else, a case that misses a value, an output assigned on fewer paths than another, and a conditional assignment in a loop.
always_comb turns the latch into a diagnostic; plain always @(*) does not.
Rule of thumb: if a path does not assign the output, the hardware must remember it.
The Complete-Assignment Pattern
Assign every output before any conditional, then let branches override.
Use blocking = in always_comb and nonblocking <= in always_ff, and do not mix them.
For next-state logic the natural default is next = state.
Rule of thumb: treat any latch warning as a failure, and never write y = y; to silence it.
Intentional Latches
A latch is transparent while its enable is active and holds otherwise. A flip-flop is two latches that are never open together.
The gate latch is open only while clk is low, so en cannot change the AND output while clk is high.
Write intentional latches with always_latch, comment why, and review each one.
Rule of thumb: in real designs use the library's clock-gating cell rather than a hand-built latch.
Mini project: a 32-bit leading-zero counter and normaliser
Practice question: A level-sensitive latch: when it is risky and how to code it safely
Practice question: A safe clock-gating cell with a latch-based enable
Interview: run a mock interview on this topic