如何防止推断锁存器和锁存器在 Verilog 中的不安全行为?

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

我的程序的特定部分有问题,在 always 块中:

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

本质上,ans_sig 是一个 1024 字节长的数组,我想将其加总为一个数字 (sum) 并最终(不是此处)取其平均值。当我遍历 ans_sig 数组时,我还想确定数组中的最大值 (max_val),这就是嵌套 if 语句所做的。然而,当我在 Quartus 中编译时,我收到以下严重警告:

“max_val[8]”的推断闩锁 compare_block.sv”

“13012 闩锁 compare_block:compare|max_val[8] 存在不安全行为”

“13013 锁存器上的端口 D 和 ENA 由同一信号馈送compare_block:compare|LessThan473~synth”(对于 max_val[8])

我得到了 max_val [0] 到 max_val [8] 的所有这些错误。

如果这个模块是用于模拟目的,也许你不需要关心警告(我不太确定。如果我错了请纠正我)。但是,如果是为了实现,则需要使用时序逻辑来生成 summax_val,其中 ans_sig_done 是使能信号。你有 1024 个 11 位长的数据,永远不要想着做这样一个零时间消耗的计算。让我们谈谈您收到的警告。由于 always 块是组合的,所以当 ans_sig_done 为假时你会期望什么。缺少分支的组合逻辑会导致闩锁行为。顺便说一句,您有一个 sumans_sig 数组中的每个数据具有相同的位宽,这将导致在计算过程中潜在的数据丢失,以及一个 max_val 具有更窄的位宽.

此代码表示一个 null-statement,实际上表示一个闩锁而不是消除它:

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

使用这样的语句没有多大意义,除非你想证明它具有闩锁行为。

您只在初始块中初始化了 max_val 一次。闩锁行为是预期的行为:您在 sum for 循环的多次调用之间保持 max_val

如果不是这种情况,并且您每次都需要 re-calculate max_val,您应该像 sum 一样在 always 块中初始化它。

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

这样你就可以摆脱闩锁了。