A latch is inferred within a combinatorial block where the net is not assigned to a known value. Assign a net to itself will still infer a latch. Latches can also be inferred by missing signals form a sensitivity list and feedback loops.
The proper way of inferring a intended latch in Verilog/SystemVerilog are:
/* Verilog */ //// /* SystemVerilog */
always @* //// always_latch
begin //// begin
if (en) q = d; //// if (en) q = d;
end //// end
Ways latches are accidentally inferred:
-
Signal(s) missing for the sensitivity list (this is why
@*
should be used):always @(a or b) // inferred latch :: "c" missing for the sensitivity list. begin out = a + b + c; end
-
Missing Condition:
always @* begin case(in[1:0]) 2'b00: out = 1'b0; 2'b01: out = 1'b1; 2'b10: out = 1'b1; // inferred latch "out" :: missing condition 2'b11/default endcase end always @* begin next0 = flop0; next1 = flop1; // inferred latch "next2" :: missing initial condition next3 = flop3; case(a[2:0]) 3'b001: next0 = in; 3'b010: if(b) next1 = in; 3'b100: if(c) next2 = in; default: if(!b&&!c) next3 = in; endcase end
-
Feedback Loop:
assign out = en ? in : out; // inferred latch "out" :: feedback to mux assign a = en ? z : c; // ... any amount of code between ... assign z = en ? a : y; // inferred latch "a" :: feedback chain
- Feedback loops can traverse through the hierarchy and design.
How to mitigate the risk of unintended latches:
- Make intended latches simple and identifiable:
- Put intended latches in their own always blocks with as little combinatorial logic as possible; ideally put the latches’ combinatorial logic in its own separate always block. Be as explicit and identify intended latches. Use comments, labels, and if possible use the SystemVerilog
always_latch
.
- Put intended latches in their own always blocks with as little combinatorial logic as possible; ideally put the latches’ combinatorial logic in its own separate always block. Be as explicit and identify intended latches. Use comments, labels, and if possible use the SystemVerilog
- All combinatorial logic blocks need to be defined with
always @*
or SystemVerilog’salways_comb
. - Make sure all variables assigned in a combinatorial logic blocks have an initial or default assignment.
case
statements should have adefault
condition.if
statements should have a correspondingelse
.- When the combinatorial logic blocks is assigning many variables, giving each variable an initial value at the start of the block (before any
case
orif
).
- Know where the inputs are coming from and where the outputs are going to.
- The inputs of combinatorial logic should be flops or the outputs combinatorial logic should be flops.
- Do code reviews, use linting tools and logical-equivalency-checking tools.
- Code review requires the reviewer(s) to know where latches could hide.
- Using SystemVerilog’s
always_comb
can help identify inferred latches with linting and logical-equivalency-checking tools.
Worst case scenario, put all logic inside synchronous blocks. All inferred latches become inferred flip-flops. This is usually a bad idea because it can unnecessarily increases the gate count, create more routing, and impact timing.