System Verilog Classes
System Verilog Classes
System Verilog Classes
CONTENTS
• Introduction
• Data Types
• ARRAYS
• TASKS & FUNCTIONS
• OOPS
• Class
• Object
• Inheritance
• Polymorphism
• $Cast
• ABSTRACTION (OR) VIRTUAL CLASS
• SUPER.NEW() KEYWORD
• THIS KEYWORD
• EXTERN KEYWORD
• SHALLOW COPY
• DEEP COPY
• MAILBOX
• SEMAPHORE
• RANDOMIZATION
• CONSTRAINTS
• Distribution Constraints
• Inline Constraints
• Conditional Constraints
• Soft Constraints
• SEMAPHORE
• MODPORTS
• CODE COVERAGE
• FUNCTIONAL COVEARGE
• TB ARCHITECTURE
logic 1-bit
Integer 32-bit
Time 64-bit
Strings
Logic
• Logic –functionality similar to reg
• It is synthesizable and it can be used to define both combinational and sequential
logics
• Logic data types are 4- state data types
•It can be used anywhere i.e input, inout, output ports
System Verilog:
• Default value = x module counter(count, flag, clk, rst);
• Verilog:
module counter(count, flag, clk, rst); output logic [3:0] count;
output logic flag; // excluding logic will also insert a wire by
output reg [3:0] count; default
output flag; // by default it will be wire input clk, rst;
input clk, rst;
//assign flag = (count == 10) ? 1'b1 : 1'b0;
endmodule
Enum Datatype:- (list of values)
• An Enumerated data type defines a set of named values.
Example 1: enum { red, green, blue, yellow, white }
• The actual values are defaulted to integers starting at 0 and then increase.
• So in this example by default variable will get the default value of 0,1,2,3,4.
Str_name i1;
i1.opcode = 3; or i1 = {3, 100};
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)
Types of Arrays :
• Fixed Size Arrays
• Packed and Un-packed Arrays
• Dynamic Array
• Associative Array
• Queues
• String
In system Verilog we have following type arrays:-
7 6 5 4 3 2 1 0
7 6 5 4 3 2 1 0
7 6 5 4 3 2 1 0
Dynamic
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 []; bit [5:0] array_2 [];
• Array creation : array_1 = new [16Gb]; // 15:0 – Gb
• Methods : size() // it will print how many locations are
present - 10
delete()
Array_1[0] = 32’h1234_5678;
Array_1[0][16] = 1’b1;
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); // See what is this operation means – resizing
$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
Associative Array:-
• num(),
• first(var),
• last(var),
• next(var),
• perv(var),
• delete(index),
• exists(index)
code of Associative array
using(int):
module assoc; int $display("display the first index array_1=%0d",index,array_1[index]);
array_1[5]=900; if (array_1.exists(7))
• size()
• insert(1,5)
• delete()
• push_front()
• push_back()
• pop_front()
• pop_back()
module sv;
int queue_1[$]; code of queue:
queue_1.pop_back();
initial
$display("size of the queue(pop_back) is
begin queue_1=%0d",queue_1.size());
$display("size of the queue is queue_1=%0d",queue_1.size());
queue_1= {1,2,3,4,5,7,8,10};
queue_1.insert(1,766);
foreach(queue_1[i]) $display("size of the queue(insert) is
queue_1=%0d",queue_1.size());
$display("size of the queue(size) is
queue_1[%0d]=%0d",i,queue_1[i]);
foreach(queue_1[i])
queue_1.push_front(100); $display("size of the
$display("size of the queue(push_front) is queue(size after all
queue_1=%0d",queue_1.size()); methods)
queue_1.push_back(200); is queue_1[%0d]=
%0d",i,queue_1[i]);
$display("size of the queue(push_back) is
queue_1=%0d",queue_1.size());
queue_1.pop_front(); queue_1.delete();
$display("size of the queue(pop_front) is $display("size of the
queue_1=%0d",queue_1.size()); queue(delete) is
queue_1=%0d",queue_1.size());
STRING :
• String is a group of characters.
• String should be with in the double
quotes(“”).
• We can put & get characters in the string.
Syntax:
String s1 = “SemiConducTors”;
• String Methods:
tolower()
toupper()
putc()
getc()
substr()
len()
STRING code:
•It will start all the process/statements in parallel and waits for the completion of the
processes/statements.
•Any delay specified inside the block is relative to the time at which the fork join block
has entered.
Fork-join-any
The parent process blocks until any one of the processes wait by this fork completes.
Fork-join-none
The parent process will not block further process.
Initial Example : Fork_join
fork - join module sv;
Begin
Initial
Clk =0; begin fork begin
fork
#5; #10 $display($time,"i am cat");
end
Fork begin
#5 a = 0; // t = 10 #20 $display($time,"i am fat");
end begin
#10 b = 0; // t = 15
#30 $display($time,"i am dog"); end
Join Clk becomes 1 join
join at t=15 #40 $display($time,"i am rat");
Clk= 1;
end
end endmodule
fork – join_any Initial
Example : Fork join_any
Begin module sv; initial begin
fork begin
Clk =0; #10 $display($time,"i am cat"); end
fork #5 begin
#20 $display($time,"i am fat");
Fork end
#5 a = 0; begin
#30 $display($time,"i am dog");
#10 b = 0; end
Join_any join_any
Clk becomes 1 #40 $display($time,"i am rat");
Join_any Clk= 1; at t=10 end
endmodule
#2 $finish;
end
Initial
Begin
fork – join_none
Clk =0;
Example : Fork Join_none
#5 module sv;
initial begin fork begin
Fork T= 5, a = 0
fork #10 $display($time,"i am cat");
a = 0; T= 15, b = 0 end
begin
#10 b = 0; #20 $display($time,"i am fat");
Join_none end
Clk becomes 1 begin
#2 Clk= 1; at t=7 #30 $display($time,"i am dog");
T= 12, c = 0
#5 C = 0; end
Join_none join_none
#6 b = 1; #40 $display($time,"i am rat");
end
disable fork;
endmodule
end
INTERFACE
INTERFACE
• Bundle of Interconnects.
• Provide an abstract encapsulation of communication between blocks
• Signal directions can be given in below two formats
• Directional information (modports)
• Timing (clocking blocks)
Example:
device1 interface device2 interface bus_a (input clock);
logic [7:0] address;
interface
• Generally interface will have all the signals defined and the DUT_wrapper
directions are specified in the modport. Addr, data,
• A modport can include all the signals or only some signals. mode
Design_1 Design_2
• modport des_1 (input ready, output addr, data, mode);
ready
• modport des_1 (input ready, output addr, data);
module DUT_wrapper(……);
Example:
input clk;
Interface bus_b (input clock);
bus_b bus (clk); //interface
logic [7:0] addr, data;
Design_1 d1 (bus.des_1);
logic [1:0] mode ;
Design_2 d2 (bus.des_2); // instantiating
bit ready ;
specific
modport des_1 (input ready, output addr, data, mode);
modport
modport des_2 (input addr, data, mode, output ready);
….
endinterface: bus_b
endmodule
CLOCKING BLOCK
• Specify synchronization characteristics of the design
• Offer a clean way to drive and sample signals Interface M1(clk, enin, din, enout, dout);
input clk,enin;
• Features
input [31:0] din ;
• Clock specification output enout ;
• Input skew,output skew output [31:0] dout ;
• Cycle delay (##)
clocking sd @(posedge clk); Signals will be
• Can be declared inside interface,module or program
sampled 2ns
input #2ns ein,din;
before posedge
output #3ns enout, dout; clk
endclocking:sd
classes
OOP
polymorphism inheritance
Class
• The class definition describes all the properties, behavior, and identity of objects present within that class. It is the central
point of OOP and that contains data and codes with behavior.
Inheritance is an OOP concept that allows the user to create classes that are built upon existing classes.
The new class will be with new properties and methods along with having access to all the properties and
methods of the original class.
Child can access the parent properties/methods, but parent cannot access the child properties/methods.
//module
//base class module inheritence;
class parent_class; initial begin
bit [31:0] addr; child_class c = new();
endclass c.addr = 10;// accessing the parent property
from child object
//child class c.data = 20;
class child_class extends parent_class;
bit [31:0] data; $display("Value of addr = %0d data =
endclass %0d",c.addr,c.data); // addr = 10, data = 20
end
endmodule
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.
// module
// base class module class_polymorphism;
class base_class; initial begin
function void display(); //declare and create extended class
$display("Inside base class"); ext_class_1 c_1 = new();
endfunction //base class handle
endclass base_class b_c;
//assigning extended class to base class
// extended class 1 b_c = c_1;
class ext_class_1 extends base_class; //accessing extended class methods using base class
function void display(); handle
$display("Inside extended class 1"); b_c.display();
endfunction end
Endclass endmodule
Imp keywords
The “this” keyword is used to unambiguously refer to
class properties or methods of the current instance. • The “super” keyword is used in a
derived class to refer to the members of
class packet;
//class properties the parent class.
bit [31:0] data; // GLOBAL
//constructor class parent_class;
module inheritence;
function new(bit [31:0] data); // constructor fun bit [31:0] addr;
initial begin
this.data = data; // LOCAL TO FUN function display();
child_class c=new();
endfunction $display("Addr = %0d",addr);
c.addr = 10;
//method to display class properties endfunction
c.data = 20;
function void display(); endclass
module sv_const; c.display(); // will
bit [31:0] data;
packet execute both the display
this.data = data; class child_class extends parent_class;
functions
$display("\t data = %0h",this.data); pkt;//handle bit [31:0] data;
initial begin end
endfunction function display();
pkt = new(10);// endmodule
endclass super.display(); // call parent display
obj $display("Data = %0d",data);
pkt.data = 14; endfunction
pkt.display(); endclass
end
$cast:
In polymorphism we are assigning parent = child but there is no possibility to assign child=parent,
but by using $cast we can perform child = parent, which will be legal in this case.
• Syntax :
virtual class parent;
Code of Abstract
class:
virtual class parent;
function void display();
$display("Iam in parent");
endfunction
endclass
//constructor
function new();
addr = 32'h10;
data = 32'hFF;
ar = new(); //creating object
// -- module ---
module class_assignment;
packet pkt_1;
packet pkt_2;
initial begin
pkt_1 = new(); //creating pkt_1 object
$display("\t**** calling pkt_1 display ****");
pkt_1.display();
pkt_2 = new pkt_1; //creating pkt_2 object and copying pkt_1 to pkt_2
$display("\t**** calling pkt_2 display ****");
pkt_2.display();
//changes made to pkt_2.ar properties reflected on pkt_1.ar, so only handle of the object
get copied, this is called shallow copy
pkt_1.display();
$display("\t**** calling pkt_2 display after changing pkt_2 properties ****");
pkt_2.display(); //
end
endmodule
Deep Copy:
• Both Data & Objects of parent class are
copied.
• .copy() method is used to perform deep_copy.
pt1=new();
class simple; pt2=new();
int a,b; pt2=pt1.copy();
function simple copy(); $display("a=
%d,b=
copy=new(); %d",pt1.a,pt1.b)
copy.a=2; ;
copy.b=4; $display("a=
endfunction %d,b=
endclass %d",pt2.a,pt2.b)
;
module main();
pt1.a=5;
simple pt1,pt2; pt1.b=7;
initial begin $display("a=
%d,b=
%d",pt1.a,pt1.b)
RANDOMIZATION
Randomization:
• 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.
• 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.
• If we declare a rand method i.e., rand & randc we need to use .randomize() method also.
class test;
rand bit [31:0] addr;
bit [127:0] data;
enclass
module TB;
bit success;
test t_h = new;
initial begin
#10;
success = t_h.randomize;
end
function void pre_randomize();
$dispaly(addr)
data = addr * 2;
endfunction
• rand : In the declared list of values , when we use rand keyword , it can
repeat values at any point of time.
• randc: random cyclic it means values are not repeated until one cycle
completes.
• Value will repeated only after all the possible values have been assigned at
least once.
randc bit [1:0] val; // 2'b00 - 01 - 10 - 11
repeat(10)
t_h.randomize - 00 - 01 - 11 - 00 - 01 - 11 - 11
rand
00 - 01 - 11 - 00 - 01 - 11 - 11
randc
00 - 11 - 01 - 10 - 01 - 11 - 10 - 00 - 10 - 11
Code of Randomization:
class parent;
rand bit[7:0] a;
endclass
module sv;
parent p;
initial
begin
p=new();
repeat(10)
begin
p.rando
mize();
$display("a
=%0d",p.a);
end
end
CONSTRAINTS
Constraints
• Constraints are declared with in the class.
• In class after randomization only, constraints are possible.
• Constraints are limited to particular value.
• Control the values getting assigned on randomization, this can be achieved by writing
constraints.
Syntax :
constraint <constraint_name> { variable condition;}
Ex:
constraint sname{a==5;}
constraint sname{a%5==0;}
constraint sname_1{a%3==0;}
• constraint_modes:
• Constraint_mode(1) --- It will enable the constraint. By default
constraints are enabled
• Constraint_mode(0) --- It will disable the constraint.
• rand_modes:
• rand_mode(1) ----- It will enable the randomization. By default
randomization is enable
• rand_mode(0) ----- It will disable the randomization.
Types of Constraints:
• Inline constraint
• Inside constraint
• Distributional constraint
• Conditional constraints
• Solve before constraint
• Soft constraint
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
If(pkt.rando
mize()
with
{ addr ==
8; data ==
• 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 range of values.
the
• Values with in the inside block can be variable, constant or range.
Syntax:
constraint addr {data inside {1,3,[5:10],12,[13:15]};}
constraint data_range { data inside {[1:9]}; }
constraint data_range { data > 0; data < 10; length == size**2; size == 2;}
In the above example 1,3 are set of values and [13:15] represents range.
Inside operator:
class packet;
rand bit [3:0] addr; rand bit [3:0] wr; rand
bit [3:0] rd;
extern 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
Extern constraints :
class packet;
rand bit [3:0] addr;
rand bit [3:0] wr;
rand bit [3:0] rd;
extern constraint addr_1_range {} // 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] := 0};}
2) :/ assigns weight to whole
value. Syntax: [101:123]:/ 20
-------
// 20/23 = 0.86 => 1
In the above example each item
Conditional Constraint:
• The implication operator can be used to declaring conditional relations
between two variables.
Syntax:
Constraint identifier {expression ->{constraint_set};}
Example:
module sv;
bit [3:0] a, b, c;
bit success;
initial begin
Success = std::randomize(a, b) with {a > 10; b > 10;};
$display(“a = %d, b = %d, c = %d, success = %d”, a, b, c, success);
end
endmodule
Keypoints of Constraints:
• Constraints are declared with in the class.
• Constraints are possible only after randomization.
• Constraint overriding is possible only by declaring the same name in another constraint
also.
• Syntax: constraint c1 {a == 10;}
constraint c1 { a == 20;}
• Constraint Conflict:
Syntax constraint c1 {a >10 ;}
: constraint c2 {a <10 ;}
In the above example , as we have declared the same variable name , randomization
cannot choose what constraint has to be randomized. So in this case constraint conflict
occurs.
MAILBOX
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.
Ex:
Mailbox #(interface intf) gen2drv;
SEMAPHORE
Semaphore:
• 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;
task automatic semaphore_ex::display();
semaphore sema; //handle
sema.get(4); //getting '4' keys from
Extern task automatic display();
sema
initial
$display($time,"Current Simulation Time");
begin sema=new(4); // object - key = 4
fork
#20;
display();
sema.put(4) //putting '4' keys to sema
display();
; endtask
join end
endmodule
STRATIFIED EVENT QUEUE
Detailed:
Stratified event scheduler:
Virtual Interface:
• An interface is a named as group of signals.
• Virtual Interface is Bi-directional.
• In interface we are declaring input , output signals by using logic data type.
• Virtual Interface is dynamic in nature, we can change virtual interface during the run_time.
• Virtual Interface contains Modports & Clocking blocks.
• Virtual interface point outs the physical interface which is present in the sv_library or
uvm_library.
• An interface can have parameters, constants, variables, functions, and tasks.
COVERAGE
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.
• Code Coverage
• Functional Coverage
Code Coverage :
• Code coverage measures how much of the “design Code” is covered.
•The simulator tool will automatically extract the code coverage from the design code.
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;
2. Statement Coverage :
Conveys the number of
statements covered.
Syntax: y = a+b;
x = b+c;
3. Toggle / Transition
Coverage : It covers
the toggle
i.e., 0-1 or 1-0
conditions.
Functional
coverage :
• 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.
• Functional coverage is user-defines implemented at environment side.
coverpoints,
bins ,
cross coverage.
Cover group:
covergroup cg @(posedge clk)
c1 : coverpoint addr disable iff (rst == 1){
Bins = {[100 : 200]};
bins[5] = {[300 : 500]};
} illegal bin = {[201:299]};
c2 : coverpoint data {
bins [ ] = {[10:50]};
bins [2] = {[60:90]};
}
c1 *c2 : cross c1,c2;
endgroup
• Once covergroup is created we need to create a handle for that.
Syntax: cg cg_inst;
• Once covergroup is instantiated we need to assign memory
for that.
Syntax: cg_inst = new();
• Once memory is assigned we need to sample the covergroup.
• cg_inst.sample ();
Defining cover
• points
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.
• 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
• Bins are explicitly declared within curly braces { } along with the bins keyword followed by
bin name and variable value/range, immediately after the coverpoint identifier.
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
auto_bin_max :
cross_auto_bin_max :
eg
covergroup cg
@(posedge clk);
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)