SystemVerilog Array Reduction methods

Array Reduction methods

SystemVerilog Array Reduction methods operate on an unpacked array to reduce the array to a single value.

built-in array reduction methods are,

Method Description
sum() returns the sum of all the array elements
product() returns the product of all the array elements
and() returns the bit-wise AND ( & ) of all the array elements
or() returns the bit-wise OR ( | ) of all the array elements
xor() returns the logical XOR ( ^ ) of all the array elements

‘with’ clause is allowed for sort and rsort methods.

About ‘with’:
expression specified in “with” clause will be evaluated for each array element and performs the operation on an array.

Array reduction methods SUM and PRODUCT

On calling sum() method sum of array_1 elements (1,2,3,4) will be returned to variable t_sum.
On calling product() method product of array_1 elements (1,2,3,4) will be returned to variable t_product.

module fixedsize_array;
  
  //declaration of array’s
  int array_1[4];
 
  int t_sum,t_product;
  
  initial begin
    //array initialization
    array_1  = '{1,2,3,4};

    t_sum = array_1.sum(); //t_sum = 1+2+3+4
    $display("Sum of array_1 is \t%0d",t_sum);

    t_product = array_1.product(); //t_product = 1*2*3*4
    $display("product of array_1 is \t%0d",t_product);
  end
  
endmodule 

Simulator Output

Sum of array_1 is 10
product of array_1 is 24

Click to execute on   

Array reduction method AND

On calling and() method, bit-wise and (&) will be performed on all the array elements and returned.
Let’s consider an example of an array with 2, 3 and 4 elements.

Before looking into examples, see to the Truth table for AND.

A B Y =
A & B
0 0 0
0 1 0
1 0 0
1 1 1

1. Array with 2 elements.
Consider A=2 and B=3.
Y = A & B;

Binary Decimal
A 0010 2
B 0011 3
Y = A & B 0010 2

Consider A=2 and B=1.
Y = A & B;

Binary Decimal
A 0010 2
B 0001 1
Y = A & B 0000 0

2. Array with 3 elements.
Consider A=10, B=9, and C=8.

AND operation of 3 elements performed in 2 steps, In first step A & B, will be performed. In the second step result of the first step & C will be done. Considering X as the first step result.

X = A & B;
Y = X & C;

Binary Decimal
A 1010 10
B 1001 9
X = A & B 1000 8
C 1000 8
Y = X & C 1000 8

2. Array with 4 elements.
Consider A=3, B=5, C=7, and D=9.

Consider X and Y as intermediate results.
X = A & B;
Y = X & C;
Z = Y & D;

Binary Decimal
A 0011 3
B 0101 5
X = A & B 0001 8
C 0111 7
Y = X & C 0001 8
D 1001 9
Z = Y & D 0001 1

Complete code with above examples.

module fixedsize_array;
  
  //declaration of array’s
  int array_1[2];
  int array_2[2];
  int array_3[3];
  int array_4[4];
  
  int b_and;
  
  initial begin
    //array initialization
    array_1  = '{2,3};
    array_2  = '{2,1};
    array_3  = '{10,9,8};
    array_4  = '{3,5,7,9};
    
    b_and = array_1.and();
    $display("Bit-wise AND of array_1 is \t%0d",b_and);
    
    b_and = array_2.and();
    $display("Bit-wise AND of array_2 is \t%0d",b_and);
    
    b_and = array_3.and();
    $display("Bit-wise AND of array_3 is \t%0d",b_and);    

    b_and = array_4.and();
    $display("Bit-wise AND of array_4 is \t%0d",b_and);    
  end
endmodule

Simulator Output

Bit-wise AND of array_1 is 2
Bit-wise AND of array_2 is 0
Bit-wise AND of array_3 is 8
Bit-wise AND of array_4 is 1

Click to execute on   

Array reduction method OR

On calling or() method, bit-wise or (|) will be performed on all the array elements and returned.
Let’s consider an example of an array with 2, 3 and 4 elements.

Before looking into examples, see to the Truth table for OR.

A
B
Y = A | B
0 0 0
0 1 1
1 0 1
1 1 1

1. Array with 2 elements.
Consider A=2 and B=3.
Y = A | B;

Binary
Decimal
A
0010
2
B
0011
3
Y = A | B
0011
3

Consider A=2 and B=1.
Y = A | B;

Binary
Decimal
A
0010
2
B
0001
1
Y = A | B
0011
3

2. Array with 3 elements.
Consider A=10, B=9, and C=8.

OR operation of 3 elements performed in 2 steps, In first step A | B will be performed. In the second step result of the first step | C will be done. Considering X as the first step result.

X = A | B;
Y = X | C;

Binary
Decimal
A
1010
10
B
1001
9
X = A | B
1011
11
C 1000 8
Y = X | C 1011 11

2. Array with 4 elements.
Consider A=3, B=5, C=7, and D=9.

Consider X and Y as intermediate results.
X = A | B;
Y = X | C;
Z = Y | D;

Binary
Decimal
A
0011
3
B
0101
5
X = A | B
0111
7
C 0111 7
Y = X | C 0111 7
D 1001 9
Z = Y | D 1111 15

Complete code with above examples.

module fixedsize_array;
  
  //declaration of array’s
  int array_1[2];
  int array_2[2];
  int array_3[3];
  int array_4[4];
  
  int b_or;
  
  initial begin
    //array initialization
    array_1  = '{2,3};
    array_2  = '{2,1};
    array_3  = '{10,9,8};
    array_4  = '{3,5,7,9};
    
    b_or = array_1.or();
    $display("bit-wise OR of array_1 is \t%0d",b_or);
    
    b_or = array_2.or();
    $display("bit-wise OR of array_2 is \t%0d",b_or);
    
    b_or = array_3.or();
    $display("bit-wise OR of array_3 is \t%0d",b_or);    

    b_or = array_4.or();
    $display("bit-wise OR of array_4 is \t%0d",b_or);    
  end
  
endmodule

Simulator Output

bit-wise OR of array_1 is 3
bit-wise OR of array_2 is 3
bit-wise OR of array_3 is 11
bit-wise OR of array_4 is 15

Click to execute on   

❮ Previous Next ❯

SystemVerilog Array Ordering methods

Array manipulation methods

SystemVerilog Array manipulation methods provide several built-in methods to operate on arrays.
they are,

  • Array Ordering methods
  • Array Reduction methods
  • Array Locator methods
  • Array Iterator index querying

Array Ordering methods

  • operate on single dimensional arrays or queues.
  • these methods useful for reordering the array elements.

built-in array ordering methods are,

Method Description
reverse() reverses all the elements of the array(packed or unpacked)
sort() sorts the unpacked array in ascending order
rsort() sorts the unpacked array in descending order
shuffle() randomizes the order of the elements in the array

‘with’ clause is allowed for sort and rsort methods.

About ‘with’:
expression specified in “with” clause will be evaluated for each array element and performs the operation on an array.

As mentioned above, these methods operate on all kinds of array types. below are the examples of using array ordering methods.

Array Ordering methods On Fixed Size Array

Below example is for using reverse, sort, rsort and shuffle method on fixed size array.

module fixedsize_array;
  
  //declaration of array’s
  int array_1[4];
  int array_2[4];
  int array_3[4];
  int array_4[4];

  initial begin
    //array initialization
    array_1  = '{0,1,2,3};
    array_2  = '{2,3,1,0};
    array_3  = '{2,3,1,0};
    array_4  = '{0,1,2,3};
    

    $display("-======= reverse =======-");
    $display("Before:\t %p",array_1);
    array_1.reverse();
    $display("After :\t %p",array_1);
    $display("-=======================-");    

    $display("\n-=======   sort   =======-");
    $display("Before:\t %p",array_2);
    array_2.sort();
    $display("After :\t %p",array_2);
    $display("-=======================-"); 
    
    $display("\n-=======   rsort  =======-");
    $display("Before:\t %p",array_3);    
    array_3.rsort();
    $display("After :\t %p",array_3);
    $display("-=======================-");
    
    $display("\n-======= shuffle =======-");
    $display("Before:\t %p",array_4);
    array_4.shuffle();
    $display("After :\t %p",array_4);
    $display("-=======================-");  
    
  end
  
endmodule 

Simulator Output

-======= reverse =======-
Before: '{0, 1, 2, 3} 
After : '{3, 2, 1, 0} 
-=======================-

-======= sort =======-
Before: '{2, 3, 1, 0} 
After : '{0, 1, 2, 3} 
-=======================-

-======= rsort =======-
Before: '{2, 3, 1, 0} 
After : '{3, 2, 1, 0} 
-=======================-

-======= shuffle =======-
Before: '{0, 1, 2, 3} 
After : '{2, 3, 1, 0} 
-=======================-

Click to execute on   

Array Ordering methods On Dynamic Array

Below example is for using reverse, sort, rsort and shuffle method on the dynamic array.

module dynamic_size_array;
  
  //declaration of array’s
  int array_1[];
  int array_2[];
  int array_3[];
  int array_4[];

  initial begin
    array_1 = new[4];
    array_2 = new[4];
    array_3 = new[4];
    array_4 = new[4];
    
    //array initialization
    array_1  = '{0,1,2,3};
    array_2  = '{2,3,1,0};
    array_3  = '{2,3,1,0};
    array_4  = '{0,1,2,3};
    
    $display("-======= reverse =======-");
    $display("Before:\t %p",array_1);
    array_1.reverse();
    $display("After :\t %p",array_1);
    $display("-=======================-");    

    $display("\n-=======   sort   =======-");
    $display("Before:\t %p",array_2);
    array_2.sort();
    $display("After :\t %p",array_2);
    $display("-=======================-"); 
    
    $display("\n-=======   rsort  =======-");
    $display("Before:\t %p",array_3);    
    array_3.rsort();
    $display("After :\t %p",array_3);
    $display("-=======================-");
    
    $display("\n-======= shuffle =======-");
    $display("Before:\t %p",array_4);
    array_4.shuffle();
    $display("After :\t %p",array_4);
    $display("-=======================-");  
    
  end
  
endmodule 

Simulator Output

-======= reverse =======-
Before: '{0, 1, 2, 3} 
After : '{3, 2, 1, 0} 
-=======================-

-======= sort =======-
Before: '{2, 3, 1, 0} 
After : '{0, 1, 2, 3} 
-=======================-

-======= rsort =======-
Before: '{2, 3, 1, 0} 
After : '{3, 2, 1, 0} 
-=======================-

-======= shuffle =======-
Before: '{0, 1, 2, 3} 
After : '{2, 3, 1, 0} 
-=======================-

Click to execute on   

Array Ordering methods On Associative Array

Below example is for using reverse, sort, rsort and shuffle method on the associative array.

Note:
whereas in fixed/dynamic/queue array types index will be incremental but in associative array index shall be random.

In associative array, based on ordering methods elements will be stored to available different index locations.

module assoc_size_array;
  
  //declaration of array’s
  int array_1[*];
  int array_2[*];
  int array_3[*];
  int array_4[*];

  initial begin
    
    //array initialization
    array_1[3] = 8;
    array_1[5] = 2;
    array_1[7] = 6;
    array_1[9] = 1;
    
    array_2[3] = 8;
    array_2[5] = 2;
    array_2[7] = 6;
    array_2[9] = 1;
    
    array_3[3] = 8;
    array_3[5] = 2;
    array_3[7] = 6;
    array_3[9] = 1;
    
    array_4[3] = 8;
    array_4[5] = 2;
    array_4[7] = 6;
    array_4[9] = 1;
    
    $display("-======= reverse =======-");
    $display("Before:\t %p",array_1);
    array_1.reverse();
    $display("After :\t %p",array_1);
    $display("-=======================-");    

    $display("\n-=======   sort   =======-");
    $display("Before:\t %p",array_2);
    array_2.sort();
    $display("After :\t %p",array_2);
    $display("-=======================-"); 
    
    $display("\n-=======   rsort  =======-");
    $display("Before:\t %p",array_3);    
    array_3.rsort();
    $display("After :\t %p",array_3);
    $display("-=======================-");
    
    $display("\n-======= shuffle =======-");
    $display("Before:\t %p",array_4);
    array_4.shuffle();
    $display("After :\t %p",array_4);
    $display("-=======================-");  
    
  end
  
endmodule 

Simulator Output

-======= reverse =======-
Before: '{0x3:8, 0x5:2, 0x7:6, 0x9:1}
After : '{0x3:1, 0x5:6, 0x7:2, 0x9:8}
-=======================-
-======= sort =======-
Before: '{0x3:8, 0x5:2, 0x7:6, 0x9:1}
After : '{0x3:1, 0x5:2, 0x7:6, 0x9:8}
-=======================-
-======= rsort =======-
Before: '{0x3:8, 0x5:2, 0x7:6, 0x9:1}
After : '{0x3:8, 0x5:6, 0x7:2, 0x9:1}
-=======================-
-======= shuffle =======-
Before: '{0x3:8, 0x5:2, 0x7:6, 0x9:1}
After : '{0x3:6, 0x5:1, 0x7:2, 0x9:8}
-=======================-

Click to execute on   

Array Ordering methods On Queue

Below example is for using reverse, sort, rsort and shuffle method on the queue.

module queue_manipulation;
  
  //declaration of array’s
  int queue_1[$];
  int queue_2[$];
  int queue_3[$];
  int queue_4[$];
  
  initial begin
    queue_1.push_back(8);
    queue_1.push_back(2);
    queue_1.push_back(6);
    queue_1.push_back(1);

    queue_2.push_back(8);
    queue_2.push_back(2);
    queue_2.push_back(6);
    queue_2.push_back(1);
    
    queue_3.push_back(8);
    queue_3.push_back(2);
    queue_3.push_back(6);
    queue_3.push_back(1);
    
    queue_4.push_back(8);
    queue_4.push_back(2);
    queue_4.push_back(6);
    queue_4.push_back(1);
    
    //array initialization
    $display("-======= reverse =======-");
    $display("Before:\t %p",queue_1);
    queue_1.reverse();
    $display("After :\t %p",queue_1);
    $display("-=======================-");    

    $display("\n-=======   sort   =======-");
    $display("Before:\t %p",queue_2);
    queue_2.sort();
    $display("After :\t %p",queue_2);
    $display("-=======================-"); 
    
    $display("\n-=======   rsort  =======-");
    $display("Before:\t %p",queue_3);    
    queue_3.rsort();
    $display("After :\t %p",queue_3);
    $display("-=======================-");
    
    $display("\n-======= shuffle =======-");
    $display("Before:\t %p",queue_4);
    queue_4.shuffle();
    $display("After :\t %p",queue_4);
    $display("-=======================-");  
    
  end
endmodule

Simulator Output

-======= reverse =======-
Before: '{8, 2, 6, 1}
After : '{1, 6, 2, 8}
-=======================-
-======= sort =======-
Before: '{8, 2, 6, 1}
After : '{1, 2, 6, 8}
-=======================-
-======= rsort =======-
Before: '{8, 2, 6, 1}
After : '{8, 6, 2, 1}
-=======================-
-======= shuffle =======-
Before: '{8, 2, 6, 1}
After : '{6, 1, 2, 8}
-=======================-

Click to execute on   

Array Ordering methods ‘SORT’ Associative Array using ‘with’ clause

In the below example, Objects of type packet are stored in an associative array. elements of an array can be sorted for particular type on using sort along with ‘with‘ clause.

On sort method, an item with the lower value of ‘a’ will move into a lower index position of the array, the same will be repeated for all the array elements.

class packet;
  int a;
  int b;
  
  function void display();
    $display("\tValue of a = %0d",a);
    $display("\tValue of b = %0d",b);
  endfunction
endclass


module assoc_array;
  //declaration of array’s
  packet array_1[*];

  packet pkt;
  
  initial begin
    
    pkt = new();
    pkt.a = 8;
    pkt.b = 3;
    array_1[3] = pkt;
    
    pkt = new();
    pkt.a = 0;
    pkt.b = 6;
    array_1[7] = pkt;
    
    pkt = new();
    pkt.a = 2;
    pkt.b = 1;
    array_1[9] = pkt;

    $display("-======= sort =======-");
    $display("Before:");
    foreach(array_1[i]) begin //{
      $display("array_1[%0d]:",i);
      array_1[i].display();
    end //}
    
    array_1.sort with (item.a);
    
    $display("\nAfter:");
    foreach(array_1[i]) begin //{
      $display("array_1[%0d]:",i);
      array_1[i].display();
    end //}
    $display("-=======================-");        
  end
  
endmodule 

Simulator Output

-======= sort =======-
Before:
array_1[3]:
 Value of a = 8
 Value of b = 3
array_1[7]:
 Value of a = 0
 Value of b = 6
array_1[9]:
 Value of a = 2
 Value of b = 1

After:
array_1[3]:
 Value of a = 0
 Value of b = 6
array_1[7]:
 Value of a = 2
 Value of b = 1
array_1[9]:
 Value of a = 8
 Value of b = 3
-=======================-

Description: 
As explained above, on calling sort method. items are sorted w.r.t value of 'a' and stored in 
different index location. item with a=0 stored to index 3,
a=2 to next index 7 and a=8 to next index 9 

Click to execute on   

Array Ordering methods ‘RSORT’ Associative Array using ‘with’ clause

class packet;
  int a;
  int b;
  
  function void display();
    $display("\tValue of a = %0d",a);
    $display("\tValue of b = %0d",b);
  endfunction
endclass


module assoc_array;
  //declaration of array’s
  packet array_1[*];

  packet pkt;
  
  initial begin
    
    pkt = new();
    pkt.a = 8;
    pkt.b = 3;
    array_1[3] = pkt;
    
    pkt = new();
    pkt.a = 0;
    pkt.b = 6;
    array_1[7] = pkt;
    
    pkt = new();
    pkt.a = 2;
    pkt.b = 1;
    array_1[9] = pkt;

    $display("-======= rsort =======-");
    $display("Before:");
    foreach(array_1[i]) begin //{
      $display("array_1[%0d]:",i);
      array_1[i].display();
    end //}
    
    array_1.rsort with (item.a);
    
    $display("\nAfter:");
    foreach(array_1[i]) begin //{
      $display("array_1[%0d]:",i);
      array_1[i].display();
    end //}
    $display("-=======================-");        
  end
  
endmodule 

Simulator Output

-======= rsort =======-
Before:
array_1[3]:
Value of a = 8
Value of b = 3
array_1[7]:
Value of a = 0
Value of b = 6
array_1[9]:
Value of a = 2
Value of b = 1

After:
array_1[3]:
Value of a = 8
Value of b = 3
array_1[7]:
Value of a = 2
Value of b = 1
array_1[9]:
Value of a = 0
Value of b = 6
-=======================-

Click to execute on   

❮ Previous Next ❯

SystemVerilog Program Block

Program Block

The Program construct provides a race-free interaction between the design and the testbench, all elements declared within the program block will get executed in the Reactive region. Non-blocking assignments within the module are scheduled in the active region, initial blocks within program blocks are scheduled in the Reactive region.

Statements within a program block (scheduled in the Reactive region) that are sensitive to changes in design signals declared in modules (scheduled in the active region), an active region is scheduled before the reactive region this avoids the race condition between testbench and design.

Program block syntax

program test(input clk, input [7:0] addr, output [7:0] wdata);
    ...
endprogram
 
    or
 
program test (interface mem_intf);
    ...
endprogram

Program block,

  • can be instantiated and ports can be connected the same as a module
  • can contain one or more initial blocks
  • cannot contain always blocks, modules, interfaces, or other programs
  • In the program block, variables can only be assigned using blocking assignments. Using non-blocking assignments within the program shall be an error

difference between module and program

In the examples below, find the difference between writing testbench with module block and program block.
In example-1 writing testbench with module block, because of race condition testbench gets the dut signal addr value as 0.

In example-2 writing testbench with program block, testbench gets the dut signal addr value as 1.

Therefore writing testbench with program block provides race-free interaction between the design and the testbench.

example-1 with module block

//-------------------------------------------------------------------------
//design code
//-------------------------------------------------------------------------
module design_ex(output bit [7:0] addr);
  initial begin
    addr <= 10;
  end   
endmodule

//-------------------------------------------------------------------------
//testbench
//-------------------------------------------------------------------------
module testbench(input bit [7:0] addr);
  initial begin
    $display("\t Addr = %0d",addr);
  end
endmodule

//-------------------------------------------------------------------------
//testbench top
//-------------------------------------------------------------------------
module tbench_top;
  wire [7:0] addr;

  //design instance
  design_ex dut(addr);

  //testbench instance
  testbench test(addr);
endmodule

Simulator Output

Addr = 0

Click to execute on   

example-2 with a program block

//-------------------------------------------------------------------------
//design code
//-------------------------------------------------------------------------
module design_ex(output bit [7:0] addr);
  initial begin
    addr <= 10;
  end   
endmodule

//-------------------------------------------------------------------------
//testbench
//-------------------------------------------------------------------------

program testbench(input bit [7:0] addr);
  initial begin
    $display("\t Addr = %0d",addr);
  end
endprogram

//-------------------------------------------------------------------------
//testbench top
//-------------------------------------------------------------------------
module tbench_top;
  wire [7:0] addr;

  //design instance
  design_ex dut(addr);
  //testbench instance
  testbench test(addr);
endmodule

Simulator Output

Addr = 10

Click to execute on   

❮ Previous Next ❯

SystemVerilog Random System Methods

Random System Functions

$urandom( )

The system function $urandom provides a mechanism for generating pseudorandom numbers. The function returns a new 32-bit random number each time it is called. The number shall be unsigned.

variable = $urandom(seed);

The seed is an optional argument that determines the sequence of random numbers generated. The seed can be an integral expression. for a particular seed, the same value will get generated.

bit [31:0] addr1;
bit [31:0] addr2;
bit [64:0] addr3;
bit [31:0] data;
addr1 = $urandom();
addr2 = $urandom(89);
addr3 = {$urandom(),$urandom()};
data  = $urandom * 6;

$random( )

$random() is same as $urandom() but it generates signed numbers.

$urandom_range( )

The $urandom_range() function returns an unsigned integer within a specified range.

$urandom_range( int unsigned maxval, int unsigned minval = 0 );addr1 = $urandom_range(30,20);
addr2 = $urandom_range(20);    //takes max value as '0'
addr3 = $urandom_range(20,30); //considers max value as '30' and min value as '20'

random system methods examples

In the example below,
Shows usage of $urandom and $urandom_range.

module system_funcations;
  bit [31:0] addr1;
  bit [31:0] addr2;
  bit [64:0] addr3;
  bit [31:0] data;
  initial begin
    addr1 = $urandom();
    addr2 = $urandom(89);
    addr3 = {$urandom(),$urandom()};
    data  = $urandom * 6;

    $display("addr1=%0d, addr2=%0d, addr3=%0d, data=%0d",addr1,addr2,addr3,data);
 
    addr1 = $urandom_range(30,20);
    addr2 = $urandom_range(20); //takes max value as '0'
    addr3 = $urandom_range(20,30); //considers max value as '30' and min value as '20'
    $display("addr1=%0d, addr2=%0d, addr3=%0d",addr1,addr2,addr3);
  end
endmodule

Simulator Output

addr1=303379748, addr2=2153631232, addr3=423959822444962108, data=546103870
addr1=27, addr2=6, addr3=25

Click to execute on   

❮ Previous Next ❯

SystemVerilog Event Examples

events examples

trigger and wait for an event at the same time

In the example below,
event triggering and waiting for the event trigger will happen at the same time.
wait(); the operator is used to detects the event triggering.

module events_ex;
  event ev_1; //declaring event ev_1

  initial begin
    fork
      //process-1, triggers the event
      begin
         $display($time,"\tTriggering The Event");
        ->ev_1;
      end
   
      //process-2, wait for the event to trigger
      begin
        $display($time,"\tWaiting for the Event to trigger");
        wait(ev_1.triggered);
        $display($time,"\tEvent triggered");
      end
    join
  end
endmodule

Simulator Output

0 Triggering The Event
0 Waiting for the Event to trigger
0 Event triggered

Click to execute on   

trigger and wait for an event at the same time

In the example below,
event triggering and waiting for the event trigger will happen at the same time.@() operator is used to detecting the event trigger. but as triggering and waiting happens at the same time, @() operator will not detect the event. this can be solved by using wait() operator;

module events_ex;
  event ev_1; //declaring event ev_1

  initial begin
    fork
      //process-1, triggers the event
      begin
         $display($time,"\tTriggering The Event");
        ->ev_1;
      end
    
      //process-2, wait for the event to trigger
      begin
        $display($time,"\tWaiting for the Event to trigger");
        @(ev_1.triggered);
        $display($time,"\tEvent triggered");
      end
    join
  endendmodule

Simulator Output

0 Triggering The Event
0 Waiting for the Event to trigger

Click to execute on   

wait_order example

In the example below,
There are three events ev_1, ev_2 and ev_3. the wait_order(); is used to see to the order in which the events are triggered.

module events_ex;
  event ev_1; //declaring event ev_1
  event ev_2; //declaring event ev_2
  event ev_3; //declaring event ev_3
 
  initial begin
    fork
      //process-1, triggers the event ev_1
      begin
        #6;
        $display($time,"\tTriggering The Event ev_1");
        ->ev_1;
      end
      //process-2, triggers the event ev_2
      begin
        #2;
        $display($time,"\tTriggering The Event ev_2");
        ->ev_2;
      end
      //process-3, triggers the event ev_3
      begin
        #8;
        $display($time,"\tTriggering The Event ev_3");
        ->ev_3;
      end
      //process-4, wait for the events to trigger in order of ev_2,ev_1 and ev_3
      begin
        $display($time,"\tWaiting for the Event's to trigger");
        wait_order(ev_2,ev_1,ev_3)
          $display($time,"\tEvent's triggered Inorder");
        else
          $display($time,"\tEvent's triggered Out-Of-Order");
      end
    join
  end
endmodule

Simulator Output

0 Waiting for the Event's to trigger
2 Triggering The Event ev_2
6 Triggering The Event ev_1
8 Triggering The Event ev_3
8 Event's triggered Inorder

Click to execute on   

wait_order example

In the example below,
There are three events ev_1, ev_2 and ev_3. the wait_order(); is used to see to the order in which the events are triggered.

But events are triggered in out of order, leads to execution of else part of wait_order().

module events_ex;
  event ev_1; //declaring event ev_1
  event ev_2; //declaring event ev_2
  event ev_3; //declaring event ev_3

  initial begin
    fork
      //process-1, triggers the event ev_1
      begin
        #6;
        $display($time,"\tTriggering The Event ev_1");
        ->ev_1;
      end

      //process-2, triggers the event ev_2
      begin
        #2;
        $display($time,"\tTriggering The Event ev_2");
        ->ev_2;
      end

      //process-3, triggers the event ev_3
      begin
        #1;
        $display($time,"\tTriggering The Event ev_3");
        ->ev_3;
      end
      //process-4, wait for the events to trigger in order of ev_2,ev_1 and ev_3
      begin
        $display($time,"\tWaiting for the Event's to trigger");
        wait_order(ev_2,ev_1,ev_3)
          $display($time,"\tEvent's triggered Inorder");
        else
          $display($time,"\tEvent's triggered Out-Of-Order");
      end
    join
  end
endmodule

Simulator Output

0 Waiting for the Event's to trigger
1 Triggering The Event ev_3
1 Event's triggered Out-Of-Order
2 Triggering The Event ev_2
6 Triggering The Event ev_1

Click to execute on   

❮ Previous Next ❯

SystemVerilog Events

SystemVerilog Events

Events are static objects useful for synchronization between the process. Events operations are of two staged processes in which one process will trigger the event, and the other processes will wait for an event to be triggered.

  • Events are triggered using -> operator or ->> operator
  • wait for an event to be triggered using @ operator or wait() construct

SystemVerilog events act as handles to synchronization queues. thus, they can be passed as arguments to tasks, and they can be assigned to one another or compared.

Event triggering

 -> operator

Named events are triggered via the -> operator. Triggering an event unblocks all processes currently waiting on that event.

 ->> operator

Non-blocking events are triggered using the ->> operator.

Waiting for event trigger

@ operator

wait for an event to be triggered is via the event control operator, @.

@(event_name.triggered);
  • The @ operator blocks the calling process until the given event is triggered.
  • For a trigger to unblock a process waiting on an event, the waiting process must execute the @ statement before the triggering process executes the trigger operator, ->

Note:  If the trigger executes first, then the waiting process remains blocked.

wait operator

If the event triggering and waiting for event trigger with @ operator happens at the same time, @ operator may miss detecting the event trigger.

Whereas wait(); construct will detect the event triggering.

wait(event_name.triggered);

wait_order();

The wait_order construct is blocking the process until all of the specified events are triggered in the given order (left to right). event trigger with out of order will not unblock the process.

Example:

wait_order(a,b,c);

Blocks the process until events a, b, and c trigger in the order a –> b –> c. If the events trigger out of order, a run-time error is generated.

Example:

wait_order( a, b, c ) else $display( "Error: events out of order" );

In this example, the fail statement specifies that upon failure of the construct, a user message is displayed, but without an error being generated.

Example:

bit success;
wait_order( a, b, c ) success = 1; else success = 0;

In this example, the completion status is stored in the variable success, without an error being generated.

Merging events

When one event variable is assigned to another, the two become merged. Thus, executing -> on either event variable affects processes waiting on either event variable.

Event examples

the event waiting with @ operator

The below example shows the event triggering and waiting for the event trigger.

module events_ex;
  event ev_1; //declaring event ev_1

  initial begin
    fork
      //process-1, triggers the event
      begin
        #40;
        $display($time,"\tTriggering The Event");
        ->ev_1;
      end
    
      //process-2, wait for the event to trigger
      begin
        $display($time,"\tWaiting for the Event to trigger");
        @(ev_1.triggered);
        $display($time,"\tEvent triggered");
      end
    join
  end
endmodule

Simulator Output

0 Waiting for the Event to trigger
40 Triggering The Event
40 Event triggered

Click to execute on   

trigger first and then waiting for a trigger

In the below example,
event triggering happens first and then the waiting for trigger happens. As the waiting happens later, it will be blocking, so the statements after the wait for the trigger will not be executed.

module events_ex;

  event ev_1; //declaring event ev_1

  initial begin
    fork
      //process-1, triggers the event
      begin
        #40;
        $display($time,"\tTriggering The Event");
        ->ev_1;
      end
    
      //process-2, wait for the event to trigger
      begin
        $display($time,"\tWaiting for the Event to trigger");
        #60;
        @(ev_1.triggered);
        $display($time,"\tEvent triggered");
      end
    join
  end
  initial begin
    #100;
    $display($time,"\tEnding the Simulation");
    $finish;
  end
endmodule

Simulator Output

0  Waiting for the Event to trigger
40  Triggering The Event
100 Ending the Simulation

Click to execute on   

event examples are continued in the next page

❮ Previous Next ❯

SystemVerilog Mailbox

SystemVerilog Mailbox

A mailbox is a communication mechanism that allows messages to be exchanged between processes. The process which wants to talk to another process posts the message to a mailbox, which stores the messages temporarily in a system defined memory object, to pass it to the desired process.

Based on the sizes mailboxes are categorized as,

  • bounded mailbox
  • unbounded mailbox

A bounded mailbox is with the size defined. mailbox becomes full when on storing a bounded number of messages. A process that attempts to place a message into a full mailbox shall be suspended until enough space becomes available in the mailbox queue.

Unbounded mailboxes are with unlimited size.

Mailbox types

There are two types of mailboxes,

  • Generic Mailbox
  • Parameterized mailbox

Generic Mailbox (type-less mailbox)

The default mailbox is type-less. that is, a single mailbox can send and receive data of any type.

mailbox mailbox_name;

Parameterized mailbox (mailbox with particular type)

Parameterized mailbox is used to transfer a data of particular type.

mailbox#(type) mailbox_name;

Mailbox Methods

SystemVerilog Mailbox is a built-in class that provides the following methods. these are applicable for both Generic and Parameterized mailboxes

new();           - Create a mailbox
put();           - Place a message in a mailbox
try_put();       - Try to place a message in a mailbox without blocking
get(); or peek();- Retrieve a message from a mailbox
num();           - Returns the number of messages in the mailbox
try_get(); or try_peek();  - Try to retrieve a message from a mailbox without blocking

new( );

Mailboxes are created with the new() method.

mailbox_name = new();        // Creates unbounded mailbox and returns mailbox handle

mailbox_name = new(m_size);  //Creates bounded mailbox with size m_size and returns mailbox handle ,where m_size is integer  variable

SystemVerilog Mailbox example

In the example below,
Mailbox is used for communication between generator and driver.

  • Process-1(Generator class) will generate (created and randomize) the packet and put into the mailbox mb_box
  • Process-2(Driver class) gets the generated packet from the mailbox and display the fields
//-------------------------------------------------------------------------
// Packet 
//-------------------------------------------------------------------------
class packet;
  rand bit [7:0] addr;
  rand bit [7:0] data;

  //Displaying randomized values
  function void post_randomize();
    $display("Packet::Packet Generated");
    $display("Packet::Addr=%0d,Data=%0d",addr,data);
  endfunction
endclass

//-------------------------------------------------------------------------
//Generator - Generates the transaction packet and send to driver
//-------------------------------------------------------------------------
class generator;
  packet pkt;
  mailbox m_box;
  //constructor, getting mailbox handle
  function new(mailbox m_box);
    this.m_box = m_box;
  endfunction
  task run;
    repeat(2) begin
      pkt = new();
      pkt.randomize(); //generating packet
      m_box.put(pkt);  //putting packet into mailbox
      $display("Generator::Packet Put into Mailbox");
      #5;
    end
  endtask
endclass

//-------------------------------------------------------------------------
// Driver - Gets the packet from generator and display's the packet items
//-------------------------------------------------------------------------
class driver;
  packet pkt;
  mailbox m_box;

  //constructor, getting mailbox handle
  function new(mailbox m_box);
    this.m_box = m_box;
  endfunction

  task run;
    repeat(2) begin
      m_box.get(pkt); //getting packet from mailbox
      $display("Driver::Packet Recived");
      $display("Driver::Addr=%0d,Data=%0d\n",pkt.addr,pkt.data);
    end
  endtask
endclass

//-------------------------------------------------------------------------
//     tbench_top  
//-------------------------------------------------------------------------
module mailbox_ex;
  generator gen;
  driver    dri;
  mailbox m_box; //declaring mailbox m_box

  initial begin
    //Creating the mailbox, Passing the same handle to generator and driver, 
    //because same mailbox should be shared in-order to communicate.
    m_box = new(); //creating mailbox

    gen = new(m_box); //creating generator and passing mailbox handle
    dri = new(m_box); //creating driver and passing mailbox handle
    $display("------------------------------------------");
    fork
      gen.run(); //Process-1
      dri.run(); //Process-2
    join
    $display("------------------------------------------");
  end
endmodule

Simulator Output

------------------------------------------
Packet::Packet Generated
Packet::Addr=3,Data=38
Generator::Packet Put into Mailbox
Driver::Packet Recived
Driver::Addr=3,Data=38

Packet::Packet Generated
Packet::Addr=118,Data=92
Generator::Packet Put into Mailbox
Driver::Packet Recived
Driver::Addr=118,Data=92
------------------------------------------

Click to execute on   

❮ Previous Next ❯

SystemVerilog Semaphore example

Semaphore Examples

Semaphore access with 2 keys

In the example below,
Creating semaphore with ‘4’ keys. ‘2’ keys are required to get access to the method.

At the same time, two processes will get access to the method and the other process will be blocked until the one other process puts the key.

module semaphore_ex;
  semaphore sema; //declaring semaphore sema

  initial begin
    sema=new(4); //creating sema with '4' keys
    fork
      display(); //process-1
      display(); //process-2
      display(); //process-3
    join
  end

  //display method
  task automatic display();
    sema.get(2); //getting '2' keys from sema
    $display($time,"\tCurrent Simulation Time");
    #30;
    sema.put(2); //putting '2' keys to sema
  endtask
endmodule

Simulator Output

0 Current Simulation Time
0 Current Simulation Time
30 Current Simulation Time

Click to execute on   

Putting back more keys

In the example below,
Creating semaphore with ‘1’ key, putting more number of keys back to the semaphore.

module semaphore_ex;
  semaphore sema; //declaring semaphore sema

  initial begin
    sema=new(1); //creating sema with '1' keys
    fork
      display(1); //process-1
      display(2); //process-2
      display(3); //process-3
    join
  end

  //display method
  task automatic display(int key);
    sema.get(key); //getting 'key' number of keys from sema
    $display($time,"\tCurrent Simulation Time, Got %0d keys",key);
    #30;
    sema.put(key+1); //putting 'key' number of keys to sema
  endtask
endmodule

Simulator Output

0 Current Simulation Time, Got 1 keys
30 Current Simulation Time, Got 2 keys
60 Current Simulation Time, Got 3 keys

Click to execute on   

the process with more than 1 key

In the example below, Creating a semaphore with the ‘4’ keys, the method will be blocked until it gets enough keys.

module semaphore_ex;
  semaphore sema; //declaring semaphore sema

  initial begin
    sema=new(4); //creating sema with '4' keys
    fork
      display(2); //process-1
      display(3); //process-2
      display(2); //process-3
      display(1); //process-4
    join
  end

  //display method
  task automatic display(int key);
    sema.get(key); //getting 'key' number of keys from sema
    $display($time,"\tCurrent Simulation Time, Got %0d keys",key);
    #30;
    sema.put(key); //putting 'key' number of keys to sema
  endtask
endmodule

Simulator Output

0 Current Simulation Time, Got 2 keys
0 Current Simulation Time, Got 2 keys
30 Current Simulation Time, Got 1 keys
30 Current Simulation Time, Got 3 keys

Click to execute on   

using try_get

In the example below,
Creating semaphore with ‘4’ key, try_get() will check for the keys if the keys are not available simulation will proceed(non-blocking).

module semaphore_ex;
  semaphore sema; //declaring semaphore sema

  initial begin
    sema=new(4); //creating sema with '4' keys
    fork
      display(4); //process-1
      display(4); //process-2
    join
  end

  //display method
  task automatic display(int key);
    sema.try_get(key); //getting 'key' number of keys from sema
    $display($time,"\tCurrent Simulation Time, Got %0d keys",key);
    #30;
    sema.put(key); //putting 'key' number of keys to sema
  endtask
endmodule

Simulator Output

0 Current Simulation Time, Got 4 keys
0 Current Simulation Time, Got 4 keys

Click to execute on   

❮ Previous Next ❯

SystemVerilog Semaphore

Semaphore

Semaphore is a SystemVerilog built-in class, used for access control to shared resources, and for basic synchronization.

A semaphore is like a bucket with the number of keys. processes using semaphores must first procure a key from the bucket before they can continue to execute, All other processes must wait until a sufficient number of keys are returned to the bucket.

Imagine a situation where two processes try to access a shared memory area. where one process tries to write and the other process is trying to read the same memory location. this leads to an unexpected result. A semaphore can be used to overcome this situation.

Semaphore syntax

semaphore semaphore_name;

Semaphore methods

Semaphore is a built-in class that provides the following methods,

  • new(); Create a semaphore with a specified number of keys
  • get();   Obtain one or more keys from the bucket
  • put();   Return one or more keys into the bucket
  • try_get(); Try to obtain one or more keys without blocking

new( );

The new() method is used to create the Semaphore.

semaphore_name = new(numbers_of_keys);
  • the new method will create the semaphore with number_of_keys keys in a bucket; where number_of_keys is integer variable.
  • the default number of keys is ‘0’
  • the new() method will return the semaphore handle or null if the semaphore cannot be created

put( );

The semaphore put() method is used to return key/keys to a semaphore.

semaphore_name.put(number_of_keys); or semaphore_name.put();

When the semaphore_name.put() method is called, the specified number of keys are returned to the semaphore. The default number of keys returned is 1.

get( );

The semaphore get() method is used to get key/keys from a semaphore.

semaphore_name.get(number_of_keys); or semaphore_name.get();

When the semaphore_name.get() method is called,

  • If the specified number of keys are available, then the method returns and execution continues
  • If the specified number of keys are not available, then the process blocks until the keys become available
  • The default number of keys requested is 1

try_get();

The semaphore try_get() method is used to procure a specified number of keys from a semaphore, but without blocking.

semaphore_name.try_get(number_of_keys); or semaphore_name.try_get();

When the semaphore_name.try_get() method is called,

  • If the specified number of keys are available, the method returns 1 and execution continues
  • If the specified number of keys are not available, the method returns 0 and execution continues
  • The default number of keys requested is 1

Semaphore examples

two processes accessing the same resource

In the example below,
semaphore sema is created with the 1 key, two processes are accessing the display method at the same time, but only one process will get the semaphore key and the other process will wait till it gets the key.

module semaphore_ex;
  semaphore sema; //declaring semaphore sema
  initial begin
    sema=new(1); //creating sema with '1' key
    fork
      display(); //process-1
      display(); //process-2
    join
  end

  //display method
  task automatic display();
    sema.get(); //getting '1' key from sema
    $display($time,"\tCurrent Simulation Time");
    #30;
    sema.put(); //putting '1' key to sema
  endtask
endmodule

Simulator Output

0 Current Simulation Time
30 Current Simulation Time

Click to execute on   

Semaphore with 4 keys

In the example below,
Creating semaphore with ‘4’ keys.

module semaphore_ex;
  semaphore sema; //declaring semaphore sema
  initial begin
    sema=new(4); //creating sema with '4' keys
    fork
      display(); //process-1
      display(); //process-2
    join
  end
  //display method
  task automatic display();
    sema.get(4); //getting '4' keys from sema
    $display($time,"\tCurent Simulation Time");
    #30;
    sema.put(4); //putting '4' keys to sema
  endtask
endmodule

Simulator Output

0 Current Simulation Time
30 Current Simulation Time

Click to execute on   

Semaphore examples are continued in next page
❮ Previous Next ❯