always_comb 和 always@(*) 之间的行为差​​异

Behavior difference between always_comb and always@(*)

我刚刚发现always@(*)在涉及function.

时没有按预期工作

请参阅下面的简单示例代码。

http://www.edaplayground.com/x/J7M

module test;
  reg a, b, c;

  function reg my_func();
    if (b==0) begin
      $display("DEBUG 0 @%0t", $time);
      return a;
    end
    else if (b==1) begin
      $display("DEBUG 1 @%0t", $time);
      return ~a;
    end
    else begin
      $display("DEBUG 2 @%0t", $time);
      return 0;
    end
  endfunction

  always @(*) begin
  //always_comb begin
    c = my_func();
  end

  initial begin
    a = 0; #10;
    a = 1; #10;
    a=0; 
  end
endmodule

尝试在模拟中切换always @(*)always_comb。如果我使用 always @(*),则不会显示任何内容。但是如果我使用 always_comb,它会显示如下预期结果:

DEBUG 2 @0
DEBUG 2 @0
DEBUG 2 @10
DEBUG 2 @20

以上代码只是简单的组合逻辑。 为什么 always @(*)always_comb 显示不同的结果?只是模拟问题吗?进一步的实验我注意到它可能与 always 块中 function 的使用有关。

always @(*) 块对所有变量值的变化很敏感,即由 always 块读取,或者我们可以说哪些在 always 块内的右侧。

在您的示例中,always 块中没有使用任何变量,因此 always @(*) 块在这里不起作用。

根据 SV LRM,

always_comb is sensitive to changes within the contents of a function, whereas always @* is only sensitive to changes to the arguments of a function.

即,每当函数内的变量发生变化时,always_comb 就会触发,但在您的情况下,只有当我们在函数中传递参数时,@(*) 才会始终触发。

所以你可以使用,

  always @(*) begin
    c = my_func(b);  
  end

或者你可以使用,

  always_comb begin
    c = my_func();  
  end

我已经修改了你的代码。请在下面 link.

中找到它

http://www.edaplayground.com/x/JiS

always @(*) 由 Verilog IEEE 1364-2001 标准添加,并在 SystemVerilog IEEE 1800-2005 标准中被 always_comb 取代。 always @(*) 不应再使用,因为它不能在所有情况下正确模拟硬件。除了您注意到的函数差异之外,它还不能正确处理常量逻辑。

parameter C = 0;
reg A,B;
always @(*) A = B && C;
B 发生变化之前,

A 仍然未知。而使用 always_comb 将立即将 A 设置为 0,因为保证在时间 0 执行。