san*_*you 0 verilog system-verilog
我想在零时刻执行总是阻塞.例如,下面的代码将不会在零时执行.
always @* begin
//functional code
end
Run Code Online (Sandbox Code Playgroud)
我在最后移动了敏感度列表,以便代码将在零时执行,
always begin
//funcitonal code
@*;
end
Run Code Online (Sandbox Code Playgroud)
此代码在零时执行,但在零时间之后根本不执行,即使块内使用的输入发生了变化.例如,请参阅下面的代码及其输出:
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
Run Code Online (Sandbox Code Playgroud)
输出:
**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**
Run Code Online (Sandbox Code Playgroud)
模拟通过$ finish(1)在时间9 NS + 0完成
任何人都可以解释为什么第二个总是在代码中阻塞后不会在零时间后执行?
有没有一种方法可以实现总是阻塞,以便它在零时执行而不使用初始块?(类似于SV中的always_comb?)
许多人没有意识到这@
是一个语句修饰语,而不是单独构造.它说要延迟发生事件之前的声明.@(A or B)
意味着等到A
或的值发生变化B
(不要与结果的变化相混淆A|B
).@*
意味着查看后面的语句,并构建一个隐含的信号敏感列表以等待更改.
在您的第一个中always
,后面的语句是一个begin/end
块,因此reg_A
被添加到灵敏度列表中.在您的第二个中always
,后面的语句是一个空语句,因此对任何更改都没有敏感性.
确保always @*
在零时执行的唯一方法是在块0中对变量进行一些引用,该变量在时间0处有变化.然后对该变量使用非阻塞赋值以避免任何时间0竞争条件.
更好的是,使用alway_comb
它是专门为解决这个问题而设计的.