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

如何在Verilog中防止推断的闩锁和闩锁不安全行为?,verilog,system-verilog,quartus,Verilog,System Verilog,Quartus,我的程序的某个特定部分有问题,在“始终”块中: 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 filt

我的程序的某个特定部分有问题,在“始终”块中:

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
模块比较块(时钟、复位、结果、led);
参数数据_宽度=8//数据输入的宽度,包括符号位
参数大小=1024;
输入时钟,复位;
输入[(数据宽度+2):0]结果//从过滤器--双重检查宽度
逻辑[(数据宽度):0]来自rom的数据//预先计算的1Hz正弦波
逻辑[10:0]添加到rom;
输出reg led;
reg[(数据宽度+2):0]ans_sig[size-1:0];
整数i,iii,jj,j,ii;
注册信号完成、过滤信号完成、补偿信号完成;
reg[(数据宽度+2):0]和;
reg[数据宽度:0]最大值,错误值;
初始最大值为b000000000;
...
总是开始
总和=0;
如果(信号完成)开始
对于(j=4;j最大值)开始
max_val=ans_sig[j];
结束,否则开始
最大值=最大值;
完//else
完//
结束//如果
结束//始终
...
端模
本质上,
ansu sig
是一个数组,长度为1024字节,我想将其和为一个数字(
sum
),并最终(不在此)取其平均值。当我遍历
ansu sig
数组时,我还想确定数组中的最大值(
max\u val
),这就是嵌套if语句所做的。但是,当我在Quartus中编译时,会收到以下严重警告:

比较块sv处“最大值[8]”的推断闩锁

“13012闩锁比较_块:比较|最大值[8]具有不安全行为”

“锁存器上的13013个端口D和ENA由同一个信号比较块提供:比较| LessThan473~synth”(用于最大值[8])


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

如果此模块用于模拟目的,您可能不需要关心警告(我不太确定。如果我错了,请纠正我)。但是,如果是为了实现,则需要使用顺序逻辑生成
sum
max\u val
,其中
ans\u sig\u done
为启用信号。您有1024个11位长的数据,永远不要考虑在零时间消耗的情况下进行这样的计算。让我们谈谈你收到的警告。由于
始终
块是组合的,因此当
ans_sig_done
为false时,您希望看到什么。缺少分支的组合逻辑会导致锁存行为。顺便说一句,您有一个与
ans_sig
数组中的每个数据具有相同位宽的
和,这将导致计算过程中的潜在数据丢失,还有一个位宽更窄的
最大值

此代码表示空语句,实际上表示锁存,而不是消除锁存:

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

这样您就可以摆脱闩锁。

这是否回答了您的问题?
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