我想在零时刻执行始终阻止。 对于例如下面的代码不会在零时执行。
always @* begin
//functional code
end
我在最后移动了敏感度列表,以便代码将在零时刻执行,
always begin
//funcitonal code
@*;
end
此代码在零时刻执行,但在零时间之后根本不执行,即使块内使用的输入发生了变化。例如,请参阅下面的代码及其输出:
module AlwaysTimeZeroTest_v();
reg reg_A;
initial begin
$display ("I'm in Initial begin block \tTime=%f, reg_A=%b\n",$stime,reg_A);
#1
reg_A=1'bZ;
#1
reg_A=1'b1;
#1
reg_A=1'b0;
#1
reg_A=1'bZ;
#5 $finish;
end
always @* begin
$display ("I'm in Non-time Zero always block\tTime=%f, reg_A=%b\n",$stime,reg_A);
end
always begin
$display ("I'm in time Zero always block \tTime=%f, reg_A=%b\n",$stime,reg_A);
@*;
end
endmodule
输出:
**I'm in Initial begin block Time=0.000000, reg_A=x
I'm in time Zero always block Time=0.000000, reg_A=x
I'm in Non-time Zero always block Time=1.000000, reg_A=z
I'm in Non-time Zero always block Time=2.000000, reg_A=1
I'm in Non-time Zero always block Time=3.000000, reg_A=0
I'm in Non-time Zero always block Time=4.000000, reg_A=z**
在时间9 NS + 0
时通过$ finish(1)完成模拟任何人都可以解释为什么在时间零之后,代码中的第二个始终阻塞根本不执行吗?
有没有办法可以实现总是阻塞,以便它在零时执行而不使用初始块? (类似于SV中的always_comb?)
答案 0 :(得分:5)
许多人没有意识到@
是一个语句修饰符,而不是自己构造。它说要延迟发生事件之前的声明。 @(A or B)
表示等到A
或B
的值发生变化(不要与A|B
的结果发生变化混淆)。 @*
表示查看后面的语句,并构建一个隐含的信号敏感列表以等待更改。
在您的第一个always
中,后面的语句是begin/end
块,因此reg_A
会被添加到敏感列表中。在您的第二个always
中,后面的语句是 null 语句,因此对任何更改都没有敏感性。
确保always @*
在零时执行的唯一方法是对块中的变量进行一些引用,该变量在时间0处有变化。然后对该变量使用非阻塞赋值以避免任何变量时间0比赛条件。
更好的是,使用专为解决此问题而设计的alway_comb
。
答案 1 :(得分:0)
你标记了这个系统 - verilog所以我会给出答案。
如果您当前的使用率是always @*
并且您没有从多个always块驱动输出,请使用always_comb。每LRM,always_comb
将在0时执行。
module AlwaysTimeZeroTest_v();
reg reg_A;
initial begin
$display ("I'm in Initial begin block \tTime=%f, reg_A=%b\n",$stime,reg_A);
#1
reg_A=1'bZ;
#1
reg_A=1'b1;
#1
reg_A=1'b0;
#1
reg_A=1'bZ;
#5 $finish;
end
always_comb begin
$display ("I'm in Non-time Zero always block\tTime=%f, reg_A=%b\n",$stime,reg_A);
end
always_comb begin
$display ("I'm in time Zero always block \tTime=%f, reg_A=%b\n",$stime,reg_A);
// @*;
end
endmodule