If statement SystemVerilog中的“if”语句始终为“非纯组合逻辑”错误

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

我糊涂了!有点沮丧。我花了相当多的时间在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

我想知道错误的来源是什么


感谢您的帮助。

您并不是在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,都会为信号指定一些内容。这种方式通常更容易,因为有许多复杂的条件控制信号