System Verilog
System Verilog
CONTENTS
• DATA TYPES
• ARRAYS
• OOPS
• Class
• Object
• Inheritance
• Polymorphism
• $Cast
• SUPER.NEW() KEYWORD
• THIS KEYWORD
• EXTERN KEYWORD
• SHALLOW COPY
• DEEP COPY
• MAILBOX
• RANDOMIZATION
logic 1-bit
Integer 32-bit
Time 64-bit
Enum Datatype:- (list of values)
• An Enumerated data type defines a set of named values.
• NOTE:-If an automatically incremented value is assigned elsewhere in the same enumeration, this
shall be a syntax error.
• Example 3: enum { red=0, green, blue=4, yellow, white=5 }
Code of Enum:
module enums;
enum{red=0,green=1,yellow=2,blue=3,pink=4}clr; initial
begin
clr=clr.first();
$display("display the first clr=%0s",clr);
clr=clr.last();
$display("display the last clr=%0s",clr);
clr=clr.next();
$display("display the next clr=%0s",clr);
clr=clr.prev();
$display("display the prev clr=%0s",clr);
end endmodule
Typedef Data Type:-
• Typedef allows users to create their own names for type definition that they will use
frequently in their code.
• Typedefs can be very convenient when building up complicated array definitions.
• By using typedef we can define any data type.
• By using typedef we can declare outside of the module , with the help of handle we can
access inside the module.
• Syntax of typedef:
• typedef enum;
• typedef bit;
• typedef int
Code of Typedef:
typedef enum{red=0,green=1,yellow=2,blue=3,pink=4}colours;
module sv;
colours clr;
initial begin
clr=clr.first();
$display("display the first clr=%0s",clr);
clr=clr.last();
$display("display the last clr=%0s",clr);
clr=clr.next();
$display("display the next clr=%0s",clr);
clr=clr.prev();
$display("display the prev clr=%0s",clr);
end
endmodule
Struct Data Types:- static
• Collection of variables of different data types.
• It is fixed data type.
• Memory allocations can be done at compilation time.
Sample code of Struct:
module sv;
struct packed{ int addr;
bit data;
byte arun; }pkt;
initial
begin
pkt='{1,2,3};
$display("pkt=%0d",pkt);
$display("addr=%0d,data=%0d,arun=%0d",pkt.addr,pkt.data,pkt.arun); end
endmodule
DATA SIGNED/U SIZE STATE COMPATIBILITY SYNTAX
TYPES NSIGNED (IN
BITS
)
reg Unsigned 1 4 SV/V Reg <variable_name>;
wire Unsigned 1 4 SV/V Wire <variable_name>;
logic Unsigned 1 4 SV Logic <variable_name>;
integer Signed 32 4 SV/V Integer <variable_name>;
real Signed 64 4 SV/V real <variable_name>;
realtime Unsigned 64 4 SV/V realtime <variable_name>;
time Unsigned 64 4 SV/V time <variable_name>;
int Signed 32 2 SV Int <variable_name>;
bit Unsigned 1 2 SV bit <variable_name>;
byte signed 8 2 SV byte <variable_name>;
shortint Signed 16 2 S shortint <variable_name>;
longint Signed 64 2 SV longint <variable_name>;
STRATIFIED EVENT QUEUE
Detailed:
Stratified event scheduler:
System Verilog (ARRAYS)
SYSTEM VERILOG - ARRAYS
ARRAYS:
An array is collection of variables of same type, and accessed using the
same name plus one or more indices.
Types of Arrays :
• Fixed Size Arrays
• Packed and Un-packed Arrays
• Dynamic Array
• Associative Array
• Queues
• String
array1 = '{0,1,2,3,4,5};
array2 = '{0,1,2,3,4,5};
//declaration of array’s
int array4[4:0];
initial begin
//array initialization
array1 = '{0,1,2,3,4,5};
array2 = '{0,1,2,3,4,5};
array3 = '{'{0,1,2,3},'{4,5,6,7},'{8,9,10,11}};
$display("-------displaying array1-------");
$display("-------displaying array2-------");
$display("-------displaying array3-------");
end
endmodule
Simulator Output:
-------displaying array1-------
array1[0] = 0
array1[1] = 1
array1[2] = 2
array1[3] = 3
array1[4] = 4
array1[5] = 5
-------displaying array2-------
array2[0] = 5
array2[1] = 4
array2[2] = 3
array2[3] = 2
array2[4] = 1
array2[5] = 0
-------displaying array3-------
array3[2][3] = 0
array3[2][2] = 1
array3[2][1] = 2
array3[2][0] = 3
array3[1][3] = 4
array3[1][2] = 5
array3[1][1] = 6
array3[1][0] = 7
array3[0][3] = 8
array3[0][2] = 9
array3[0][1] = 10
array3[0][0] = 11
-------displaying uninitialized array4-------
array4[0] = 0
array4[1] = 0
array4[2] = 0
array4[3] = 0
array4[4] = 0
Packed and Unpacked Arrays:
The term packed array is used to refer to the dimensions declared before the data identifier name
The term unpacked array is used to refer to the dimensions declared after the data identifier name
Packed array:-
• Packed arrays can be of single bit data types like reg, logic, bit.
• Dimensions declared before the data identifier name.
Syntax: logic[15:0] arr;
• Packed arrays are fixed sized , single or multidimensional array.
• Packed array is guaranteed to be represented as a contiguous set of bits.
• Syntax : bit [2:0][7:0] array1;
• The below example shows storing packed array as a contiguous set of bits.
7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0
UnPacked array
• A dynamic array is unpacked array whose size can be set or changed at runtime.
• During the runtime we can increase size and decrease the size.
• Dynamic array can be represented as [ ]; Syntax :
int array_1 [ ];
• Array creation : array_1 = new [10];
• data_type array_name [ ];
//declaration
bit [7:0] d_array1[ ];
int d_array2[ ];
//memory allocation
//array initialization
d_array1 = {0,1,2,3};
foreach(d_array2[j]) d_array2[j] = j;
//Change the length of the array after declaration/initialization
In the above syntax, d_array1 will get allotted with 10 new memory locations and old values of d_array1 will get deleted. old values of d_array1
elements can be retained by extending the current array by using the below syntax.
d_array1 = new[10](d_array1);
c
//delete array
d_array1.delete;
module dynamic_array;
int d_array2[];
initial begin
//memory allocation
d_array1 = new[4];
d_array2 = new[6];
//array initialization
d_array1 = {0,1,2,3};
foreach(d_array2[j]) d_array2[j] = j;
$display("---------------------------------");
$display("---------------------------------");
end
endmodule
Simulator Output:
Size of d_array1 0
Size of d_array2 0
Size of d_array1 4
Size of d_array2 6
d_aaray1[0] = 0
d_aaray1[1] = 1
d_aaray1[2] = 2
d_aaray1[3] = 3
---------------------------------
d_aaray2[0] = 0
d_aaray2[1] = 1
d_aaray2[2] = 2
d_aaray2[3] = 3
d_aaray2[4] = 4
d_aaray2[5] = 5
---------------------------------
int d_array2[];
initial begin
//memory allocation
d_array1 = new[2];
d_array2 = new[3];
//array initialization
d_array1 = {2,3};
foreach(d_array2[j]) d_array2[j] = j;
$display("---------------------------------");
$display("---------------------------------");
//delete array
d_array1.delete;
d_array2.delete;
end
endmodule
Simulator Output:
d_aaray1[0] = 2
d_aaray1[1] = 3
---------------------------------
d_aaray2[0] = 0
d_aaray2[1] = 1
d_aaray2[2] = 2
---------------------------------
Size of d_array1 0
Size of d_array2 0
The below example shows the increasing dynamic array size by overriding and retaining old values.
module dynamic_array;
int d_array2[];
initial begin
//memory allocation
d_array1 = new[2];
d_array2 = new[3];
//array initialization
d_array1 = {2,3};
foreach(d_array2[j]) d_array2[j] = j;
end
endmodule
Simulator Output:
----- d_array1 Values are -----
d_aaray1[0] = 2
d_aaray1[1] = 3
d_aaray2[0] = 0
d_aaray2[1] = 1
d_aaray2[2] = 2
d_aaray1[0] = 0
d_aaray1[1] = 0
d_aaray1[2] = 0
d_aaray1[3] = 0
d_aaray2[0] = 0
d_aaray2[1] = 1
d_aaray2[2] = 2
d_aaray2[3] = 0
d_aaray2[4] = 0
Sample code for Dynamic array:
module sv;
int array_1[];
initial
begin
$display("display the size of the array_1=%0d",array_1.size());
array_1=new[10];
$display("display the size of the array_1=%0d",array_1.size());
array_1=new[50](array_1);
$display("display the size of the array_1=%0d",array_1.size());
array_1.delete();
$display("display the size of the array_1=%0d",array_1.size());
end
endmodule
Unpacked Array:-
7 6 5 4 3 2 1 0
7 6 5 4 3 2 1 0
7 6 5 4 3 2 1 0
Associative Array:-
Syntax:
int array_1[*] //associative array of integer (unspecified index).
Array Declaration
where:
data_type – data type of the array elements.
array_name – name of the associative array.
index_type – data-type to be used as an index, or *.
* indicates the array is indexed by any integral expression of arbitrary size.
initial begin
//allocating array and assigning value to it
repeat(3) begin
a_array[index] = index*2;
index=index+4;
end
//exists()-Associative array method
if(a_array.exists(8))
$display("Index 8 exists in a_array");
else
$display("Index 8 doesnt exists in a_array");
initial begin
//allocating array and assigning value to it
a_array1[5] = 10;
a_array1[8] = 20;
a_array2["GOOD_PKT"] = 1;
a_array2["BAD_PKT"] = 0;
foreach(a_array1[index])
$display("a_array1[%0d] = %0d",index,a_array1[index]);
foreach(a_array2[index])
$display("a_array2[%0s] = %0d",index,a_array2[index]);
end
endmodule
Simulator Output:
a_array1[5] = 10
a_array1[8] = 20
a_array2[BAD_PKT] = 0
a_array2[GOOD_PKT] = 1
initial begin
//allocating array and assigning value to it
repeat(3) begin
a_array[index] = index*2;
index=index+4;
end
array_1[3]=300; if(array_1.exists(2))
Queue Initialization
queue_1 = {0,1,2,3};
queue_4 = {“Red”,"Blue”,"Green”};
Unbounded Queue
SystemVerilog queue
Bounded Queue
endmodule
Simulator Output:
----- Queue_1 size is 4 -----
queue_1[0] = 0
queue_1[1] = 1
queue_1[2] = 2
queue_1[3] = 3
----- Queue_2 size is 3 -----
queue_2[0] = Red
queue_2[1] = Blue
queue_2[2] = Green
----- Queue_2 size after inserting Orange is 4 -----
queue_2[0] = Red
queue_2[1] = Orange
queue_2[2] = Blue
queue_2[3] = Green
----- Queue_2 size after Delete is 3 -----
queue_2[0] = Red
queue_2[1] = Orange
queue_2[2] = Blue
example ;
module queues_array;
//declaration
bit [31:0] queue_1[$];
int lvar;
initial begin
//Queue Initialization:
queue_1 = {0,1,2,3};
//Size-Method
$display("\tQueue_1 size is %0d",queue_1.size());
//Push_front Method
queue_1.push_front(22);
$display("\tQueue_1 size after push_front is %0d",queue_1.size());
//Push_back Method
queue_1.push_back(44);
$display("\tQueue_1 size after push_back is %0d",queue_1.size());
//Pop_front Method
lvar = queue_1.pop_front();
$display("\tQueue_1 pop_front value is %0d",lvar);
//Pop_back Method
lvar = queue_1.pop_back();
$display("\tQueue_1 pop_back value is %0d",lvar);
end
endmodule
Simulator Output:
Queue_1 size is 4
Queue_1 size after push_front is 5
Queue_1 size after push_back is 6
Queue_1 pop_front value is 22
Queue_1 pop_back value is 44
module queues_array;
//declaration
int queue[$:2];
int index;
int temp_var;
initial begin
//Queue Initialization:
queue = {7,3,1};
$display("Queue elements are,");
$display("\tqueue = %p",queue);
queue.push_back(10);
$display("After push_back Queue elements are,");
$display("\tqueue = %p",queue);
queue.push_front(10);
$display("After push_front Queue elements are,");
$display("\tqueue = %p",queue);
end
endmodule
Simulator Output:
Queue elements are,
queue = '{7, 3, 1}
After push_back Queue elements are,
queue = '{7, 3, 1}
After push_front Queue elements are,
queue = '{10, 7, 3}
qu.push_back(2);
qu.push_back(13);
qu.push_back(5);
qu.push_back(65);
$display("[Before-Delete] Queue size is %0d",qu.size());
qu.delete();
$display("[After -Delete] Queue size is %0d",qu.size());
end
endmodule
Simulator Output:
[Before-Delete] Queue size is 4
[After -Delete] Queue size is 0
code of queue:
queue_1.pop_back();
module sv; $display("size of the queue(pop_back) is
int queue_1[$]; queue_1=%0d",queue_1.size());
initial
begin
$display("size of the queue is queue_1=%0d",queue_1.size()); queue_1=%0d",queue_1.size());
queue_1= {1,2,3,4,5,7,8,10};
foreach(queue_1[i])
foreach(queue_1[i])
$display("size of the queue(size after all methods)
is queue_1[%0d]=%0d",i,queue_1[i]);
queue_1.delete();
$display("size of the queue(delete) is
queue_1=%0d",queue_1.size());
end endmodule
STRING :
Syntax :
class driver ;
…..
endclass
Object Creation :
Syntax for Object Creation:
this Keyword:
• this keyword shows the local and global variable difference.
• Local variable means inside the module,
• Global variable means outside the module.
• By using this keyword we can access outside module variables.
INHERITANCE
Child class can access the parent class properties with the help of child class handle.
Child class inherits all the properties and methods of parent class by using child class handle.
Code Of Inheritance:
module sv;
class parent; parent p;
int addr; int child c;
data; initial
function void display(); begin
$display ("i am in parent "); c=new();
endfunction c.display();
endclass c.addr=20;
c.data=90;
class child extends parent; c.data1=100;
int data1; c.addr1=200;
int addr1;
function void display(); $display("addr=%0d,data=%0d,data1=%0d,addr1=
$display("i am in child"); %0d",c.addr,c.data,c.data1,c.addr1); end
endfunction endmodule
endclass
Super keyword:
• Syntax :
virtual class parent;
Code of Abstract class:
• Only properties parent class are copied , but not object of subclass.
• Shallow copy creates a separate memory only for the properties of the class but not the subclass object.
• System Verilog randomization provides a built-in method randomize. The randomize() method generates random
values for all the active random variables of an object.
• Variables declared with the rand keyword will get random values on the object.randomize()
method call.
• rand : In the declared list of values , when we use rand keyword , it generates repeated values.
• randc: random cyclic it means values are not repeated until one cycle completes.
• Value will repeated only after all the values have been assigned at least once.
• constraint_modes:
• Constraint_mode(1) --- It will enable the constraint.
• Constraint_mode(0) --- It will disable the constraint.
• rand_modes:
• rand_mode(1) ----- It will enable the randomization.
• rand_mode(0) ----- It will disable the randomization.
Code of Randomization:
Syntax :
constraint constraint_name{a=5;}
Types of Constraints:
• Inline constraint
• Inside constraint
• Distributional constraint
• Conditional constraints
• Soft constraint
• inline constraints: used to introduce an additional constraint represented as
randomize() with;
• Inside Operator:
• During randomization , it might require to randomize the variable with in the range of values.
• Values with in the inside block can be variable, constant or range.
Syntax:
Constraint addr {data inside {1,3,[5:10],12,[13:15]};}
In the above example 1,3 are set of values and [13:15] represents range.
Inline example:
class packet;
rand bit [3:0] addr;
rand bit [3:0] data;
module inline_constr;
initial begin
packet pkt; pkt
= new();
repeat(2) begin
pkt.randomize() with { addr == 8;};
$display("\taddr = %0d data = %0d",pkt.addr,pkt.data);
end
end
endmodule
Inside operator:
class packet;
rand bit [3:0] addr;
rand bit [3:0] wr; rand
bit [3:0] rd;
constraint addr_1_range { addr inside {[wr:rd]}; } // We can add values also with in the
range.
endclass
module constr_inside;
initial begin
packet pkt; pkt
= new();
repeat(3) begin
pkt.randomize();
$display("wr = %0d,rd = %0d",pkt.wr,pkt.rd);
$display("addr = %0d",pkt.addr); end
end
endmodule
Distribution constraints:
• Controls
the values on randomization.
• Repetition of the same value on randomization can be controlled by weighted distribution.
• There are 2 types of operators in distribution constraints.
1) := for each declared range, assigns weight to every value.
Syntax: [101:200] := 200
In the above example from 101 , 102, …,200 … each value gets a weight of
200.
Constraint c1 {a.dist { [101:200] };}
2) :/ assigns weight to whole value. Syntax:
[101:200] :/ 200
In the above example each item gets a weight of 2.
• By default the weight is 1.
Conditional Constraint:
• The implication operator can be used to declaring conditional relations between two variables.
Syntax:
Constraint identifier {expression ->{constraint_set};}
Implication Operator:
If else : if else block allows conditional executions of constraints. If the expression is true, all the constraints in the first
constraint/constraint-block must be satisfied, otherwise all the constraints in the optional else constraint/constraint-block must
be satisfied.
Syntax:
{if (exp) {constraint_set {else constraint_set}};}
Example:
constraint address_range { if(addr == "true") data < 8;
else
data > 8;
}
Soft Constraint:
• To override the constraint we use the soft keyword, any conflict between class constraint leads to a randomization
failure, from this it is clear that it is not possible to override the class constraint by inline constraint.
• solve before constraints are used to force the constraint block to specify the
order of constraint solving.
• Unique values to set of variables or unique elements to an array can be generated by using Unique
Constraint.
Syntax:
module sv; packet
class packet;
pkt; initial begin
rand bit [31:0] array[10];
pkt = new();
constraint array_c {unique {array}; pkt.randomize();
foreach(array[i]) array[i] < 10;} pkt.display();
function display(); end endmodule
$display("array = %p",array);
endfunction
endclass
Keypoints of Constraints:
module sv;
initial begin
fork
begin
#10 $display($time,"i am cat"); end
begin
#20 $display($time,"i am fat");
end
begin
#30 $display($time,"i am dog");
end
join_any
#40 $display($time,"i am rat");
end
endmodule
fork_join_none : fork-join_none means it will not join the threads.
Example :
module sv;
initial begin
fork
begin
#10 $display($time,"i am cat");
end
begin
#20 $display($time,"i am fat");
end
begin
#30 $display($time,"i am dog");
end
join_none
#40 $display($time,"i am rat");
end
endmodule
MAILBOX :
• A mailbox is a Inter Process communication mechanism between two components (i.e., generator
& driver) , (monitor & Scoreboard) in system Verilog.
• In generator we are using put() method , to place some data and using get() method we can
retrieve the data in driver.
Syntax:
• Semaphore is a System Verilog built-in class, used for access control to shared resources, and for basic
synchronization and mutual exclusion purpose.
• A semaphore is like a bucket with number of keys.
• By using semaphore we can put the keys and get the keys to access any files.
Semaphore methods:
• Semaphore is a built-in class that provides the following methods,
• new(); Create a semaphore with a specified number of keys.
• get(); Obtain one or more keys from the bucket.
• put(); Return one or more keys into the bucket.
• try_get(); Try to obtain one or more keys without blocking.
• try_put(); To return one or more keys without blocking.
Semaphore code:
module semaphore_ex;
semaphore sema; initial task automatic display();
Interface syntax:
interface mem_intf;
logic clk;
logic [7:0]addr;
logic wr_rd;
endinterface
Virtual Interface:
• Modports provides the direction to the module ports i.e. ,they specify the inputs & outputs to
the module.
Syntax:
interface intf;
logic a;
logic b;
modport driver (input a , output b); // modport declaration
modport monitor (input a, input b);
endinterface
Clocking Blocks:
• 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. types of coverage metrics,
• Code Coverage
• Functional Coverage
Code Coverage :
• The simulator tool will automatically extract the code coverage from the design code.
1. Line Coverage
2. Statement Coverage
4. FSM Coverage
7. Path Coverage
1. Line Coverage : Conveys the number of lines covered in the design.
Syntax: input a;
output b;
Syntax: y = a+b;
x = b+c;
3. Toggle / Transition Coverage : It covers the toggle i.e., 0-1 or 1-0 conditions.
4. FSM Coverage : It covers the states of a Finite machine i.e., melay and moore states.
• Functional coverage is a user-defined metric that measures how much of the design specifications or how many features
have been covered in verification of the design.
coverpoints , bins ,
cross coverage.
Cover group:
• A covergroup can contain one or more coverage points. A coverage point can be an integral variable or an integral
expression. Each coverage point is associated with “bin”. On each sample clock simulator will increment the associated
bin value.
• An automatically single bin will be created for each value of the coverpoint variable range. These are called
automatic, or implicit, bins.
• For an “n” bit integral coverpoint variable, a 2^n number of automatic bins will get created.
• A separate bin is created for each value in the given range of variable or a single/multiple bins for the range of values.
• Bins are explicitly declared within curly braces { } along with the bins keyword followed by bin name and variable
Ignore bins: Ignore bins are excluded from the coverage if you declare , the bin as ignore it will give
the fatal error. It is not included in the coverage , but simulator will give the coverage list which are
ignored.
illegal bins: illegal_bins are not added in the coverage , it is excluded from the coverage , if we declare illegal bin , simulator throws
at_least :
auto_bin_max :
cross_auto_bin_max :
eg
Scenario 1:
When Code Coverage is 90% & Functional coverage is 100% ?
• When code is covered till 90% remaining 10% is not covered due to missing of some blocks,
statements, toggle conditions , lines or FSM states etc.,
Scenario 2:
When Functional Coverage is 90% & Code Coverage is 100%?
• When code is Covered 100% ,but if functional coverage is less compared to code coverage because of some
features are missing, even though if we cover all features we cannot expect 100% coverage.
Scenario 3:
Refinement File : When Functional Coverage is 98% , remaining 2% can be achieved by refinement file. Refinement File can be collected
from RTL designer.
Assertions / Checkers:
• Assertion is a property , that the design should operate and which is always true.
• These are used to monitor the internal signals.
• To check the proper assertion quality, stimulus must be driven.
• $countones( ) : Returns the number of 1’s in an expression , any value other than one will be ignored.
• Syntax : $countones (expr)