If statement SystemVerilog中的“if”语句始终为“非纯组合逻辑”错误
我糊涂了!有点沮丧。我花了相当多的时间在Modelsim中开发一些SystemVerilog。我把它带到了一个特定的阶段,我可以在我的硬件上测试它,但是在Quartus中编译是不成功的。我知道这可能发生,但在这种情况下,我的错误似乎没有意义 下面的代码位于always_comb块中。编译时,出现以下错误:If statement SystemVerilog中的“if”语句始终为“非纯组合逻辑”错误,if-statement,system-verilog,If Statement,System Verilog,我糊涂了!有点沮丧。我花了相当多的时间在Modelsim中开发一些SystemVerilog。我把它带到了一个特定的阶段,我可以在我的硬件上测试它,但是在Quartus中编译是不成功的。我知道这可能发生,但在这种情况下,我的错误似乎没有意义 下面的代码位于always_comb块中。编译时,出现以下错误: Error (10166): SystemVerilog RTL Coding error at fifo_interface.sv(80): always_comb construct do
Error (10166): SystemVerilog RTL Coding error at fifo_interface.sv(80): always_comb construct does not infer purely combinational logic.
我真的不明白。这是代码,它只是一个多路复用器
always_comb
if(fifo_select == 0)
begin
fifo0_data_in = data_in;
fifo0_in_clk = in_clk;
fifo0_in_dn = in_dn;
in_rdy = fifo0_in_rdy;
fifo1_in_clk = 0; //Prevent 'in_clk' entering fifo1
end
else
begin
if(fifo_select == 1)
begin
fifo1_data_in = data_in;
fifo1_in_dn = in_dn;
fifo1_in_clk = in_clk;
in_rdy = fifo1_in_rdy;
fifo0_in_clk = 0; //Prevent 'in_clk' entering fifo0
end
end
end
当我将块更改为“始终”类型时,Modelsim的行为会很奇怪。它将在代码中中断或与退出代码211一起崩溃。将类型更改回“always_comb”并不能解决此问题,因此我必须重新启动modelsim以成功模拟HDL
我想知道错误的来源是什么
感谢您的帮助。您并不是在mux的所有分支中分配所有输出。例如,如果fifo\U select==0,则会分配fifo\U data\U in。但如果fifo_select==1,则它不会得到任何值。这意味着如果fifo_选择更改,fifo_数据_in需要记住其值。因此,合成将推断出该输出的锁存器 以下是我认为您想要的:
always_comb
if(fifo_select == 0)
begin
fifo0_data_in = data_in;
fifo1_data_in = '0;
fifo0_in_clk = in_clk;
fifo1_in_clk = '0;
fifo0_in_dn = in_dn;
fifo1_in_dn = '0;
in_rdy = fifo0_in_rdy;
end
else
begin
fifo1_data_in = data_in;
fifo0_data_in = '0;
fifo1_in_clk = in_clk;
fifo0_in_clk = '0;
fifo1_in_dn = in_dn;
fifo0_in_dn = '0;
in_rdy = fifo1_in_rdy;
end
end
而且,由于您似乎将时钟选通到未使用的FIFO,您可以进一步简化,如下所示:
assign fifo0_data_in = data_in;
assign fifo1_data_in = data_in;
assign fifo0_in_dn = in_dn;
assign fifo1_in_dn = in_dn;
always_comb
if(fifo_select == 0)
begin
fifo0_in_clk = in_clk;
fifo1_in_clk = '0;
in_rdy = fifo0_in_rdy;
end
else
begin
fifo0_in_clk = '0;
fifo1_in_clk = in_clk;
in_rdy = fifo1_in_rdy;
end
end
您没有在mux的所有分支中分配所有输出。例如,如果fifo\U select==0,则会分配fifo\U data\U in。但如果fifo_select==1,则它不会得到任何值。这意味着如果fifo_选择更改,fifo_数据_in需要记住其值。因此,合成将推断出该输出的锁存器 以下是我认为您想要的:
always_comb
if(fifo_select == 0)
begin
fifo0_data_in = data_in;
fifo1_data_in = '0;
fifo0_in_clk = in_clk;
fifo1_in_clk = '0;
fifo0_in_dn = in_dn;
fifo1_in_dn = '0;
in_rdy = fifo0_in_rdy;
end
else
begin
fifo1_data_in = data_in;
fifo0_data_in = '0;
fifo1_in_clk = in_clk;
fifo0_in_clk = '0;
fifo1_in_dn = in_dn;
fifo0_in_dn = '0;
in_rdy = fifo1_in_rdy;
end
end
而且,由于您似乎将时钟选通到未使用的FIFO,您可以进一步简化,如下所示:
assign fifo0_data_in = data_in;
assign fifo1_data_in = data_in;
assign fifo0_in_dn = in_dn;
assign fifo1_in_dn = in_dn;
always_comb
if(fifo_select == 0)
begin
fifo0_in_clk = in_clk;
fifo1_in_clk = '0;
in_rdy = fifo0_in_rdy;
end
else
begin
fifo0_in_clk = '0;
fifo1_in_clk = in_clk;
in_rdy = fifo1_in_rdy;
end
end
nguthrie的回答是对的,但是你在理解一些非常重要的事情上犯了错误,所以我想写一个更明确的版本 如果我们将您的代码简化,这样我们只需查看fifo0_data_中的赋值,就更容易讨论了
always_comb
begin
if(fifo_select == 0)
begin
fifo0_data_in = data_in;
end
end
所以,当fifo_select为零时,我们分配给fifo_data_in,当fifo_select不为零时,我们。。。。呃。。。不执行任何操作,这意味着它需要保留以前的值
我们描述的是一个锁存器,锁存器不是组合的,它们保留信息,所以它们不可能存在于一个永远的梳子中。它们必须处于“始终锁定”或“始终锁定”状态
使用always块时,意外闩锁是一个非常常见的错误,通常您永远不会想要它们。SystemVerilog添加了always_comb,这样,在您的情况下,当fifo_select不为零时,当设计师忘记为代码路径中的信号定义值时,类似这样的错误会告诉设计师
解决这一问题的另一种方法,以及一种值得熟悉的风格是:
always_comb
begin
fifo0_data_in = '0; // Default value
if(fifo_select == 0)
begin
fifo0_data_in = data_in;
end
end
在这里,我们在开始时指定一个默认值,因此无论if条件是否为true,都会为信号指定一些内容。这种风格通常更容易,因为有很多复杂的条件控制信号。nguthrie的答案是正确的,但你在一些非常重要的事情上绊倒了,需要理解,所以我想写一个更明确的版本 如果我们将您的代码简化,这样我们只需查看fifo0_data_中的赋值,就更容易讨论了
always_comb
begin
if(fifo_select == 0)
begin
fifo0_data_in = data_in;
end
end
所以,当fifo_select为零时,我们分配给fifo_data_in,当fifo_select不为零时,我们。。。。呃。。。不执行任何操作,这意味着它需要保留以前的值
我们描述的是一个锁存器,锁存器不是组合的,它们保留信息,所以它们不可能存在于一个永远的梳子中。它们必须处于“始终锁定”或“始终锁定”状态
使用always块时,意外闩锁是一个非常常见的错误,通常您永远不会想要它们。SystemVerilog添加了always_comb,这样,在您的情况下,当fifo_select不为零时,当设计师忘记为代码路径中的信号定义值时,类似这样的错误会告诉设计师
解决这一问题的另一种方法,以及一种值得熟悉的风格是:
always_comb
begin
fifo0_data_in = '0; // Default value
if(fifo_select == 0)
begin
fifo0_data_in = data_in;
end
end
在这里,我们在开始时指定一个默认值,因此无论if条件是否为true,都会为信号指定一些内容。这种方式通常更容易,因为有许多复杂的条件控制信号