ID:13481 Verilog HDL Always Construct warning at <location>: inferring latch(es) for variable "<name>", which holds its previous value in one or more paths through the always construct

CAUSE: In an always construct at the specified location in a Verilog Design File (.v), you updated the value of the specified variable. However, you did not assign a new value to the variable in every possible path through the sequence of statements in the always construct. Consequently, the variable holds its previous value under certain conditions. For example, in the following code, the conditional statement explicitly assigns q_latch to its previous value when en is false. Note: The else branch in the conditional statement is redundant and can be removed without changing the simulation or synthesis semantics.
reg q_latch;
 
               
always @ (en or a) begin
   if(en)
       q_latch = a;
   else
      q_latch = q_latch;
  end

            
The following code also shows an example of a variable that holds its previous value. In this example, the case statement is incomplete, meaning some values of the case expression (the 2-bit variable sel) do not match any case item. To be more explicit, variable sel has a total of four possible binary values: 2'b00, 2'b01, 2'b10, and 2'b11, but the case items cover only three of the input values (Quartus Prime Integrated Synthesis considers only binary values when computing the input value set for a case expression). When sel == 2'b11, q_latch holds its previous value.
reg [1:0] sel;
reg q_latch, a, b, c;
 
               
always @ (sel or a or b or c) begin
   case(sel)
      2'b00:  q_latch = a;
      2'b01:  q_latch = b;
      2'b10:  q_latch = c;
      -- Missing Case Item for sel == 2'b11
   endcase
end

            
When a variable asynchronously holds its previous value under certain conditions, the variable will infer a latch. Important: The inferred latch may or may not function correctly in your target device depending on the complexity of the conditions under which the variable holds its previous value. Integrated Synthesis will identify functional problems and issue warnings for any unsafe latches. An unsafe latch has a race condition caused by two more inputs being fed by the same signal. In the previous example, the latch inferred by the case statement is unsafe: The data and enable inputs to the latch both depend on sel. The synthesized behavior of a design with unsafe latches will not likely match its simulated behavior. In some cases, you may receive this warning unexpectedly. These unexpected, and sometimes false, warnings occur because Quartus Prime Integrated Synthesis does not eliminate false paths prior to checking for potential combinational loops. False paths are sequences of statements that cannot occur. For example, in the following code, the conditional statements update foo when sel == 1'b1 and sel == 1'b0. Quartus Prime Integrated Synthesis warns about variable foo because the sequence of conditional statements implies the possibility of a path in which foo holds its value, that is, when sel != 1'b1 and sel != 1'b0. Though this condition may occur during simulation, it cannot occur in the synthesized netlist because sel always has a binary value. Nevertheless, Quartus Prime Integrated Synthesis will initially infer a latch for foo. In most cases, Integrated Synthesis will eliminate the latch during a later optimization step.
reg foo;
 
               
always @ (sel or a or b) begin
   if(sel == 1'b1)
       foo = a;
   if(sel == 1'b0)
      foo = b;
end

            
ACTION: If you intended for the variable to infer a latch, then no action is required. Otherwise, to avoid inferring a latch, explicitly assign a new value to the variable in every possible path through the always construct. In particular, look for incomplete case statements and, if necessary, make them complete by adding a default case item or by using the full_case synthesis attribute, which forces Quartus Prime Integrated Synthesis to treat the case statement as complete. For the previous case statement example, you can use the following code:
reg [1:0] sel;
reg q_latch, a, b, c;
 
               
always @ (sel or a or b or c) begin
   case(sel)
       2'b00:  q_latch = a;
      2'b01:  q_latch = b;
      2'b10:  q_latch = c;
      -- Assign a Don't Care value in the default Case Item
      default:  q_latch = x;
    endcase
end