我正在学习verilog分层事件队列。我对非活动事件有一点疑问。我知道它们是在所有活动事件在当前模拟时间完成之后执行的。但我写了一个简单的代码来更好地理解这个概念,但我得到的结果让我感到困惑。这是我写的代码:
module main;
int x;
initial begin
$monitor("x is %0d",x);
#0 x = 5; // inactive event
x = 3; // active event
end
endmodule
结果:x为3。
根据我的知识,#0延迟创建了一个非活动事件,因此结果应该是x是5.但是我对这个概念的理解可能在某个地方是错误的。任何帮助将不胜感激。感谢。
答案 0 :(得分:2)
在您的代码中,x在同一时间步中被覆盖。根据{{3}}:
当使用一个或多个参数调用$ monitor任务时, 模拟器建立一种机制,每次一个变量或一个 参数列表中的表达式更改整个参数列表的值 在时间步的结尾显示 。
如果在每个语句后使用$ display,您将看到每个值都发生变化:
module main;
int x;
initial begin
$monitor("x in $monitor is %0d",x);
#0 x = 5; // inactive event
$display ("x in $display=%0d", x);
x = 3; // active event
$display ("x in $display=%0d", x);
end
endmodule
输出:
$ in display = 5
$ in display = 3
$ monitor中的是3
退出
答案 1 :(得分:2)
来自IEEE Std 1800-2012的区域的定义:
4.4.2.2活动事件区域
活动区域保持正在评估的当前活动区域集事件,并且可以按任何顺序处理。
4.4.2.3非活动事件区域
在处理完所有活动事件后,非活动区域保存要评估的事件。
如果正在活动区域集中执行事件,则显式#0
延迟控制要求暂停进程并将事件调度到当前时隙的非活动区域,以便可以在next非活动迭代。
的 ... 强>
4.4.2.9推迟事件区域
$monitor
,$strobe
和其他类似事件安排在延期区域。 一旦到达延期区域,当前时间段内不允许发生新的价值变化。
在此区域内,将值写入任何网络或变量或在当前时间段内的任何先前区域中安排事件是非法的。
图表见图4-1 - 事件区域
上的调度程序图您的理解是正确的#0
将x = 5;
置于非活动区域。但是,此#0
也会阻止x = 3;
在第一次进入活动区域时执行。它在第二次传递中执行到由非活动区域操纵的活动区域。这是因为阻塞语句总是始终是顺序的。所有其他区域完成后,$monitor()
始终显示在时间步的末尾,因此只有x
才能获得最终值。
通过将语句放在fork-join中,这两个语句将并行执行。这将允许x = 3;
在第一次进入活动区域时执行。
module main;
int x;
initial begin
$monitor("From $monitor: x is %0d",x);
#0 x = 5; // inactive event
x = 3; // active event (after inactive event)
#1; // go to next time stamp
fork
#0 x = 7; // inactive event
x = 11; // active event
join
end
// reactive event, x value from the observed region
always @* $display("From @* $display: x is %0d",x);
endmodule
输出:
From @* $display: x is 3
From $monitor: x is 3
From @* $display: x is 11
From @* $display: x is 7
From $monitor: x is 7