Search code examples
verilogsystem-verilogquartus

How to prevent inferred latch and latch unsafe behavior in Verilog?


I am having trouble with a specific part of my program, here in the always block:

module compare_block (clk, reset_n, result, led);
    
    parameter data_width = 8; //width of data input including sign bit
    parameter size = 1024;

    input clk, reset_n;
    input [(data_width+2):0] result; //from filter -- DOUBLE CHECK WIDTH
    logic [(data_width):0] data_from_rom; //precalculated 1 Hz sine wave
    logic [10:0] addr_to_rom;
    output reg led;
    
    reg [(data_width + 2):0] ans_sig [size-1:0];
    
    integer i, iii, jj, j, ii;
    reg ans_sig_done, filt_sig_done, comp_sig_done;
    reg [(data_width+2):0] sum; 
    reg [data_width:0] max_val, error_val;


    initial max_val='b000000000;
   ...
always @* begin
    sum = 0; 
    if (ans_sig_done) begin  
      for (j=4; j<(size-1); j=j+2) begin
                sum = sum + ans_sig[j];     
        if (ans_sig[j] > max_val) begin
            max_val = ans_sig[j];
        end else begin
             max_val = max_val;
      end//else
    end //for
    end//if
    end//always
...
endmodule

Essentially, ans_sig is an array, 1024 bytes long that I want to sum into one number (sum) and eventual (not here) take the average of. While I am traversing the ans_sig array, I also want to identify the maximum value within the array (max_val), which is what the nested if-statement is doing. However I get the following severe warnings when I'm compiling in Quartus:

"Inferred latch for "max_val[8]" at compare_block.sv"

"13012 Latch compare_block:compare|max_val[8] has unsafe behavior"

"13013 Ports D and ENA on the latch are fed by the same signal compare_block: compare|LessThan473~synth" (for max_val[8])

I get all of these errors for max_val [0] through max_val [8].


Solution

  • this code represents a null-statement and actually signifies a latch rather than eliminating it:

      end else begin
                 max_val = max_val; <<< null statement
    

    It does not make much sense in using such statement unless you want to show that this has a latch behavior.

    You initialized the max_val only once in the initial block. There for the latch behavior is an expected one: you keep max_val between multiple invocations of the sum for loop.

    If this is not the case, and you need to re-calculate the max_val every time, you should initialize it in the always block same way as you do sum.

    always @* begin
        sum = 0;
        max_val = 0; 
        if (ans_sig_done) begin  
          for (j=4; j<(size-1); j=j+2) begin
                    sum = sum + ans_sig[j];     
            if (ans_sig[j] > max_val) begin
                max_val = ans_sig[j];
            end 
          end//else
        end //for
        end//if
        end//always
    

    this way you will get rid of the latch.