I tried to figure out the inferred latch and why it is needed internally, but I couldn\'t find any resources with enough detail.
A latch is inferred when the output of combinatorial logic has undefined states, that is it must hold its previous value.
Combinatorial logic does not have any flip-flop to hold state therefore the output should always be defined by the inputs.
A short example might be:
always @* begin
if (a == 1'b1) begin
b = x|y|z;
end
end
What is b
when a == 1'b0
. b
is not being overridden so it would hold its value. How can something hold its value when it does not have the concept of state. You have to introduce state by inferring a latch. This is normally a really bad thing.
You can imply latches and be carefull about the timing etc but inferred latches are nominally from buggy code.
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
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
always_latch
.always @*
or SystemVerilog's always_comb
.case
statements should have a default
condition.if
statements should have a corresponding else
.case
or if
).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.
Latches are only generated with combinational always blocks. Sequential logic will never generate a latch.
For more information read about how transparent latches are created and how to avoid inferring latches