关于python:Evaluation Event Scheduling – Verilog Stratified Event Queue

Evaluation Event Scheduling - Verilog Stratified Event Queue

我正在尝试用 Python 实现一个简单的基于事件的 Verilog 模拟器,但实际上我很难在规范中找到一些细节(IEEE 1364-2005 的第 11 节)。

假设我刚刚在 clk 上执行了一个更新事件,它现在获得了新值 1(之前为 0)。根据规范,这要求我为敏感进程安排\\'评估事件\\'。

我是否必须将 always @(posedge clk) 块的评估安排为活动或非活动事件?我猜后者是对的?

或者实际上,更笼统地说。基本上所有事件都被安排为非活动事件,但有以下例外:

  • 非阻塞赋值更新为非阻塞赋值事件
  • 作为活动事件的连续分配

非常感谢!


默认情况下,一切都在活动区域??中运行。例外情况是:

  • #0 阻塞分配位于非活动区域
  • 非阻塞分配在 NBA 地区
  • $monitor、$strobe 和 PLI/VPI 位于 Monitor 区域

我们可以通过在任何现有模拟器中运行以下命令来证明 @ 发生在 Active 区域中:

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

显示报告的次数多于监控。这排除了 @ 在 Monitor 或 Future 区域中的累积。显示正在报告每个事件区域。每个事件区域只能循环回活动区域。因此,@ 必须在 Active region 中处理,并且每个更新变量 x 的区域都会触发一个新的 Active region 事件。

这也可以通过了解 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 赛事进入 if (E is an update event) 的真实条件,修改对象并安排新的评估赛事(下次进入 Active region 时处理)。一旦所有激活的事件都完成,调度就会回到 while 循环的顶部。 NBA 赛区只赋值,评估实际上是在更早的 Active region 阶段进行的。从你的例子:

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