On SystemVerilog Scheduler-2

Some examples

Akash Suresh
5 min readJul 17, 2019

In the last article, we had seen about simulation time and how it is different from our sense of time. We also saw how each simulator time slot was split into several event regions to avoid simulation race.

Now, let us look at some incremental examples to understand things better.

Example-1: Basic

module sample_1;
int i;
int j;
int k;
initial begin
i = 1;
j = 2;
$display("s1 1. %d %d %d\n", i ,j, k);
end
endmodule
Remember this?

What region set will these come in?

Active region set. Statements inside “modules” are considered in active region sets, whereas the ones inside “program” block come under the reactive region set.

What kind of statements are they?

  • Blocking statements.
  • Display system function

Which region would they fit?

We had seen that blocking assignments and display functions come under the active region.

So, the spawning happens in the below order:

  • i=1;
  • j=2;
  • $display

Example-2 : Starting out on concurrency.

module sample_2;
int i;
int j;
int k;
initial begin
i=1;
j=2;
$display("s2 1. %d %d %d \n", i,j,k);
end
initial begin
k=2;
$display("s2 2. %d %d %d\n",i,j,k);
end
endmodule

Again, they are in the active region set and are blocking assignments; hence will be executed in the active region.

But what comes first? i=1? Or i=2?

In a case like this where there are concurrent blocks, the SV language manual leaves the order of execution to the simulator (Except that execution inside each block must be sequential).

Synopsys’s VCS executes them in their order of occurrence.

So here, the order of execution would be as follows:

  • i=1
  • j=2
  • $display(“s2 1. …”)
  • i=2
  • $display(“s2 2. …”)

Example-3 : Here come NBAs

module sample_3;
int i;
int j;
int k;
initial begin
i<=1;
j=2;
$display("s3 1. %d %d %d\n", i,j,k);
end
initial begin
k<=3;
$display("s3 2. %d %d %d\n", i,j,k);
end
initial begin
k=5;
$display("s3 3. %d %d %d\n",i,j,k);
end
endmodule

Region set? Active region set

Statement types?

  • Blocking
  • Display
  • Non-blocking
  • Monitor

With a newcomer amidst, the output is:

Now, how did we get this?

Recall that only LHS of NBAs are evaluated in the active phase. The actual updation happens only in the NBA region.

So, the sequence of events will be as follows:

Active region set-Active state :

  • i <= 1 (Evaluate LHS, value is not updated. So, i is still 0)
  • j=2
  • $display(“s3 1. …”)
  • k<=3 (Evaluate LHS, value is not updated. So, k is still 0)
  • $display(“s3 2. …”)
  • k=5

Active region set-NBA :

  • i<=1 (Update value of i; so i is now 1)
  • k<=3 (Update value of k; so i is now 3)

Postponed :

  • $monitor(“…”) (This shows the values at the end of time slot)

Example-4 Icing on the cake: #0 statements

module sample_4;
int i;
int j;
int k;
initial begin
i=1;
j=2;
$display("s4 1. %d %d %d \n", i,j,k);
#0 k = 3;
$display("s4 2. %d %d %d\n", i,j,k);
end
initial begin
i=3;
$display("s4 3. %d %d %d\n", i,j,k);
end
endmodule

Region set? Active region set

Types of statements:

  • Blocking
  • Display
  • #0 delay statements

We know about delays in an HDL code. But here, the delay is within a time slot. In other words, all statements below a #0 delay statement are pushed to the inactive region. They are spawned by the scheduler only after all available active region statements are spawned.

So, can you figure out the output? Bingo if you have got this:

The sequence of events will be as follows:

Active set-Active region:

  • i=1
  • j=2
  • $display(“s4 1. …”)
  • i=3
  • $display(“s4 3. …”)

Active set-Inactive region(moved eventually to active state):

  • k=3 (All active region statements are spawned. So, statements in the inactive region are pushed to the active region)
  • $display(“s4 2. …”)

Example 5: Intra and inter assignment delays

I’m sure this would confused many:

module sample_5;
int i;
int j;
int k;
initial begin
j = #1 1;
$display("s5 1. %d %d %d\n", i,j,k);
#0 i<=1;
$display("s5 2. %d %d %d\n", i,j,k);
end
initial begin
#2;
i=10;
#0 j=10;
$display("s5 3. %d %d %d", i,j,k);
end
endmodule

The output is as follows:

In the previous examples, we had seen statements falling under a single time slot. Here, we have statements from multiple time slots. Added to this are intra and inter statement delays.

Intra assignment delays only delay that particular statement. None coming after it. In this example,

j = #1 1 delays evaluation of LHS to time slot 1, and hence updation as well. But other statements ($display(“ s5 1. ..“) etc) below this inside the block are not affected and spawned in time slot 0.

Inter assignment delays push anything coming under it. So, all statements below #2 delay on line-12 are pushed to time slot-2.

Separating statements according to time slots,

Time: 0 unit

Active set-Active region:

  • $display(“s5 1. …”)

Active set-Inactive region (to be pushed to active after all active statements are spawned):

  • i<=1 (Evaluation of LHS)
  • $display(“s5 2. …”)

Active set-NBA:

  • i<=1 (i gets updated to 1)

Time: 1 unit

Active set-Active region:

  • j= #1 1

Time: 2 unit

Active set-Active region:

  • i=10

Active set- Inactive region (to be pushed to active after all active statements are spawned):

  • j=10
  • $display(“s5 3. …”)

This brings us to the end of this article. I hope these articles would have made SV/Verilog scheduler’s working clear.

Now that you know the fundamentals, I encourage you to make a mash-up of all kinds of statements and fiddle around.

Feel free to reach out if you get stuck.

Link to the previous article incase you want to look back.

--

--