Video 3 of 4 · ~12 minutes
Dr. Mike Borowczak · Electrical & Computer Engineering · CECS · UCF
“Zero inferred latches” is a line item on virtually every FPGA/ASIC design checklist. Synopsys DC, Xilinx Vivado, and Intel Quartus all emit latch warnings — which senior engineers treat as errors. Static timing analysis tools can't reliably analyze a design with latches, so they break your sign-off flow.
Every Day 3+ lab checks for latch warnings during make stat. If Yosys reports “inferred latch,” your grader sees it. This video is your insurance policy: three independent techniques, each of which alone prevents the bug.
“I didn't write posedge clk, so there's no memory in my always @(*) block. Whatever I forgot to assign just stays undefined.”
Any signal that must retain a value through some path of your logic needs storage. If your always @(*) doesn't assign the output on some path, the synthesizer infers a level-sensitive latch to hold the prior value. No clock required — the latch watches your condition signal.
// Missing else → latch on y
always @(*) begin
if (sel) y = a;
// when sel=0: y must "hold" its previous value → LATCH
end
// Missing default + missing case → latch
always @(*) begin
case (opcode)
2'b00: y = a;
2'b01: y = b;
// 2'b10 and 2'b11 not assigned → LATCH
endcase
end
always @(*) begin
y = 4'b0; // default FIRST
if (sel) y = a;
// no latch!
end
always @(*) begin
if (sel) y = a;
else y = 4'b0;
end
always @(*) begin
case (opcode)
2'b00: y = a;
2'b01: y = b;
default: y = 4'b0;
endcase
end
if-without-else and missing-case in one line. I put it in every single always @(*) block I write.
Which of these always @(*) blocks will infer a latch?
// Block A
always @(*) begin
if (en) y = a;
else y = 0;
end
// Block B
always @(*) begin
case (sel)
2'b00: y = a;
2'b11: y = b;
endcase
end
// Block C
always @(*) begin
y = 0;
if (en) y = a;
end
You synthesize this code. What exact warning do you expect from Yosys?
always @(*) begin
case (opcode)
2'b00: result = a + b;
2'b01: result = a - b;
endcase
end
Warning: Latch inferred for signal \result\ in process...
Followed by: list of conditions under which the signal is not assigned (opcodes 2'b10 and 2'b11). Some synthesizers also report the estimated latch gate count.
~5 minutes
▸ COMMANDS
cd labs/week1_day03/ex3_latch_demo/
# 1. Buggy version:
make stat 2>&1 | grep -i 'latch\|infer'
# 2. Fix: add 'default:' line
sed -i 's|endcase| default: y = 0;\n endcase|' buggy.v
# 3. Re-synth:
make stat 2>&1 | grep -i 'latch\|infer'
▸ EXPECTED OUTPUT
# BEFORE fix:
Warning: Latch inferred for
signal `\y' in process
$proc$.../buggy.v:6$1
# AFTER fix:
(no warnings)
SB_DFF 0
SB_LUT4 2
▸ KEY OBSERVATION
The warning disappears. Cell count drops. The fix is one line of code and saves you hours of timing-closure debugging later.
Same module, buggy vs fixed:
SB_DFFE 4 ← level-sensitive
SB_LUT4 8
Warning: latch inferred
Yosys uses SB_DFFE with level trigger — a faux-latch. Timing-unsafe.
SB_DFF 0 ← no storage
SB_LUT4 4
(no warnings)
Pure combinational. Smaller area, faster timing, clean STA.
Paste this buggy code and ask AI: “Will this infer a latch on iCE40? If so, give me three different fixes.”
always @(*)
if (enable) out = data;
TASK
Ask AI: latch? What fixes?
BEFORE
Predict: 3 fixes — default at top, explicit else, rewrite with assign.
AFTER
Good AI identifies the latch and suggests all 3. Weak AI may miss the default-at-top pattern.
TAKEAWAY
Latch-hunting is a well-solved problem; AI is actually reliable here. Use it as a second pair of eyes.
① A latch appears when any input combination leaves an output unassigned.
② Three fixes: default at top, complete if/else, case with default.
③ Default at top is universal — use it always.
④ Grep synthesis logs for “latch” every session. Zero tolerance.
🔗 Transfer
Video 4 of 4 · ~6 minutes
▸ WHY THIS MATTERS NEXT
You've seen = (blocking) inside every always @(*) so far. Tomorrow we introduce <= (nonblocking) for sequential logic. Video 4 previews the rule: = for combinational, <= for sequential, never mix. Day 4 will prove why, but you need the rule in memory before you get there.