Evaluation Event Scheduling - Verilog Stratified Event Queue

蹲街弑〆低调 提交于 2020-01-04 02:48:09

问题


I am trying to implement a simple event based Verilog simulator in Python, but I actually struggle to find some details in the specification (section 11 of IEEE 1364-2005).

Let's say I just perfomed an update event on clk which now obtained the new value 1 (0 before). According to the specification this requires me to schedule 'evaluation events' for sensitive processes.

Do I have to schedule the evaluation of an always @(posedge clk) block as active or inactive event? I'm guessing that the latter is correct?

Or actually, to speak more general. Are basically all events scheduled as inactive events with the following exceptions:

  • Non blocking assignment updates as non-blocking assignment events
  • continuous assignments as active events

Thanks a lot!


回答1:


By default everything runs in the Active region. The exceptions being:

  • #0 blocking assignments are in the Inactive region
  • Non-blocking assignments are in the NBA region
  • $monitor, $strobe, and PLI/VPI are in the Monitor region

We can prove that @ happens in the Active region, by running the following in any existing simulator:

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

Outputs:

 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

Display reports more times then monitor. This rules out @ accruing in the Monitor or Future region. Display is is reporting on every event region. Each event region can only loop back to the Active region. Therefor, the @ must be handled in the Active region and each region that updates the variable x is triggering a new Active region event.

This can also be proved by knowing looking at the history of Verilog. Unfortunately, this is not well documented. I leaned learned about it through people that were using/developing verilog in the late '80s early '90s. The over all explanation is: The Inactive and NBA regions were added to Verilog before IEEE Std 1364-1995, @ predates these two region. The regions were added to add determinism to a non-deterministic simulator.

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



clarification based on feedback from comments

Events are activated, not moved. Activated NBA events enter the true condition of if (E is an update event), modified object and schedule new evaluation events (handled the next time Active region entered). Once all the activated events are completed, the schedule goes back to the top of the while-loop. The NBA region only assigns values, the evaluation was actually done in an earlier Active region stage.
From your example:
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

Each iteration of the while loop would look something like this:

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


来源:https://stackoverflow.com/questions/22815281/evaluation-event-scheduling-verilog-stratified-event-queue

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!