评估事件调度 - Verilog分层事件队列

时间:2014-04-02 14:53:09

标签: python verilog fpga hdl

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

让我们说我刚刚在clk上执行了更新事件,现在获得了新值1(之前为0)。根据规范,这要求我安排评估活动'敏感过程。

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

或实际上,说得更一般。基本上所有事件都被安排为非活动事件,但以下情况除外:

  • 非阻止分配更新为非阻塞分配事件
  • 连续分配为活动事件

非常感谢!

1 个答案:

答案 0 :(得分:3)

默认情况下,所有内容都在 Active 区域中运行。例外是:

  • #0阻止分配位于非活动区域
  • 非阻止作业位于 NBA 区域
  • $ monitor,$ strobe和PLI / VPI位于监控区域

我们可以通过在任何现有的模拟器中运行以下内容来证明@在活动区域​​中发生:

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); 

输出:

 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

显示报告的次数,然后进行监控。这排除了监视器或未来区域中的@累积。显示是报告每个事件区域。每个事件区域只能循环回活动区域。因此,必须在活动区域​​中处理@,并且更新变量x的每个区域都会触发新的活动区域事件。

这也可以通过了解Verilog的历史来证明。不幸的是,这没有很好的记录。我倾向于通过在80年代末90年代后期使用/开发verilog的人了解它。最重要的解释是:在IEEE Std 1364-1995之前,Inactive和NBA地区被添加到Verilog,@早于这两个地区。添加区域以向非确定性模拟器添加确定性。

always @(posedge clk) pipe0 = in;
always @(posedge clk) pipe1 = pipe0; // unpredictable, non-deterministic order
always @(posedge clk) #0 pipe0 = in; // Inactive region added some determinism
always @(posedge clk) pipe1 = pipe0; 
always @(posedge clk) #0 pipe0 = in; // But was fragile
always @(posedge clk) #0 pipe1 = pipe0; // unpredictable order again
always @(posedge clk) pipe2 = pipe1; 
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)的真实条件,修改对象并安排新的评估事件(下次输入活动区域时处理)。完成所有激活的事件后,计划将返回到while循环的顶部。 NBA 区域仅指定值,评估实际上是在较早的 Active 区域阶段完成的。
从你的例子:

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循环的每次迭代都看起来像这样:

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