如何防止推断锁存器和锁存器在 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] 的所有这些错误。
如果这个模块是用于模拟目的,也许你不需要关心警告(我不太确定。如果我错了请纠正我)。但是,如果是为了实现,则需要使用时序逻辑来生成 sum
和 max_val
,其中 ans_sig_done
是使能信号。你有 1024 个 11 位长的数据,永远不要想着做这样一个零时间消耗的计算。让我们谈谈您收到的警告。由于 always
块是组合的,所以当 ans_sig_done
为假时你会期望什么。缺少分支的组合逻辑会导致闩锁行为。顺便说一句,您有一个 sum
与 ans_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
这样你就可以摆脱闩锁了。
我的程序的特定部分有问题,在 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] 的所有这些错误。
如果这个模块是用于模拟目的,也许你不需要关心警告(我不太确定。如果我错了请纠正我)。但是,如果是为了实现,则需要使用时序逻辑来生成 sum
和 max_val
,其中 ans_sig_done
是使能信号。你有 1024 个 11 位长的数据,永远不要想着做这样一个零时间消耗的计算。让我们谈谈您收到的警告。由于 always
块是组合的,所以当 ans_sig_done
为假时你会期望什么。缺少分支的组合逻辑会导致闩锁行为。顺便说一句,您有一个 sum
与 ans_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
这样你就可以摆脱闩锁了。