我很困惑!而且有点沮丧。我花了很多时间在Modelsim上的一些SystemVerilog上工作。我把它带到了某个阶段,我可以在我的硬件上测试它,但在Quartus中编译是不成功的。我明白这可能会发生,但在这种情况下,我的错误似乎没有意义。
以下代码位于always_comb块内。当我编译时,我收到以下错误:
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。
我有兴趣知道错误的来源是什么?
感谢您的帮助。
答案 0 :(得分:4)
您没有在多路复用器的所有分支中分配所有输出。例如,fifo0_data_in
会分配fifo_select == 0
。但是如果fifo_select == 1
那么它就没有价值。这意味着fifo0_data_in
需要记住fifo_select
更改时其值的含义。因此,合成将推断出该输出的锁存器。
这是我认为你想要的:
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
答案 1 :(得分:1)
nguthrie的答案是正确的,但你已经绊倒了一些非常重要的理解,所以我想写一个更明确的版本。
如果我们接受您的代码并对其进行简化,那么我们只需查看fifo0_data_in
的分配,就会更容易讨论。
always_comb
begin
if(fifo_select == 0)
begin
fifo0_data_in = data_in;
end
end
所以,当fifo_select
为零时我们分配给fifo0_data_in
,当fifo_select
不为零时,我们......错误...什么都不做,这意味着它需要保持它以前的价值。
我们所描述的是“锁存器”,并且锁存器不是组合的(它们保留信息),因此它们不能存在于always_comb
中。它们必须位于always_latch
或always
块中。
使用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
条件是否为真,都会为信号分配一些内容。这种风格通常更容易,因为有很多复杂的条件可以控制信号。