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.
中找到它
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 执行。
我刚刚发现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.
中找到它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 执行。