Interview Question · Code Reading
A Case Statement, a Default Arm and a Latch
The Question
The interviewer asks
This block has a default arm. Does it infer a latch? If so, on which signal?
module opdec (input logic [1:0] op,
input logic [7:0] a, b,
output logic [7:0] res,
output logic valid);
always @* begin
case (op)
2'd0: begin res = a + b; valid = 1'b1; end
2'd1: begin res = a - b; valid = 1'b1; end
2'd2: begin res = a & b; end
default: begin res = 8'h00; valid = 1'b0; end
endcase
end
endmodule
You have two and a half minutes. Speak or type, then press Get Feedback under your answer. No credits needed.
Speech-to-text runs in your browser. Chrome and Edge may send audio to their own speech service.
You can edit your answer before you send it. Feedback uses AI and checks your answer only against our written answer. No credits are used and your answer is not saved.
Reveal the Model Answer
Yes, one latch, on valid. The default arm covers values of op that no other arm lists. It does not cover outputs that a listed arm forgets. In the op == 2 arm nothing assigns valid, so it keeps its last value. res is assigned in every arm, so it has no latch.
- Cycle 3
The last cycle of the test:
enis 1,selis 3,yis 1000. Everything looks right. - Cycle 4
enfalls. Theifis false and no statement assignsy, soykeeps 1000. Peripheral 3 stays selected. - Cycle 5
selchanges to 1 whileenis still 0. Nothing changes: a held value does not follow its inputs. That is the definition of a latch. - Cycle 6
enrises andyfollowsselagain: 0010. - Cycle 7
enfalls andyholds 0010. Peripheral 1 stays selected this time. Which line is stuck depends on what came before: the mark of memory.
Measured in lesson R1.3 on a decoder with an if and no else. A path that assigns nothing holds the old value, just as valid does here.
The snippet on the pinned Yosys flow: one latch, for valid.
module opdec (input logic [1:0] op,
input logic [7:0] a, b,
output logic [7:0] res,
output logic valid);
always @* begin
case (op)
2'd0: begin res = a + b; valid = 1'b1; end
2'd1: begin res = a - b; valid = 1'b1; end
2'd2: begin res = a & b; end
default: begin res = 8'h00; valid = 1'b0; end
endcase
end
endmodule
Self-Check
Tick each key point you covered in your answer.
What Interviewers Listen For (Junior)
A good junior answer walks the arms one output at a time. It finds the arm that leaves valid unassigned.
What Interviewers Listen For (Mid-Level)
A good mid-level answer predicts the latch count before synthesizing. It fixes the block with defaults at the top, then checks each default value against the spec.
Cross-Questions
Where the interviewer goes next. Open a node to practise that follow-up.
WhyWhat IfProve ItBreak ItCompare
- A Case Statement, a Default Arm and a Latch
-
WhyWhat a Default Arm CoversL1 Junior
Why does a
defaultarm not prevent a latch on an output that one arm forgets?2:30You have two and a half minutes. Speak or type, then press Get Feedback under your answer. No credits needed.
Speech-to-text runs in your browser. Chrome and Edge may send audio to their own speech service.
You can edit your answer before you send it. Feedback uses AI and checks your answer only against our written answer. No credits are used and your answer is not saved.
Reveal the Model Answer
Latch inference is decided per variable, per path. The default arm adds one path: the case values no other arm lists. Each listed arm is still its own path. If a listed arm skips an output, that path still holds the output.
Self-Check
Tick each key point you covered in your answer.
Half-Truth
"A full case can never infer a latch."
A full case covers every value of the case expression. It still infers a latch when some arm leaves an output unassigned.
Source Sutherland, RTL Modeling with SystemVerilog (2017) ch. 9.2 Unintentional latch inference
-
CompareDefaults at the Top vs Unique CaseL2 Mid-Level
Compare fixing the block with defaults at the top against adding
uniqueto the case.2:30You have two and a half minutes. Speak or type, then press Get Feedback under your answer. No credits needed.
Speech-to-text runs in your browser. Chrome and Edge may send audio to their own speech service.
You can edit your answer before you send it. Feedback uses AI and checks your answer only against our written answer. No credits are used and your answer is not saved.
Reveal the Model Answer
Defaults at the top give every output a value on every path, so the latch goes away.
uniqueonly makes promises about which arms match. It does not assignvalidin theop == 2arm, so the latch stays. Use the defaults to remove the latch, and adduniqueonly if the arms truly cannot overlap.Self-Check
Tick each key point you covered in your answer.
Misconception
"
unique caseremoves latches because it means full case."uniquetells synthesis that some arm always matches. A matching arm that skips an output still leaves that output unassigned.Source Sutherland, RTL Modeling with SystemVerilog (2017) ch. 9.3.5 Latch avoidance style 3, unique and priority decision modifiers
-
What IfAssigning X in the Default ArmL2 Mid-LevelL3 Senior
What if someone fixes it by assigning
valid = 'xin the default and at the top?2:30You have two and a half minutes. Speak or type, then press Get Feedback under your answer. No credits needed.
Speech-to-text runs in your browser. Chrome and Edge may send audio to their own speech service.
You can edit your answer before you send it. Feedback uses AI and checks your answer only against our written answer. No credits are used and your answer is not saved.
Reveal the Model Answer
The latch goes away, because every path now assigns something. Synthesis reads X as "don't care" and may pick any value that gives smaller logic. Simulation shows X, which helps catch a path that should never run. The guideline today is
uniqueorpriorityinstead, because they give the same freedom with built-in checks.Self-Check
Tick each key point you covered in your answer.
Misconception
"An X assignment makes the gates output X."
Gates cannot output X. Synthesis replaces it with a 0 or 1, chosen for the smallest logic, so RTL and gates may disagree on that path.
Source Sutherland, RTL Modeling with SystemVerilog (2017) ch. 9.3.6 Latch avoidance style 4, X assignments for unused decision values
-
Break ItHow an X Default Can Hide a BugL2 Mid-LevelL3 Senior
Break it: show how the
'xdefault can hide a real bug in simulation.2:30You have two and a half minutes. Speak or type, then press Get Feedback under your answer. No credits needed.
Speech-to-text runs in your browser. Chrome and Edge may send audio to their own speech service.
You can edit your answer before you send it. Feedback uses AI and checks your answer only against our written answer. No credits are used and your answer is not saved.
Reveal the Model Answer
Downstream logic such as
if (valid)treats X as false and takes the else branch. So the path that should never run looks harmless in simulation. Synthesis may choose 1 for that X, and the gates then assertvalidthere. An assertion thatvalidis never unknown catches it at the source.Self-Check
Tick each key point you covered in your answer.
Misconception
"An X default makes any bad path show up as X downstream."
An
ifon X takes the else branch, so the X can disappear one stage later.Source IEEE 1800-2017 §12.4
-
Prove ItSolve R1.3.2: The Interrupt That Never ClearedSimulator-graded
Show it, don't just say it: this Silicon Lab problem is graded by the simulator.
What People Get Wrong
Common wrong answers and why they fail. Run It shows the wrong belief failing on a real simulator.
Misconception
"There is a default arm, so every output is covered."
A default arm handles case values, not outputs. The twin goes from op = 3 to op = 2 and valid keeps the 0 from the default arm.
Run It
The snippet, simulated, then the fix with defaults before the case.
op=2 after op=3: valid=0 FAIL: the default arm did not cover op=2; valid kept its old valueSee the Fix
module opdec (input logic [1:0] op,
input logic [7:0] a, b,
output logic [7:0] res,
output logic valid);
always @* begin
res = 8'h00; valid = 1'b0; // the fix: defaults before the case
case (op)
2'd0: begin res = a + b; valid = 1'b1; end
2'd1: begin res = a - b; valid = 1'b1; end
2'd2: begin res = a & b; valid = 1'b1; end
default: begin res = 8'h00; valid = 1'b0; end
endcase
end
endmodule
module tb;
logic [1:0] op; logic [7:0] a = 8'd6, b = 8'd3, res; logic valid;
opdec dut (.op(op), .a(a), .b(b), .res(res), .valid(valid));
initial begin
op = 2'd3; #1; // default arm: valid = 0
op = 2'd2; #1; // the AND arm
$display("op=2 after op=3: valid=%b", valid);
if (valid !== 1'b1) $display("FAIL: the default arm did not cover op=2; valid kept its old value");
else $display("PASS: valid is 1 in the op=2 arm");
end
endmodule
Prints: op=2 after op=3: valid=1 PASS: valid is 1 in the op=2 arm
Misconception
"res and valid both get latches: 9 in total."
res is written in every arm, including the default, so every path assigns it. Only valid has a path with no assignment. The run counts one latch.
Source Measured: the run on this question, Yosys 0.70+290 (OSS CAD Suite 2026-11-02), slang front end, synth -flatten with ABC, ltp -noff
Delivery
Answers "no latch, there is a default" in two seconds, without reading each arm.
The interviewer chose this code to see whether you trace outputs arm by arm. A quick pattern match is the answer they expect to reject.