Evaluation Event Scheduling - Verilog Stratified Event Queue
我正在尝试用 Python 实现一个简单的基于事件的 Verilog 模拟器,但实际上我很难在规范中找到一些细节(IEEE 1364-2005 的第 11 节)。
假设我刚刚在
我是否必须将
或者实际上,更笼统地说。基本上所有事件都被安排为非活动事件,但有以下例外:
- 非阻塞赋值更新为非阻塞赋值事件
- 作为活动事件的连续分配
非常感谢!
默认情况下,一切都在活动区域??中运行。例外情况是:
- #0 阻塞分配位于非活动区域
- 非阻塞分配在 NBA 地区
- $monitor、$strobe 和 PLI/VPI 位于 Monitor 区域
我们可以通过在任何现有模拟器中运行以下命令来证明
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | 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 #0 fork // inactive region #0 x = 2; // inactive event x = 5; // active event x <= 4; // NBA event join end // active event region always @* $display("From @* $display: x is %0d",x); |
输出:
1 2 3 4 5 6 7 8 | From @* $display: x is 3 From $monitor: x is 3 From @* $display: x is 11 From @* $display: x is 7 From @* $display: x is 5 From @* $display: x is 2 From @* $display: x is 4 From $monitor: x is 4 |
显示报告的次数多于监控。这排除了
这也可以通过了解 Verilog 的历史来证明。不幸的是,这没有得到很好的记录。我从 80 年代末 90 年代初使用/开发 verilog 的人那里了解到了它。总体解释是: Inactive 和 NBA 区域在 IEEE Std 1364-1995 之前被添加到 Verilog,
1 2 | always @(posedge clk) pipe0 = in; always @(posedge clk) pipe1 = pipe0; // unpredictable, non-deterministic order |
1 2 | always @(posedge clk) #0 pipe0 = in; // Inactive region added some determinism always @(posedge clk) pipe1 = pipe0; |
1 2 3 | always @(posedge clk) #0 pipe0 = in; // But was fragile always @(posedge clk) #0 pipe1 = pipe0; // unpredictable order again always @(posedge clk) pipe2 = pipe1; |
1 2 3 4 5 | always @(posedge clk) pipe0 <= in; always @(posedge clk) pipe1 <= pipe0; always @(posedge clk) pipe2 <= pipe1; // NBA region fixed it ... always @(posedge clk) pipeN <= pipeM; // and made it scalable |
基于评论反馈的澄清
事件被激活,而不是移动。已激活的 NBA 赛事进入
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | module TEST; reg test = 0; reg test2 = 0; reg clk = 0; initial begin clk <= 1; test <= 1; end always @(posedge clk) begin test2 <= test; end endmodule |
while 循环的每次迭代看起来像这样:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | Iteration:0 Active: <----- This is region is executing clk$tmp = eval(1) test$tmp = eval(1) Inactive: NBA: clk = clk$tmp test = test$tmp Iteration:1 Active: Inactive: NBA: <----- This is region is executing clk = clk$tmp test = test$tmp Active.schedule( eval("@(posedge clk)" ) Iteration:2 Active: <----- This is region is executing eval("@(posedge clk)" ) Active.schedule("test2$tmp = eval(test)" ) NBA.schedule("test2 = test2$tmp" ) Inactive: NBA: Iteration:3 Active: <----- This is region is executing test2$tmp = eval(test) Inactive: NBA: test2 = test2$tmp Iteration:4 Active: Inactive: NBA: <----- This is region is executing test2 = test2$tmp Iteration:5 --> next simulation cycle |