Verilog 中的事件调度

ji8*_*8in 5 verilog system-verilog

我正在学习verilog分层事件队列。我对非活动事件有一个小小的疑问。我知道它们是在当前模拟时间完成所有活动事件后执行的。但我编写了一个简单的代码来更好地理解这个概念,但得到的结果让我感到困惑。这是我写的代码:

module main;

    int x; 

    initial begin 

       $monitor("x is %0d",x); 

       #0 x = 5; // inactive event 
       x = 3; // active event 
     end 

endmodule
Run Code Online (Sandbox Code Playgroud)

结果:x 为 3。

据我所知,#0 延迟会创建一个非活动事件,因此结果应该是 x 为 5。但我对这个概念的理解可能在某个地方是错误的。任何帮助将不胜感激。谢谢。

Gre*_*reg 3

IEEE Std 1800-2012中区域的定义:

\n\n
\n

4.4.2.2 活动事件区域
\n 活动区域保存正在评估的当前活动区域集事件,并且可以按任何顺序进行处理。

\n 4.4.2.3 非活动事件区域
\n 非活动区域保存所有活动事件处理完毕后要评估的事件。

\n 如果事件正在活动区域​​集合中执行,则显式#0延迟控制要求挂起进程并将事件调度到当前时隙的非活动区域中,以便可以在下一个非活动到主动迭代。

\n ...

\n 4.4.2.9 推迟事件区域
\n $monitor$strobe和其他类似事件都安排在推迟区域中。\n 一旦到达推迟区域,当前时间段内不允许发生新的值更改。

\n 在此区域内,向任何网络或变量写入值或在当前时隙内的任何先前区域中安排事件都是非法的。

\n
\n\n

图表参见图4-1\xe2\x80\x94事件区域上的调度程序图

\n\n

您的理解是正确的,将#0放入x = 5;非活动区域。但是,这#0也会阻止x = 3;第一次进入活动区域时执行。它在由非活动区域操纵的活动区域的第二遍中执行。这是因为阻塞语句始终是连续的。$monitor()始终显示在时间步的末尾,在所有其他区域完成之后,因此您只能在 时获得最终值x

\n\n

通过将语句放置在 fork-join 中,这两个语句将并行执行。这将允许x = 3;在第一次进入活动区域时执行。

\n\n
module main;\n    int x; \n    initial begin \n       $monitor("From    $monitor: x is %0d",x); \n       #0 x = 5; // inactive event \n       x = 3; // active event (after inactive event)\n       #1; // go to next time stamp\n       fork\n         #0 x = 7; // inactive event \n         x = 11; // active event \n       join\n    end \n    // reactive event, x value from the observed region\n    always @* $display("From @* $display: x is %0d",x); \nendmodule\n
Run Code Online (Sandbox Code Playgroud)\n\n

输出:

\n\n
From @* $display: x is 3\nFrom    $monitor: x is 3\nFrom @* $display: x is 11\nFrom @* $display: x is 7\nFrom    $monitor: x is 7\n
Run Code Online (Sandbox Code Playgroud)\n