0% found this document useful (0 votes)
28 views

system verilog

Uploaded by

DevikaRani
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
28 views

system verilog

Uploaded by

DevikaRani
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 425

Semi Design

1
Semi Design

What is mean by Verification?


Verification is done before silicon development. It is done at time of product
development for quality checking and bug fixing in design.
There are different type of verification, like
• IP verification
• RTL verification
• Timing verification etc.
Many people used SOC verification name in broader term.
Example:
If we have a counter design in verilog, We can simulate the verilog file and verify if
the sequence is correct. This is functionality check.

2
Semi Design

What is the purpose of Verification?


A primary purpose for functional verification is to detect failures so that bugs can be
identified and corrected before it gets shipped to costumer.
If RTL designer makes a mistake in designing or coding, this results as a bug in the
Chip.
If this bug is executed, in certain situations the system will produce wrong results,
causing a failure.
Sometimes miscommunications between teams may lead to wrong design.
So Design verification is needed before manufacturing the IC.

3
Semi Design

How to Verify the Design?


1. Consider a Design.

Design
(DUT)

2. Need to compare the received DUT output with reference values

DUT
Apply input Get the
(Design
stimulus output
Under Test)
4
Semi Design
3. DUT output will be compared with reference model output.
equal
Reference Compare
inputs = = outputs

DUT
(Design
Under Test)

4. Compare the DUT output with expected result, If there are equal the
design is bug free.

5
Semi Design

Not equal
Referenc Compare
e inputs != outputs

DUT
(Design
Under Test)

5. If there are not equal the design is failed.

6. If there is a failure, need to fix the issue and re-verify the Design

6
Semi Design
Semi Design

Linear Test bench


Linear Testbench is the simplest, fastest and easiest way of writing testbenchs. It
is also slowest way to execute stimulus. Typically, linear testbenchs are written in
the VHDL or Verilog. In this Testbench, simple linear sequence of test vectors is
mentioned.
Typically, linear testbenchs perform the following tasks:

• Instantiate the design under test (DUT)


• Stimulate the DUT by applying test vectors.
• Output results waveform window or to a terminal for visual inspection manually.

8
Semi Design
Example : Linear Testbench

// Example Design // testbench using hardcoded values


module example(a,b,c); module test();
input [2:0] a; reg [15:0] a;
input [2:0] b; reg [15:0] b;
output [3:0] c; wire [16:0] c;

assign c = a * b; example DUT(a,b,c);

endmodule initial begin


a = 16'h45;
To test all possible scenarios which b = 16'h12;
are known to us, it is not an easy #10
task. Development time increases $display("a=%0d,b=%0d,c=%0d",a,b
exponentially as the number of ,c);
scenarios. Instead of listing out all end
the possible scenarios, pickup some endmodule
9
randomly and check the DUT.
Semi Design

Random Test bench


// Random test bench
module top(); Random TestBench don't use Hardcoded
reg [15:0] a; values like linear testbenchs. Input
reg [15:0] b; stimulus is generated using random values.
wire [16:0] c; In Verilog, system function $random
provides a mechanism for generating
adder DUT(a,b,c); random numbers.
The main disadvantage of this testing is
repeat(100) that we never know what random values
begin a = $random; are generated and it may waste simulation
b = $random; cycles by generating same values again
#10 $ and again.
$display(" a=%0d,b=%0d,c=%0d",a,b,c); 10
end endmodule
Semi Design
Semi Design

Evolution of System Verilog


• System Verilog is an extension of Verilog.
• Gateway Design Automation introduced Verilog as an evolutionary HDL in 1985.

The current version is the IEEE standard 1800-2017.

SystemVerilog can be divided into two distinct based on its roles


- SystemVerilog for design is an extension of Verilog-2005
- SystemVerilog for verification

12
Semi Design

System Verilog for Verification


Testbench or Verification Environment is used to check the functional
correctness of the Design Under Test (DUT) by generating and driving a
predefined input sequence to a design, capturing the design output and
comparing with-respect-to expected output.
The verification environment can be written by using SystemVerilog
concepts.

System Verilog Testbench:


TestBench or Verification environment is a group of classes or components.
where each component is performing a specific operation. i.e, generating
stimulus, driving, monitoring, etc. and those classes will be named based on
the operation. 13
Semi Design

System Verilog Architecture


Testbench_Top
Test
env

interface
generator driver DUT
transaction

Scoreboard monitor
transaction
14
Semi Design
Semi Design

System Verilog Data types


SystemVerilog extends Verilog by introducing C like data types.
SystemVerilog adds a new 2-state data types that can only have bits with 0 or 1
values unlike verilog 4-state data types which can have 0, 1, X and Z.
SystemVerilog also allows user to define new data types.
Then a 4-state value is automatically converted to a 2-state value, X and Z will
be converted to zeros.
Different Data types in System verilog are :
1. Signed and Unsigned Data types
2. Strings
3. User defined
4. Enumerations
5. Structures and unions
6. Typedef 16
7. Reg and Logic
Semi Design

Signed and Unsigned Data types

Shortint - 16bits
int - 32bits
Signed Data types longint - 64bits
byte - 8bits
integer - 32bits
bit - User defined size
logic - Identical to reg
Unsigned Data types Reg - User defined size
time - 64bit

17
Semi Design

String Data type


SystemVerilog adds new keyword "string" which is used to declare string data types
unlike verilog. String data types can be of arbitrary length and no truncation occurs.

// Syntax for string data type


string myName = "TEST BENCH";

String Methods:
str.len() It returns the length of the string, i.e., the number of characters
in the string.
str.putc(i, c) It replaces the ith character in str with the given integral value.
str.getc(i) It returns the ASCII code of the ith character in str.
18
str.toupper() returns a string with characters in str converted to uppercase.
Semi Design
str.tolower() It returns a string with characters in str converted to lowercase.
str.compare(s) It compares str and s, and return value. This comparison is case
sensitive.
str.icompare(s) It compares str and s, and return value .This comparison is case
insensitive.
str.substr(i, j) It returns a new string that is a substring formed by index i
through j of str.
str.atoi() It returns the integer corresponding to the ASCII decimal
representation in str.
str.atoreal() It returns the real number corresponding to the ASCII decimal
representation in str.
str.itoa(i) It stores the ASCII decimal representation of i into str (inverse
of atoi).
str.hextoa(i) It stores the ASCII hexadecimal representation of i into str 19
(inverse of atohex).
Semi Design
// Example using String methods
module str_method;
string X;
string Y;
// Simulation results:
initial begin
4
X = "TEST ";
h
Y = "Bench";
test
$display(" %d ",X.len() );
BENCH
$display(" %s ",Y.getc(4) );
-18
$display(" %s ",X.tolower);
-32
$display(" %s ",Y.toupper);
ST
$display(" %d ",Y.compare(X) );
$display(" %d ",X.compare("test") );
$display(" %s ",X.substr(2,3) );
end
endmodule

20
Semi Design

String Operators
SystemVerilog provides a set of operators that can be used to manipulate
combinations of string variables and string literals.
1. Equality Operator:

Checks whether the two strings are equal. Result is 1 if they are equal
and 0 if they are not.

// Syntax for String Equality


String1 == String2

21
Semi Design

// Example program using string equality


operator
program main;
initial begin
string a, b, c;
a = “SYSTEM VERILOG";
b = “SYSTEM VERILOG";
c = “system verilog";
// Simulation results:
if(a == b)
a and b are equal
$display(" a and b are equal");
a and c are not equal
else
$display(" a and b are not equal");
if(a == c)
$display(" a and c are equal");
else
$display(" a and c are not equal");
end
22
endprogram
Semi Design
2. Inequality Operator:
// Example program using string
// Syntax for String Inequality inequality operator
String1 != String2 program main;
initial begin
string a, b, c;
a = “SYSTEM VERILOG";
b = “SYSTEM VERILOG";
// Simulation results: c = “system verilog";
a and b are equal if(a != b)
a and c are not equal $display(" a and b are not equal");
else
$display(" a and b are equal");
if(a != c)
$display(" a and c are not equal");
else
$display(" a and c are equal");
end
23
endprogram
Semi Design
3. Comparison:
// Example program using string equality
operator
// Syntax for String Comparision
program main;
String1 < String2
initial begin
String1 <= String2
string x, y, z;
String1 > String2
x = "c";
String1 >= String2
y = "d";
z = "e";
if(x < y)
// Simulation results: $display(" x < y ");
x<y if(x <= y)
x <= y $display(" x <= y ");
z>y if(z > y)
z >= y $display(" z > y");
if(z >= y)
$display(" z >= y");
end
24
endprogram
Semi Design
4. Concatenation:
// Example program using string
// Syntax for String Comparison Concatenation operator
{String1, String2, String3..} program main;
initial begin
string a, b, c, d, e;
a = "WWW.";
// Simulation results: b = “SEMI";
c = "";
WWW. SEMIDESIGN.IN d = “DESIGN";
e= ".IN";

$display(" %s ",{a, b, c, d, e});

end
endprogram

25
Semi Design
5. Replication:

// Example program using string


// Syntax for String Comparison Replication operator
multiplier{String}
program main;
initial begin
string a, b;
// Simulation results: a = "W";
b = ".SEMI DESIGN.IN”;
WWW. SEMI DESIGN.IN
$display(" %s ",{{3{a}},b});

end
endprogram

26
Semi Design

User Defined Data types


Systemverilog allows the user to define datatypes. There are different ways to
define user defined datatypes. They are

1. Class.
2. Enumarations.
3. Struct.
4. Union.
5. Typedef.

27
Semi Design

Enumaration Data type


Enumerated data types assign a symbolic name to each legal value taken by the data
type.

// Syntax for enum datatype


enum {state1, state2, state3…} states;

Default state assignment : state1 = 0, state2 = 1, state3 = 2.

enum {a=4, b=6, c} value; // c is automatically assigned the increment-value of 7

enum {a=0, b=5, c, d=6} alphabet; // Syntax error: c and d are both assigned 6

enum {a, b=7, c} alphabet; // a=0, b=7, c=8


28
Semi Design

Enumarated Methods:

first() method returns the value of the first member of the


enumeration.
last() method returns the value of the last member of the
enumeration.
next() method returns the Nth next enumeration value (default is the
next one) starting from the current value of the given variable.
prev() method returns the Nth previous enumeration value (default is
the previous one) starting from the current value of the given
variable.

29
Semi Design
// Example code for enum methods
module enum_method;
typedef enum {red,blue,green} colour;
colour c;

initial
begin // Simulation results:
c = c.first(); red
$display(" %s ",c.name); Blue
c = c.next(); green
$display(" %s ",c.name); blue
c = c.last();
$display(" %s ",c.name);
c = c.prev();
$display(" %s ",c.name);
end

endmodule 30
Semi Design

Structure data type


Structure is a method of packing data of different types. A structure is a
convenient method of handling a group of related data items of different data
types.
// Example code using Struct data type
The keyword "struct" declares a struct {
structure to holds the details of four int a;
fields namely a,b and c. These are byte b;
members of the structures. Each bit [7:0] c;
member may belong to different or } my_data_struct;
same data type. The structured
variables can be accessed using the my_data_struct.a = 123;
variable name "my_data_struct". $display(" a value is %d ",my_data_struct.a);

// Simulation results: 31
a value is 123
Semi Design

Union Data type


That is a Union offers a way for a section of memory to be treated as a variable of
one type on one occasion and as a different variable of a different type on another
occasion.

// Example code using Union data type


union {
int a;
byte b; // Simulation results:
bit [7:0] c; a value is 321
} my_data;

my_data.a = 321;
$display(" a value is %d ",my_data.a); 32
Semi Design

Memory allocation for Struct and Union

Memory allocation for the above defined struct "my_data_struct".


0………7……….15………..23…………..31

Bit [0:7] c XXXXXXXXXX

Byte b XXXXXXXXXX
Integer a

Memory allocation for the above defined union "my_data_union".

0………7……….15………..23…………..31

Bit [0:7] c / Byte b / Integer a


33
Semi Design

Typedef Data type


A typedef declaration lets you define your own identifiers that can be used in
place of type specifiers such as int, byte, real.

// example for typedef data type

typedef bit[3:0] nibble;


nibble a, b;

34
Semi Design

Logic Data type


SystemVerilog extended the variable type so that, it can be used to connect gates
and modules. All variables can be written either by one continuous assignment,
or by one or more procedural statements. It shall be an error to have multiple
continuous assignments or a mixture of procedural and continuous assignments.

Now we saw logic and wire are closer. Wire (net) is used when driven by
multiple drivers, where as logic is used when it is driven by only one driver.
logic just holds the last value assigned to it, while a wire resolves its value based
on all the drivers.

// Syntax for Logic data type

logic a; 35
Semi Design

// Example using logic data type


module logic_test();
parameter cycle = 20;
logic q, qn, d, clk, rst; Assigned in a procedural
block(always)
initial begin
clk = 0; // procedural assignment
rst = 0;
forever # (cycle/2) clk = ~ clk;
@ (negedge clk)
rst = ‘1; Assigned in a continuous
end assignment (assign)

assign qn = ~ q; // continuos assignment

dff DUT(q, d, clk, rst);


endmodule : logic_test
36
Semi Design
Semi Design

Arrays
Arrays are classified into :
1. Fixed-sized arrays (static arrays)
whose size cannot change once their declaration is done.

2. Dynamic arrays
which can be resized.

3. Associative arrays
Associative arrays give you another way to store information. When
the size of the collection is unknown or the data space is sparse, an
associative array is a better option. 38
Semi Design

Static Arrays
Fixed arrays are classified as:
1. Packed arrays
2. Unpacked arrays

1. Packed arrays:
"Packed array" to refer to the dimensions declared before the object name

reg [0:10] arr; // 1-dimensional packed array


wire [31:0] [1:0] arr; // 2-dimensional packed array

2. UnPacked arrays:
"unpacked array" refers to the dimensions declared after the object name. 39
Semi Design
wire arr [31:0]; // 1-dimensional Unpacked array
wire arr [32][4:0]; // 2-dimensional Unpacked array
integer arr [7:0][0:31][15:0]; // 3-dimensional unpacked array of integers
reg [31:0] arr1 [0:255]; // unpacked array of 256 registers each
reg [31:0] arr2 [256]; // register is packed 32 bit wide

bit arr[1:2][1:4][1:3] bit [1:3] arr [1:2][1:4] bit [1:3][1:4] arr [1:2]

Smallest unit of unpacked Smallest unit of unpacked Smallest unit of unpacked


element is 12 bit packed array
element is 1 bit element is 3 bit packed array 40
Semi Design

Dynamic Arrays
Verilog does not allow changing the dimensions of the array once it is declared.
Most of the time in verification, we need arrays whose size varies based on the
some behavior. For example Ethernet packet varies length from one packet to
other packet. In verilog, for creating Ethernet packet, array with Maximum packet
size is declared and only the number of elements which are require for small
packets are used and unused elements are waste of memory.
To overcome this deficiency, System Verilog provides Dynamic Array. A
dynamic array is unpacked array whose size can be set or changed at runtime
unlike verilog which needs size at compile time.

41
Semi Design
Declaration of Dynamic Array:

integer d_arr [ ];
integer multi_d_arr[ ][ ];

Memory allocation of Dynamic Array:

New[]:The built-in function new allocates the storage and initializes the
newly allocated array elements either to their default initial value.
0 1 2 3 4
integer d_arr = new [5];

Initializing of Dynamic Array:


0 1 2 3 4
integer d_arr = {4,3,2,1,0}; 4 3 2c 1 0
42
Semi Design
Resizing Dynamic Array:

d_arr = new[10]; //Increasing the size by overriding the old values

0 1 2 3 4 5 6 7 8 9

d_arr = new[10](d_arr); //previous 5 data preserved

0 1 2 3 4 5 6 7 8 9

4 3 2 1 0

Copying of Dynamic Array:

d_arr1 = new[10](d_arr); // allocating and copying 100 elements


d_arr = [100]; // previous data lost, 100 elements are allocated
43
Semi Design
Example for Dynamic array:

module dynamic_array();
integer arr[]; d_arr[ ]

initial
begin 8
arr = new[4]; // Simulation results:
$display(d_arr.size); 5 4
arr[1] = 8; 8
arr[3] = 5; 0
arr = new[8] (arr);
$display(d_arr.size);
d_arr.delete;
$display(d_arr.size);
end

endmodule 44
Semi Design

Associative Arrays
Dynamic arrays are useful for dealing with contiguous collections of
variables whose number changes dynamically. Associative arrays give you
another way to store information. When the size of the collection is
unknown or the data space is sparse, an associative array is a better option.
In Associative arrays Elements Not Allocated until Used. Index Can Be of
Any Packed Type, String or Class. Associative elements are stored in an
order that ensures fastest access.
In an associative array a key is associated with a value.

// Syntax for Associative array


data_type array_id [key_type];
-- data_type is the data type of the array elements.
-- array_id is the name of the array being declared. 45
-- key_type is the data-type to be used as an key.
Semi Design
Associative Array methods:

num() returns the number of entries in the associative array


delete() returns the number of entries in the associative array
exists() returns 1 if an element exists at the specified index else returns 0
first() assigns the value of first index to the variable var
last() assigns the value of last index to the variable var
next() assigns the value of next index to the variable var
prev() assigns the value of previous index to the variable var

46
Semi Design

module associative_array;
int a_array[*]; // array declaration
int i;
initial begin
repeat(3) begin
a_array[i] = i*2; //allocating array and assigning value to it
i=i+4;
end
//num() –Associative array method
$display("\tNumber of entries in a_array is %0d",a_array.num());
foreach(a_array[i])
$display("\ta_array[%0d] \t = %0d",i,a_array[i]);

a_array.first(i); //first()-Associative array method


$display("\First entry is \t a_array[%0d] = %0d",index,a_array[i);

a_array.last(i); //last()-Associative array method


47
$display("\Last entry is \t a_array[%0d] = %0d",index,a_array[i]);
Semi Design

if(a_array.exists(8)) //exists()-Associative array method


$display("Index 8 exists in a_array");
else
$display("Index 8 doesnt exists in a_array");

a_array.last(i); //last()-Associative array method


$display("Last entry is a_array[%0d] = %0d",index,a_array[i]);

a_array.prev(i); //prev()-Associative array method


$display("entry is a_array[%0d] = %0d",index,a_array[i]);

a_array.next(i); //next()-Associative array method


$display("entry is a_array[%0d] = %0d",index,a_array[i]);

end
endmodule
48
Semi Design

// Simulation results:
Number of entries in a_array is 3
a_array[0] = 0
a_array[4] = 8
a_array[8] = 16

First entry is a_array[0] = 0


Last entry is a_array[8] = 16

Index 8 exists in a_array


Last entry is a_array[8] = 16
entry is a_array[4] = 8
entry is a_array[8] = 16

49
Semi Design
Semi Design

Queues
A queue is a variable-size, ordered collection of homogeneous elements.
Queues can be used to model a last in, first out buffer or first in, first out buffer.
Queues support insertion and deletion of elements from random locations using an
index.
Queue Methods:
size() method returns the number of items in the queue. If the queue is
empty, it returns 0.
insert() method inserts the given item at the specified index position.
delete() method deletes the item at the specified index.
pop_front() method removes and returns the first element of the queue.
pop_back() method removes and returns the last element of the queue.
push_fornt() method inserts the given element at the front of the queue.
51
push_back() method inserts the given element at the end of the queue.
Semi Design

module queues;
byte qu [$] ;

initial begin
qu.push_front(2);
qu.push_front(12); // Simulation results:
qu.push_front(22); 5
qu.push_back(11); 22
qu.push_back(99); 99
$display(" %d ",qu.size() ); 3
$display(" %d ",qu.pop_front() ); 0
$display(" %d ",qu.pop_back() );
$display(" %d ",qu.size() );
qu.delete;
$display(" %d ",qu.size() );
end
endmodule 52
Semi Design
Semi Design

Casting
Verilog is loosely typed . Assignments can be done from one data type to other
data types based on predefined rules.The compiler only checks that the destination
variable and source expression are scalars. Otherwise, no type checking is done at
compile time. Systemverilog has complex data types than Verilog. It's necessary
for SystemVerilog to be much stricter about type conversions than Verilog, so
Systemverilog provided the cast(`) operator.

SystemVerilog adds 2 types of casting.

1. Static casting
2. Dynamic casting.

54
Semi Design

Static Casting
A data type can be changed by using a cast ( ` ) operation. In a static cast, the
expression to be cast shall be enclosed in parentheses that are prefixed with the
casting type and an apostrophe. If the expression is assignment compatible with the
casting type, then the cast shall return the value that a variable of the casting type
would hold after being assigned the expression.

//Syntax for Static casting


int`(34.2 * 3.22)
shortint`{{8’hCD, 8`hA3}};
signed`(x)

55
Semi Design

Dynamic Casting
SystemVerilog provides the $cast system task to assign values to variables that
might not ordinarily be valid because of differing data type. $cast can be called as
either a task or a function.

// Syntax for Dynamic casting


function int $cast( singular dest_var, singular source_exp );
task $cast( singular dest_var, singular source_exp );

56
Semi Design

typedef enum { PENNY=1, FIVECENTS=5, QUARTER=25, DOLLAR=100 } Cents;


module tb;
Cents myCent;

initial begin
$cast (myCent, 10 + 5 + 10);
$display ("Money = %s", myCent.name());
end
endmodule

// Simulation results:
Money = QUARTER

57
Semi Design
Semi Design

Program block Syntax


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.
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.

// Syntax for Program block


program test(input clk, input [7:0] addr, output [7:0] wdata);
...
endprogram
59
Semi Design
Program Block:

• Can be instantiated and ports can be connected the same as a module


• Can contain one or more initial block.
• Cannot contain always blocks, modules, interfaces, or other programs
• In the program block, variables can only be assigned using blocking
assignments.
Difference between module block and program block

In the examples below, find the difference between writing testbench


with module block and program block.
Example-1
writing testbench with module block, because of race condition testbench
gets the dut signal ‘A’ value as 0.
Example-2
writing testbench with program block, testbench gets the dut signal ‘A’
value as 1.
Therefore writing testbench with program block provides race-free 60
interaction between the design and the testbench.
Semi Design
module DUT();
reg A = 0;
reg clk = 0;
initial #10
clk = 1;
always @(posedge clk)
A <= 1; // Simulation results:
endmodule Module_based_TB : A = 0
program_based_TB : A = 1
module mod__TB();
always @ (posedge DUT.clk)
$display("Module_based_TB : A = %b\n", DUT.A);
endmodule

program Pro_TB();
initial
forever @(posedge DUT.clk)
$display("Program_based_TB : A = %b\n", DUT.A); 61
endprogram
Semi Design
Semi Design

Fork Join
A Verilog fork...join block always causes the process executing the fork
statement to block until the termination of all forked processes. With the addition
of the join_any and join_none keywords, SystemVerilog provides three choices
for specifying when the parent (forking) process resumes execution.

1. Fork Join None


2. Fork Join Any
3. Fork join All

63
Semi Design
fork fork fork

--- --- --- --- --- --- --- --- ---


--- --- --- --- --- --- --- --- ---
--- --- --- --- --- --- --- --- ---
--- --- --- --- --- --- --- --- ---
--- --- --- --- --- --- --- --- ---
- - -- - - -- - - -- - - -- - - -- - - -- - - -- - - -- - - --
--- --- --- --- --- --- --- --- ---

64
Join [all] Join any Join none
Semi Design
fork join_all : The parent process blocks until all the processes spawned by this fork
complete.
program main();
initial begin
#(10);
$display(" BEFORE fork time = %d ",$time );

fork // Simulation results:


begin # (20); $display("time = %d # 20 ",$time ); BEFORE fork time = 10
end time = 15 # 5
begin #(10); $display("time = %d # 10 ",$time ); time = 20 # 10
end time = 30 # 20
begin #(5); $display("time = %d # 5 ",$time ); time = 30 Outside the main fork
end
join
$display(" time = %d Outside the main fork ",$time );
#(40);
end 65
endprogram
Semi Design
fork join_any : The parent process blocks until any one of the processes spawned by
this fork completes.
program main();
initial begin
#(10);
$display(" BEFORE fork time = %d ",$time );

fork // Simulation results:


begin # (20); $display("time = %d # 20 ",$time ); BEFORE fork time = 10
end time = 15 # 5
begin #(10); $display("time = %d # 10 ",$time ); time = 15 Outside the main fork
end time = 20 # 10
begin #(5); $display("time = %d # 5 ",$time ); time = 30 # 20
end
join_any
$display(" time = %d Outside the main fork ",$time );
#(40);
end 66
endprogram
Semi
fork join_none : The parent process continues to execute concurrently with all theDesign
processes spawned by the fork. The spawned processes do not start executing until
the parent thread executes a blocking statement.
program main();
initial begin
#(10);
$display(" BEFORE fork time = %d ",$time );
// Simulation results:
fork BEFORE fork time = 10
begin # (20); $display("time = %d # 20 ",$time ); time = 10 Outside the main fork
end time = 15 # 5
begin #(10); $display("time = %d # 10 ",$time ); time = 20 # 10
end time = 30 # 20
begin #(5); $display("time = %d # 5 ",$time );
end
join_none
$display(" time = %d Outside the main fork ",$time );
#(40); 67
end
endprogram
Semi Design
Wait_fork statement : The wait fork statement is used to ensure that all immediate
child subprocesses (processes created by the current process, excluding their
descendants) have completed their execution.
program main();
initial begin
#(10);
$display(" BEFORE fork time = %d ",$time );
fork // Simulation results:
begin # (20); $display("time = %d # 20 ",$time ); BEFORE fork time = 10
end time = 15 # 5
begin #(10); $display("time = %d # 10 ",$time ); time = 15
end Outside the main fork
begin #(5); $display("time = %d # 5 ",$time ); time = 20 # 10
end time = 30 # 20
join_any time = 30 After wait fork
$display(" time = %d Outside the main fork ",$time );
wait fork ;
$display(" time = %0d After wait fork ",$time ); 68
end
endprogram
Semi Design
Disable_fork statement : The disable fork statement terminates all active
descendants (subprocesses) of the calling process.

program main();
initial begin
#(10);
$display(" BEFORE fork time = %d ",$time );
fork // Simulation results:
begin # (20); $display("time = %d # 20 ",$time ); BEFORE fork time = 10
end time = 15 # 5
begin #(10); $display("time = %d # 10 ",$time ); time = 15
end Outside the main fork
begin #(5); $display("time = %d # 5 ",$time ); Killed the child processes
end
join_any
$display(" time = %d Outside the main fork ",$time );
disable fork;
$display(" Killed the child processes"); 69
end
endprogram
Semi Design
Semi Design

Semaphore
Conceptually, a semaphore is a bucket. When a semaphore is allocated, a bucket
that contains a fixed number of keys is created. Processes using semaphores
must first procure a key from the bucket before they can continue to execute. If
a specific process requires a key, only a fixed number of occurrences of that
process can be in progress simultaneously. All others must wait until a sufficient
number of keys is returned to the bucket. Semaphores are typically used for
mutual exclusion, access control to shared resources, and basic synchronization.
Semaphore is a built-in class that provides the following methods:
new() Create a semaphore with a specified number of keys
put() Obtain one or more keys from the bucket
get() Return one or more keys into the bucket
71
try_get() Try to obtain one or more keys without blocking
Semi Design
program main ;
semaphore sema = new(1);
initial begin
repeat(2)
begin sema.get(1);
fork $display("2: Got the Key");
////////// PROCESS 1 //////////////// #(10); //Do some work
begin sema.put(1);
$display("1: Waiting for key"); $display("2: Returning back key ");
sema.get(1); #(10);
$display("1: Got the Key"); end
#(10); // Do some work join
sema.put(1); end #1000;
$display("1: Returning back key "); end
#(10); endprogram
end
////////// PROCESS 2 ////////////////
begin 72
$display("2: Waiting for Key");
Semi Design

// Simulation results:
1: Waiting for key
1: Got the Key
2: Waiting for Key
1: Returning back key
2: Got the Key
2: Returning back key
1: Waiting for key
1: Got the Key
2: Waiting for Key
1: Returning back key
2: Got the Key
2: Returning back key

73
Semi Design
Semi Design

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.

There are two types of mailboxes


1. Generic Mailbox
2. Parameterized mailbox

75
Semi Design
1. Generic Mailbox:
The default mailbox is type-less. that is, a single mailbox can send and
receive data of any type.

// Syntax for Generic Mailbox


mailbox mailbox_name;

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

// Syntax for Generic Mailbox


mailbox #(type) mailbox_name;

76
Semi Design
Mailbox methods():

new() Create a mailbox


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

Blocking means it will wait until packet available where as non blocking means it
doesn’t wait. Suppose that you have a mailbox in that you don’t have any
message. So blocking method will wait until a message will come in mailbox. On 77
other hand non blocking will not wait for the same.
Semi Design
program main ; task get_packets();
mailbox my_m; integer i, packet;
initial begin begin
my_m= new(); for (i=0; i<10; i++)
if (my_m) begin
begin my_m.get(packet);
fork $display("Got packet %d @time
put_packets(); %d", packet, $time);
get_packets(); task put_packets(); end
#10000; integer i; end
join_any begin endtask
end for (i=0; i<10; i++) endprogram
#(1000); begin #(10);
$display("END of Program"); my_m.put(i);
end $display("Done putting packet %d
@time %d",i, $time);
end
end 78
endtask
Semi Design

// Simulation results
Done putting packet 0 @time 10
Got packet 0 @time 10
Done putting packet 1 @time 20
Got packet 1 @time 20
Done putting packet 2 @time 30
Got packet 2 @time 30 Done putting packet 7 @time 80
Done putting packet 3 @time 40 Got packet 7 @time 80
Got packet 3 @time 40 Done putting packet 8 @time 90
Done putting packet 4 @time 50 Got packet 8 @time 90
Got packet 4 @time 50 Done putting packet 9 @time 100
Done putting packet 5 @time 60 Got packet 9 @time 100
Got packet 5 @time 60 END of Program
Done putting packet 6 @time 70
Got packet 6 @time 70

79
// Example for mailbox Semi Design
class generator;
rand transaction t1;
mailbox g2d; //declaring mailbox

function new(mailbox gen2driv); //constructor


//getting the mailbox handle from env
this.g2d = g2d;
endfunction

task main();
repeat(repeat_count) begin
t1 = new();
if( !t1.randomize() )
$fatal("Gen:: trans randomization failed");
g2d.put(t1);
end
-> ended; //triggering indicatesthe end of generation
endtask 80
endclass
Semi Design
class driver; task main;
//used to count the number of transactions forever begin
int no_transactions; transaction t1;
g2d.get(t1);
//creating virtual interface handle @(posedge v_i.clk);
virtual intf v_i; v_i.valid <= 1;
v_i.a <= t1.a;
//creating mailbox handle v_i.b <= t1.b;
mailbox g2d; @(posedge v_i.clk);
v_i.valid <= 0;
//constructor t1.c <= v_i.c;
function new(virtual intf v_i,mailbox @(posedge v_i.clk);
g2d); t1.display("[ Driver ]");
//getting the interface no_transactions++;
this.v_i = v_i; end
//getting the mailbox handles endtask
from environment endmodule
this.g2d = g2d; 81
endfunction
Semi Design
Semi Design

Events
An identifier declared as an event data type is called a named event. Named event is
a data type which has no storage. In verilog, a named event can be triggered
explicitly using "->" . Verilog Named Event triggering occurrence can be recognized
by using the event control "@" .

Triggered:
The "triggered" event property evaluates to true if the given event has been
triggered in the current time-step and false otherwise. If event_identifier is
null, then the triggered event property evaluates to false. Using this
mechanism, an event trigger shall unblock the waiting process whether the
wait executes before or at the same simulation time as the trigger operation.

83
Triggered: Semi Design

module tri;
event e;
initial // Simulation results
repeat(4) e is FALSE at 10
begin e is triggered at 20
#20; e is TRUE at 20
->e ; e is FALSE at 30
$display(" e is triggered at %t ",$time); e is triggered at 40
end e is TRUE at 40
initial e is FALSE at 50
#100 $finish; e is triggered at 60
always begin #10; e is TRUE at 60
if(e.triggered) e is FALSE at 70
$display(" e is TRUE at %t",$time); e is triggered at 80
else e is TRUE at 80
$display(" e is FALSE at %t",$time); e is FALSE at 90
end 84
endmodule
Semi Design
Wait():
module wait_ex;
event a;
initial
repeat(4) // Simulation results
#20 -> a; 20 ONE :: EVENT A is triggered
20 TWO :: EVENT A is triggered
always begin 40 ONE :: EVENT A is triggered
@a; 40 TWO :: EVENT A is triggered
$display($time, " ONE :: EVENT A is triggered " ); 60 ONE :: EVENT A is triggered
end 60 TWO :: EVENT A is triggered
80 ONE :: EVENT A is triggered
always begin 80 TWO :: EVENT A is triggered
wait(a.triggered);
$display($time, " TWO :: EVENT A is triggered ");
#1;
end
85
endmodule
Semi Design
Merging events:

module merg_ex;
event a,b;

initial
begin
#20 -> a;
#20 -> b; // Simulation results
#20 -> a; 20 EVENT A is triggered
end 40 EVENT B is also triggered
60 EVENT A is triggered
always@(a)
$display($time, " EVENT A is triggered ");

always@(b)
$display($time, " EVENT B is also triggered ");
86
endmodule
Semi Design
Wait_order:
module main;
event e1,e2,e3;
initial
begin
#10; -> e1; -> e2; -> e3;
#10; -> e3; -> e1; -> e2;
#10; -> e3; -> e2; -> e3;
// Simulation results
end
10 Events are in order
10 Events are out of order
always
10 Events are out of order
begin
wait_order(e1,e2,e3)
$display($time, " Events are in order ");
else
$display($time, " Events are out of order ");
end
87
endmodule
Semi Design
Semi Design

Interface
The communication between blocks of a digital system is a critical area. In Verilog,
modules are connected using module ports. For large modules, this is not productive as
it involves
• Manually connecting hundreds of ports may lead to errors.
• Detailed knowledge of all the port is required.
• Difficult to change if the design changes.
• More time consuming.
• Most port declaration work is duplicated in many modules.
In Verilog, the communication between blocks is specified using module ports.
SystemVerilog adds the interface construct which encapsulates the
communication between blocks. An interface is a bundle of signals or nets
through which a testbench communicates with a design. A virtual interface is a
variable that represents an interface instance. this section describes the interface, 89
interface over traditional method and virtual interface.
Semi Design

Interface construct
The interface construct is used to connect the design and testbench.
Above diagram shows connecting design and testbench without interface.

addr
W_en

Testbench R_en Design


W_data
R_data

90
clk clk
Semi Design
Below diagram shows connecting design and testbench with interface.

Testbench interface Design

An interface is a named bundle of wires, the interfaces aim is to encapsulate


communication.
Also specifies the,
• Directional information, i.e modports
• Timing information, i.e clocking blocks 91
An interface can have parameters, constants, variables, functions, and tasks.
Semi Design

// Syntax for Interface


interface interface_name;
...
interface_items
...
endinterface

Advantages of the interface over the traditional connection:

• Allows the number of signals to be grouped together and represented as a


single port, the single port handle is passed instead of multiple signal/ports.
• Interface declaration is made once and the handle is passed across the
modules/components.
• Addition and deletion of signals are easy.

92
Semi Design
Connecting testbench and design without interface construct:
module tbench_top;
module memory ( clk, addr, reg clk;
wr_rd, wdata, rdata); reg [7:0] w_addr;
input clk; reg w_wr_rd;
input [7:0] addr; reg [7:0] w_wdata;
input wr_rd; reg [7:0] w_rdata;
input [7:0] wdata; wire [7:0] rdata;
output [7:0] rdata;
…… // DUT instance
endmodule memory dut(
.clk(clk),
.addr(w_addr),
.wr_rd(w_wr_rd),
.wdata(w_wdata),
.rdata(r_data)
); 93
endmodule
Semi Design
Connecting testbench and design with interface construct:
module memory ( clk, addr,
wr_rd, wdata, rdata); module tbench_top;`
input clk; //Interface instance
input [7:0] addr; mem_intf intf();
input wr_rd;
input [7:0] wdata; //DUT(Design Under Test)
output [7:0] rdata; instance
…… memory dut(
endmodule .clk(intf.clk),
.addr(intf.addr),
interface mem_intf; .wr_rd(intf.wr_rd),
logic clk; .wdata(intf.wdata),
logic [7:0] addr; .rdata(intf.rdata));
logic wr_rd;
logic [7:0] wdata; endmodule
logic [7:0] rdata;
94
endinterface
Semi Design
Interface Example:
Writing interface:

interface intf;

//declaring the signals


logic [6:0] a;
logic [6:0] b;
logic [8:0] c;

endinterface

Interface declaration:

//creatinng instance of interface


intf i_i();
95
Semi Design
Connecting interface with design:

//DUT instance
adder DUT (.a(i_i.a), .b(i_i.b), .c(i_i.c) );

Acessing interface signal:

i_i.a = 6;
i_i.b = 4;
i_i.c = i_i.a + i_i.b;

$display("Value of a = %0d, b = %0d",i_i.a,i_i.b);


#5;
$display("Sum of a and b, c = %0d",i_i.c);

// Simulation results
Value of a = 6, b = 4
Sum of a and b, c = 10 96
Semi Design
Semi Design

Virtual interface
A virtual interface is a variable that represents an interface instance.

• The virtual interface must be initialized before using it. i.e, Virtual interface
must be connected/pointed to the actual interface.
• Accessing the uninitialized virtual interface result in a run-time fatal error.
• Virtual interfaces can be declared as class properties, which can be initialized
procedural or by an argument to new().
• Virtual interface variables can be passed as arguments to the tasks, functions,
or methods.
• All the interface variables/Methods can be accessed via a virtual interface
handle. i.e virtual_interface.variable

98
Semi Design
Syntax for virtual interface:
// Syntax for Virtual interface
virtual interface_name instance_name;

Virtual interface example:


// Syntax for Virtual interface
virtual intf v_i; // intf – interface_name, v_i – instance_name

What is the need for a virtual interface in SystemVerilog?


SystemVerilog interface is static in nature, whereas classes are dynamic in
nature. because of this reason, it is not allowed to declare the interface within
classes, but it is allowed to refer to or point to the interface. A virtual interface is
a variable of an interface type that is used in classes to provide access to the
interface signals.

99
Semi Design
Accessing interface signal using a virtual interface handle

interface intf(input logic clk,reset); class environment;


virtual intf vif;
//declaring the signals
logic valid; function new(virtual intf vif);
logic [3:0] a; this.vif = vif;
logic [3:0] b; endfunction
logic [6:0] c;
task run;
endinterface vif.a = 6;
vif.b = 4;
$display("Value of a = %0d, b =
%0d",vif.a,vif.b);
// Simulation results #5;
Value of a = 6, b = 4 $display("Sum of a and b, c =
Sum of a and b, c = 10 %0d",vif.c);
$finish; 10
endtask endclass 0
Semi Design

Modport
System Verilog Modport. The Modport groups and specifies the port
directions to the wires/signals declared within the interface. modports are
declared inside the interface with the keyword modport.
• By specifying the port directions, modport provides access restrictions.
• The keyword modport indicates that the directions are declared as if inside
the module.
• Modport wire declared with input is not allowed to drive or assign, any
attempt to drive leads to a compilation error.
• The Interface can have any number of modports, the wire declared in the
interface can be grouped in many modports.
• Modpports can have, input, inout, output, and ref.

101
Semi Design
Declaration of Modport:
interface i_i;
logic x;
logic y;

//modport delcaration
modport driver (input x, output y);
modport monitor (input x, input y);

endinterface

driver modport:
It groups the signals x and y with the access direction input and output
respectively

monitor modport:
It groups the signals x and y with the access restricted to input for both the 10
signals. As the monitor need only monitoring the signals, driving access is 2
restricted by specifying direction as input.
Semi Design
Modport example:

interface intf(); module adder(


logic [3:0] a; input [3:0] a,
logic [3:0] b; input [3:0] b,
logic [6:0] c; output [6:0] c );

modport driver (output a, b, input c); assign c = a + b;


endinterface
endmodule
task run;
// Simulation results:
vif.driver.a = 6;
Value of a = 6, b = 4 Sum of a
vif.driver.b = 4;
and b, c = 10
$display("Value of a = %0d, b = %0d",vif.driver.a,vif.driver.b);
#5;
$display("Sum of a and b, c = %0d",vif.driver.c);
$finish; 10
endtask 3
Semi Design

interface intf();
logic [3:0] a;
logic [3:0] b; // Simulation results:
logic [6:0] c; Port 'a' of modport 'driver' has
been restricted as an input port.
modport driver (input a, b, output c); Input ports cannot be driven.
endinterface Port 'b' of modport 'driver' has
been restricted as an input port.
task run; Input ports cannot be driven.
vif.driver.a = 6;
vif.driver.b = 4;

$display("Value of a = %0d, b = %0d",vif.driver.a,vif.driver.b);


#5;
$display("Sum of a and b, c = %0d",vif.driver.c);
$finish;
endtask 10
4
Semi Design

Clocking blocks
SystemVerilog adds the clocking block that identifies clock signals, and captures
the timing and synchronization requirements of the blocks being modeled. A
clocking block assembles signals that are synchronous to a particular clock, and
makes their timing explicit. The clocking block is a key element in a cycle-based
methodology, which enables users to write testbenches at a higher level of
abstraction. Simulation is faster with cycle based methodology.
Depending on the environment, a testbench can contain one or more clocking
blocks, each containing its own clock plus an arbitrary number of signals. These
operations are as follows:
• Synchronous events
• Input sampling
• Synchronous drives 10
5
Semi Design
Syntax for Clocking block:

clocking cb @(posedge clk);


default input #10ns output #2ns;
output read,enable,addr;
input negedge data;
endclocking

In the above example, the first line declares a clocking block called cb that is to
be clocked on the positive edge of the signal clk. The second line specifies that
by default all signals in the clocking block shall use a 10ns input skew and a 2ns
output skew by default. The next line adds three output signals to the clocking
block: read, enable and addr. The fourth line adds the signal data to the clocking
block as input. Fourth line also contains negedge which overrides the skew ,so
that data is sampled on the negedge of the clk.

10
6
Semi Design

Skew
If an input skew is specified then the signal is sampled at skew time units
before the clock event. If output skew is specified, then output (or inout)
signals are driven skew time units after the corresponding clock event. A
skew must be a constant expression, and can be specified as a parameter.

Signals sampled here Signals driven here

Input skew Output skew


10
7
Semi Design
If skew is not specified, default input skew is 1step and output skew is 0. Specifying
a clocking block using a SystemVerilog interface can significantly reduce the
amount of code needed to connect the TestBench without race condition. Clocking
blocks add an extra level of signal hierarchy while accessing signals.

interface intf (input clk);


logic read, enable;
logic [7:0] addr,data;

clocking cb @(posedge clock); // clocking block for testbench


default input #10ns output #2ns;
output read,enable,addr;
input data;
endclocking

modport dut (input read,enable,addr,output data);


modport tb (clocking cb); 10
endinterface :intf 8
Semi Design
Skew can be specified in 3 ways.
#d : The skew is d time units. The time unit depends on the timescale of the block.
#dns : The skew is d nano seconds.
#1step : Sampling is done in the preponed region of current time stamp.

Cycle delay:
The ## operator can be used to delay execution by a specified number of
clocking events, or clock cycles. What constitutes a cycle is determined by the
default clocking in effect of module, interface, or program.

// Syntax for clock delay


## <integer expression>;

##3; // wait 3 cycles


##1 tb_if.addr <= 8'h00;// waits for 1 cycle and then writes address.

10
9
Semi Design
Semi Design

Introduction to OOP
Unlike procedural programming, here in the OOP programming model programs are
organized around objects and data rather than actions and logic. Objects represent
some concepts or things and like any other objects in the real Objects in programming
language have certain behavior, properties, type, and identity. In OOP based language
the principal aim is to find out the objects to manipulate and their relation between
each other. OOP offers greater flexibility and compatibility then procedural language
like verilog.
Objects are key to understanding object-oriented technology. Look around right now
and you'll find many examples of real-world objects: your system, your desk, your
chair.
Real-world objects share two characteristics: They all have state and behavior.
System have state (name, color) and behavior (playing music,switch off).
Identifying the state and behavior for real-world objects is a great way to begin 111
thinking in terms of object-oriented programming.
Semi Design
SystemVerilog is a object oriented programming and to understand the functionality of
OOP in SystemVerilog, we first need to understand several fundamentals related to
objects. These include class, method, inheritance, encapsulation, abstraction,
polymorphism etc.

Class:
It is the central point of OOP and that contains data and codes with behavior. In
SystemVerilog OOPS , everything happens within class and it describes a set of
objects with common behavior. The class definition describes all the properties,
behavior, and identity of objects present within that class.

Object:
Objects are the basic unit of object orientation with behavior, identity. As we
mentioned above, these are part of a class but are not the same. An object is
expressed by the variable and methods within the objects. Again these variables
and methods are distinguished from each other as instant variables, instant methods
and class variable and class methods.
112
Semi Design
Methods:
We know that a class can define both attributes and behaviors. Again attributes are
defined by variables and behaviors are represented by methods. In other words,
methods define the abilities of an object.

Inheritance:
This is the mechanism of organizing and structuring program. Though objects are
distinguished from each other by some additional features but there are objects that
share certain things common. In object oriented programming classes can inherit
some common behavior and state from others. Inheritance in OOP allows to define
a general class and later to organize some other classes simply adding some details
with the old class definition. This saves work as the special class inherits all the
properties of the old general class and as a programmer you only require the new
features. This helps in a better data analysis, accurate coding and reduces
development time.

113
Semi Design
Abstraction:
The process of abstraction in SystemVerilog is used to hide certain details and only
show the essential features of the object. In other words, it deals with the outside
view of an object.

Encapsulation:
This is an important programming concept that assists in separating an object's
state from its behavior. This helps in hiding an object's data describing its state
from any further modification by external component. In SystemVerilog there are
three different terms used for hiding data constructs and these are public, private
and protected . As we know an object can associated with data with predefined
classes and in any application an object can know about the data it needs to know
about. So any unnecessary data are not required by an object can be hidden by this
process. It can also be termed as information hiding that prohibits outsiders in
seeing the inside of an object in which abstraction is implemented.

114
Semi Design
Polymorphism:
It describes the ability of the object in belonging to different types with specific
behavior of each type. So by using this, one object can be treated like another and in
this way it can create and define multiple level of interface. Here the programmers
need not have to know the exact type of object in advance and this is being
implemented at runtime.

115
Semi Design

Class
A class is the implementation of an abstract data type . It defines attributes and
methods which implement the data structure and operations of the abstract data
type, respectively. Instances of classes are called objects. Consequently, classes
define properties and behavior of sets of objects.

// Syntax for class


class A ;
// attributes:
int i
// methods:
task print ()
endclass
116
Semi Design

Object:
An object is an instance of a class. It can be uniquely identified by its name and it
defines a state which is represented by the values of its attributes at a particular
time.

class simple ;
int i, j; obj_1 = new();
task printf(); obj_2 = new();
$display( i , j ); obj_1.i = 2;
// Simulation results:
endtask obj_1.j = 5;
2 5
endclass obj_2.i = 4;
4 0
obj_1.printf();
program main; obj_2. printf();
initial begin end
simple obj_1; endprogram 117
simple obj_2;
Semi Design
Declaration of objects:
//Example of declaration objects:
Packet pkt;
Driver driv;

If you declare pkt like this, its value will be undetermined until an object is
actually created and assigned to it using the new method. Simply declaring a
reference variable does not create an object. For that, you need to use the new
operator. You must assign an object to pkt before you use it in your code.
Otherwise, you will get a compiler error.

Creating objects:

//Example of creating objects:


Packet pkt = new();
Driver driv = new();
118
Semi Design
class packet ; class packet ;
int length = 0; int length = 0;

function new (int l); function new (int l);


length = l; length = l;
endfunction endfunction
endclass endclass

program main; program main;


initial begin initial begin
packet pkt; packet pkt;
pkt.length = 10; packet pkt = new(10);
end end
endprogram endprogram

// Simulation results: // Simulation results:


Error: null object access Length = 10
119
Semi Design

This
‘this’ keyword is used to refer to class properties. this keyword is used to
unambiguously refer to class properties or methods of the current instance. this is a
pre-defined class handle referring to the object from which it is used,
calling this.variable means object.variable.

• this keyword shall only be used within non-static class methods


• this keyword refers to the object handle in which it is invoked

12
0
Semi Design

class packet;
byte a
Compiler gets confused on which is the class
byte b;
variable
function void data(byte a, b);
a = a;
b = b; Using this will solve the issue
endfunction this.a = a;
this.b = b;
endclass

121
class packet; Semi Design
bit [31:0] addr;
bit [31:0] data;
bit write;
string pkt_type;

function new(bit [31:0] addr,data,bit write,string pkt_type);


addr = addr;
data = data; module sv_constructor;
write = write; packet pkt;
pkt_type = pkt_type; initial begin
endfunction pkt = new(32'h10,32'hFF,1,"GOOD_PKT");
pkt.display();
function void display(); end
$display("\t addr = %0h",addr); endmodule
$display("\t data = %0h",data);
$display("\t write = %0h",write);
$display("\t pkt_type = %0s",pkt_type);
12
endfunction 2
endclass
Semi Design
The addr, data, write and pkt_type are the property of both class and an argument
to the function new, as the name in both are same.this will lead to an ambiguity
in assignment and values will not be assigned properly.

// simulation result
addr = 0
data = 0
write = 0
pkt_type =

The above problem can be overcome by using “this” keyword to the


class properties.

12
3
class packet; // simulation result Semi Design
bit [31:0] addr; addr = 10
bit [31:0] data; data = ff
bit write; write = 1
string pkt_type; pkt_type = GOOD_PKT

function new (bit [31:0] addr,data,bit write,string pkt_type);


this.addr = addr;
this.data = data; module sv_m;
this.write = write; packet pkt;
this.pkt_type = pkt_type; initial begin
endfunction pkt = new(32'h10,32'hFF,1,"GOOD_PKT");
pkt.display();
function void display(); end
$display("\t addr = %0h",addr); endmodule
$display("\t data = %0h",data);
$display("\t write = %0h",write);
$display("\t pkt_type = %0s",pkt_type);
12
endfunction 4
endclass
Semi Design

Inheritance
Inheritance:
Inheritance is the mechanism which allows a class A to inherit properties of a
class B. We say ``A inherits from B''. Objects of class A thus have access to
attributes and methods of class B without the need to redefine them. The
following definition defines two terms with which we are able to refer to
participating classes when they use inheritance.

Superclass (or) parent class:


If class A inherits from class B, then B is called superclass of A.

Subclass (or) child class (or) extended class (or) derived class:
12
If class A inherits from class B, then A is called subclass of B. 5
Semi Design
The idea of inheritance is simple but powerful: When you want to create a new class
and there is already a class that includes some of the code that you want, you can
derive your new class from the existing class. In doing this, you can reuse the fields
and methods of the existing class without having to write (and debug!) them yourself.

What you can do in a Subclass:


A subclass inherits all of the public and protected members of its parent. You can
use the inherited members as is, replace them, hide them, or supplement them with
new members:
The inherited fields can be used directly, just like any other fields.
• You can declare a field in the subclass with the same name as the one in the
superclass, thus hiding it (not recommended).
• You can declare new fields in the subclass that are not in the superclass.
• The inherited methods can be used directly as they are.
• You can write a new instance method in the subclass that has the same
12
signature as the one in the superclass, thus overriding it. 6
Semi Design
• You can write a new static method in the subclass that has the same signature as the
one in the superclass, thus hiding it.
• You can declare new methods in the subclass that are not in the superclass.
• You can write a subclass constructor that invokes the constructor of the superclass,
either implicitly or by using the keyword super.

12
7
Semi Design
Overriding: class parent;
task printf();
$display(" THIS IS PARENT CLASS ");
endtask endclass
class subclass extends parent;
task printf();
// simulation result $display(" THIS IS SUBCLASS ");
THIS IS PARENT CLASS endtask endclass
THIS IS SUBCLASS
program main;
initial begin
parent p;
subclass s;
p = new();
s = new();
p.printf();
s.printf(); 12
end endprogram 8
Semi Design
Super: class parent;
task printf();
The super keyword is used from $display(" THIS IS PARENT CLASS ");
within a derived class to refer to endtask
members of the parent class. It is endclass
necessary to use super to access class subclass extends parent;
members of a parent class when task printf();
those members are overridden by super.printf();
the derived class. endtask
endclass

// simulation result program main;


THIS IS PARENT CLASS initial begin
subclass s;
s = new();
s.printf();
end 12
endprogram 9
Semi Design
Is only method: class parent;
task printf();
Programmers can override the $display(" THIS IS PARENT CLASS ");
existing code/functionality before endtask
existing code and replaces with endclass
new code as shown in below class subclass extends parent;
example. task printf();
$display(" THIS IS SUBCLASS ");
endtask
endclass

// simulation result program main;


THIS IS SUBCLASS initial begin
subclass s;
s = new();
s.printf();
end 13
endprogram 0
Semi Design
class parent;
Is first method:
task printf();
$display(" THIS IS PARENT CLASS ");
Programmers can add new lines of
endtask
code/functionality before existing
endclass
code as shown in below example.
class subclass extends parent;
task printf();
$display(" THIS IS SUBCLASS ");
super.printf();
// simulation result endtask
THIS IS SUBCLASS endclass
THIS IS PARENT CLASS
program main;
initial begin
subclass s;
s = new();
s.printf();
end 131
endprogram
class parent; Semi Design
Is Also method: task printf();
$display(" THIS IS PARENT CLASS ");
Programmers can add new lines of endtask
code/functionality after the endclass
existing code as shown in below class subclass extends parent;
example. task printf();
super.printf();
$display(" THIS IS SUBCLASS ");
endtask
// simulation result endclass
THIS IS PARENT CLASS
THIS IS SUBCLAS program main;
initial begin
subclass s;
s = new();
s.printf();
end
13
endprogram 2
Semi Design

Encapsulation
The technique of hiding the data within the class and making it available only
through the methods, is known as encapsulation.
Because it seals the data (and internal methods) safely inside the “capsule” of
the class, where it can be accessed only by trusted users (i.e., by the methods
of the class).
By default all the members and methods of a class are accessible from
anywhere using the object handle, sometimes this could corrupt the class
members values, which should not be touched at all.
Access control rules that restrict the members of a class from being used
outside the class, this is achieved by prefixing the class members with the
keywords,
• Local
13
• Protected 3
Semi Design
Local class members:
External access to the class members can be avoided by declaring members as
local.
Any violation could result in a compilation error.

// Syntax for local class members


local data_type variable;

Protected class members:


In some use cases, it is required to access the class members only by the derived
class’s, this can be done by prefixing the class members with the protected keyword.
Any violation could result in a compilation error.

// Syntax for Protected class members


protected data_type variable;
13
4
Accessing a Local variable outside the class ( not allowed ) Semi Design

class parent_class;
local bit [31:0] a;
The local variable declared inside the class is trying
function new(bit [31:0] r_i); to access from outside the class by using object
a = r_i + 10; handle.
endfunction As the variable is declared as local, which leads to a
compilation error.
function display();
$display("tmp_addr = %0d",a);
endfunction // simulation result
endclass Error- Illegal class variable access
testbench.sv, Local member ‘a’ of
module encapsulation; class 'parent_class' is not visible to
initial begin scope 'encapsulation'.
parent_class p_c = new(5);
p_c.a = 20; //Accessing local variable outside the class
p_c.display(); 13
end 5
endmodule
Accessing a Local variable within the class (allowed ) Semi Design

class parent_class;
local bit [31:0] a;
The local variable declared inside the class is being
function new(bit [31:0] r_i); accessed inside the class. as it is allowed, no
a = r_i + 10; compilation error is observed.
endfunction

function display();
$display("tmp_addr = %0d",a);
endfunction // simulation result
endclass tmp_addr = 15

module encapsulation;
initial begin
parent_class p_c = new(5);
p_c.display();
end 13
endmodule 6
Accessing a Protected variable outside the class ( not allowed ) Semi Design

class parent_class;
protected bit [31:0] a;
module encapsulation;
function new(bit [31:0] r_i);
initial begin
a= r_i + 10;
parent_class p_c = new(5);
endfunction
child_class c_c = new(10);
function display();
// variable declared as protected cannot be
$display("tmp_addr = %0d",a);
accessed outside the class
endfunction
p_c.a= 10;
endclass
p_c.display();
class child_class extends parent_class;
end
function new(bit [31:0] r_i);
endmodule
super.new(r_i);
endfunction

function void incr_addr(); 13


a ++; 7
endfunction endclass
Semi Design

In the above example, The protected variable declared inside the class is
trying to access from outside the class by using object handle.
As the variable is declared as protected, which leads to a compilation
error.

// simulation result
Error- Illegal class variable access testbench.sv, Protected
member ‘a' of class 'parent_class' is not visible to scope
'encapsulation'.

13
8
Accessing a Protected variable in the extended class (allowed ) Semi Design

class parent_class;
protected bit [31:0] a;
function new(bit [31:0] r_i); module encapsulation;
a= r_i + 10; initial begin
endfunction child_class c_c = new(10);

function display(); c_c.incr_addr(); //Accessing protected


$display("tmp_addr = %0d",a); variable in extended class
endfunction c_c.display();
endclass end
endmodule
class child_class extends parent_class;
function new(bit [31:0] r_i);
super.new(r_i);
endfunction

function void incr_addr(); 13


a ++; 9
endfunction endclass
Semi Design

In the above example, The protected variable declared inside the class is
being accessed inside the extended class. as it is allowed, no compilation
error is observed.

// simulation result
tmp_addr = 21

14
0
Semi Design

Abstract class
SystemVerilog class declared with the keyword virtual is referred to as
an abstract class.
Abstract classes are those which can be used for creation of handles. However their
methods and constructors can be used by the child or extended class. The need for
abstract classes is that you can generalize the super class from which child classes
can share its methods. The subclass of an abstract class which can create an object
is called as "concrete class".

// Syntax for Abstract class


virtual class abc;
//Class defination
endclass
141
Semi Design
Instantiating Virtual class:
Creating an object of a virtual class. An abstract class can only be derived,
creating an object of a virtual class leads to a compilation error.
virtual class packet;
bit [31:0] addr;
endclass

module virtual_class;
initial begin
packet p;
p = new();
end
endmodule

// simulation result
virtual_class, "p = new();" Instantiation of the object 'p' can not be done
because its type 'packet' is an abstract base class. Perhaps there is a 14
derived class that should be used. 2
Semi Design
Deriving Virtual class:
virtual class packet;
bit [31:0] addr;
endclass
An abstract class is derived and
class extended_packet extends packet; written extend the class and creating
function void display; it.
$display("Value of addr is %0d", addr);
endfunction
endclass // simulation result
Value of addr is 10
module virtual_class;
initial begin
extended_packet p;
p = new();
p.addr = 10;
p.display();
14
end endmodule 3
Semi Design
Virtual methods():
1. Virtual Functions:
A function declared with a virtual keyword before the function keyword is
referred to as virtual Function
// Syntax for virtual functions
virtual function function_name;
// Function definition
endfunction

2. Virtual Tasks:
Task declared with a virtual keyword before the task keyword is referred to as
virtual task
// Syntax for virtual functions
virtual task task_name;
// task definition
endtask 14
4
Semi Design
Method without virtual keyword:
class vir_ex;
function void display; module virtual_class;
$display("Inside base_class"); initial begin
endfunction vir_ex v_e;
endclass child c;

class child extends vir_ex; c = new();


function void display; v_e = c;
// simulation result
$display("Inside extended class"); v_e.display();
Inside base_class
endfunction end
endclass endmodule

The method inside the base class is declared without a virtual keyword, on
calling method of the base class which is pointing to the extended class
will call the base class method.
14
5
Semi Design
Method with virtual keyword:
class vir_ex;
virtual function void display; module virtual_class;
$display("Inside base_class"); initial begin
endfunction vir_ex v_e;
endclass child c;

class child extends vir_ex; c = new();


function void display; v_e = c;
// simulation result
$display("Inside extended class"); v_e.display();
Inside extended class
endfunction end
endclass endmodule

The method inside the base class is declared with a virtual keyword, on
calling method of the base class which is pointing to an extended class will
call the extended class method.
14
6
Semi Design

Polymorphism
Polymorphism means many forms. Polymorphism in SystemVerilog provides an
ability to an object to take on many forms.
Method handle of super-class can be made to refer to the subclass method, this
allows polymorphism or different forms of the same method.
Example of polymorphism:

class A

14
class B_1 class B_2 class B_2 7
Semi Design
1. Let’s write the base_class with a method display()
class base_class;
virtual function display();
$display("Inside base class");
endfunction
endclass

2. Writing three extended classes of base_class, with display method overridden in it.
class ext_class_1 extends base_class;
function display();
$display("Inside extended class 1");
endfunction
endclass
class ext_class_3 extends base_class;
class ext_class_2 extends base_class; function display();
function display(); $display("Inside extended class 3");
$display("Inside extended class 2"); endfunction 14
endfunction endclass 8

endclass
Semi Design
3. Create an object of each extended class

ext_class_1 ec_1 = new();


ext_class_2 ec_2 = new();
ext_class_3 ec_3 = new();

4. Create an object of parent class

base_class b_c[3];

5. Assign extend class handles to base class handles.

b_c[0] = ec_1;
b_c[1] = ec_2;
b_c[2] = ec_3;

14
9
Semi Design
class base_class;
virtual function void display();
$display("Inside base class");
endfunction
endclass

class ext_class_1 extends base_class;


function void display();
$display("Inside extended class 1");
endfunction
endclass
class ext_class_3 extends base_class;
class ext_class_2 extends base_class; function void display();
function void display(); $display("Inside extended class 3");
$display("Inside extended class 2"); endfunction
endfunction endclass
endclass 15
0
Semi Design
module class_polymorphism;
initial begin

ext_class_1 ec_1 = new();


ext_class_2 ec_2 = new();
ext_class_3 ec_3 = new();

base_class b_c[3];

b_c[0] = ec_1;
b_c[1] = ec_2; // simulation result
b_c[2] = ec_3; Inside extended class 1
Inside extended class 2
Inside extended class 3
b_c[0].display();
b_c[1].display();
b_c[2].display();
end
151
endmodule
Semi Design

Parameterized Classes
Parameterized classes are same as the parameterized modules in the verilog.
parameters are like constants local to that particular class.
The parameter value can be used to define a set of attributes in class. default values can
be overridden by passing a new set of parameters during instantiation. this is called
parameter overriding.
class packet #(parameter int ADDR_WIDTH = 32,DATA_WIDTH = 32);
bit [ADDR_WIDTH-1:0] address;
bit [DATA_WIDTH-1:0] data ;
packet pkt; –> creates pkt handle with default
ADDR_WIDTH and DATA_WIDTH values.
function new();
The default parameter value can be overridden when
address = 10;
the class is instantiated.
data = 20;
packet #(32,64) pkt; –> creates pkt handle with 15
endfunction
ADDR_WIDTH = 32 and DATA_WIDTH = 64. 2
endclass
Semi Design
Pass a data type to a class:

class packet #(parameter type T = int);


T address;
T data ;

function new();
address = 10;
data = 20; packet pkt; –> address and data type is int
endfunction packet #(bit [31:0]) pkt; –> address and data type
endclass is bit [31:0]

15
3
Semi Design

Constants
Constant class:
An instance of a class (an object handle) can also be declared with the const
keyword.
// Example
const class_name object = new(3,3,4);

In other words, the object acts like a variable that cannot be written. The arguments
to the new method must be constant expressions. The members of the object can be
written (except for those members that are declared const).

15
4
Semi Design
Global Constant:
Global constant class properties include an initial value as part of their declaration.
They are similar to other const variables in that they cannot be assigned a value
anywhere other than in the declaration.

class A ;
const int i = 10;
endclass

program main ; // simulation result


A my_a; Error : Variable 'i' declared as 'const' .
initial begin
my_a = new();
my_a.i = 55;
end
endprogram
15
5
Semi Design
Instance Constant:
Instance constants do not include an initial value in their declaration, only the
const qualifier. This type of constant can be assigned a value at run time, but
the assignment can only be done once in the corresponding class constructor
not from outside or any other method.

class A ; class A ;
const int i; const int i;
function new(); function new();
i = 20; i = 20;
endfunction i++;
endclass endfunction
endclass
program main ;
A my_a;
// simulation result // simulation result
initial begin
20 Instance constants assignment can
my_a = new();
only be done once 15
$display(my_a.i); 6
end endprogram
Semi Design

Static
A static property is a class variable that is associated with the class, rather than
with an instance of the class. This means that when it is changed, its change is
reflected in all instances of the class. Static properties are declared with the static
keyword. If you need to access a static property inside a class, you can also use
the magic keywords "this" and "super", which resolve to the current class and the
parent of the current class, respectively. Using "this" and "super" allows you to
avoid having to explicitly reference the class by name.

15
7
Semi Design
class A ;
static int i;
endclass

program main ;
A obj_1;
A obj_2;
initial begin
obj_1 = new();
obj_2 = new();
obj_1.i = 123;
$display(obj_2.i);
end
endprogram

// simulation result
123 15
8
class A ; Semi Design
static task incr(); // simulation result
int j; //automatic variable Static task - static task with automatic
j++; variables
$display("J is %d",j); J is 1
endtask J is 1
endclass J is 1
J is 1
program main ; J is 1
A obj_1; A obj_2;
initial begin
$display("Static task - static task with automatic variables");
obj_1 = new();
obj_2 = new();
obj_1.incr();
obj_2.incr();
obj_1.incr();
obj_2.incr();
15
obj_1.incr(); 9
end endprogram
Semi Design

class A ;
int j;
static task incr(); A static method has no access to nonstatic members
j++; (class properties or methods), but it can directly
$display("J is %d",j); access static class properties or call static methods
endtask of the same class. Access to nonstatic members or to
endclass the special this handle within the body of a static
method is illegal and results in a compiler error.
program main ;
A obj_1;
A obj_2; // simulation result
initial begin A static method has no access to nonstatic
obj_1 = new(); members (class properties or methods)
obj_2 = new();
obj_1.incr();
obj_2.incr();
end 16
endprogram 0
Semi Design

Copy
The terms "deep copy" and "shallow copy" refer to the way objects are copied, for
example, during the invocation of a copy constructor or assignment operator.
class B;
int i;
endclass In the above example, both objects are pointing to
same memory. The properties did not get copied.
program main; Only the handle is copied.
initial begin
B b1; B b2; // simulation result
b1 = new(); 123
b1.i = 123;
b2 = b1;
$display( b2.i ); 161
end
endprogram
Semi Design
Shallow Copy:
A shallow copy of an object copies all of the member field values.

class B; This works well if the fields are values, but may not
int i; be what you want for fields that point to
endclass dynamically allocated memory. The pointer will be
copied. but the memory it points to will not be
program main; copied -- the field in both the original object and the
initial begin copy will then point to the same dynamically
B b1; B b2; allocated memory, which is not usually what you
b1 = new(); want. The assignment operator make shallow copies.
b1.i = 123;
b2 = new b1; // simulation result
b2.i = 321; 123
$display( b1.i ); 321
$display( b2.i );
end 16
endprogram 2
class A; Semi Design
int i;
endclass In the above example, the varible i is
class B; changed to which is inside the object of .
A a; This changes in seen in also because both
endclass the objects are pointing to same memory
location.
program main;
initial begin
B b1; B b2; // simulation result
b1 = new(); 123
b1.a = new(); 123
b1.a.i = 123; 321
b2 = new b1; 321
$display( b1.a.i );
$display( b2.a.i );
b1.a.i = 321;
$display( b1.a.i ); 16
$display( b2.a.i ); 3
end endprogram
Semi Design
Deep Copy:
A deep copy copies all fields, and makes copies of dynamically allocated memory
pointed to by the fields. To make a deep copy, you must write a copy constructor and
overload the assignment operator, otherwise the copy will point to the original, with
disasterous consequences.

class A; program main;


int i; initial begin
endclass B b1; B b2;
b1 = new(); b1.a = new();
class B; b1.a.i = 123;
A a; b2 = new b1;
task copy(A a); b2.copy(b1.a);
this.a = new a; $display( b1.a.i );
endtask $display( b2.a.i );
endclass b1.a.i = 321;
$display( b1.a.i );
$display( b2.a.i ); 16
end 4

endprogram
Semi Design

Scope Resolution operator


The class scope operator :: is used to specify an identifier defined within the scope
of a class.
• Classes and other scopes can have the same identifiers
• The scope resolution operator uniquely identifies a member of a particular class

Class Resolution operator allows access to static members (class properties and
methods) from outside the class, as well as access to public or protected elements of
super classes from within the derived classes.

16
5
Semi Design
class packet;
bit [31:0] addr;
static bit [31:0] id; A static member of the class is accessed
outside the class by using class resolution
function display(bit [31:0] a,b); operator ::
$display("Values are %0d %0d",a,b);
endfunction
endclass // simulation result
Values are 20 10
module sro_class;
int id=10;
initial begin
packet p;
p = new();
packet::id = 20;
p.display(packet::id,id);
end
endmodule 16
6
Semi Design

Null
The Null is perhaps the most "intelligent" pattern of all. It knows exactly what to
do all the time, every time. Its does nothing. The Null is somewhat difficult to
describe, since it resides in an abstract hierarchy tree, having no particular place
at all, but occupying many roles. It is somewhat like the mathematical concept of
zero: it is a placeholder, but is in itself nothing, and has no value. Null Object is a
behavioral pattern designed to act as a default value of an object in most OOPs
tools. These references need to be checked to ensure they are not null before
invoking any methods, because one can't invoke anything on a null reference; this
tends to make code less readable. If you forgot to create an object anew passed it
to method, where the method has some operation on the object, the simulation
fails. So , If the method is expecting an object , then check weather the object is
created or not else take necessary action. The advantage of this approach over a
working default implementation is that a Null Object is very predictable and has 16
no side effects. 7
Semi Design
class B;
task printf();
$display(" Hi ");
endtask
endclass

program main; // simulation result


initial begin b Object is not created
B b;
print(b);
end
endprogram

task print(B b);


if(b == null)
$display(" b Object is not created ");
else
b.printf(); 16
endtask 8
Semi Design

External Declaration
Class methods and Constraints can be defined in the following places:
• inside a class.
• outside a class in the same file.
• outside a class in a separate file.
The extern qualifier indicates that the body of the method (its implementation) or
constraint block is to be found outside the declaration.
NOTE : class scope resolution operator :: should be used while defining.

16
9
Semi Design

class B;
extern task printf();
endclass

task B::printf(); // simulation result


$display(" Hi "); Hi
endtask
program main;
initial begin
B b;
b = new();
b.printf();
end
endprogram

17
0
Semi Design
Semi Design

Introduction
Historically,verification engineers used directed test bench to verify the functionality
of their design.Rapid changes have occurred during the past decades in design and
verification.High Level Verification Languages (HVLS) such as e, System
c,Vera,SystemVerilog have become a necessity for verification environments.
Constraint Random stimulus generation is not new. Everybody uses verilog and
VHDL at very low level abstraction for this purpose. HVLS provide constructs to
express specification of stimulus at high level of abstraction and constraint solver
generates legal stimulus.
Writing constraints at higher level of absctraction,makes the programming closer
to specation.
A constraint language should support:
• Expressions to complex scenarios. 17
• Felxibility to control dynamically. 2
• Combinational and sequential constraints.
Semi Design

Verilog CRV
Constrained Random Stimulus Generation In Verilog:
Verilog has system function $random, which can be used to generate random input
vectors. With this approach,we can generate values which we wouldnt have got, if
listed manually. In this topic I would like to discuss what natural things happening
behind $random and how we use it in different manners.

17
3
Semi Design

module Tb();
integer address; We have seen how to generate random
initial begin numbers.But the numbers randge from -
repeat(5) (2**32 -1) to 2 **32. Most of the time,
#1 address = $random; the requirement is dont need this range.
end For example, take a memory. The
address starts from 0 to some 1k or
initial 1m.Generating a random address which
$monitor("address = %0d;",address); DUT is not supporting is meaning less.
endmodule In verilog there are no constructs to
constraint randomization. Following
// simulation result example demonstrated how to generate
address = 303379748; random number between 0 to 10.Using %
address = -1064739199; operation,the remainder of any number is
address = -2071669239; always between 0 to 10.
address = -1309649309;
17
address = 112818957; 4
Semi Design

module Tb();
integer add_1;
// simulation result
initial begin
add_1 = 8;
repeat(5)
add_1 = 4294967287;
begin #1;
add_1 = 4294967295;
add_1 = $random % 10;
add_1 = 9;
end
add_1 = 9;
end

initial
$monitor("add_1 = %0d",add_1);
endmodule

17
5
Semi Design
module Tb();
integer add_2; The above example shows the generation
reg [31:0] add_1; of numbers from 0 to N. Some
integer add_3; specification require the range to start
initial begin from non Zero number. MIN +
repeat(5) {$random} % (MAX - MIN ) will
begin #1; generate random numbers between MIN
add_1 = $random % 10; and MAX.
add_2 = {$random} %10 ;
add_3 = $unsigned($random) %10 ; // simulation result
end add_3 = 7;add_2 = 7;add_1 = 8
end add_3 = 7;add_2 = 7;add_1 = 4
add_3 = 1;add_2 = 2;add_1 = 4
initial add_3 = 7;add_2 = 8;add_1 = 9
$monitor("add_3 = %0d;add_2 = %0d;add_1 = add_3 = 9;add_2 = 2;add_1 = 9
%0d",add_3,add_2,add_1);
endmodule
17
6
Semi Design

module Tb(); Now how to generate a random number


integer add; between two ranges? The number should
initial begin be between MIN1 and MAX1 or MIN2
repeat(5) and MAX2. The following example
begin #1; show how to generate this specification.
add = 40 + {$random} % (50 - 40) ;
$display("add = %0d",add);
// simulation result
end
add = 48
end
add = 47
endmodule
add = 47
add = 47
add = 47

177
Semi Design

module Tb();
integer add; All the random numbers generated above
initial are 32 bit vectors, which is not always
begin the same requirement. For example, to
repeat(5) generate a 5 bit and 45 bit vector random
begin #1; number, the following method can be
if( $random % 2) used.
add = 40 + {$random} % (50 - 40) ;
else
// simulation result
add = 90 + {$random} % (100 - 90) ;
add = 97
$display("add = %0d",add);
add = 47
end
add = 47
end
add = 42
endmodule
add = 49

17
8
Semi Design

module Tb();
integer num_1,num_2,tmp; All the above examples show that the
initial random numbers are integers only. In
begin verilog there is no special construct to
repeat(5) generate a random real number.The
begin following method shows generation of
num_1 = ($random / 3)*3; random real numbers.
num_2 = ($random / 5)*5;
$display("num_1 = %d,num_2 = %d",num_1,num_2);
end
end
endmodule
// simulation result
num_1 = 303379746,num_2 = -1064739195
num_1 = -2071669239,num_2 = -1309649305
num_1 = 112818957,num_2 = 1189058955
num_1 = -1295874969,num_2 = -1992863210 17
9
num_1 = 15983361,num_2 = 114806025
Semi Design

module Tb();
integer num_1,num_2,num_3;
real r_num; To generate random real number , system
initial begin function $bitstoreal can also be used.
repeat(5)
begin #1;
num_1 = $random;
num_2 = $random;
num_3 = $random;
r_num = num_1 + ((10)**(-(num_2)))*(num_3);
$display("r_num = %e",r_num);
end // simulation result
end r_num = -2.071669e+03
endmodule r_num = 2641.189059e+013
r_num = 976361.598336e+01
r_num = 57645.126096e+02
r_num = 24589.097015e+0 18
0
Semi Design

module Tb();
real r_num;
initial begin
repeat(5)
begin #1;
r_num = $bitstoreal({$random,$random});
$display("r_num = %e",r_num);
end
end
endmodule

If you want more control over // simulation result


randomizing real numbers interms of r_num = 1.466745e-221
sign, exponential and mantissa, use r_num = -6.841798e-287
$bitstoreal() as shown in example below. r_num = 2.874848e-276
For positive numbers use sgn = 0 and for r_num = -3.516622e-64
negative numbers use sgn = 1 . r_num = 4.531144e-304 181
Semi Design
module Tb();
reg sgn; Some times it is required to generate
reg [10:0] exp; random numbers without repetition. The
reg [51:0] man; random numbers should be unique. For
real r_num; example,to generate 10 random numbers
initial begin between 0 to 9 without repetition, the
repeat(5) following logic can be used.
begin
sgn = $random;
exp = $random;
man = $random;
r_num = $bitstoreal({sgn,exp,man}); // simulation result
$display("r_num = %e",r_num); r_num = 3.649952e+193
end r_num = -1.414950e-73
end r_num = -3.910319e-149
endmodule r_num = -4.280878e-196
r_num = -4.327791e+273
18
2
module Tb(); Random number returned by $random system
integer num,i,j,index; function should be deterministic, i.e when ever we
integer arr[9:0]; run with simulator it should return values in same
reg ind[9:0]; sequence. Otherwise the bug found today cant be
reg got; found return. For this purpose it has one argument
initial begin called seed. The seed parameter controls the
index=0; numbers that $random returns, such that different
for(i=0;i<10;i=1+1) seeds generate different random streams. The seed
begin arr[i] = i; ind[i] = 1; parameter shall be either a reg, an integer, or a
end time variable. The seed value should be assigned
for(j = 0;j<10; j=j+1) to this variable prior to calling $random.
begin got = 0;
while(got == 0) // simulation result
begin | num= 8 || num= 7 || num= 5
index = { $random } % 10; || num= 2 || num= 1 || num= 9
if(ind[index] == 1) begin ind[index] = 0; end || num= 6 || num= 4 || num= 0
got = 1; end || num= 3 |
num = arr[index]; endmodule
18
end end 3
$write("| num=%2d |",num);
Semi Design
module Tb();
integer num,seed,i,j;
initial begin
for(j = 0;j< 10; i=i+1)
begin // simulation result
num = { $random(seed) } % 10; seed is 0 | num= 8 || num= 7 || num= 7 || num= 7 ||
$write("| num=%2d |",num); num= 7 || num= 7 || num= 5 || num= 2 || num= 1 ||
end num= 9 |
$display(" "); seed is 1 | num= 8 || num= 8 || num= 2 || num= 2 ||
end num= 6 || num= 3 || num= 8 || num= 5 || num= 5 ||
end num= 5 |
endmodule seed is 2 | num= 8 || num= 1 || num= 0 || num= 5 ||
num= 0 || num= 8 || num= 6 || num= 7 || num= 1 ||
num= 6 |
seed is 3 | num= 8 || num= 2 || num= 2 || num= 3 ||
num= 8 || num= 6 || num= 1 || num= 4 || num= 3 ||
num= 9 |
18
4
Semi Design
module Tb();
integer num_1,num_2,seed; // simulation result
initial begin num_1 = 20,num_2 = 50
seed = 10; num_1 = 23,num_2 = 55
repeat(5) num_1 = 22,num_2 = 54
begin #1; num_1 = 25,num_2 = 51
num_1 = $dist_uniform(seed,20,25); num_1 = 23,num_2 = 55
num_2 = $dist_uniform(seed,50,55);
$display("num_1 = %d,num_2 = %d",num_1,num_2);
end
end
endmodule $dist_uniform(seed, min, max) is similar to min +
{$random(seed)}%(max-min+1), the difference is that in $dist_uniform
the distribution is uniform. $dist_uniform returns a number between
min and max. In the $dist_uniform function, the start and end
parameters are integer inputs that bound the values returned. The start
value should be smaller than the end value.
18
5
Semi Design

SystemVerilog CRV
SystemVerilog Constrained Random Stimulus Generation:
We have seen how to get random values and constrain them. These constraints are at
very low level of abstraction. Todays verification needs a better way to describe the
constraints. SystemVerilog has randomization constructs to support todays
verification needs.
Following are the features of SystemVerilog which support Constraint Random
Verification (CRV) :
1) Constraints : Purely random stimulus takes too long to generate interesting
scenarios. Specify the interesting subset of all possible stimulus with constraint blocks.
These are features provided by SystemVerilog for constraining randomness. Random
variable generated in verilog Boolean expressions, foreach (for constraining elements
18
of array), set membership, inline constraints, rand case, rand sequence, Conditional 6
constraints and implication constraints.
Semi Design
2) Randomization : random function, constrained and unconstrained randomization,
uniform distribution, weighted distribution, weighted range, weighted case, pre
randomization, post randomization, declaration of random variable and non
repeating sequence.

3) Dynamic constraints : inline constraints, guarded constraints, disabling/enabling


constraints, disabling/enabling random variables and overriding of constraint blocks.

4) Random Stability : Thread stability, object stability and manual seeding.

In verilog only system functions like $random are used for stimulus generation. In
SystemVerilog, constraint random stimulus can be generated in following ways.

18
7
Random Number Generator System Functions: Semi Design

In addition to the system function which are in verilog, SystemVerilog has


$urandom() and $urandom_range(). $urandom() and $urandom_range() returns a
unsigned values.
The following example demonstrates random generation of unsigned numbers.

module Tb();
integer unsigned address;
// simulation result
initial begin
address = 3468265955;
repeat(5)
address = 541037099;
begin
address = 3836988758;
address = $urandom();
address = 3611785217;
$display("address = %d;",address);
address = 978699393;
end
end
endmodule

18
8
Semi Design
$urandom_range:
The $urandom_range() function returns an unsigned integer within a specified
range. The syntax for $urandom_range() is as follows: function int unsigned
$urandom_range( int unsigned maxval,int unsigned minval = 0 ); The function
shall return an unsigned integer in the range of maxval ... minval.

module Tb(); // simulation result


integer num_1,num_2; num_1 = 25,num_2 = 55
initial begin num_1 = 22,num_2 = 55
repeat(5) num_1 = 23,num_2 = 52
begin #1; num_1 = 21,num_2 = 54
num_1 = $urandom_range(25,20); num_1 = 25,num_2 = 54
num_2 = $urandom_range(55,50);
$display("num_1 = %0d,num_2 = %0d",num_1,num_2);
end
end
endmodule
18
9
Semi Design

If minval is omitted, the function shall


return a value in the range of maxval ...
0.

module Tb(); // simulation result


integer num_1,num_2; num_1 = 3,num_2 = 5
initial begin num_1 = 2,num_2 = 5
repeat(5) num_1 = 1,num_2 = 2
begin #1; num_1 = 3,num_2 = 4
num_1 = $urandom_range(3); num_1 = 1,num_2 = 4
num_2 = $urandom_range(5);
$display("num_1 = %0d,num_2 = %0d",num_1,num_2);
end
end
endmodule

19
0
Semi Design

If maxval is less than minval, the arguments are


automatically reversed so that the first argument is
larger than the second argument.

module Tb(); // simulation result


integer num_1,num_2; num_1 = 25,num_2 = 55
initial begin num_1 = 22,num_2 = 55
repeat(5) num_1 = 23,num_2 = 52
begin #1; num_1 = 21,num_2 = 54
num_1 = $urandom_range(20,25); num_1 = 25,num_2 = 54
num_2 = $urandom_range(50,55);
$display("num_1 = %0d,num_2 = %0d",num_1,num_2);
end
end
endmodule

191
Semi Design

Scope Randomize Function:


The scope randomize function, randomize(), enables users to randomize data in the
current scope.Variables which are passed as arguments are randomized and there is
no limit on the number of arguments.For simpler applications,randomize() function
leads to stright farward implimentation.This gives better control over the
$random,as it allows to add constraints using inline constraints and constraint
solver gives valid solution.Variables which are in the constraint block and not
passed as arguments to randomize() function are not randomized.In the following
example Variable Var is randomized and MIN is not randomized.

19
2
Semi Design
module scope;
integer Var;
initial begin
for ( int i = 0;i<7;i++);
if( randomize(Var))
$display(" Randomization sucsessfull : Var = %0d ",Var);
else
$display("Randomization failed");
$finish;
end // simulation result
endmodule Randomization sucsessfull : Var = -826701341
Randomization sucsessfull : Var = 541037099
Randomization sucsessfull : Var = -457978538
Randomization sucsessfull : Var = -683182079
Randomization sucsessfull : Var = 978699393
Randomization sucsessfull : Var = 717199556
Randomization sucsessfull : Var = 1114265683
19
3
Scope randomize function gives better control over the
$random, as it allows to add constraints using inline
module scope; constraints and constraint solver gives valid solution.
integer Var; Variables which are in the constraint block and not
integer MIN; passed as arguments to randomize() function are not
initial begin randomized. In the following example Variable Var is
MIN = 50; randomized and MIN is not randomized.
for ( int i = 0;i< 100 ; i=i+1)
if( randomize(Var) with { Var < 100 ; Var > MIN ;})
$display(" Randomization sucsessfull : Var = %0d Min = %0d",Var,MIN);
else
$display("Randomization failed"); // simulation result
$finish; Randomization sucsessfull : Var = 94 Min = 50
end Randomization sucsessfull : Var = 69 Min = 50
endmodule Randomization sucsessfull : Var = 53 Min = 50
Randomization sucsessfull : Var = 71 Min = 50
Randomization sucsessfull : Var = 51 Min = 50
Randomization sucsessfull : Var = 78 Min = 50 19
Randomization sucsessfull : Var = 95 Min = 50 4
Semi Design
Randomizing Objects:
Generating random stimulus within objects :
SystemVerilog allows object-oriented programming for random stimulus generation,
subjected to specified constraints. During randomization, variables declared as rand
or randc inside class are only considered for randomization. Built-in randomize()
method is called to generate new random values for the declared random variables.
program s_s; // simulation result
class Simple; Randomization sucsessfull : Var = -82993358
rand integer Var; Randomization sucsessfull : Var = -112342886
endclass Randomization sucsessfull : Var = -867551972
Simple obj; Randomization sucsessfull : Var = -34537722
initial begin obj = new(); Randomization sucsessfull : Var = 1977312553
repeat(5)
if(obj.randomize())
$display(" Randomization successful : Var = %0d ",obj.Var);
else
$display("Randomization failed"); 19
end 5

endprogram
Semi Design
Random Unpacked Structs:
SystemVerilog allows unpackedstructs to be declared as rand for randomization. Only
members of struct which are declared as rand or randc are only randomized. randc is
not allowed on unpacked structs. If Struct is not declared as rand, solver considers it as
state variable.
class Rand_struct;
typedef struct { randc int Var1; int Var2; } Struct_t;
rand Struct_t Str; // To randomize Var1 and Struct_t type has to declared as rand
endclass
program stru_rand_6;
Rand_struct RS ;
initial begin // simulation result
RS = new(); Var1 : -430761355
repeat(5) Var1 : 424439941
if(RS.randomize()) Var1 : -1129955555
$display(" Var1 : %d",RS.Str.Var1); Var1 : 1781908941
end Var1 : -752252755 `
19
endprogram 6
Semi Design

program ran_c;
class Ch; Simillar to struct, the same can be achived using class
rand int Var1; by calling the randomize() function on the object,
int Var2; which is created by using class.
endclass
class R_c;
rand Ch obj; // To randomize Var1,Class_t type has to declared as rand function
function new();
obj = new(); // simulation result
endfunction Var1 : 733126180 Var2 : 0
end Var1 : -119008195 Var2 : 0
Var1 : 342785185 Var2 : 0
R_c RC = new(); Var1 : 679818185 Var2 : 0
initial repeat(5) Var1 : -717162992 Var2 : 0
if(RC.randomize())
$display(" Var1 : %0d Var2 : %0d",RC.obj.Var1,RC.obj.Var2);
endprogram 19
7
Semi Design
Semi Design

Randomization
Randomization is the process of making something random; SystemVerilog
randomization is the process of generating random values to a variable. Verilog
has a $random method for generating the random integer values. This is good for
randomizing the variables alone, but it is hard to use in case of class object
randomization. for easy randomization of class properties, SystemVerilog
provides rand keyword and randomize() method.

19
9
Semi Design

Random Variable
The class variables which get random values on randomization are called random
variables. In order to make variables as random variables, Class variables need to
be declared using the rand and randc type-modifier keywords.
Following types can be declared as rand and randc,
• singular variables of any integral type
• arrays
• arrays size
• object handle’s

20
0
Semi Design
rand keyword:
Variables declared with the rand keyword are standard random variables. Their values
are uniformly distributed over their range.
//Syntax:
rand bit [3:0] A;
A is a 4-bit unsigned integer with a range of 0 to 15. on randomization this variable
shall be assigned any value in the range 0 to 15 with equal probability.
randc keyword:
randc is random-cyclic. For the variables declared with the randc keyword, on
randomization variable values don’t repeat a random value until every possible value
has been assigned.
//Syntax:
randc bit wr_rd;
In order to randomize the object variables, the user needs to call randomize()
method. 20
1
//Example:
object.randomize();
Semi Design
class packet;
rand bit [2:0] addr1;
randc bit [2:0] addr2;
endclass
// simulation result
addr1 = 6 addr2 = 4
module rand_methods;
addr1 = 4 addr2 = 3
initial begin
addr1 = 2 addr2 = 0
packet pkt;
addr1 = 6 addr2 = 6
pkt = new();
addr1 = 1 addr2 = 7
repeat(5) begin
pkt.randomize();
$display("\taddr1 = %0d \t addr2 = %0d",pkt.addr1,pkt.addr2);
end
end addr1 – takes the random value on every randomization
endmodule addr2 – takes the random value on every randomization, but takes
random value until every possible value has been assigned
20
2
Semi Design

Randomization Methods
SystemVerilog randomization provides a built-in method randomize. The
randomize() method generates random values for all the active random variables of
an object, subject to the active constraints. Variables declared with the rand keyword
will get random values on the object.randomize() method call.The randomize()
method returns 1 if the randomization is successful i.e on randomization it’s able to
assign random values to all the random variables, otherwise, it returns 0.

randomize method associated with below callbacks,


• pre_randomize
• post_randomize

20
3
Semi Design

pre randomize and post randomize methods

On calling randomize(), pre_randomize() and post_randomize() functions will get


called before and after the randomize call respectively
Users can override the pre_randomize() and post_randomize() functions
pre_randomize:
The pre_randomize function can be used to set pre-conditions before the object
randomization.
For example, Users can implement randomization control logic in pre_randomize
function. i.e randomization enable or disable by using rand_mode() method.
post_randomize:
The post_randomization function can be used to check and perform post-
conditions after the object randomization. 20
For example, Users can override the randomized values or can print the 4
randomized values of variables
Semi Design
Pre_randomize And Post_randomize:
Every class contains pre_randomize() and post_randomize() methods, which are
automatically called by randomize() before and after computing new random
values. When randomize() is called,it first invokes the pre_randomize() then
randomize() finally if the randomization is sucesusful only post_randomize is
invoked. These methods can be used as hooks for the user to perform operations
such as setting initial values and performing functions after assigning random
variables.

20
5
Semi Design
program pre_rand;
class simple;
function void pre_randomize;
$display(" PRE_RANDOMIZATION ");
endfunction

function void post_randomize; // simulation result


$display(" POST_RANDOMIZATION "); PRE_RANDOMIZATION
endfunction POST_RANDOMIZATION
endclass

simple obj = new();


Overriding of pre_randomize and post_randomize
initial
functions is allowed by child class. If parent class
void'(obj.randomize());
functions are not called when overriding
endprogram
pre_randomize() and post_randomize functions,
parent class function definations will be omitted.
20
6
Overriding of pre_randomize and post_randomize functions is allowed by child Semi Design
class. If parent class functions are not called when overriding pre_randomize() and
post_randomize functions, parent class function definations will be omitted.
class Base;
function void pre_randomize;
$display(" BASE PRE_RANDOMIZATION ");
endfunction
function void post_randomize;
$display(" BASE POST_RANDOMIZATION ");
endfunction
endclass

class Extend_1 extends Base;


function void pre_randomize;
$display(" EXTEND_1 PRE_RANDOMIZATION ");
endfunction
function void post_randomize;
$display(" EXTEND_1 POST_RANDOMIZATION "); 20
endfunction 7
endclass
Semi Design
class Extend_2 extends Base;
function void pre_randomize;
super.pre_randomize();
$display(" EXTEND_2 PRE_RANDOMIZATION ");
endfunction
function void post_randomize;
super.post_randomize();
$display(" EXTEND_2 POST_RANDOMIZATION ");
endfunction

endclass program pre_post_16;


Base B = new();
Extend_1 E1 = new();
Extend_2 E2 = new();
initial begin
void'(B.randomize());
void'(E1.randomize());
void'(E2.randomize()); 20
8
end endprogram
Semi Design
// simulation result
BASE PRE_RANDOMIZATION
BASE POST_RANDOMIZATION
EXTEND_1 PRE_RANDOMIZATION
EXTEND_1 POST_RANDOMIZATION
BASE PRE_RANDOMIZATION
EXTEND_2 PRE_RANDOMIZATION
BASE POST_RANDOMIZATION
EXTEND_2 POST_RANDOMIZATION

In the extended class EXTEND_1, when overiding the builtin functions, parent
class functions are not called. In the extended class EXTEND_2, super.methods
are called which invokes the parent class methods also.

20
9
The pre_randomize() and post_randomize() methods are not virtual. Semi Design
However because they are automatically called by the randomize() method, which is
virtual, they appear to behave as virtual methods. This example demonstrates that these
functions are not virtual but simulation results show that, it executed extended class
definition functions. Extended class object is created and assigned to base class object.
Calls to pre_randomize and post_randomize calls in object B ,executed the extended
class definitions.
class Base;
function void pre_randomize;
$display(" BASE PRE_RANDOMIZATION ");
endfunction
virtual function void post_randomize;
$display(" BASE POST_RANDOMIZATION ");
endfunction class Extend extends Base;
endclass function void pre_randomize;
$display(" EXTEND PRE_RANDOMIZATION ");
endfunction
function void post_randomize; 21
0
$display(" EXTEND POST_RANDOMIZATION ");
endfunction endclass
Semi Design
program pre_post_17;
Base B = new();
Extend E = new();
initial begin
B=E;
void'(B.randomize());
void'(E.randomize());
end
endprogram

// simulation result
There should be compilation error

In the above example compilation error is due to the declaration of


post_randmoize() function as virtual. By removing the virtual keyword for the
post_randomize() function, calling the randomize() function by parent and child
class, both will execute functions of child class only. Which is a virtual
function behaviour. 211
class Base; Semi Design
function void pre_randomize;
$display(" BASE PRE_RANDOMIZATION ");
endfunction program pre_post_17; Base B ;
function void post_randomize; Extend E = new();
$display(" BASE POST_RANDOMIZATION "); initial begin
endfunction B=E;
endclass void'(B.randomize());
void'(E.randomize());
class Extend extends Base; end
function void pre_randomize; endprogram
$display(" EXTEND PRE_RANDOMIZATION ");
endfunction
function void post_randomize;
$display(" EXTEND POST_RANDOMIZATION ");
endfunction // simulation result
endclass EXTEND PRE_RANDOMIZATION
EXTEND POST_RANDOMIZATION 21
EXTEND PRE_RANDOMIZATION 2
EXTEND POST_RANDOMIZATION
class Base; Semi Design
function void pre_randomize;
$display(" BASE PRE_RANDOMIZATION ");
endfunction
function void post_randomize;
$display(" BASE POST_RANDOMIZATION ");
endfunction
endclass
// simulation result
BASE PRE_RANDOMIZATION
class Extend extends Base;
BASE POST_RANDOMIZATION
endclass
If the class is a derived class and no user-defined
program pre_post_19; implementation of pre_randomize() and
Extend E = new(); post_randomize() exists, then pre_randomize() and
initial void'(E.randomize()); post_randomize() will automatically invoke
endprogram super.pre_randomize() and super.post_randomize()
respectively
21
3
Semi Design
class Base;
function void pre_randomize;
$display(" BASE PRE_RANDOMIZATION \n");
program pre_post;
endfunction
Base B;
function void post_randomize;
Extend E = new();
$display(" BASE POST_RANDOMIZATION \n");
initial begin
endfunction
B = E;
endclass
if(B.randomize())
$display(" randomization done \n");
class Extend extends Base;
end
function void pre_randomize;
endprogram
super.pre_randomize();
$display(" EXTENDED PRE_RANDOMIZATION \n");
endfunction
function void post_randomize;
$display(" EXTENDED POST_RANDOMIZATION \n");
endfunction
endclass 21
4
Semi Design

// simulation result
BASE PRE_RANDOMIZATION
EXTENDED PRE_RANDOMIZATION
EXTENDED POST_RANDOMIZATION
randomization done

Results show that, if extended class is having new definition, explicitly


super.pre_ or post_ has to be called. super.pre_randomize() is called in
extended class, but super.post_randomize() is not called in above example. See
the difference in results. If a class A instance is in Class B,To randomize class
A by calling the randomize function of class B,Class A instance has to be
declared as rand variable.

21
5
Semi Design

Disable randomization
The variable declared without rand or randc will not get random values on
randomization. what if for some reason it is required not to generate a random value
for a random variable. Yes, it is possible to disable the randomization of a variable
by using the systemverilog randomization method rand_mode.
rand_mode methods:
The rand_mode() method is used to disable the randomization of a variable declared
with the rand/randc keyword.
• rand_mode(1) means randomization enabled
• rand_mode(0) means randomization disabled
• The default value of rand_mode is 1, i.e enabled
21
6
Semi Design
• Once the randomization is disabled, it is required to make rand_mode(1) enable
back the randomization
• rand_mode can be called as SystemVerilog method, the randomization
enables/disable status of a variable can be obtained by calling
vairble.rand_mode().
• The rand_mode method returns 1 if randomization is enabled else returns 0

// rand_mode syntax

<object_hanlde>.<variable_name>.rand_mode(enable);
//enable = 1, randomization enable
//enable = 0, randomization disable

21
7
randomization disable examples: Semi Design

// without randomization disable


class packet; In the example,
rand byte addr; The class packet has random variables addr and
rand byte data; data, on randomization, these variables will get
endclass random value.

module rand_methods;
initial begin
packet pkt;
pkt = new(); // simulation result
addr = 110 data = 116
//calling randomize method
pkt.randomize();

$display("\taddr = %0d \t data = %0d",pkt.addr,pkt.data);


end
endmodule 21
8
randomization disable for a class variable: Semi Design

class packet;
rand byte addr; In the example,
rand byte data; The class packet has random variables addr and
endclass data, randomization is disabled for a variable addr,
module rand_methods; on randomization only data will get random value.
initial begin The addr will not get any random value.
packet pkt; rand_mode() method is called in a display to know
pkt = new(); the status.

pkt.addr.rand_mode(0); //disable rand_mode of addr variable of pkt


pkt.randomize(); //calling randomize method

$display("\taddr = %0d \t data = %0d",pkt.addr,pkt.data);


// simulation result
$display("\taddr.rand_mode() = %0d \t data.rand_mode() = addr = 0 data = 110
%0d",pkt.addr.rand_mode(),pkt.data.rand_mode()); addr.rand_mode() = 0
end data.rand_mode() = 1 21
endmodule 9
randomization disable for all class variable: Semi Design

class packet; randomization for all the class variable is disabled


rand byte addr; by calling obj.rand_mode(0);
rand byte data;
endclass // simulation result
module rand_methods; addr.rand_mode() = 1 data.rand_mode() = 1
initial begin addr = 0 data = 0
packet pkt; addr.rand_mode() = 0 data.rand_mode() = 0
pkt = new();
$display("\taddr.rand_mode() = %0d \t data.rand_mode() =
%0d",pkt.addr.rand_mode(),pkt.data.rand_mode());

pkt.rand_mode(0); //disable rand_mode of object


pkt.randomize(); //calling randomize method

$display("\taddr = %0d \t data = %0d",pkt.addr,pkt.data);


$display("\taddr.rand_mode() = %0d \t data.rand_mode() =
%0d",pkt.addr.rand_mode(),pkt.data.rand_mode()); 22
end 0
endmodule
Semi Design

Constraint Block
Constraint block contains declarative statements which restrict the range of variable or
defines the relation between variables. Constraint programming is a powerful method
that lets users build generic, resuble objects that can be extended or more constrained
later. constraint solver can only support 2 state values. If a 4 state variable is used,
solver treates them as 2 state variable.. Constraint solver fails only if there is no
solution which satisfies all the constraints. Constraint block can also have nonrandom
variables, but at least one random variable is needed for randomization. Constraints are
tied to objects. This allows inheritance, hierarchical constraints, controlling the
constraints of specific object.

// Synatx:
constraint <constraint_block_name> { <condition/expression>;
...
22
<condition/expression>; } 1
Semi Design
Constraint Inheritance:
Like class members, constraints also will get inherited from parent class to child class.
Constraint blocks can be overridden by writing constraint block with the same name as
in parent class.
In the example below,
Constraint to an addr > 5 of the parent class is overridden with constraint addr < 5 in
child class.

class packet;
rand bit [3:0] addr;
constraint addr_range { addr > 5; }
endclass

class packet2 extends packet;


constraint addr_range { addr < 5; } //overriding constraint of parent class
endclass
22
2
Semi Design

module cons;
initial begin
packet pkt1;
// simulation result
packet2 pkt2;
pkt1:: addr = 14
pkt1:: addr = 10
pkt1 = new();
pkt1:: addr = 9
pkt2 = new();
pkt1:: addr = 8
repeat(5) begin
pkt1:: addr = 9
pkt1.randomize();
$display("\tpkt1:: addr = %0d",pkt1.addr);
pkt2:: addr = 0
end
pkt2:: addr = 1
repeat(5) begin
pkt2:: addr = 2
pkt2.randomize();
pkt2:: addr = 0
$display("\tpkt2:: addr = %0d",pkt2.addr);
pkt2:: addr = 2
end
end
endmodule 22
3
Semi Design
class Base;
rand integer Var;
constraint range { Var < 100 ; Var > 0 ;}
endclass

class Extended extends Base;


constraint range { Var < 100 ; Var > 50 ;} // Overrighting the Base class constraints.
endclass

program inhe_31;
Extended obj;
initial begin
obj = new();
for(int i=0 ; i < 100 ; i++)
if(obj.randomize())
$display(" Randomization sucsessfull : Var = %0d ",obj.Var);
else
$display("Randomization failed"); 22
end 4
endprogram
Semi Design

// simulation result
Randomization sucsessfull : Var = 91
Randomization sucsessfull : Var = 93
Randomization sucsessfull : Var = 77
Randomization sucsessfull : Var = 68
Randomization sucsessfull : Var = 67
Randomization sucsessfull : Var = 52
Randomization sucsessfull : Var = 71
Randomization sucsessfull : Var = 98
Randomization sucsessfull : Var = 69

Adding new constraints in the derived class, can change the solution space.
Solver has to solve both constraints defined in base class and derived class. In
the example given below, Constraint range_1 defines the range that Var is
between 0 to 100.Constraint range_2 limits the Var to be greater than 50 and
solver has to solve both the constraints and the solution space is between 50 to
22
100. 5
Semi Design
class Base;
rand integer Var;
constraint range_1 { Var < 100 ; Var > 0 ;}
endclass

class Extended extends Base;


constraint range_2 { Var > 50 ;} //Adding new constraints in the Extended class
endclass

program inhe_32; // simulation result


Extended obj; Var = 91 :: Var = 93 :: Var = 77 :: Var = 68 ::
initial begin obj = new(); Var = 67 :: Var = 52 :: Var = 71 :: Var = 98 ::
for(int i=0 ; i < 20 ; i++) Var = 69 :: Var = 70 :: Var = 96 :: Var = 88 ::
if(obj.randomize()) Var = 84 :: Var = 99 :: Var = 68 :: Var = 83 ::
$write(": Var = %0d :",obj.Var); Var = 52 :: Var = 72 :: Var = 93 :: Var = 80 :
else
$display("Randomization failed");
end 22
6
endprogram
Overrighting Constraints : Semi Design
The randomize() task is virtual. Accordingly it treats the class constraints in a virtual
manner. When a named constraint is redefined in an extended class, the previous
definition is overridden and when casting extended class to base class does not change
the constraint set.
class Base;
rand integer Var;
constraint range { Var < 100 ; Var > 0 ;} endclass
class Extended extends Base;
constraint range { Var == 100 ;} // Overrighting the Base class constraints
endclass
program inhe_33;
Extended obj_e; Base obj_b;
initial begin obj_e = new();
obj_b = obj_e;
for(int i=0 ; i < 7 ; i++)
if(obj_b.randomize())
$display(" Randomization sucsessfull : Var = %0d ",obj_b.Var); 22
else $display("Randomization failed"); 7

end endprogram
Semi Design

// simulation result
Randomization sucsessfull : Var = 100
Randomization sucsessfull : Var = 100
Randomization sucsessfull : Var = 100
Randomization sucsessfull : Var = 100
Randomization sucsessfull : Var = 100
Randomization sucsessfull : Var = 100
Randomization sucsessfull : Var = 100
Randomization sucsessfull : Var = 100
Randomization sucsessfull : Var = 100

22
8
Semi Design
class Base;
rand integer Var;
constraint range_1 { Var < 100 ; Var > 0 ;}
endclass
class Extended extends Base;
constraint range_2 { Var > 50 ;}
endclass
program inhe_34;
Extended obj_e;
Base obj_b;
initial begin obj_e = new();
obj_b = obj_e;
for(int i=0 ; i < 10 ; i++)
if(obj_b.randomize())
$display(" Randomization sucsessfull : Var = %0d ",obj_b.Var);
else
$display("Randomization failed");
end 22
endprogram 9
Semi Design

// simulation result
Randomization sucsessfull : Var = 91
Randomization sucsessfull : Var = 93
Randomization sucsessfull : Var = 77
Randomization sucsessfull : Var = 68
Randomization sucsessfull : Var = 67
Randomization sucsessfull : Var = 52
Randomization sucsessfull : Var = 71
Randomization sucsessfull : Var = 98
Randomization sucsessfull : Var = 69
Randomization sucsessfull : Var = 70

23
0
Semi Design

Inline Constraint
Inline constraints allows to add extra constraints to already existing constraints which
are declared inside class. If you have constraints already defined for variable var,
solver solves those constraints along with the in-line constraints.
class inline;
rand integer Var;
constraint default_c { Var > 0 ; Var < 100;}
endclass
program inline_p_35;
inline obj;
initial begin obj = new();
repeat(5)
if( obj.randomize() with { Var == 50;})
$display(" Randodmize sucessful Var %d ",obj.Var); 23
1
else $display(" Randomization failes");
end endprogram
Semi Design

// simulation result
Randodmize sucessful Var 50
Randodmize sucessful Var 50
Randodmize sucessful Var 50
Randodmize sucessful Var 50
Randodmize sucessful Var 50

In the above example, by default only default_c constraints are considered.


Using inline constraint Var == 50 resulted value on variable Var based on both
the default_c and inline constraints.

23
2
Semi Design

Global Constraint
SystemVerilog allows to have constraints between variables of different objects. These
are called global constraints. Using the hierarchy notation, constraints can be applied
on variables of different objects. When object is randomized, so are the contained
objects and all other constraints are considered simultaneously.

23
3
Semi Design
class child;
rand int Var1;
endclass
class parent;
rand child child_obj;
rand int Var2;
constraint global_c { Var2 < child_obj.Var1 ;}
function new();
child_obj = new(); // simulation result
endfunction Var1 = 903271284 ,Var2 = -1102515531
endclass Var1 = 2112727279 ,Var2 = -838916208
program random_37; Var1 = 1614679637 ,Var2 = 1572451945
initial for(int i=0;i<5; i=i+1) Var1 = 1284140376 ,Var2 = -373511538
begin Var1 = 463675676 ,Var2 = -516850003
parent parent_obj = new();
void'(parent_obj.randomize ());
$display(" Var1 = %0d ,Var2 = %0d ",parent_obj.child_obj.Var1,parent_obj.Var2 ); 23
end endprogram 4
Semi Design

Constraint Mode
Disabling Constraint Block:
SystemVerilog supports to change the status of constraint block dynamically. To
change the status of a Constraint block, built in constraint_mode() method is
used. By default all the constraint blocks are active. When it is called as task, the
arguments to the task determines the operation to be performed. If the arguments
are 0 or 1, then all the constraints blocks are effected .

23
5
Semi Design
class rand_mo;
rand integer Var1; // simulation result
rand integer Var2; Var1 : 20 Var2 : 10
constraint Var_1 { Var1 == 20;} Var1 : 733126180 Var2 : -119008195
constraint Var_2 { Var2 == 10;} Var1 : 20 Var2 : 10
endclass

program rand_mo_p_38;
rand_mo obj = new();
initial begin
void'(obj.randomize()); //By default all constraints are active.
$display(" Var1 : %d Var2 : %d ",obj.Var1,obj.Var2);
obj.constraint_mode(0); //Both constraints Var_1 and Var_2 are turned off.
void'(obj.randomize());
$display(" Var1 : %d Var2 : %d ",obj.Var1,obj.Var2);
obj.constraint_mode(1); //Both constraints Var_1 and Var_2 are turned on.
void'(obj.randomize());
$display(" Var1 : %d Var2 : %d ",obj.Var1,obj.Var2); 23
end endprogram 6
Semi Design

Randomization Controlability
Controlability :
Additional to the controllability feauters supported by SystemVerilog, following
are more points with which controlabiity can be achieved. In the following
example, MACROS MIN_D and MAX_D are defined. Set the MIN and MAX
values in the pre_randomize as shown. As MIN_D and MAX_D are macros, they
can be assigned from command line. Biggest disadvantage for the method shown
below is dynamic controllability.

23
7
Semi Design
`define MAX_D 100
`define MIN_D 50
class Base;
rand integer Var;
integer MIN,MAX;
constraint randge { Var < MAX ; Var > MIN ;}
function void pre_randomize ();
this.MIN = `MIN_D;
this.MAX = `MAX_D;
$display( " PRE_RANDOMIZE : MIN = %0d , MAX = %0d ",MIN,MAX);
endfunction
endclass
program inhe_42;
Base obj;
initial begin obj = new();
for(int i=0 ; i < 100 ; i++) if(obj.randomize())
$display(" Randomization sucsessfull : Var = %0d ",obj.Var);
else 23
$display("Randomization failed"); 8
end endprogram
// simulation result Semi Design
PRE_RANDOMIZE : MIN = 50 , MAX = 100
Randomization sucsessfull : Var = 91
PRE_RANDOMIZE : MIN = 50 , MAX = 100
Randomization sucsessfull : Var = 93
PRE_RANDOMIZE : MIN = 50 , MAX = 100
Randomization sucsessfull : Var = 77
PRE_RANDOMIZE : MIN = 50 , MAX = 100
Randomization sucsessfull : Var = 68
PRE_RANDOMIZE : MIN = 50 , MAX = 100
Randomization sucsessfull : Var = 67
PRE_RANDOMIZE : MIN = 50 , MAX = 100
Randomization sucsessfull : Var = 52
PRE_RANDOMIZE : MIN = 50 , MAX = 100
Randomization sucsessfull : Var = 71
PRE_RANDOMIZE : MIN = 50 , MAX = 100
Randomization sucsessfull : Var = 98….etc

As in this example,a single object is created and randomized 100 times. Due to 23
this,pre_reandomize is called 100 times, which may not be preferred. By assigning the values9
while declaration itself this can be avoided. Simpler way to achieve the above logic.
Semi Design
`define MAX_D 100
`define MIN_D 50
class Base;
rand integer Var;
integer MIN = `MIN_D;
integer MAX = `MAX_D;
constraint range { Var < MAX ; Var > MIN ;}
endclass

program inhe_43;
Base obj;
initial begin
obj = new();
for(int i=0 ; i < 100 ; i++)
if(obj.randomize())
$display(" Randomization sucsessfull : Var = %0d ",obj.Var);
else $display("Randomization failed");
end 24
endprogram 0
Semi Design
// simulation result
Randomization sucsessfull : Var = 91
Randomization sucsessfull : Var = 93
Randomization sucsessfull : Var = 77
Randomization sucsessfull : Var = 68
Randomization sucsessfull : Var = 67
Randomization sucsessfull : Var = 52
Randomization sucsessfull : Var = 71
Randomization sucsessfull : Var = 98
Randomization sucsessfull : Var = 69
Randomization sucsessfull : Var = 70

With the above approach also, dynamic controlability is lost. For dynamic
controllability, define a task, pass this values as arguments when ever the
changed is needed.

24
1
class Base; Semi Design
rand integer Var;
integer MIN = 10,MAX = 20; // Define default values,If function set is not
called,with this it will work
constraint randge {Var < MAX ; Var > MIN ;}
task set (integer MIN,integer MAX);
this.MIN = MIN;
this.MAX = MAX;
$display( " SET : MIN = %0d , MAX = %0d ",MIN,MAX);
endtask
endclass if(obj.randomize())
program inhe_44; $display(" Randomization sucsessfull : Var = %0d ",obj.Var);
Base obj; else
initial begin $display("Randomization failed");
obj = new(); obj.set(50,100) ;
obj.set(0,100) ; for(int i=0 ; i < 5 ; i++)
for(int i=0 ; i < 5 ; i++) if(obj.randomize())
$display(" Randomization sucsessfull : Var = %0d ",obj.Var);
else 24
$display("Randomization failed"); 2

end endprogram
Semi Design
// simulation result
SET : MIN = 0 , MAX = 100
Randomization sucsessfull : Var = 24
Randomization sucsessfull : Var = 68
Randomization sucsessfull : Var = 43
Randomization sucsessfull : Var = 11
Randomization sucsessfull : Var = 4
SET : MIN = 50 , MAX = 100 #
Randomization sucsessfull : Var = 52
Randomization sucsessfull : Var = 71
Randomization sucsessfull : Var = 98
Randomization sucsessfull : Var = 69
Randomization sucsessfull : Var = 70

More simpler way to dynamically modifying the constraints is by modifying


the data members of class via object reference.
24
3
Semi Design

Static Constraints
SystemVerilog static constraints are similar to static class properties. A constraint
block can be defined as static by including the static keyword in its definition.
constraint block with the static keyword followed by constraint keyword is called as a
static constraint. the static constraint is shared across all the class instances.
•only the mode change of static constraint will get affected in all the instances
of a class
•mode change is enable or disable of a constraint by constrain_mode() method
•a static class can be enabled or disabled by any object handle of its class, mode
change with one object handle will reflect all other objects of same class type

// Syntax
static constraint constraint_name { ....; } 24
4
Semi Design
Non-static constraint:
In the below example,
The class packet has two instances pkt1 and pkt2. constraint addr_range is defined
to control the value of random variable addr.
On randomization, pkt1.addr and pkt2.addr will take value based on the constraint.
The constraint is disabled using a pkt2 handle. As constraint is non-static only for
pkt2 constraint will get disabled. On randomization, pkt1.addr will get value based
on the constraint.

24
5
class packet; Semi Design
rand bit [7:0] addr;
constraint addr_range { addr == 5; }
endclass
module static_constr;
initial begin
packet pkt1; packet pkt2;
pkt1 = new(); pkt2 = new();
$display("Before disabling constraint");
pkt1.randomize();
$display("\tpkt1.addr = %0d",pkt1.addr);
pkt2.randomize();
$display("\tpkt2.addr = %0d",pkt2.addr);
pkt2.addr_range.constraint_mode(0);
$display("After disabling constraint");
pkt1.randomize();
$display("\tpkt1.addr = %0d",pkt1.addr);
pkt2.randomize();
24
$display("\tpkt2.addr = %0d",pkt2.addr); 6
end
Semi Design
// simulation result
Before disabling constraint
pkt1.addr = 5
pkt2.addr = 5
After disabling constraint
pkt1.addr = 5
pkt2.addr = 134

24
7
Semi Design
class packet;
rand bit [7:0] addr;
static constraint addr_range { addr == 5; }
endclass
module static_constr;
initial begin
packet pkt1; packet pkt2;
pkt1 = new(); pkt2 = new();
$display("Before disabling constraint");
pkt1.randomize();
$display("\tpkt1.addr = %0d",pkt1.addr);
pkt2.randomize();
$display("\tpkt2.addr = %0d",pkt2.addr);
pkt2.addr_range.constraint_mode(0);
$display("After disabling constraint");
pkt1.randomize();
$display("\tpkt1.addr = %0d",pkt1.addr);
pkt2.randomize(); 24
$display("\tpkt2.addr = %0d",pkt2.addr); 8
end endmodule
Semi Design

// simulation result
Before disabling constraint
pkt1.addr = 5
pkt2.addr = 5
After disabling constraint
pkt1.addr = 22
pkt2.addr = 134

The example below is the same as the above example, the only change is the
constraint is made as static.
The constraint is disabled by using one of the object handles. as the constraint
is static in nature, the constraint will get disabled for both the objects.

24
9
Semi Design

Constraint Expression
A constraint_expression is any SystemVerilog expression or one of the constraint
specific operators( -> (Implication) and dist). Functions are allowed to certain
limitation. Operators which has side effects are not allowed like ++,--.

Set Membership:
A set membership is a list of expressions or a range. This operator searches for the
existences of the value in the specified expression or range and returns 1 if it is
existing.

25
0
Semi Design

class C_e;
rand integer Var;
constraint range { Var inside {0,1,[50:60],[90:100]}; }
function void post_randomize();
$write("%0d__",Var);
endfunction
endclass
program set;
// simulation result
C_e obj = new();
50__57__60__93__100__94__90__1__54__1
initial
00__
repeat(10)
void'(obj.randomize());
endprogram

25
1
Semi Design
If you want to define a range which is outside the set, use negation.

class C_e;
rand bit [0:2] Var;
constraint range { !( Var inside {0,1,5,6});}
function void post_randomize();
$write("%0d__",Var);
endfunction
endclass
program set;
C_e obj = new();
// simulation result
initial
7__4__4__4__7__2__2__3__2__7__
repeat(10)
void'(obj.randomize());
endprogram

25
2
Semi Design
class set_mem;
rand bit [0:2] Var;
endclass
Engineers often mistaken that set
membership operator is used only in
program set;
constraint block. It can also be used in other
set_mem obj = new();
scopes also.
initial begin
obj.Var = 1;
repeat(10) // simulation result
begin Var = 4
void'(obj.randomize()); Var = 5
while ( obj.Var inside {[1:5]}) Var = 1
begin Var = 1
$display("Var = %0d",obj.Var); Var = 2
break; Var = 2
end
end
end endprogram 25
3
Semi Design

Bidirectional Constraints
SystemVerilog constraints are solved bidirectionally, which means constraints on all
random variables will be solved parallel.
Consider a constraint example,

constraint c_name { if(a == 0) b == 1;


else b == 0; }

We see that ‘b’ is dependent on ‘a’.


but constraint solver see’s it as ‘a’ is dependent on ‘b’ and ‘b’ is dependent on ‘a’.
i.e if ‘b’ is inline constrained as ‘1’, in order to satisfy, ‘a’ should take the value ‘0’.
As constraints are considered from all the aspects, SystemVerilog constraints are
called as bidirectional constraints.
25
4
Bidirectional constraint example1: Semi Design

class packet;
rand bit [3:0] a;
rand bit [3:0] b;
rand bit [3:0] c;
constraint a_value { a == b + c; }
constraint b_value { b > 6; }
constraint c_value { c < 8; }
endclass

module bidirectional_constr;
initial begin
packet pkt;
pkt = new();
repeat(5)
begin
pkt.randomize();
$display("Value of a = %0d \tb = %0d \tc =%0d",pkt.a,pkt.b,pkt.c); 25
end end 5
endmodule
Semi Design
Value of a should be sum of b and c, b should be greater than 6 and c
should be less than 8. so in this case constraint solver will choose a
value to ‘a’ in such a way that it should be sum of b and c, also ‘b’ and
‘c’ should satisfies their constraint.

// simulation result
Value of a = 8 b = 8 c =0
Value of a = 0 b = 14 c =2
Value of a = 14 b = 14 c =0
Value of a = 6 b = 15 c =7
Value of a = 13 b = 11 c =2
Value of a = 8 b = 8 c =0
Value of a = 0 b = 14 c =2
Value of a = 14 b = 14 c =0
Value of a = 6 b = 15 c =7
Value of a = 13 b = 11 c =2
25
6
Bidirectional constraint example 2: Semi Design

class packet;
rand bit a;
rand bit b;
constraint a_value { a == 1; }
constraint b_value { if(a == 0) b == 1;
else b == 0; }
endclass

module bidirectional_const;
initial begin
packet pkt;
pkt = new();
pkt.randomize() with { b == 1; };
$display("Value of a = %0d \tb = %0d",pkt.a,pkt.b);
end
endmodule
25
7
Semi Design

In aboveexample,
Generation of value for b is depending on value of a.
i.e if(a == 0) b = 1;
this condition can be re-written as,
if(b == 1) a = 0;
but there is a constraint for ‘a’ that value for ‘a’ should be always ‘1’.
so ‘b’ should not take value of ‘1’ (to satisfy constraint if(a == 0) b ==
1;)
What if we make ‘b’ value as ‘1’ with inline constraint?

// simulation result
Constraints are inconsistent and cannot be solved.
Please check the inconsistent constraints being printed
above and rewrite them.
25
8
Semi Design

Variable ordering
Solve before is the constraint property. solve before is used inside the constraint
block to specify the order of constraint solving. If the variables are dependent, due
to the bidirectional nature of constraints value of one variable will influence the
value of another variable.
• solve before constraints are used to force the constraint solver to choose the order
in which constraints are solved.
• constraint solver will give equal weight-age to all the possible values. i.e On
multiple randomization solver should assign all the possible values.

25
9
Solve before constraint example: Semi Design

// without solve before


class packet;
rand bit a;
rand bit [3:0] b;
constraint a_b { (a == 1) -> b == 0; }
endclass

module inline_constr;
initial begin
packet pkt;
pkt = new();
repeat(10)
begin
pkt.randomize();
$display("\tValue of a = %0d, b = %0d",pkt.a,pkt.b);
end
end 26
0
endmodule
Semi Design

this example is without solve before


constraint, so we can see the
simulation result that the occurrence // simulation result
of value a == 1 is less. Value of a = 0, b = 6
As ‘b’ value ranges 0:15, Probability Value of a = 0, b = 3
of getting b == 0 is very less. Value of a = 1, b = 0
so it will impact the value of a, i.e if Value of a = 0, b = 15
value of b != 0, which will lead to Value of a = 0, b = 7
value of ‘a’ to become ‘0’. Value of a = 0, b = 2
What if in some situations it is Value of a = 0, b = 15
required to generate a value of ‘a’ to Value of a = 0, b = 4
‘1’ more frequently. by using ‘solve Value of a = 0, b = 7
before’ it can be done. Value of a = 0, b = 11
Writing below constraint will direct
solver to solve ‘a’ first, so more
frequently a will take value of 1.
26
1
Semi Design
// with solve before
class packet;
This example is to solve before constraint, so we
rand bit a;
can see the simulation result that the occurrence
rand bit [3:0] b;
of value a == 1 is more than without solve
constraint sab { solve a before b;}
before constraint.
constraint a_b { (a == 1) -> b == 0;}
endclass // simulation result
Value of a = 0, b = 9
module inline_constr; Value of a = 0, b = 14
initial begin Value of a = 0, b = 3
packet pkt; Value of a = 0, b = 13
pkt = new(); Value of a = 1, b = 0
repeat(10) Value of a = 1, b = 0
begin Value of a = 1, b = 0
pkt.randomize(); Value of a = 0, b = 5
$display("\tValue of a = %0d, b = %0d",pkt.a,pkt.b); Value of a = 0, b = 3
end end Value of a = 0, b = 4 26
endmodule 2
Semi Design
// Example program
class slove_before;
rand integer x,y;
constraint C {x == 0; x < y; solve y before x; }
endclass
// simulation result
program sv; x : 0 :: y : 2064490291
slove_before obj ; x : 0 :: y : 203514063
initial begin x : 0 :: y : 1279931677
obj = new(); x : 0 :: y : 2112945927
repeat(5) x : 0 :: y : 1977312554
if(obj.randomize())
$display(" x : %d :: y :%d ",obj.x,obj.y);
else
$display("Randomization failed "); In the following case, x has only one possible
end assignment (0), so x can be solved for before y.
endprogram The constraint solver can use this flexibility to
26
speed up the solving process. 3
Semi Design

Iterative Constraints
Iterative constraints allow Constraining individual elements of fixed-size, dynamic,
associative arrays or queue. foreach construct specifies iteration over the each
elements of array.

NOTE: Remember while randomizing each element of array also array should be
declared as random variable otherwise randomization wont happen.

26
4
// Example program Semi Design
class Eth_pt;
rand byte Payload[] ;

constraint size_c { Payload.size() inside {[10:1500]}; }


constraint element_c { foreach ( Payload[ i ] ) Payload[ i ] inside {[50:100]}; }

function void post_randomize;


foreach(Payload[i]) // simulation result
$display( " Payload[ %0d ] :%d ",i,Payload[ i ] ); Payload[ 0 ] : 87
endfunction Payload[ 1 ] : 52
endclass Payload[ 2 ] : 70
program iterative_60; Payload[ 3 ] : 76
Eth_pt obj; Payload[ 4 ] : 71
initial begin Payload[ 5 ] : 63
obj = new(); Payload[ 6 ] : 62
if(obj.randomize()) Payload[ 7 ] : 63
$display(" RANDOMIZATION DONE "); Payload[ 8 ] : 66….etc 26
end 5
endprogram
Semi Design

Soft Constraints
SystemVerilog constraints declared with the keyword soft is called as soft
constraints. any conflict between class constraint and inline constraint leads to a
randomization failure, from this it is clear that it is not possible to override the class
constraint by inline constraint. Some test scenarios demand to override the
constraints, this can be done by writing a soft keyword in class constraint.
A soft constraint is a constraint on a random variable, which allows overriding the
constraint.

// Syntax
constraint c_name { soft variable { condition }; }

26
6
Semi Design
Example of real-time soft constraint:

This is one of the situations where soft constraints are useful.


Lets Consider, In a verification testbench transaction class constraint is written
to generate normal stimulus. For error stimulus generation, error testcase need
to have an inline constraint that may conflict with the constraint defined inside
the class. In this situation, we have only the option to change the constraint
defined inside the transaction class, but changing the constraint in the
transaction class will reflect in all other test cases. so this kind of problem can
be avoided using soft constraints.

26
7
Example without soft constraint: Semi Design

class packet; In the class packet, the addr variable is


rand bit [3:0] addr; constrained to greater than 6 and the same addr
constraint addr_range { addr > 6; } variable is constrained to less than 6 in the inline
endclass constraint. that means expecting the value of
addr to be less than and greater than 6, this is not
module soft_constr; possible and leads to a randomization failure.
initial begin this problem is resolved in the next example
packet pkt; using soft constraint.
pkt = new();
repeat(2)
begin // simulation result
pkt.randomize() with { addr < 6;}; Constraints inconsistency failure
$display("\taddr = %0d",pkt.addr); Constraints are inconsistent and cannot be
end solved.
end Please check the inconsistent constraints
endmodule being printed above and rewritethem.
addr = 0 26
8
Example using soft constraint: Semi Design

class packet; // simulation result


rand bit [3:0] addr; addr = 2
constraint addr_range { soft addr > 6; } addr = 3
endclass addr = 0
addr = 1
module soft_constr; addr = 2
initial begin addr = 3 A previous example
packet pkt; addr = 0 problem is solved using
pkt = new(); addr = 2 soft constraints,
repeat(10) addr = 1 Constraint declared
begin addr = 5 inside the class will get
pkt.randomize() with { addr < 6;}; suppressed by inline
$display("\taddr = %0d",pkt.addr); constraints.
end
end
endmodule
26
9
Semi Design

Unique Constraints
SystemVerilog constraint defined with the keyword unique is called as a unique
constraint. On randomization, unique values to set of variables or unique elements to
an array can be generated by using unique constraints.
Unique constraint allows us to,
• Generate unique values across the variables
• Generate unique elements in an array (Fixed Size Array, Dynamic Array,
Associative array and Queue)

// Syntax
constraint c_name { unique {variable's/array}; }
27
0
Unique constraint example: Semi Design
class u_e;
rand bit [3:0] var_1,var_2,var_3;
rand bit [7:0] array[6];
constraint varis_c {unique {var_1,var_2,var_3};}
constraint array_c {unique {array};}
function void display();
$display("var_1 = %p",var_1); On randomization unique values to
$display("var_2 = %p",var_2); a variable var_1, var_2, var_3 can
$display("var_3 = %p",var_3); be obtained by writing unique
$display("array = %p",array); constraints. Also, a unique
endfunction constraint is written to an array to
endclass get unique array elements.

program u_e_r;
u_e pkt;
initial begin // simulation result
pkt = new(); pkt.randomize(); var_1 = 8 var_2 = 14 var_3 = 11 27
pkt.display(); array = '{'h81, 'h7b, 'h4, 'h47, 'he1, 'h17} 1
end endprogram
unique array of elements example: Semi Design

class u_e;
rand bit [31:0] array[10];
constraint array_c {unique {array};
foreach(array[i]) array[i] < 10;} Unique elements for an array is
generated by using a unique
function void display(); keyword. Also considered that the
$display("array = %p",array); value of elements is less than 10.
endfunction
endclass

program u_e_r;
u_e pkt;
initial begin
pkt = new(); // simulation result
pkt.randomize(); array = '{'h5, 'h7, 'h8, 'h1, 'h6, 'h9, 'h2, 'h3, 'h4, 'h0}
pkt.display();
end 27
endprogram 2
Semi Design
Note:
To see the difference, remove “unique {array};” and execute.
Below is the result on removing the “unique {array};” from constraint.

array = '{'h8, 'h4, 'h3, 'h2, 'h3, 'h0, 'h4, 'h8, 'h6, 'h2}

without unique, we can see the repeated values.

27
3
Semi Design

Rand case
randcase is a case statement that randomly selects one of its branches. The randcase
item expressions are non-negative integral values that constitute the branch
weights. An item weight divided by the sum of all weights gives the probability of
taking that branch. Randcase can be used in class are modules. The randcase
weights can be arbitrary expressions, not just constants.
// Example:
randcase
3 : x = 1;
1 : x = 2;
4 : x = 3;
endcase
27
4
Semi Design
// Example:
module rand_case;
integer x;
integer cnt_1,cnt_2,cnt_3;
initial begin
cnt_1 = 0; cnt_2=0; cnt_3 = 0;
repeat(100000) begin
randcase
3 : x = 1;
1 : x = 2;
4 : x = 3;
endcase
if(x == 1) cnt_1++;
else if(x == 2) cnt_2++;
else if(x ==3) cnt_3++;
end $display("count_1 =%0d count_2 =%0d count_3 =%0d ",cnt_1,cnt_2,cnt_3);
$display("Probability of count_1 =%0f count_2 =%0f count_3 =%0f
",(cnt_1/100000.0),(cnt_2/100000.0),(cnt_3/100000.0)); 27
end 5
endmodule
Semi Design

The sum of all weights is 8; therefore, the probability of taking the first branch is
0.375, the probability of taking the second is 0.125, and the probability of taking the
third is 0.5. If a branch specifies a zero weight, then that branch is not taken. The sum
of all weights (SUM) is computed (negative values contribute a zero weight). If SUM
is zero or exceeds (2*32-1), no branch is taken. Each call to randcae statement will
return a random number in the range from 0 to SUM. $urandom_range(0,SUM) is used
to generate a random number. As the random numbers are generated using $urandom
are thread stable, randcase also exhibit random stability.

// simulation result
count_1 =37578 count_2 =12643 count_3 =49779
Probability of count_1 =0.375780 count_2 =0.126430 count_3 =0.497790

27
6
Semi Design

Rand sequence
The random sequence generator is useful for randomly generating sequences of
stimulus. For example, to verify a temporal scenario, a sequence of packets are
needed. By randomizing a packet, it will generate most unlikely scenarios which
are not interested. These type of sequence of scenarios can be generated using
randsequence. A randsequence grammar is composed of one or more productions.
Production items are further classified into terminals and nonterminals. A terminal
is an indivisible item that needs no further definition than its associated code block.

27
7
Semi Design

// Example:
module rs();
initial begin
repeat(5)
begin

randsequence( main )
main : one two three ;
one : {$write("one");};
two : {$write(" two");};
three : {$display(" three");};
endsequence

end
end
endmodule
27
8
Semi Design

The production main is defined in terms of three nonterminals: one, two and three.
Productions one,two and three are terminals. When the main is chosen, it will select
the sequence one, two and three in order.

// simulation result
one two three
one two three
one two three
one two three
one two three

27
9
Semi Design
Random production:

// Example:
module rs();
initial
repeat(8)

randsequence( main )
main : one | two | three ;
one : {$display("one");};
two : {$display("two");};
three: {$display("three");};
endsequence

endmodule

28
0
Semi Design

Results show that one, two and three are selected randomly.

// simulation result
three
three
three
three
one
three
two
two

28
1
Semi Design
Semi Design

Coverage
Coverage is used to measure tested and untested portions of the design. Coverage
is defined as the percentage of verification objectives that have been met.
There are two types of coverage metrics,

1. Code Coverage
2. Functional Coverage

28
3
Semi Design
Code Coverage:
• Code coverage measures how much of the “design Code” is exercised.
• This includes the execution of design blocks, Number of Lines, Conditions, FSM,
Toggle and Path.
• The simulator tool will automatically extract the code coverage from the design
code.

Functional Coverage:
Functional coverage is a user-defined metric that measures how much of the
design specification has been exercised in verification.
There are two types of functional coverage,
• Data-oriented Coverage – Checks combinations of data values have
occurred. We can get Data-oriented coverage by writing Coverage groups,
coverage points and also by cross coverage
• Control-oriented Coverage – Checks whether sequences of behaviors have
occurred. We can get assertion coverage by writing SystemVerilog
28
Assertions 4
Semi Design

Cover group
The covergroup construct encapsulates the specification of a coverage model.
Each covergroup specification can include the following components:

A clocking event that synchronizes the sampling of coverage points


• A set of coverage points
• Cross coverage between coverage points
• Optional formal arguments
• Coverage options

28
5
Semi Design
A Cover group is defined between key words covergroup & endgroup. A
Covergroup Instance can be created using the new() operator.

// Syntax
covergroup cg;
... ... ...
endgroup
cg cg_inst = new;

The above example defines a covergroup named "cg". An instance of "cg" is


declared as "cg_inst" and created using the "new" operator.

28
6
Semi Design

Sample

Coverage should be triggered to sample the coverage values. Sampling can be


done using
• Any event expression -edge, variable
• End-point of a sequence
• Event can be omitted Calling sample() method.
// Syntax
covergroup cg @(posedge clk);
...
...
endgroup
The above example defines a covergroup named "cg". This covergroup will be
automatically sampled each time there is a posedge on "clk" signal. 28
7
Semi Design
// Syntax
covergroup cg;
...
...
endgroup

cg cg_inst = new;
initial // or task or function or always block
begin
...
...
cg_inst.sample();
...
...
end

The above example defines a covergroup named "cg". An instance of "cg" is


declared as "cg_inst" and created using the "new" operator. 28
8
Semi Design

Cover Points
A covergroup can contain one or more coverage points. A coverage point can be an
integral variable or an integral expression. A coverage point creates a hierarchical
scope, and can be optionally labeled. If the label is specified then it designates the
name of the coverage point.

28
9
Semi Design
// Syntax In the above example, we are
program main; sampling the cover point "y". The
bit [0:2] y; cover point is named
bit [0:2] values[$]= '{3,5,6}; "cover_point_y" . In the Coverage
report you will see this name. A
covergroup cg; cover group "cg" is defined and its
cover_point_y : coverpoint y; instance "cg_inst" is created. The
endgroup value of "y" is sampled when
cg_inst.sample() method is called.
cg cg_inst = new(); Total possible values for Y are
initial 0,1,2,3,4,5,6,7. The variable "y" is
foreach(values[i]) assigned only values 3,5,6. The
begin y = values[i]; coverage engine should report that
cg_inst.sample(); only 3 values are covered and there
end are 8 possible values.
endprogram

29
0
Semi Design

Coverage Filter
The expression within the iff construct specifies an optional condition that disables
coverage for that cover point. If the guard expression evaluates to false at a sampling
point, the coverage point is ignored.

// Syntax
covergroup cg;
coverpoint cp_varib iff(!reset); // filter condition
endgroup

In the preceding example, cover point varible "cp_varib" is covered only if the
value reset is low.

29
1
Semi Design

Coverage Bins
A coverage-point bin associates a name and a count with a set of values or a
sequence of value transitions. If the bin designates a set of values, the count is
incremented every time the coverage point matches one of the values in the set. If
the bin designates a sequence of value transitions, the count is incremented every
time the coverage point matches the entire sequence of value transitions.
Bins can be created implicitly or explicitly.

29
2
Semi Design

Implicit Bins
While define cover point, if you do not specify any bins, then Implicit bins are created.
The number of bins creating can be controlled by auto_bin_max parameter.
// Example:
program main;
bit [0:2] y;
bit [0:2] values[$] = '{3,5,6};
covergroup cg;
cover_point_y : coverpoint y { option.auto_bin_max = 4 ; }
endgroup
cg cg_inst = new();
initial foreach(values[i]) In the above example, the auto_bin_max is declared as 4.
begin So, the total possible values are divided in 4 parts and each
y = values[i]; part correspoits to one bin. The total possible values for 29
cg_inst.sample(); variable "y" are 8. They are divided in to 4 groups. 3

end endprogram
Bin[0] for 0 and 1 Semi Design
Bin[1] for 2 and 3
Bin[2] for 4 and 5
Bin[3] for 6 and 7
Variable Y is assigned values 3,5 and 6. Values 3,5 and 6 belongs to bins
bin[1],bin[2] and bin[3] respectively. Bin[0] is not covered.
// simulation result
Coverage report:
--------------------
VARIABLE : cover_point_y
Expected : 4
Covered : 3
Percent: 75.00
Uncovered bins
------------------
auto[0:1]
Covered bins
------------------ 29
4
auto[2:3] auto[4:5] auto[6:7]
Semi Design
// Example:
typedef enum { A,B,C,D } alpha;
program main;
alpha y;
alpha values[$] = '{A,B,C};
covergroup cg;
cover_point_y : coverpoint y;
endgroup
cg cg_inst = new();
initial
foreach(values[i])
begin
y = values[i];
cg_inst.sample();
end
endprogram

In The above example, the variable "y" is enum data type and it can have 4 enum 29
5
members A,B,C and D. Variable Y is assigned only 3 Enum members A,B and C.
Semi Design

// simulation result
Coverage report:
---------------------
VARIABLE : cover_point_y
Expected : 4
Covered : 3
Percent: 75.00
Uncovered bins
--------------------
auto_D
Covered bins
--------------------
auto_C
auto_B
auto_A

29
6
Semi Design

Explicit Bins
Explicit bin creation is recommended method. Not all values are interesting or relevant
in a cover point, so when the user knows the exact values he is going to cover, he can
use explicit bins. You can also name the bins.

29
7
Semi Design
// Example:
program main;
bit [0:2] y;
bit [0:2] values[$] = '{3,5,6};
covergroup cg;
cover_point_y : coverpoint y {
bins a = {0,1};
bins b = {2,3}; In the above example, bins
bins c = {4,5}; are created explicitly. The
bins d = {6,7}; } bins are named a,b,c and d.
endgroup
cg cg_inst = new();
initial
foreach(values[i])
begin y = values[i];
cg_inst.sample();
end 29
endprogram 8
Semi Design

// simulation result
Coverage report:
-------------------
VARIABLE : cover_point_y
Expected : 4
Covered : 3
Percent: 75.00
Uncovered bins
--------------------
a
Covered bins
--------------------
b
c
d

29
9
Array Of Bins: Semi Design
To create a separate bin for each value (an array of bins) the square brackets, [], must
follow the bin name.
// Example:
program main;
bit [0:2] y;
bit [0:2] values[$] = '{3,5,6};
covergroup cg;
cover_point_y : coverpoint y{
bins a[] = {[0:7]}; In the above example, bin a
} is array of 8 bins and each
endgroup bin associates to one number
cg cg_inst = new(); between 0 to 7.
initial foreach(values[i])
begin
y = values[i];
cg_inst.sample();
end 30
endprogram 0
Semi Design
// simulation result
Coverage report:
--------------------
VARIABLE :
cover_point_y
Expected : 8
Covered : 3
Percent: 37.50
Uncovered bins
-------------------
a_0
a_1
a_2
a_4
a_7
Covered bins
-------------------
a_3 a_5 a_6 30
1
To create a fixed number of bins for a set of values, a number can be Semi Design
specified inside the square brackets.

// Example:
program main;
bit [0:3] y;
bit [0:2] values[$] = '{3,5,6};
covergroup cg;
cover_point_y : coverpoint y { bins a[4] = {[0:7]}; }
endgroup
cg cg_inst = new();
initial
foreach(values[i]) In the above example, variable y is 4 bit width vector.
begin y = values[i]; Total possible values for this vector are 16. But in the
cg_inst.sample(); cover point bins, we have giving the interested range as 0
end to 7. So the coverage report is calculated over the range 0
endprogram to 7 only. In this example, we have shown the number
bins to be fixed to size 4.
30
2
Semi Design

// simulation result
Coverage report:
--------------------
VARIABLE : cover_point_y
Expected : 4
Covered : 3
Percent: 75.00
Uncovered bins
-------------------
a[0:1]
Covered bins
------------------
a[2:3]
a[4:5]
a[6:7]

30
3
Default Bin: Semi Design
The default specification defines a bin that is associated with none of the defined
value bins. The default bin catches the values of the coverage point that do not lie
within any of the defined bins. However, the coverage calculation for a coverage
point shall not take into account the coverage captured by the default bin.
// Example:
program main;
bit [0:3] y;
bit [0:2] values[$] = '{3,5,6};
covergroup cg;
cover_point_y : coverpoint y {
bins a[2] = {[0:4]};
bins d = default; }
endgroup
cg cg_inst = new(); In the above example, we have specified only 2 bins to
initial cover values from 0 to 4. Rest of values are covered in
foreach(values[i]) default bin d which is not using in calculating the
begin y = values[i]; coverage percentage. 30
cg_inst.sample(); 4

end endprogram
Semi Design

// simulation result
Coverage report:
--------------------
VARIABLE : cover_point_y
Expected : 2
Covered : 1
Percent: 50.00
Uncovered bins
------------------
a[0:1]
Covered bins
----------------
a[2:4]
Default bin
-----------------
d
30
5
Semi Design

Transition Bins
Transitional functional point bin is used to examine the legal transitions of a value.
SystemVerilog allows to specifies one or more sets of ordered value transitions of
the coverage point.
Type of Transitions:
• Single Value Transition
• Sequence Of Transitions
• Set Of Transitions
• Consecutive Repetitions
• Range Of Repetition
• Goto Repetition
• Non Consecutive Repetition
30
6
Single Value Transition: Semi Design
Single value transition is specified as:
value1 => value2
// Example:
program main;
bit [0:3] y;
bit [0:2] values[$] = '{3,5,6};
covergroup cg;
cover_point_y : coverpoint y {
bins tran_34 = (3=>4);
bins tran_56 = (5=>6);
}
endgroup
cg cg_inst = new();
initial In the above example, 2 bins are created for covering the
foreach(values[i]) transition of point "y" from 3 to 4 and other for 5 to 6.
begin The variable y is given the values and only the transition
y = values[i]; 5 to 6 is occurring. 30
cg_inst.sample(); 7
end endprogram
Semi Design

// simulation result
Coverage report:
--------------------
VARIABLE : cover_point_y
Expected : 2
Covered : 1
Percent: 50.00
Uncovered bins
------------------
tran_34
Covered bins
----------------
tran_56

30
8
Sequence Of Transitions: Semi Design
A sequence of transitions is represented as:
value1 => value3 => value4 => value5
// Example:
program main;
bit [0:3] y;
bit [0:2] values[$] = '{3,5,6};
covergroup cg;
cover_point_y : coverpoint y {
bins tran_345 = (3=>4>=5);
bins tran_356 = (3=>5=>6);
}
endgroup In this case, value1 is followed by value3, followed by
cg cg_inst = new(); value4 and followed by value5. A sequence can be of any
initial arbitrary length.
foreach(values[i]) In the above example, 2 bins re created for covering the
begin y = values[i]; transition of point "y" from 3 to 4 to 5 and other for 3 to 5 to
cg_inst.sample(); 6. The variable y is given the values and only the transition 3 30
end to 5 to 6 is occurring. 9
endprogram
Semi Design

// simulation result
Coverage report:
--------------------
VARIABLE : cover_point_y
Expected : 2
Covered : 1
Percent: 50.00
Uncovered bins
------------------
tran_345
Covered bins
----------------
tran_356

31
0
Set Of Transitions : Semi Design
A set of transitions can be specified as:
range_list1 => range_list2
// Example:
program main;
bit [0:3] y;
bit [0:2] values[$] = '{3,5,6};
covergroup cg;
cover_point_y : coverpoint y {
bins trans[] = (3,4=>5,6);
}
endgroup
cg cg_inst = new();
initial
foreach(values[i])
begin
y = values[i];
cg_inst.sample(); 311
end endprogram
Semi Design

// simulation result
Coverage report:
--------------------
VARIABLE : cover_point_y
Expected : 4
Covered : 1
Percent: 25.00
Uncovered bins
------------------
tran_34_to_56:3->6
tran_34_to_56:4->5
tran_34_to_56:4->6
Covered bins
----------------
tran_34_to_56:3->5

31
2
Consecutive Repetitions : Semi Design
Consecutive repetitions of transitions are specified using
trans_item [* repeat_range ]
// Example:
program main;
bit [0:3] y;
bit [0:2] values[$] = '{3,3,3,4,4};
covergroup cg;
cover_point_y : coverpoint y {
bins trans_3 = (3[*5]);
bins trans_4 = (4[*2]);
}
endgroup
cg cg_inst = new();
initial
foreach(values[i])
begin
y = values[i]; 31
cg_inst.sample(); 3
end endprogram
Semi Design

// simulation result
Coverage report:
--------------------
VARIABLE : cover_point_y
Expected : 2
Covered : 1
Percent: 50.00
Uncovered bins
------------------
trans_3
Covered bins
----------------
trans_4

31
4
Range Of Repetition: Semi Design
An example of a range of repetition is:
3 [* 3:5] is the same as 3=>3=>3, 3=>3=>3=>3, 3=>3=>3=>3=>3
// Example:
program main;
bit [0:3] y;
bit [0:2] values[$] = '{4,5,3,3,3,3,6,7};
covergroup cg;
cover_point_y : coverpoint y {
bins trans_3[] = (3[*3:5]);
}
endgroup
cg cg_inst = new();
initial
foreach(values[i])
begin
y = values[i];
cg_inst.sample(); 31
end 5
endprogram
Semi Design

// simulation result
Coverage report:
--------------------
VARIABLE : cover_point_y
Expected : 3
Covered : 1
Percent: 33.33
Uncovered bins
------------------
tran_3:3[*3]
tran_3:3[*5]
Covered bins
----------------
tran_3:3[*4]

31
6
Goto Repetition: Semi Design

The goto repetition is specified using: trans_item [-> repeat_range]. The required
number of occurrences of a particular value is specified by the repeat_range. Any
number of sample points can occur before the first occurrence of the specified
value and any number of sample points can occur between each occurrence of the
specified value. The transition following the goto repetition must immediately
follow the last occurrence of the repetition. For example: 3 [-> 3] is the same as
...=>3...=>3...=>3

31
7
Semi Design
// Example:
program main;
bit [0:3] y;
bit [0:2] values[$] = '{1,6,3,6,3,6,3,5};
covergroup cg;
cover_point_y : coverpoint y {
bins trans_3 = (1=>3[->3]=>5);
}
endgroup A goto repetition followed by an additional value is
cg cg_inst = new(); represented as follows: 1 => 3 [ -> 3] => 5 is the same as
initial 1...=>3...=>3...=>3 =>5
foreach(values[i])
// simulation result
begin y = values[i];
Coverage report:
cg_inst.sample();
--------------------
end
VARIABLE : cover_point_y
endprogram
Expected : 1
Covered : 1 31
8
Percent: 100.00
Non Consecutive Repetition: Semi Design

The nonconsecutive repetition is specified using: trans_item [= repeat_range].


The required number of occurrences of a particular value is specified by the
repeat_range. Any number of sample points can occur before the first occurrence
of the specified value and any number of sample points can occur between each
occurrence of the specified value. The transition following the nonconsecutive
repetition may occur after any number of sample points so long as the repetition
value does not occur again.
For example:
3 [= 2] is same as ...=>3...=>3

31
9
Semi Design
// Example:
program main;
bit [0:3] y;
bit [0:2] values[$] = '{1,6,3,6,3,6,5};
covergroup cg;
cover_point_y : coverpoint y {
bins trans_3 = (1=>3[=2]=>5);
}
A nonconsecutive repetition followed by an additional value
endgroup
is represented as follows:
cg cg_inst = new();
1 => 3 [=2] => 5 is the same as 1...=>3...=>3...=>5
initial
foreach(values[i]) // simulation result
begin Coverage report:
y = values[i]; --------------------
cg_inst.sample(); VARIABLE : cover_point_y
end Expected : 1
endprogram Covered : 1 32
Percent: 100.00 0
Semi Design

Wildcard Bins
By default, a value or transition bin definition can specify 4-state values. When a bin
definition includes an X or Z, it indicates that the bin count should only be
incremented when the sampled value has an X or Z in the same bit positions. The
wildcard bins definition causes all X, Z, or ? to be treated as wildcards for 0 or 1
(similar to the ==? operator).
For example:
// Example
wildcard bins g12_16 = { 4'b11?? };
The count of bin g12_16 is incremented when the sampled variable is between 12
and 16:
1100 1101 1110 1111
32
1
Semi Design
// Example:
program main;
reg [0:3] y;
reg [0:3] values[$] = '{ 4'b1100,4'b1101,4'b1110,4'b1111};
covergroup cg;
cover_point_y : coverpoint y {
wildcard bins g12_15 = { 4'b11?? } ;
}
endgroup // simulation result
cg cg_inst = new(); Coverage report:
initial --------------------
foreach(values[i]) VARIABLE : cover_point_y
begin Expected : 1
y = values[i]; Covered : 1
cg_inst.sample(); Percent: 100.00
end Covered bin
endprogram ---------------
g12_15 32
Number of times g12_15 hit : 4 2
Similarly, transition bins can define wildcard bins. For Semi Design
example:
// Example
wildcard bins T0_3 = (2'b0x => 2'b1x);

The count of transition bin T0_3 is incremented for the following transitions (as
if (0,1=>2,3)): 00 => 10 , 00 => 11, 01 => 10 , 01 => 11

32
3
Semi Design
// Example:
program main;
reg [0:1] y;
reg [0:1] values[$] = '{ 2'b00,2'b01,2'b10,2'b11};
covergroup cg;
cover_point_y : coverpoint y {
wildcard bins trans = (2'b0X => 2'b1X );
}
endgroup // simulation result
cg cg_inst = new(); Coverage report:
initial --------------------
foreach(values[i]) VARIABLE : cover_point_y
begin y = values[i]; Expected : 1
cg_inst.sample(); Covered : 1
end Percent: 100.00
endprogram Covered bin
---------------
trans Number of times trans hit : 1 (01 => 10) 32
4
Semi Design

Ignore Bins
A set of values or transitions associated with a coverage-point can be explicitly
excluded from coverage by specifying them as ignore bins.

32
5
Semi Design
// Example:
program main;
bit [0:2] y;
bit [0:2] values[$] = '{1,6,3,7,3,4,3,5};
covergroup cg;
cover_point_y : coverpoint y {
ignore_bins ig = {1,2,3,4,5};
}
endgroup
cg cg_inst = new();
initial
foreach(values[i])
begin y = values[i];
cg_inst.sample();
end
endprogram
32
6
Semi Design
// simulation result
Coverage report:
--------------------
VARIABLE : cover_point_y
Expected : 3 In the above program, total possible
Covered : 2 values for y are 0 to 7. Ignore_bins
Percent: 66.66 specified to Ignored values between 1 to
Uncovered bins 5. So the Expected values are 0,6 and 7.
------------------ Out of these expected values, only 6 and 7
auto[0] are generated.
Excluded/Illegal bins
-------------------------
auto[1] auto[2]
auto[3] auto[4]
auto[5]
Covered bins
–---------------
auto[6] auto[7] 32
7
Semi Design

Illegal Bins
A set of values or transitions associated with a coverage-point can be marked as
illegal by specifying them as illegal_bins. All values or transitions associated with
illegal bins are excluded from coverage. If an illegal value or transition occurs, a
runtime error is issued.

32
8
Semi Design
// Example:
program main;
bit [0:2] y;
bit [0:2] values[$] = '{1,6,3,7,3,4,3,5};
covergroup cg;
cover_point_y : coverpoint y {
illegal_bins ib = {7};
}
endgroup
cg cg_inst = new(); // simulation result
initial ------------
foreach(values[i]) ** ERROR **
begin Illegal state bin ib of coverpoint
y = values[i]; cover_point_y in covergroup cg got hit with
cg_inst.sample(); value 0x7
end
endprogram 32
9
Semi Design

Cross Coverage
Cross Coverage is specified between the cover points or variables. Cross coverage is
specified using the cross construct.
Cross allows keeping track of information which is received simultaneous on more
than one cover point.
Expressions cannot be used directly in a cross; a coverage point must be
explicitly defined first.

33
0
Cross coverage by cover_point name: Semi Design

// Example:
bit [3:0] a, b;
covergroup cg @(posedge clk);
c1: coverpoint a;
c2: coverpoint b;
c1Xc2: cross c1,c2;
endgroup : cg In the above example, each coverage
point has 16 bins, namely
auto[0]…auto[15]. The cross of a and b
Cross coverage by the variable name:
(labeled aXb), therefore, has 256 cross
// Example: products, and each cross product is a bin
bit [3:0] a, b; of aXb.
covergroup cov @(posedge clk);
aXb : cross a, b;
endgroup

33
1
Semi Design

Coverage Options
Coverage options control the behavior of the covergroup, coverpoint, and cross.
1. at_least
2. auto_bin_max
3. cross_auto_bin_max

33
2
Semi Design
1. at_least
A minimum number of hits for each bin. A bin with a hit count that is less than the
number is not considered covered. the default value is ‘1’.
2. auto_bin_max
A maximum number of automatically created bins when no bins are explicitly defined for
a coverpoint. the default value is ‘64’.
3. cross_auto_bin_max
A maximum number of automatically created cross product bins for a cross. there is no
default value, it is unbounded.

// Example:
covergroup cg @(posedge clk);
c1: coverpoint addr { option.auto_bin_max = 128;}
c2: coverpoint wr_rd { option.atleast = 2;}
c1Xc2: cross c1, c2 { option.cross_auto_bin_max = 128;}
endgroup : cg

33
3
Semi Design
Semi Design

Introduction
SystemVerilog adds features to specify assertions of a system. An assertion
specifies a behavior of the system. Assertions are primarily used to validate the
behavior of a design. In addition, assertions can be used to provide functional
coverage and generate input stimulus for validation.
The evaluation of the assertions is guaranteed to be equivalent between simulation,
which is event-based, and formal verification, which is cycle-based.
SystemVerilog allows assertions to communicate information to the test bench and
allows the test bench to react to the status of assertions without requiring a separate
application programming interface (API) of any kind

33
5
Semi Design
Advantages Of Assertion:

• Improving Observability.
• Reduces the debug time.
• Bugs can be found earlier and are more isolated.
• Controllable severity level.
• Can interact with C functions.
• Describe the Documentation and Specification of the design.

33
6
Semi Design

System verilog Assertions


Assertions are primarily used to validate the behavior of a design. An assertion is a
check embedded in design or bound to a design unit during the simulation. Warnings
or errors are generated on the failure of a specific condition or sequence of events.

There are two kinds of assertions:


• Immediate Assertions
• Concurrent Assertions

33
7
Immediate Assertions: Semi Design

Immediate assertions check for a condition at the current simulation time.


An immediate assertion is the same as an if..else statement with assertion control.
Immediate assertions have to be placed in a procedural block definition.

// Syntax
label: assert(expression) action_block;

• The optional statement label (identifier and colon) creates a named block
around the assertion statement
• The action block is executed immediately after the evaluation of the assert
expression
• The action_block specifies what actions are taken upon success or failure of the
assertion

// action_block
pass_statement; else fail_statement;
33
8
Semi Design
• The pass statement is executed if the expression evaluates to true
• The statement associated with else is called a fail statement and is executed if the
expression evaluates to false
• Both pass and fail statements are optional
• Since the assertion is a statement that something must be true, the failure of an
assertion shall have a severity associated with it. By default, the severity of an
assertion failure is an error.
• Other severity levels can be specified by including one of the following severity
system tasks in the fail statement:
$fatal is a run-time fatal.
$error is a run-time error.
$warning is a run-time warning, which can be suppressed in a tool-specific
manner.
$info indicates that the assertion failure carries no specific severity.
• If an assertion fails and no else clause is specified, the tool shall, by default call
$error.
33
9
Semi Design
// Example:
always @(posedge clk) assert (a && b);

Condition (a && b) will be checked at every posedge of the clock, failure in the
condition leads to an assertion failure.

34
0
Concurrent Assertions: Semi Design

Concurrent assertions check the sequence of events spread over multiple clock
cycles.
• The concurrent assertion is evaluated only at the occurrence of a clock tick
• The test expression is evaluated at clock edges based on the sampled values of
the variables involved
• It can be placed in a procedural block, a module, an interface or a program
definition
// Example
c_assert: assert property(@(posedge clk) not(a && b));

The Keyword differentiates the immediate assertion from the concurrent assertion
is “property.”

34
1
Semi Design

Event Simulation
The Problem of race condition exists if the SVA is sampling the signals exactly at
specified event. So in SystemVerilog , the language has very clear semantics to avoid
race condition while evaluating SVA.
Updates to IEEE STD 1800-20051 divide the SystemVerilog time slot into 17
ordered regions, nine ordered regions for the execution of SystemVerilog
statements and eight ordered regions for the execution of PLI code. The purpose of
dividing a time slot into these ordered regions is to provide predictable interactions
between the design and testbench code.

34
2
Semi Design
Use of Event scheduling:
Every change in the state of a net or variable in the system description being
simulated is considered an update event. When an update event is executed, all
the processes that are sensitive to those events are considered for evaluation
known as an evaluation event.
Examples of processes include, initial, always, always_comb, always_latch,
and always_ff procedural blocks, continuous assignments, asynchronous tasks,
and procedural assignment statements.
A single time slot is divided into multiple regions where events can be
scheduled. This event scheduling supports obtaining clear and predictable
interactions that provide for the ordering of particular types of execution.
This allows properties and checkers to sample data when the design under test is in
a stable state. Property expressions can be safely evaluated, and testbenches can
react to both properties and checkers with zero delay, all in a predictable manner.
This same mechanism also allows for non-zero delays in the design, clock
propagation, and/or stimulus and response code to be mixed freely and consistently
with cycle-accurate descriptions. 34
3
Semi Design

34
4
Semi Design
Preponed region:
The values of variables that are used in concurrent assertions are sampled in the
Preponed region. (Evaluation is done at observed region). Preponed region is
executed only once in each time slot, immediately after advancing simulation time.

Pre-active region:
The Pre-active region is specifically for a PLI callback control point that allows for
user code to read and write values and create events before events in the Active
region are evaluated
Active region:
The Active region holds current events being evaluated and can be processed
in any order.
• Execute all module blocking assignments.
• Evaluate the Right-Hand-Side (RHS) of all nonblocking assignments and
schedule updates into the NBA region.
• Execute all module continuous assignments
34
• Evaluate inputs and update outputs of Verilog primitives. 5
• Execute the $display and $finish commands
Inactive region: Semi Design

The Inactive region holds the events to be evaluated after all the active events are
processed. In this region #0 blocking assignments are scheduled.

Pre-NBA region:
The Pre-NBA region is specifically for a PLI callback control point that allows for
user code to read and write values and create events before the events in the NBA
region are evaluated
Non-blocking Assignment Events region (NBA):
The principal function of this region is to execute the updates to the Left-Hand-Side
(LHS) variables that were scheduled in the Active region for all currently executing
non-blocking assignments.
Post-NBA region:
The Post-NBA region is specifically for a PLI callback control point that allows
for user code to read and write values and create events after the events in the
NBA region are evaluated 34
6
Observed region: Semi Design

The principal function of this region is to evaluate the concurrent assertions using the
values sampled in the Preponed region. A criterion behind this decision is that the
property evaluations must only occur once in any clock triggering time slot. During
the property evaluation, the pass/fail code shall be scheduled in the Reactive region
of the current time slot.
Post-observed region:
The Post-observed region is specifically for a PLI callback control point that allows
for user code to read values after properties are evaluated (in Observed or earlier
region).
Re-Inactive Events region:
In this region #0 blocking assignments in a program process are scheduled.

34
7
Semi Design
Reactive region:
The code specified in the program block, and pass/fail code from property
expressions, are scheduled in the Reactive region. The principal function of
this region is to evaluate and execute all current program activity in any order
Execute all program blocking assignments.
Execute the pass/fail code from concurrent assertions.
Evaluate the Right-Hand-Side (RHS) of all program non-blocking assignments
and schedule
Execute all program continuous assignments
Execute the $exit and implicit $exit commands

Postponed Region:
The principal function of this region is to execute the $strobe and $monitor
commands that will show the final updated values for the current time slot. This
region is also used to collect functional coverage for items that use strobe
sampling.
34
8
Semi Design

SVA Building Blocks


Concurrent assertions describe behavior that spans over time. Unlike immediate
assertions, the evaluation model is based on a clock so that a concurrent assertion is
evaluated only at the occurrence of a clock tick.
There are 4 layers in concurrent assertions. They are
Boolean expressions.
Sequence expression.
Property declaration.
Verification directives.

34
9
Semi Design

Assert property

Create Property

Create sequence
expressions

Create Boolean
Expressions
35
0
Boolean expressions: Semi Design

The functionality is represented by the combination of multiple logical events. These


events could be simple Boolean expressions.
Sequence:
Boolean expression events that evaluate over a period of time involving
single/multiple clock cycles. SVA provides a keyword to represent these events
called “sequence.”

// Syntax
sequence name_of_sequence;
……
endsequence

Property:
A number of sequences can be combined logically or sequentially to create more
complex sequences. SVA provides a keyword to represent these complex 35
sequential behaviors called “property”. 1
Semi Design
// Syntax
property name_of_property;
test expression or
complex sequence expressions
endproperty

Assert:
The property is the one that is verified during a simulation. It has to be asserted to
take effect during a simulation. SVA provides a keyword called “assert” to check
the property.
// Syntax
assertion_ name: assert_property( property_name );

35
2
Semi Design

SVA Sequence
Boolean expression events that evaluate over a period of time involving
single/multiple clock cycles. SVA provides a keyword to represent these events called
“sequence”.
Boolean logic doenot have the concept of time. Temporal logic is boolean logic with
time as one more dimention. Sequence allows us to define temporal nature of the
signals using temporal expressions. Sequences can be composed by concatenation,
analogous to a concatenation of lists. The concatenation specifies a delay, using ##,
from the end of the first sequence until the beginning of the second sequence. ##
indicates cycle delay.

35
3
SVA Sequence example: Semi Design

In the below example the sequence seq_1 checks that the signal “a” is high on every
positive edge of the clock. If the signal “a” is not high on any positive clock edge,
the assertion will fail.

// Example
sequence seq_1;
@(posedge clk) a==1;
endsequence

35
4
Semi Design
Sequences with timing relationship:
Fixed Delay:
In SVA, clock cycle delays are represented by a “##” sign. For example, ##2 means 2
clock cycles.
Below sequence checks for the signal “a” being high on a given positive edge of the
clock. If the signal “a” is not high, then the sequence fails. If signal “a” is high on any
given positive edge of the clock, the signal “b” should be high 2 clock cycles after
that. If signal “b” is not asserted after 2 clock cycles, the assertion fails.

// Example
sequence seq;
@(posedge clk) a ##2 b;
endsequence

35
5
Semi Design

35
6
Semi Design
Zero Delay:

The delay ##0 indicates that the beginning of the second sequence is at the same clock
tick as the end of the first sequence. This can also be archived using boolean expressions
&& .

// Example
sequence seq;
@(posedge clk) sig1 ##0 sig2;
endsequence

This specifies that sig1 shall be true on the current clock tick, and sig2 shall be
true on the same clock tick.

35
7
Semi Design

Properties
A property defines a behavior of the design. A property can be used for verification as
an assumption, a checker, or a coverage specification. Sequences are often used to
construct properties. usage of sequences in properties brakes down the complexity.
Sequence can be reused across various properties.
A property can be declared in any of the following:
A module
An interface
A program
A clocking block
A package
A compilation-unit scope
35
8
Semi Design
Properties constructs:
1. Disable iff
2. Implication (if ..else)
3. overlapping implication (|->)
4. Non overlapping implication(||->)

1. Disable iff:
In certain design conditions, we don’t want to proceed with the check if some
condition is true. this can be achieved by using disable iff.
Below property checks that, if the signal “a” is high on given posedge of the
clock, the signal “b” should be high for 3 clock cycles followed by “c” should
be high after ”b” is high for the third time. During this entire sequence, if
reset is detected high at any point, the checker will stop.

35
9
Semi Design
// Example
property p;
@(posedge clk)
disable iff (reset) a |-> ##1 b[->3] ##1 c;
endproperty
a: assert property(p);

2. Implication (if ..else):

// Example
property p(bit x, bit y);
##1 x |-> ##[2:10] y;
//antecedent |-> consequent
endproperty
The left-hand operand sequence_expr is called the antecedent, while the right-hand
operand property_expr is called the consequent. if antecedent is false, then
consequent is not cared and property is considered as vacuous success. if 36
antecedent is True and if consequent is false then property is considered as false. if 0
antecedent is True and if consequent is true then property is considered as true.
Semi Design
Overlap Implication:
Consequent expression is evaluated on the same clock of antecedent.
// Example
a |-> b

36
1
Semi Design
Non Overlapping Implication :
Consequent expression is evaluated on the next clock of antecedent

// Example
a ||-> b

36
2
Assertion Control System Tasks: Semi Design

SystemVerilog provides three system tasks to control assertions.

$assertoff : It shall stop the checking of all specified assertions until a subsequent
$asserton. An assertion that is already executing, including execution of the pass or
fail statement, is not affected.

$assertkill: It shall abort execution of any currently executing specified assertions


and then stop the checking of all specified assertions until a subsequent $asserton.

$asserton: It shall reenable the execution of all specified assertions. When invoked
with no arguments, the system task shall apply to all assertions. When the task is
specified with arguments, the first argument indicates levels of the hierarchy,
consistent with the corresponding argument to the Verilog $dumpvars system task.
Subsequent arguments specify which scopes of the model to control. These
arguments can specify entire modules or individual assertions.

36
3
Semi Design
Boolean System Function:

$countones : Returns the numbers of 1's in a bit vector.

$past : Returns the values of the past.

$stable : If the Signal is stable, then it returns 1.

$isunknown : If th X is seen in expression , then it returns 1.

$rose : returns true if the LSB of the expression changed to 1. Otherwise, it


returns false.

$fell : returns true if the LSB of the expression changed to 0. Otherwise, it


returns false.

$onehot : returns true if only 1 bit of the expression is high.


36
$onehot0 : returns true if at most 1 bit of the expression is high. 4
Semi Design
Semi Design

DPI C++
From long time , Users have needes a simple way of communication to foreign
languages from verilog. VPI and PLI are not easy interfaces to Use . Users need
detailed knowledge of PLI and VPI even for a simple program. Most of the time, users
do not need the sophisticated capabilities of VPI and PLI. DPI also permits C/C++
code to wait for Verilog events and C/C++ tasks and functions can be disabledfrom
SystemVerilog. SystemVerilog introduces a new foreign language interface called the
Direct Programming Interface (DPI).

The DPI provides a very simple, straightforward, and efficient way to connect
SystemVerilog and foreign language code unlike PLI or VPI.

36
6
Semi Design

DPI developed based on the donations from Synopsys "DirectC interface". DPI
consists of two separate layers: the SystemVerilog layer and a foreign language layer.
Both sides of DPI-C are fully isolated. Which programming language is actually used
as the foreign language is transparent and irrelevant for the System-Verilog side of
this interface. Neither the SystemVerilog compiler nor the foreign language compiler
is required to analyze the source code in the others language.
SystemVerilog DPI (Direct Programming Interface) is an interface which can be
used to interface SystemVerilog with foreign languages. These Foreign languages
can be C, C++, SystemC as well as others.
DPI allows the user to easily call functions of other language from SystemVerilog
and to export SystemVerilog functions, so that they can be called in other languages.
Advantage of DPI is, it allows to make use of the code exists in other languages.

36
7
Semi Design
DPI Import and export methods:

Import Method:

The methods (functions/tasks) implemented in Foreign language can be called from


SystemVerilog and such methods are called Import methods.

Export methods:

The methods implemented in SystemVerilog can be called from Foreign language


such methods are called Export methods.
It is allowed to transfer the data between two languages through arguments
passing and return.

36
8
DPI Declaration: Semi Design

Import Declaration:

// Example
import “DPI-C” function int calc_parity (input int a);

Export Declaration:

// Example
export “DPI-C” my_cfunction = function myfunction;

36
9
SystemVerilog DPI Example: Semi Design

Calling C++ method from SystemVerilog file:


// Example
// SystemVerilog File
module dpi_tb;
import "DPI-C" function void c_method();
initial
begin
$display("Before calling C Method");
c_method();
$display("After calling C Method");
end // simulation result
endmodule Before calling C Method [C-Prog]
// C++ file Hello World...!
#include stdio.h After calling C Method
#include stdlib.h
extern "C" void c_method() {
printf(" Hello World...!\n"); 37
0
}
Calling SystemVerilog method from C++ file: Semi Design

// Example
// SystemVerilog File
module dpi_tb;
export "DPI-C" function sv_method;
import "DPI-C" context function void c_method();
initial
begin
$display("Before calling C Method"); // C++ file
c_method(); #include stdio.h
$display("After calling C Method"); #include iostream
end #include svdpi.h
function void sv_method(); using namespace std;
$display(" [SV-Prog] Hello World...!"); extern "C" void sv_method();
endfunction extern "C" void c_method() {
endmodule printf(" [C-Prog] Hello World...!\n");
sv_method();
} 37
1
Semi Design
// simulation result
Before calling C Method
[C-Prog] Hello World...!
[SV-Prog] Hello World...!
After calling C Method

37
2
Semi Design
Semi Design

Test bench
Testbench or Verification Environment is used to check the functional
correctness of the Design Under Test (DUT) by generating and driving a
predefined input sequence to a design, capturing the design output and comparing
with-respect-to expected output.

Verification environment is a group of class’s performing specific operation. i.e,


generating stimulus, driving, monitoring, etc. and those classes will be named
based on the operation

37
4
Semi Design

System Verilog Architecture


Testbench_Top
Test
env

interface
generator driver DUT
transaction

Scoreboard monitor
transaction
37
5
Semi Design
TestBench Components: Semi Design

Name Type Description


transaction class Defines the pin level activity generated by
agent (to drive to DUT through the driver) or
the activity has to be observed by agent
(Placeholder for the activity monitored by the
monitor on DUT signals)
generator class Generates the stimulus (create and randomize
the transaction class) and send it to Driver
driver class Receives the stimulus (transaction) from a
generator and drives the packet level data
inside the transaction into pin level (to DUT
monitor class Observes pin level activity on interface signals
and converts into packet level which is sent to
the components such as scoreboard
37
7
Semi Design

agent class An agent is a container class, which groups the class’s


(generator, driver, and monitor) specific to an
interface or protocol
scoreboard class Receives data items from monitors and compares
them with expected values.
Expected values can be either golden reference values
or generated from the reference model
environment class The environment is a container class for grouping
higher level components like agent’s and scoreboard

test program The test is responsible for,


Configuring the testbench
Initiate the testbench components construction process
Initiate the stimulus driving
testbench_top class This is the topmost file, which connects the DUT and
TestBench. It consists of DUT, Test and interface 37
instances, the interface connects the DUT and 8
TestBench
Semi Design
SystemVerilog TestBench Example — 2 : 1 Multiplexer
Let’s Write the SystemVerilog TestBench for the simple design “2 :1 Multiplexer”.
Design specification:

2 :1 Multiplexer

a [0:1]
2 : 1 MUX out
DUT
reset

sel
37
9
Semi Design
Verilog programming for 2:1 Mux
module mux2_1(a0, a1, reset, sel, out);
input [2:0] a0, a1;
input reset, sel;
output reg [2:0]out;

always @ (*)
begin
if(!reset)
if(sel)
out = a1;
else
out = a0;
else
out = 3'd0;
end
endmodule 38
0
Semi Design
Getting started with test bench
Transaction Class:
• Fields required to generate the stimulus are declared in the transaction
class.
• Transaction class can also be used as a placeholder for the activity
monitored by the monitor on DUT signals.
• So, the first step is to declare the ‘Fields‘ in the transaction class.
• Below are the steps to write the transaction class.

38
1
Semi Design
class transaction;

rand bit [2:0] a0;


rand bit [2:0] a1;
rand bit sel;
bit [2:0] out;

function void display(string name);


$display("-------------------------");
$display("- %s ",name);
$display("-------------------------");
$display("- a0 = %0d, a1 = %0d, sel = %0d",a0,a1,sel, );
$display("- out = %0d",out);
endfunction
endclass

38
2
Semi Design
Generator Class:
Generator class is responsible for,
• Generating the stimulus by randomizing the transaction class
• Sending the randomized class to driver

38
3
class generator; main task, generates(create and
randomizes) the repeat_count
rand transaction t1; number of transaction packets and
int repeat_count; puts into mailbox

mailbox g2d; task main();


event ended; repeat(repeat_count) begin
t1 = new();
function new(mailbox g2d); if(t1.randomize()) begin
this.g2d = g2d; t1.display("<< Generator >>");
endfunction #1;
g2d.put(t1);
end
Adding Mailbox and event,
else
- Mailbox is used to send the
$fatal("Gen:: trans randomization failed");
randomized transaction to
Driver.
end
- Event to indicate the end of
-> ended;
packet generation.
endtask 38
endclass 4
Semi Design
Interface:
Interface is used to group the signals.

interface intf (input logic reset);

logic [2:0] a0, a1;


logic sel; simple interface without
logic [2:0] out; modport and clocking block.

endinterface

38
5
Driver Class: Semi Design

Receive the stimulus generated from the generator and drive to DUT by
assigning transaction class values to interface signals.

class driver;

int no_of_transactions; Declare interface and


virtual intf vir; mailbox, Get the interface
and mailbox handle through
mailbox g2d; a constructor.

function new(virtual intf vir, mailbox g2d);


this.vir = vir;
this.g2d = g2d;
endfunction

38
6
task reset; Semi Design
wait(vir.reset);
$display("[Driver] ----- Reset Started -----"); task main;
vir.a0 <= 0; forever begin
vir.a1 <= 0; transaction t1;
vir.sel <= 0; g2d.get(t1);
wait(!vir.reset);
$display("[Driver] ----- Reset Ended -----"); vir.a0 <= t1.a0;
endtask vir.a1 <= t1.a1;
vir.sel <= t1.sel;
#1;
Adding a reset task, which t1.out = vir.out;
initializes the Interface
signals to default values. t1.display("<< Driver >>");
no_of_transactions++;
Adding a main task to drive end
the transaction packet to the endtask
interface signal. endclass
38
7
Semi Design
Monitor class:
• Samples the interface signals and converts the signal level activity to the
transaction level.
• Send the sampled transaction to Scoreboard via Mailbox.
• Below are the steps to write a monitor.

38
8
Semi Design
class monitor;

virtual intf vir;


mailbox m2s;
task main;
forever begin
function new(virtual intf vir, mailbox m2s);
transaction t1;
this.vir = vir;
t1 = new();
this.m2s = m2s;
#1;
endfunction
t1.a0 = vir.a0;
t1.a1 = vir.a1;
Declare interface and mailbox, Get the t1.sel = vir.sel;
interface and mailbox handle through the t1.out = vir.out;
constructor.
m2s.put(t1);
Sampling logic and sending the sampled t1.display("Monitor");
transaction to the scoreboard. end
endtask
38
endclass 9
Semi Design
Scoreboard class:
• Scoreboard receives the sampled packet from the monitor and compare with
the expected result, an error will be reported if the comparison results in a
mismatch.

39
0
Semi Design
class scoreboard;
task main;
mailbox m2s; transaction t1;
int no_of_transactions; forever begin
m2s.get(t1);
function new(mailbox m2s); no_of_transactions++;
this.m2s = m2s; t1.display("[Scoreboard]");
endfunction if (((t1.sel) &&
(t1.out==t1.a1))|((!t1.sel) &&
(t1.out==t1.a0)))
Declaring the mailbox and variable to keep $display ("result correct");
count of transactions, connecting handle else $display ("result wrong");
through the constructor. end
endtask
logic to compare the received result with
the expected result endclass

39
1
Semi Design
Environment class:
Environment is container class contains Mailbox, Generator and Driver.
Creates the mailbox, generator and driver shares the mailbox handle across the
Generator and Driver.

39
2
class environment; Semi Design
generator g1;
driver d1;
monitor m1;
scoreboard s1;

mailbox g2d;
mailbox m2s; In Construct Method, Create
virtual intf vir; - Mailbox
function new(virtual intf vir); - Generator
this.vir = vir; - Driver
and pass the interface handle
g2d = new(); through the new() method.
m2s = new();

g1 = new(g2d);
d1 = new(vir, g2d);
m1 = new(vir, m2s);
39
s1 = new(m2s); 3
endfunction
Semi Design
task pre_test();
d1.reset();
endtask For better accessibility.
Generator and Driver activity can be divided and
task test(); controlled in three methods.
fork - pre_test() – Method to call Initialization. i.e, reset
g1.main(); method.
d1.main(); - test() – Method to call Stimulus Generation and
m1.main(); Stimulus Driving.
s1.main(); - post_test() – Method to wait the completion of
join_any generation and driving.
endtask

task post_test();
wait(g1.ended.triggered);
wait(g1.repeat_count == d1.no_of_transactions);
wait(g1.repeat_count == s1.no_of_transactions); 39
endtask 4
Semi Design

task run;

pre_test();
test();
post_test(); // not required
$finish; Add a run task to call the above methods.
endtask

endclass

39
5
Semi Design
Test:
Test code is written with the program block.
The test is responsible for,
• Creating the environment.
• Configuring the testbench i.e, setting the type and number of transactions to
be generated.
• Initiating the stimulus driving.

39
6
Semi Design

program test(intf i_i);

environment e1;
- Declare and Create an environment.
initial begin
- Configure the number of transactions to
e1 = new(i_i);
be generated
e1.g1.repeat_count = 10;
- Initiating the stimulus driving
e1.run();
end

endprogram

39
7
Semi Design
TestBench Top:
• This is the topmost file, which connects the DUT and TestBench.
• TestBench top consists of DUT, Test and Interface instances.
• The interface connects the DUT and TestBench.

39
8
Semi Design
`include "header.svh"
module testbench_top;
bit reset;
initial begin
reset = 1;
#5 reset = 0; - Declare and Generate the clock and reset.
end - Create Interface instance.
- Create Design Instance and Connect
intf i_i(reset); Interface signals.
test t1(i_i);

mux2_1
d1(.a0(i_i.a0),.a1(i_i.a1),.reset(i_i.reset),.se
l(i_i.sel),.out(i_i.out));

initial begin
$dumpfile("dump.vcd");
$dumpvars; 39
end 9
endmodule
Semi Design
Header.sv file

`include "interface.sv"
`include "transaction.sv"
`include "generator.sv" It includes all .sv files in header.sv
`include "driver.sv"
`include "monitor.sv"
`include "scoreboard.sv"
`include "environment.sv"
`include "random_test.sv"

40
0
Semi Design
// simulation result
[Driver] ----- Reset Started -----
[Driver] ----- Reset Ended -----
[Generator] # KERNEL: -------------------------
# KERNEL: ------------------------- # KERNEL: - Monitor
# KERNEL: - a0 = 3, a1 = 0, sel = 0 # KERNEL: -------------------------
# KERNEL: - out = 0 # KERNEL: - a0 = 2, a1 = 6, sel = 1
# KERNEL: ------------------------- # KERNEL: - out = 6
# KERNEL: ------------------------- # KERNEL: -------------------------
# KERNEL: - [Driver] # KERNEL: -------------------------
# KERNEL: ------------------------- # KERNEL: - [Scoreboard]
# KERNEL: - a0 = 2, a1 = 6, sel = 1 # KERNEL: -------------------------
# KERNEL: - out = 6 # KERNEL: - a0 = 2, a1 = 6, sel = 1
# KERNEL: ------------------------- # KERNEL: - out = 6
# KERNEL: -------------------------
# KERNEL: result correct
# KERNEL: -------------------------
40
---- 1
Semi Design
SystemVerilog TestBench Example — D - Flipflop
Let’s Write the SystemVerilog TestBench for the simple design “D - Flipflop”.
Design specification:

D - Flipflop

Q
D D - FF
DUT
Qn

clock reset
40
2
Semi Design
Verilog programming for D - Flipflop
module d_ff(D, clk, reset, Q, Qn);
input D, clk, reset;
output reg Q;
output Qn;

assign Qn = ~ Q;

always @ (posedge clk)


begin
if (reset)
Q <= 0;
else
Q <= D;
end

endmodule 40
3
Semi Design
Getting started with test bench
Transaction Class:
• Fields required to generate the stimulus are declared in the transaction
class.
• Transaction class can also be used as a placeholder for the activity
monitored by the monitor on DUT signals.
• So, the first step is to declare the ‘Fields‘ in the transaction class.
• Below are the steps to write the transaction class.

40
4
Semi Design
class transaction;
rand bit D;
bit Q, Qn;

function void display(string name);


$display("-------------------------");
$display("- %s ",name);
$display("-------------------------");
$display("- D = %0d",D);
$display("- Q = %0d, Qn = %0d",Q, Qn);
$display("-------------------------");
endfunction

function transaction do_copy();


transaction tr;
tr = new();
tr.D = this.D;
return tr; 40
endfunction 5
endclass
Semi Design
Generator Class:
Generator class is responsible for,
• Generating the stimulus by randomizing the transaction class
• Sending the randomized class to driver

40
6
Semi Design

class generator;

transaction t1,t2;

int repeat_count; Adding Mailbox and event,


- Mailbox is used to send the
mailbox g2d; randomized transaction to
Driver.
event ended; - Event to indicate the end of
packet generation.
function new(mailbox g2d,event ended);
this.g2d = g2d;
t1=new();
this.ended = ended;
endfunction

40
7
Semi Design
function new(mailbox g2d,event ended);
this.g2d = g2d;
t1=new();
this.ended=ended;
endfunction

task main();
repeat (repeat_count)
begin main task, generates(create and
if (t1.randomize()) randomizes) the repeat_count
begin number of transaction packets and
t1.display("<< Generator >>"); puts into mailbox
t2 = t1.do_copy;
g2d.put(t2);
end else
$fatal("Gen:: trans randomization failed");
end
-> ended; 40
endtask 8
endclass
interface intf(input logic clk, reset); Semi Design
logic D;
logic Q;
logic Qn;

clocking c_b @(posedge clk); // driver


default input #1 output #1;
input Q, Qn; simple interface without
output D; modport and clocking block.
endclocking

clocking cb @(posedge clk); //monitor


default input #1 output #1;
input Q, Qn;
input D;
endclocking

modport c_b_m(clocking c_b, input clk,reset);


40
modport cb_m(clocking cb, input clk,reset); 9
endinterface
Driver Class: Semi Design

Receive the stimulus generated from the generator and drive to DUT by
assigning transaction class values to interface signals.

`define DRIV v_i.c_b_m.c_b


class driver;
Declare interface and
int no_of_trans; mailbox, Get the interface
and mailbox handle through
virtual intf v_i; a constructor.

mailbox g2d;

function new(virtual intf v_i, mailbox g2d);


this.v_i = v_i;
this.g2d = g2d;
endfunction
41
0
task reset; task run; Semi Design
wait(v_i.reset); forever begin
$display("<< Driver >>"); transaction t1;
$display("---- Reset started ----"); g2d.get(t1);
`DRIV.D <= 0; @(posedge v_i.c_b_m.clk);
wait(!v_i.reset); `DRIV.D <= t1.D;
$display("<< Driver >>"); @(posedge v_i.c_b_m.clk);
$display("---- Reset ended ----"); t1.Q = `DRIV.Q;
endtask t1.Qn = `DRIV.Qn;
t1.display("<< Driver >>");
no_of_trans++;
Adding a reset task, which end endtask
initializes the Interface
signals to default values. task main;
forever begin
Adding a main task to drive fork
the transaction packet to the wait(v_i.reset);
interface signal. run();
join_any 411
disable fork;
end endtask endclass
Semi Design
Monitor class:
• Samples the interface signals and converts the signal level activity to the
transaction level.
• Send the sampled transaction to Scoreboard via Mailbox.
• Below are the steps to write a monitor.

41
2
Semi Design
`define MON v_i.cb_m.cb
class monitor;

virtual intf v_i;


task main;
forever begin
mailbox m2s;
transaction t1 = new();
@(posedge v_i.cb_m.clk);
function new(virtual intf v_i, mailbox m2s);
t1.D = `MON.D;
this.v_i = v_i;
@(posedge v_i.cb_m.clk);
this.m2s = m2s;
t1.Q = `MON.Q;
endfunction
t1.Qn = `MON.Qn;
Declare interface and mailbox, Get the
m2s.put(t1);
interface and mailbox handle through the
t1.display("<< Monitor >>");
constructor.
end
Sampling logic and sending the sampled endtask
transaction to the scoreboard. 41
endclass 3
Semi Design
Scoreboard class:
• Scoreboard receives the sampled packet from the monitor and compare with
the expected result, an error will be reported if the comparison results in a
mismatch.

41
4
Semi Design
class scoreboard;

mailbox m2s; task main();


int no_of_transactions; transaction t1;
forever begin
function new(mailbox m2s); m2s.get(t1);
this.m2s = m2s; no_of_trans++;
endfunction t1.display("<< scoreboard >>");
if ((t1.D == t1.Q) && (t1.Qn == ~t1.Q))
$display("result correct");
Declaring the mailbox and variable to keep
else
count of transactions, connecting handle
$display("result wrong");
through the constructor.
end
endtask
logic to compare the received result with
the expected result endclass

41
5
Semi Design
Environment class:
Environment is container class contains Mailbox, Generator and Driver.
Creates the mailbox, generator and driver shares the mailbox handle across the
Generator and Driver.

41
6
class environment; Semi Design
generator g1;
driver d1;
monitor m1;
scoreboard s1;

mailbox g2d;
mailbox m2s; In Construct Method, Create
virtual intf vir; - Mailbox
function new(virtual intf vir); - Generator
this.vir = vir; - Driver
and pass the interface handle
g2d = new(); through the new() method.
m2s = new();

g1 = new(g2d);
d1 = new(vir, g2d);
m1 = new(vir, m2s);
41
s1 = new(m2s); 7
endfunction
Semi Design
task pre_test();
d1.reset();
endtask For better accessibility.
Generator and Driver activity can be divided and
task test(); controlled in three methods.
fork - pre_test() – Method to call Initialization. i.e, reset
g1.main(); method.
d1.main(); - test() – Method to call Stimulus Generation and
m1.main(); Stimulus Driving.
s1.main(); - post_test() – Method to wait the completion of
join_any generation and driving.
endtask

task post_test();
wait(g1.ended.triggered);
wait(g1.repeat_count == d1.no_of_transactions);
wait(g1.repeat_count == s1.no_of_transactions); 41
endtask 8
Semi Design

task run;

pre_test();
test();
post_test(); // not required
$finish; Add a run task to call the above methods.
endtask

endclass

41
9
Semi Design
Test:
Test code is written with the program block.
The test is responsible for,
• Creating the environment.
• Configuring the testbench i.e, setting the type and number of transactions to
be generated.
• Initiating the stimulus driving.

42
0
Semi Design

program test(intf i_i);

environment e1;
- Declare and Create an environment.
initial begin
- Configure the number of transactions to
e1 = new(i_i);
be generated
e1.g1.repeat_count = 10;
- Initiating the stimulus driving
e1.run();
end

endprogram

42
1
Semi Design
TestBench Top:
• This is the topmost file, which connects the DUT and TestBench.
• TestBench top consists of DUT, Test and Interface instances.
• The interface connects the DUT and TestBench.

42
2
Semi Design
`include "header.svh"
module testbench_top; - Declare and Generate the clock and reset.
- Create Interface instance.
bit clk; - Create Design Instance and Connect
bit reset; Interface signals.

initial clk = 0; intf i_i(clk, reset);

always #5 clk =! clk; testb t1(i_i);

initial begin d_ff


reset = 1; dut(.D(i_i.D),.clk(i_i.clk),.reset(i_i.reset),.
#20 reset = 0; Q(i_i.Q),.Qn(i_i.Qn));
end
initial begin
$dumpfile("dump.vcd");
$dumpvars;
end 42
endmodule 3
Semi Design
Header.sv file

`include "interface.sv"
`include "transaction.sv"
`include "generator.sv" It includes all .sv files in header.sv
`include "driver.sv"
`include "monitor.sv"
`include "scoreboard.sv"
`include "environment.sv"
`include "random_test.sv"

42
4
Semi Design
// simulation result
# KERNEL: << Driver >>
# KERNEL: ---- Reset started ----
# KERNEL: << Driver >>
# KERNEL: ---- Reset ended ----
# KERNEL: - << Monitor >>
# KERNEL: << Generator >>
# KERNEL: -------------------------
# KERNEL: -------------------------
# KERNEL: - D = 1
# KERNEL: - D = 1
# KERNEL: - Q = 1, Qn = 0
# KERNEL: - Q = 0, Qn = 0
# KERNEL: -------------------------
# KERNEL: -------------------------
# KERNEL: -------------------------
# KERNEL: - << Driver >>
# KERNEL: - << scoreboard >>
# KERNEL: -------------------------
# KERNEL: -------------------------
# KERNEL: - D = 1
# KERNEL: - D = 1
# KERNEL: - Q = 1, Qn = 0
# KERNEL: - Q = 1, Qn = 0
# KERNEL: -------------------------
# KERNEL: -------------------------
# KERNEL: result correct
# KERNEL: ------------------------- 42
5

You might also like