Professional Documents
Culture Documents
com
INDEX
No. of
Sl # Topics / Subtopics Session Lab - Y/N Page #
Environment of Verification
2 Datatype 2 Y 17
2satete
4 state
3 Array 3 24
4 Process creation 4 30
wait-fork,Disable fork
5 OOPS concept 5 53
Inheritance,Polymorphism,
Data hiding,
Encapsulation
class
6 Interface 6
modport Y
interface
clocking block
Randomization Method
randomization mode
7 Constraints 7 77
common constarint Y
inline constraint
inside constarint
soft constraint
8 coverage 8 99
functional coverage
coverpoints
covergroup
coverbins
9 Assertion 9 123
use of $rose,$fell,$stable
Verification of Dff,Tff,counter,register
CHAPTER - 1
It is
HDVL(Hardware Description and verification Language)
there are 4 different languages which donated the stuff that makes the system verilog.
i. Verilog was adapted for having design concept say synthesize-able system verilog.
i. This oops concept adapted so we will be dealing with classes through out the sv
session.
Randomization
i. This Domain speicific HVL vera and e was adopted for having randomization
process
Assertion language
What is verification?
Complete validation of design functionality.
Make sure design is bug free by verifying it in all aspects;all possible scenarios.
module half_adder(a,b,s,cout);
output s,cout;
input a,b;
xor1 u1(s,a,b);
nand1 u2(cout,a,b);
endmodule
Stimulating DUT (design under test) with all possible scenarios and comparing its
output with golden results..
How to verify?
Writting the code for stimulus generator like input generation such as input
a,b to the design.
Stimulus generator will provide same test cases like a,b to reference model
same like how it provided a and b for DUT.
Last task is
Comparison of logic that actually does comparison between actual output and expected
output.
Verilog was initially used for for writting test bench .But writting complex test bench
is much more of a programming task than describing hardware. No need to synthesize
test bench. So no need to constraint our self to write code into verilog.So we have come
up new language for verification that is system verilog.
The reason is -
UVM is nothing but structured SV.So Knowing SV based verification helps under
standingUVM based verification also , or else UVM feels like set of magic macros
which are doing best of themself then we never come to know actual function of
UVM verification.
Back in the 1990’s Verilog was the primary language to verify functionality of
design that were small , not very complex and had less features.
Hard description language like verilog and VHDL are used to describe hardware
behavior which is called design module so that it can be converted to digital block made
up of combinatioanl gates and sequential elements.
After designing the module We need to verify the design to make sure that the design
is an accurate representation of the specification without any bugs. So there is need for
a language with more features in oop that will support complicated testing procedure
and is often called as hardware verification language.Verification is carried out to
ensure the correctness of design, to avoid surprises at a later time, to avoid a re-spin of
the chip and to enter the market on time with good quality.
Overview
Verification Environmen
Feature Extraction
Checker Plan
Coverage Plan
Asic Verification
System verilog is extension of verilog with many such verification features that allow
engineers to verify the design using complex testbench structure and random stimuli in
simulation.
Linear Test Bench is the simplest, fastest and easiest way of writing test benches.It is
also slowest way to execute stimulus.In this Test Bench, simple linear sequence of test
vectors is mentioned.The code snippet shows some input combination only. This is also
bad for simulator performance as the simulator must evaluate and schedule a very large
number of events. This reduces simulation performance in proportion to the size of the
stimulus process.
Output [16:0] y;
Assign y=a+b;
Endmodule
Reg a,b;
Wire c;
Adder dut(.a(a),.b(b),.c(c));
Initial begin
a=4’b1001;
b=4’1100;
End
endmodule
To test all possible scenarios which are known to us, it is not an easy task.
Instead of listing out all the possible scenarios, pickup some randomly and check
the DUT.
Random Test Bench don't use Hardcoded values like linear testbenchs. Input stimulus
is generated using random values. In Verilog, system function $random provides a
mechanism for generating random numbers. The function returns a new 32-bit random
number each time it is called. These test cases are not easily readable and are also not
reusable. New tests have to be created when the specification or design changes, to
accommodate the changes. The main disadvantage of this testing is that we never know
what random values are generated and it may waste simulation cycles by generating
same values again and again.
reg a,b;
wire c;
Adder dut(.a(a),.b(b),.c(c));
Initial begin
repeat(20) begin
a=$random;
b=$random;
end
End
endmodule
How does a Verification engineer check whether the results obtained from the
simulation match the original specification of the design?
For simple test benches like the above, output is displayed in waveform window or
messages are sent to terminal for visual checking. Visually checking is the oldest
and most labor intensive technique.
The quality of the verification depends on the determination and dedication of the
individual who is doing the checking. It is not practical to verify a complex model
merely by examining the waveform or text file. Whenever a change is made to the
DUT to add a new feature or to fix a bug, same amount of effort needs to be
deployed to check the simulation results.
A self-checking Test Bench checks expected results against actual results obtained from
the simulation. Although Self-checking testbenchs require considerably more effort
during the initial test bench creation phase, this technique can dramatically Reduce the
amount of effort needed to re-check a design after a change has been made to the DUT.
Debugging time is significantly shortened by useful error-tracking information that can
be built into the Test Bench to show where a design fails.
A self-checking TestBench has two major parts, the input blocks and output blocks.
Input block consist of stimulus and driver to drive the stimulus to DUT. The output
block consists of monitor to collect the DUT outputs and verify them.
All the above approaches require the test writer to create an explicit test for each feature
of the design.
Verification approach in which each feature is written in a separate test case file is
called directed verification.
Example:
Adder example:
module tb();
Reg [3:0] a;
Reg[3:0] b;
Wire [3:0] c;
Initial
Repeat(20) begin
B=$random;
$display(“a=%b,b=%b,c=%b”,a,b,c);
$display(“error”);
end
endmodule
The Stimulus is generated in Tests case. Directed testbenchs may also use a limited
amount of randomization, often by creating random data values rather than simply
filling in each data element with a predetermined value.
Each test case verifies specific feature of the design. This becomes tedious when the
design complexity increases. As circuit
complexity increases, it becomes more difficult to create patterns that fully exercise the
design.
Test writer cannot think of all possible potential bugs scenarios and there are chances
that Bugs will escape.
With these approaches, the bugs which are not still hidden in these corners of the code
until later in the development cycle, or aren't found at all until product is taped out.
Using constraint random verification, the stimulus required to verify test features
are generated automatically.
Test writer specifies set of specification, and the Test Bench automatically creates
solution space and picks up scenarios from the solution space.
Constraint random verification also reduces manual effort and code for individual
tests.
As the scenarios are generated automatically by the TestBench, the number of test
case files gets reduced.
In Directed verification, some of the tests share similar logic, if the engineer has to
change the logic which is common to certain group of tests, then he has to edit all the
test case files and it is time consuming. But in Constraint random verification, the
number of tests case files will be very less, so changes will be mostly in environment
and minimal.
TEST_BENCH TOP MODULE this the top most file,which connect the dut and
UP test bench. it consist of dut and test bench. it
consist of dut, test bench and interface
instance,the interface connect the dut and test
bench.
In the process of verification, we are going to verify modules by driving the input to
check the design behavior. we should check the behavior of the design by driving
correct and an error input, in both cases need to observe the design as it is behaving as
expected, if not then there will be a bug.
In verilog we have used data types reg , wire etc but here logic replaces reg.
Why?
reg kyeword was getting to much confused with word flipflop.
User was not able to understand whethere reg keyword will be directly mapped with
the ff and latch. Or any other things.
By using logic - User no need to bother about that.
Logic can be reg or net depending on the usage.
0 False condition 0
1 True condition 1
z High impedence 0
state(open connection)
bit – Unsigned
byte, shortint, int, longint –Signed
String:
Program main1;
Initial begin
$display(“|string s2=%s”,s2);
End
Endprogram
Output:
String 2 s2 = h
An enumerated type defines a set of named values. The simplest enumerated type
declaration contains a list of constant names and one or more variables.
enum{red,green,blue}colors
Default variable will get default values 0,1,2 respectively from red.
first() -- > returns the value of the first member of the enumeration.
last() -- > returns the value of the last member of the enumeration.
name()-- > returns the string representation of the given enumeration value.
Example of enum :
enum{red=0, green,blue=4,yellow,white=10,black}colors
Another example:
From the above example yellow will get the increment value of 5 , the value of white
is set with 5. This will cause the syntax error.
module enum_data;
//declaration
enum{red,green,yellow,white,black}colors;
Integer i;
Initial begin
Colors=colors.first;
begin
Colors=colors.next;
end
end
endmodule
Below exapmle shows an error in case of automatic increment value , is same as the
value assigned to another enum member.
module enum_datatypes;
Initial begin
Colors=colors.first;
For(i=0;i<6; i=i+1)
end
endmodule
module enum_data;
Initial begin
Colors colors;
Colors=yellow;
$display(“colors.first=%d”, colors.first);
$display(“colors.last=%d”, colors.last);
$display(“colors.next=%d”,colors.next);
$display(“colors.prev=%d”,colors.prev);
$display(“colors.num=%d”,colors.num);
$display(“colors.name=%d”, colors.name);
end
endmodule
Output:
Colors.first=0;
Colors.last=3
Colors.next=3;
Colors.prev=1;
Colors.num=4;
Colors.name=yellow;
Structures: The disadvantages of array is that all the elements stored in then are to be
of the same data types. If we need to use collection of different data types, it is not
possible using array. When we require using a collection of different data items of
different data types we can use a structure.
Declaration:
Struct{
int a;
byte b;
Bit[7:0]c;
Packed Structure:A packed structure is a mechanism for subdividing a vector into sub
fields that can be conveniently accessed as members.
A packed structure consists of bit fields, which are packed together in memory without
gaps.
Struct packed{
int a;
bit[7:0] b;
byte c;
Union:
Unions like structure contain members whose individual data types may differ from
one another.
The members that compose a union all share the same storage area.
A union allows us to treat the same space in memory as a number of different variables.
Example:
union{
int a;
bit[7:0] b;
byte c;
String: A typedef declaration lets you define your own identifiers that can be used in
place of type specifiers such as int, byte, real.
Changing a data type in one place is easier than changing all of its uses throughout
the code.
Allows defining new data types using structs, unions and Enumerations also.
Increases re usability.
Array:
An array is a collection of variables, all of the same type, and accessed using the same
name plus one or more indices.
Initialization of Array:
marks[0]=80;//initialization of array
marks[1]=60;
marks[2]=70;
marks[3]=85;
marks[4]=75;
int marks[5]={20,30,40,50,60};
data_type array_name[rows][columns]
Initialization of 2D Array:
TYPES OF ARRAY:
Packed array
unpacked array
Dynamic array
Associative array
Queues
Packed Array:
The term packed array is used to refer to the dimensions declared before the data
identifier name.
Bit[7:0] array1;
Bit[2:0][7:0]arary5;
Unpacked array:
The term unpacked array is used to refer to the dimensions declared after the data
identifier name.
Bit [7:0]array1[2:0];
Dynamic Array:
A dynamic array is one dimension of an unpacked array whose size can be set or
changed at run-time.
The space for a dynamic array doesn’t exist until the array is explicitly created at run-
time, space is allocated when new[number] is called.
//Declaration:
Bit[7:0]d_array1;
//memory allocation
D_array1=new[6];
D_array2=new[4];
//array initialization
D_array1={0,1,2,3};
D_array1=new[10](d_array1);
Bit[7:0]d_array[];
//memory allocation
D_array=new[4];
//array initialization
D_array={0,1,2,3};
D_array1=new[10]D_array
//delete array:
D_array1.delete.
module dynamic_array;
Bit[7:0] d_array1;
int d_array2;
Integer i;
Initial begin
d_array1=new[2];
d_array2=new[3];
//array initialization
d_array1={1,2};
d_array2={11,1,4};
Foreach (d_array[i]);
$display(“d_array2=%d”,I,d_array2[i]);
d_array1.delete;
D_array2.delete;
$display(“d_array1=%d”,d_array1.size());
$display(“d_array2=%d”,d_array2.size());
End
Endmodule
Output:
d_array2=x 0
d_array1=0
d_array2=0
Associative array:
Associative arrays allocate the storage only when it is used, unless like in the dynamic
array we need to allocate memory before using it.
When the size of the collection is unknown or the data space is sparse, an associative
array is a better option.
first(var) --> assigns the value of first index to the variable var.
last(var) --> assigns the value of last index to the variable var.
next(var) --> assigns the value of next index to the variable var.
prev(var) --> assigns the value of previous index to the variable var.
//Array declaration
int a_array1[*];
Bit[31:0]a_array2[string];
Queue:
Queue Declaration:
bit queue_1[$];
int queue_2[$];
byte queue_3[$:255];
string queue_4[$];
//queue initialization
queue_1={1,2,3,4};
Queue Methods:
size() --> returns the number of items in the queue.
insert() --> inserts the given item at the specified index position.
Example:
module queues_array;
Bit[31:0] queue_1[$];
Int var1;
Initial begin
queue_1={1,2,3,4,5,6};
queue_1.push_front(45);
queue_1.push_back(55);
Var1=queue_1.pop_front():
Var1=queue_1.pop_back();
End
Endmodule
Process:
Fork join:
Fork-Join will start all the processes inside it parallel and wait for the completion of all
the processes.
Statement1
Statement2
Fork
Process-1
Process-2
Process-3
Join
Statement-3
Statement-4
On start of simulation, statements get executed sequentially.Process inside the fork will
get executed parallel.statement-3 and ststement-4 will get executed after the completion
of process inside the fork.
module fork_join;
Initial begin
$display(“a”);
#5 $dispaly(“b”);
Fork
Begin
$display(“c”);
$display(“d”);
End
begin
$display(“e”);
$display(“f”);
end
Join
$display(“g”);
$dispaly(“h”);
End
Endmodule
Output:
a,b,c,d,e,f,g,h
fork join_any:
Fork-Join_any will be unblocked after the completion of any of the Processes.
Statement1
Statement2
Fork
Process-1
Process-2
Process-3
end
Join_any
Statement-3
Statement-4
Any one of the process under fork is getting executed then statement-3 or statement-4
will be executed.
Example:
module fork_join1;
initial begin
Fork
//process-1
Begin
$display(“process-1 started”);
#5
$dispaly(“process-1 finished”);
End
//process-2
Begin
$display(“process-2 started”);
#20
$display(“process-2 finished”);
End
Join_any
End
Endmodule
Output:
Process-1 started
Process-2 started
Process-1 finished
Outside fork_join
Process-2 finished
Fork join_none:
As in the case of Fork-Join and Fork-Join_any fork block is blocking, but in case of
Fork-Join_none fork block will be non-blocking.
Processes inside the fork-join_none block will be started at the same time, fork block
will not wait for the completion of the Process inside the fork-join_none.
module fork_join1;
initial begin
Fork
//process-1
Begin
$display(“process-1 started”);
#5
$dispaly(“process-1 finished”);
End
//process-2
Begin
$display(“process-2 started”);
#20
$display(“process-2 finished”);
End
Join_any
End
Endmodule
Output:
Outside fork_join
Process-1 started
Process-2 started
Process-1finished
Process-2 finished
wait fork:
wait fork; causes the process to block until the completion of all processes started
from fork blocks.
Module wait_fork;
Initial begin
Fork
Begin
$display(“a”);
#5
$display(“b”);
End
Begin
$display(“c”);
#20
$display(“d”);
End
Join_any
//Wait fork;
$finish;
End
Endmoduloe
Module wait_fork;
Initial begin
Fork
//process-1
Begin
$display(“a”);
#5
$display(“b”);
End
//process-2
Begin
$display(“c”);
#20
$display(“d”);
End
Join_any
Wait fork;
$finish;
End
Endmoduloe
Output :
a,c,b,d.
From the above result we can say that wait fork will wait for the completion of the
second thread in the fork-join_any.
disable fork:
disable fork; causes the process to kill/terminate all the active processes started from
fork blocks.
Tasks:
Tasks and Functions provide a means of splitting code into small parts.
A Task can contain a declaration of parameters, input arguments, output arguments, in-
out arguments, registers, events, and zero or more behavioral statements.
task example:
Module sv_task;
int x;
c=a+b;
Endtask
Initial begin
Sum(10,5,x);
End
Endmodule
Fuinction:
Function example:
Module sv_function;
int x;
Sum=a+b;
Endfunction
Initial begin
X=sum(10,5);
End
Endmodule
Output: x=15
Module sv_function;
int x;
return a+b;
endfunction
Initial begin
X=sum(10,5);
$display(value of x=%d”,x);
End
endmodule
The argument passing mechanism works by copying each argument into the subroutine
area.
If any changes to arguments within the subroutine, those changes will not be visible
outside the subroutine.
Module argument_passing;
int x,y,z;
x=x+y;
Return x+y;
Endfunction
Initial begin
X=20;
Y=30;
End
Endmodule
Output:
Value of x=20
Value of y=30
Value of z=80;
Module argument_resference;
x=x+y;
Return x+y;
Endfunction
Initial begin
x=20;
y=30;
end
endmodule
Value of x=50;
Value of y=30;
Value of z=80;
Chapter-3
1. Basic
A. Datatype
B. Properties
C. Method
D. Constructor
2. Inheritance
3. Polymorphism
5. Randomization
6. Constarint
SystemVerilog Class:
A class is a user-defined data type that includes data (class properties), functions and
tasks that operate on data.
functions and tasks are called as methods, both are members of the class.
Inheritance
Polymorphis
Class Declaration
example:
Class sv_class;
// class property;
// method1;
X=I;
Endtask
//method2;
Return x;
Endfunction
Endclass
An array of classes can be created in a similar way to how you can create an int type:
module tb;
Initial begin
Pkt[i]=new();
Pkt[i].diaplay();
End
End
Endmodule
A class variable such as pkt below is only a name by which that object is known. It can
hold the handle to an object of class packet, but until assigned with something it is
always null. At this point, the class object does not exist.
Class packet;
int count;
Endclass
module tb;
// create a “handle” for the class packet that can point to an object of the class type
packet.
Packet pkt;
Initial begin
If(pkt==null)
// yet and still pointing to null. Pkt is not aware that it should hold the number.
$display(“count=%d”,pkt.count);
End
Endmodule
Class properties and methods can be accessed only after creating the object.
Class_1=new();
Class packet;
Bit[31:0] addr;
function new();
addr=32’h 23;
Module tb();
Initial begin
Packet pkt=new();
$dipslay(“”addr=%d”, adddr);
end
end
Module can be accessed by using object names followed by property or method name.
A constructor is simply method to create a new object of a particular clas data type.
By calling new method it allocates the memory and returns the address to the class
handle.
//class declaration
Class packet;
//class properties
Bit [7:0] a;
Bit [7:0] b;
Endclass
Packet pkt;
Pkt=new();
Calling new() allocates memory, returns the address and initialize the variables to
default values.
every class has a built-in new method, calling the constructor of class without
the explicit definition of the new method will invoke the default built-in new method
specifying return type to the constructor shall give a compilation error (even
specifying void shall give a compilation error)
The constructor can be used for initializing the class properties. In case of any
initialization required, those can be placed in the constructor and It is also possible to
pass arguments to the constructor, which allows run-time customization of an object.
//class declaration
Class packet;
//classa properties
Bit[3:0] addr;
Bit [3:0]data;
//constructor
Function new(bit[3:0]a,b);
Addr=a;
Data=b;
Endfunction
Endclass
Packet pkt;
Pkt=new(10,20);
Class packet;
//class properties
Bit[3:0]addr;
Bit[3:0] data;
Bit write ;
//constructor
Function new();
Addr=4’d3;
Data=4’d7;
Write=1;
endfunction
$display(“addr=%d,data=%d”,addr,data);
endfunction
endclass
Module constructor_method;
Packet pkt;
Initial begin
Pkt=new();
Pkt.display();
End
Endmodule
Output :
Addr=3
Data=7
Write=1
packet pkt_1;
pkt_1 = new();
packet pkt_2;
pkt_2 = pkt_1;
Class packet;
//class properties
Bit[3:0]addr;
Bit[3:0] data;
Bit write ;
//constructor
Function new();
Addr=4’d4;
Data=4’d7;
Write=1;
Endfunction
$display(“addr=%d,data=%d”,addr,data);
endfunction
endclass
Module assignment;
Packet pkt1;
Packet pkt2;
Initial begin
Pkt1=new();
Pkt1.display();
Pkt2=pkt1;
Pkt2.display();
Pkt2=4’d9;
© Cranes Varsity V1-2020-21 45/ 123
System verilog www.cranesvarsity.com
Pkt1.display();
End
Endmodule
Output:
Addr=13
Data=15
Addr=13
Data=15
Shallow copy:
Content in pkt will be copied into pkt2 when pkt is used along with the new() constructor for
the new object.
Packet pkt1,pkt2;
Pkt1=new();
Pkt2=new pkt1;
This method is known as shallow copy.because all of the variable are copied across integers ,
string,instance handle etc but nested nested object are not copied entirely. Only their handles
will be assigned to the new object and hence both the packets will point to the same nested
object instance.
Class packet;
Bit [7:0] a;
Bit [7:0] b;
//constructor
Function new();
a=8’h12;
b=8’h14;
Endfunction
Function display();
$display(“a=%h”,a);
$display(“b=%h”,b);
Endfunction
Endclass
Module main_class;
packet p1;
Packet p2;
Initial begin
P1=new();
P1.display();
P2=new p1;
P2.display();
P1.b=8’h15;
P1.display();
P2.display();
End
Endmodule
Output
A=15------------>change in the value of object but no nested for object b only handler copied.
Deep Copy:
SystemVerilog deep copy copies all the class members and its nested class members.
In shallow copy, Objects will not be copied, only their handles will be copied. to perform
Class packet;
Bit [7:0] a;
Bit [7:0] b;
//constructor
Function new();
a=8’h12;
b=8’h13;
endfunction
Function display();
$display(“a=%h”,a);
$display(“b=%h”,b);
endfunction
endclass
module main_class;
packet p1;
Packet p2;
Initial begin
P1=new();
P1.display();
P2=new p1;
P2.display();
P1.b=8’h15;
P1.display();
P2.display();
End
endmodule
Output:
A=12
A=12
B=1
Oops concept
Inheritance and polymorphism
Addition and changes to common code (base class) can go into the derived class
SystemVerilog Inheritance
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. Inheritance is about inheriting base class
members to the extended class.
New classes can be created based on existing classes, this is referred to as class inheritance
A derived class by default inherits the properties and methods of its parent class.
An inherited class is called a subclass of its parent class
A derived class may add new properties and methods, or modify the inherited properties
and methods
Inheritance allows re-usability. i.e. derived class by default includes the properties and
methods, which is ready to use
If the class is derived from a derived class, then it is referred to as Multilevel inheritance
Inheritance Terminology
Parent Class
Child Class
Inheritance Example:
© Cranes Varsity V1-2020-21 51/ 123
System verilog www.cranesvarsity.com
//base class
Class packet;
Bit [3:0] a;
endclass
// sub class
//child_class is derived from a base class, and it inherits the properties of the parent class.
Bit [3:0] b;
endfunction
Module inheritance;
Initial begin
Pkt.a=10; //Parent class properties are accessed using child class handle, i.e child class will
have parent class properties and methods.
//Though the addr is not declared in child_class, it is accessible. because it is inherited from the
parent class.
Pkt.b=20;
end
endmodule
Output:
Value of pkt.a= 10
Value of pkt.b= 20
SystemVerilog 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 base_class;
Endfunction
Endclass
//extended class 1
Endfunction endclass
//extended class2
Endfunction endclass
Module class_polymorphism;
Initial begin
Sub_class_1 sc_1=new();
Sub_class_2 sc_2=new();
Base_class bc[2];
Bc[0]=sc1;
Bc[1]=sc2;
Bc[0].display();
Bc[1].dispay();
End
Endmodule
Output:
Base class or parent class properties and methods can be overridden in the child class or
extended class.
display() method is re-defined in the child class, which will override the parent class
method.
c is the handle to the child class, because of override calling c.display will call display
method of the child class, not the parent class.
Example:
Calss base_class;
$display(“addr=%d”,addr);
Endfunction
Endclass
Bit[3:0] data;
Function void display(); //display method is re defined in the child class which will
overridethe parent classmethod
$display(“data=%d”,data);
Endfunction
Endclass
Module method1;
Initial begin
Sub_class c=new();
B. addr=8;
c.data=12;
C.display();
End
Endmodule
Output:
© Cranes Varsity V1-2020-21 55/ 123
System verilog www.cranesvarsity.com
Data=00001100
When class members are overridden in the derived class, It is necessary to use
the super keyword to access members of a parent class
With super keyword, it is allowed to access the class members of parent class which is
only one level up
If the method of the parent class is overridden in the child class, then using the 'super' keyword
parent class method can be accessed from the child class.
In below example,
The parent class has the method 'display'.
Implementing the method display in the child class will override the parent class method.
By calling super.display() from child class, the display method of the parent class can be
accessed.
Example:
Calss base_class;
$display(“addr=%d”,addr);
Endfunction
Endclass
Bit[3:0] data;
Function void display(); //display method is re defined in the child class which will override
the parent class method
$display(“data=%d”,data);
Super.display();
Endfunction
Endclass
Module method1;
Initial begin
Sub_class c=new();
C. addr=8;
c.data=12;
C.display();
End
Endmodule
Output:
Data=00001100
Addr=00001000
If from the above example we remove super.display() from the display method of child class
then output is
Data=00001100
SystemVerilog Casting
Casting
SystemVerilog casting means the conversion of one data type to another datatype.
$display(“addr=%d”,addr);
Endfunction
Endclass
Bit[3:0] data;
Function void display(); //display method is re defined in the child class which will
overridethe parent classmethod
$display(“data=%d”,data);
Super.display();
Endfunction
Endclass
Module method1;
Initial begin
Base_class bc=new();
Sub_class c=new();
C.addr=8;
c.data=12;
C.display();
End
Endmodule
Addr=8
Data=12
Calss base_class;
$display(“addr=%d”,addr);
Endfunction
Endclass
Bit[3:0] data;
Function void display(); //display method is re defined in the child class which will
overridethe parent classmethod
$display(“data=%d”,data);
Super.display();
Endfunction
Endclass
Module method1;
Initial begin
Base_class bc=new();
Sub_class c=new();
C.addr=8;
c.data=12;
C.display();
End
Endmodule
In the above example, assigning parent class handle (which is pointing to child class handle) to
child class handle is valid but compilation error is observed.
During the compile time, as the handle of bc is of parent class type which leads to compile
error.
With the use of $cast(), type check during compile time can be skipped.
Example:
Calss base_class;
$display(“addr=%d”,addr);
Endfunction
Endclass
Bit[3:0] data;
Function void display(); //display method is re defined in the child class which will
overridethe parent classmethod
$display(“data=%d”,data);
Super.display();
Endfunction
Endclass
Bit[3:0] data;
Function void display(); //display method is re defined in the child class which will
overridethe parent classmethod
$display(“data=%d”,data);
Super.display();
endfunction
endclass
Module method1;
Initial begin
Base_class bc=new();
Sub_class c=new();
Sub_class c1;
C.addr=8;
c.data=12;
$cast(c1,bc); //with the use of $cast, type chek will occur during runtime
C.display();
End
Endmodule
Addr=8
Data=12
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).
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
protected
Class parent;
Endclass
Program main
Initial begin
Parent p=new();
P. I=12;
End
Endprogram
Local member 'i' of class 'base' is not accessible from scope 'main'
Class parent;
Endclass
$display(I);
endfunction
Program main
Initial begin
Parent p=new();
P.display=12;
End
Endprogram
Output 12
Class parent;
Endclass
$display(I);
Endfunction
//extended class
Function new();
i=10;
endfunction
Endclass
Local member 'i' of class 'base' is not accessible from scope 'ext'
A protected class property or method has all of the characteristics of a local member, except
that it can be inherited; it is visible to subclasses.
Class parent;
Endclass
$display(I);
Endfunction
//extended class
Function new();
I=10;
endfunction
Endclass
Program main
Initial begin
Child_class sc=new();
sc.display=12;
End
Endprogram
Output:12
Class parent;
Endclass
Program main
Initial begin
Parent p=new();
P.I=12;
End
Endprogram
Protected member 'i' of class 'base' is not accessible from scope 'main'
A set of classes can be created that can be viewed as being derived from a common class
For instance a common base class that sets out the structure of the packet is never instantiated
but executed to derive useful subclasses.
© Cranes Varsity V1-2020-21 64/ 123
System verilog www.cranesvarsity.com
Since the base class is not intended to be instantiated it can be made abstract by specifying as
virtual.
If the base_class handle is referring to the extended class, then the extended class method handle
will get assigned to the base class handle.
Base_class bc;
Extended_class ec;
assigning ec to bc,
Bc=ec;
On calling bc.display()
if display() method in base_class is virtual, then extended class display method will get
called
if display() method in base_class is non-virtual, then base class display method will get
called
Class parent;
Endfunction
Endclass
Funstion display();
Endfunction
Endclass
Function display();
Endfunction end
Module main;
Extpacket1 ec1;
Extpacket2 ec2;
Parent p;
Initial begin
Ec1=new();
Ec2=new();
P=new();
P=ea1;
Q. display();
end
Endmodule
Endfunction
Endclass
Funstion display();
Endfunction
Endclass
Module main;
Extpacket1 ec1;
Extpacket2 ec2;
Parent p;
Initial begin
Ec1=new();
P=new();
P=ea1;
P.display();
end
Endmodule
randomization in SystemVerilog:
Randomization is the process of making something random;
Verilog has a $random method for generating the random integer values.
© Cranes Varsity V1-2020-21 67/ 123
System verilog www.cranesvarsity.com
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.
random variables
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.
rand keyword
Variables declared with the rand keyword are standard random variables. Their values are
uniformly distributed over their range.
addr 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.
In order to randomize the object variables, the user needs to call randomize() method.
example:
Object.randomize();
So here is example
Class randclass;
Endclass
randomization example
In the example below,
Two variables addr1 and addr2 of same bit type are declared as rand and randc respectively,
observe the randomized values of addr1 and addr2.
//class
Class packet;
Endclass
Module rand_method;
Initial begin
Packet pkt;
Pkt=new();
Repeat(10) begin
Pkt.randomize();
End
End
Endmodule
Output:
A=1 b=4
A= 5 b=6
A=12 b=0
A=2 b=2
A=15 b=12
A=9 b=12
A=0 b=14
A=2 b=8
A=1 b=10
A=2 b=5
pre_randomize
post_randomize
pre randomize and post randomize methods
//class
Class packet;
Bit rd;
If(wr==1) addr.rand_mode(0);
Else addr.rand_mode(1);
Endfunction
Rd=wr;
© Cranes Varsity V1-2020-21 71/ 123
System verilog www.cranesvarsity.com
Endfunction
Endclass
Module rand_method;
Initial begin
Packet pkt;
Pkt=new();
Repeat (4)
Pkt.randomize();
End
Endmodule
Output:
Constrained randomization
Constraint block contains declarative statements which restrict the range of variable or defines
the relation between variables.
As the name says random variable will get random value on randomization.
By writing constraints to a random variable, the user can get specific value on
randomization. constraints to a random variable shall be written in constraint blocks.
Constraint blocks:
Constraint blocks are class members like tasks, functions, and variables
Constraint blocks will have a unique name within a class
Constraint blocks consist of conditions or expressions to limit or control the values for
a random variable
© Cranes Varsity V1-2020-21 72/ 123
System verilog www.cranesvarsity.com
Constarint <constarint_block_name>{<condition/expression>;
<condition/expression>;}
Class randclass ;
Endclass
randclass myrand=new; ; after the constraint expression not after the constarint
block
Int ok;
Initial begin
…..
end
Constraint are class member and are inherited just like others members.
class randclass;
Endclass
Constraint not3 {p1!=2’b11;} rcx1 adds constraint not3 to constraint not0from randclass
Endclass
Class rcx2 extends randclass; //rcx2 my 2nd subclass and redefinig the constraint not0
Endclass
Rcx1 myrand=new;
Initial begin
Ok=myrand.randomize();
…...
Types of constraint:
inside constarint is particularly used for when u want to build the list of values that property
can be randomized within it.
Class randclass;
Endclass
Int ok;
Initial begin
Ok=myrand.randomize();
…...
end
Now u can also invert the any constraint suppose any list of values cannot be taken inside the
constraint block.
So the example is :
Class not_inside;
Endclass
with dist operator, some values can be allocated more often to a random variable. this is
called a weighted distribution.
it's possible to control the occurrence or repetition of the same value on randomization.
Class packet;
Endclass
Module method;
Initial begin
Packet pktl;
Pkt=new()
Repeat(3)
Begin pkt.randomize();
$display(“ addr=%d”,pkt.addr);
End
End
endmodule
:/ - this assign weight to the item or to a range as whole divide of the weight among all the
values in a range.
If the expression on the LHS of implication operator (->) is true, then the only constraint on the
RHS will be considered.
i. e implication operator is used to mention condition between the two variables addr_range
and addr.
Class packet;
String addr_range;
Constraint adress_range{(addr_range==”small”)->(addr<9);}
Endclass
Module method;
Initial begin
Packet pkt;
© Cranes Varsity V1-2020-21 76/ 123
System verilog www.cranesvarsity.com
Pkt=new();
Pkt.addr_range=”small”;
Repeat(4) begin
Pkt.randomize();
$display(“addr_range=%d addr=%d”,pkt.addr_range,pkt.addr);
End
end
Endmodule
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.
Example:
Class packet;
String addr_range;
Addr<9
Else
else condition.
endclass
Module method;
Initial begin
Packet pkt;
Pkt=new();
Pkt.addr_range=”small”;
Repeat(4) begin
Pkt.randomize();
$display(“addr_range=%d addr=%d”,pkt.addr_range,pkt.addr);
End
End
Endmodule
• Constraint Modes
• The constraint_mode() method can be used to disable any particular constraint block.By
default constraint_mode value for all the constraint blocks will be 1.
• packet.addr_range.constraint_mode(0);
• Static Constraints
• A constraint block can be defined as static, by including static keyword in its definition.
static constraint addr_range { addr > 5; }
• Any mode change of static constraint will afect in all the objects of same class type.
class packet;
endclass
module static_constr;
initial begin
packet pkt1;
packet pkt2;
pkt1 = new();
pkt2 = new();
pkt1.randomize();
$display("\taddr = %0d",pkt1.addr);
pkt1.addr_range.constraint_mode(0);
pkt1.randomize();
$display("\taddr = %0d",pkt1.addr);
pkt2.randomize();
$display("\taddr = %0d",pkt2.addr);
end
endmodule
• during randomization, constraint solver will consider both inline constraints and
constraints written inside the class
• the inline constraint will not override the constraints written inside the class
• the inline constraint shouldn't conflict with the constraint written inside the class, else it
will lead to randomization failure
• for example, constraint inside the class written as var < 5, and inline constraint written
as var > 5
class packet;
endclass
module inline_constr;
initial begin
packet pkt;
© Cranes Varsity V1-2020-21 79/ 123
System verilog www.cranesvarsity.com
pkt = new();
repeat(2) begin
$display("\taddr = %0d",pkt.addr);
end
end
endmodule
• The addr is the random variable. constraint inside the class written as addr < 5, and
inline constraint written as addr > 5.
• Conclusion: Conflict between the class and inline constraints leads to randomization
failure.
class packet;
endclass
module inline_constr;
initial begin
packet pkt;
pkt = new();
repeat(2) begin
$display("\taddr = %0d",pkt.addr);
end
end
endmodule
• The addr is the random variable. constraint inside the class written as addr between 6:12,
and inline constraint is written as addr == 8.
class packet;
endclass
module inline_constr;
initial begin
packet pkt;
pkt = new();
repeat(2) begin
$display("\taddr = %0d",pkt.addr);
end
end
endmodule
Functions in Constraints
• In some cases constraint can't be expressed in a single line, in such cases function call
can be used to constrain a random variable. calling the function inside the constraint is
referred to as function in constraints.
• Constraint logic shall be written inside the function as function definition and function
call shall be placed inside the constraint block
• Functions shall be called before constraints are solved, and their return values shall be
treated as state variables.
class packet;
if(e_addr < 4)
s_addr = 0;
else
s_addr = e_addr - 4;
endfunction
endclass
module func_constr;
initial begin
packet pkt;
pkt = new();
repeat(3) begin
pkt.randomize();
end
end
endmodule
• Functions in Constraints
• In some cases constraint can't be expressed in a single line, in such cases function call
can be used to constrain a random variable. calling the function inside the constraint is
referred to as function in constraints.
• Constraint logic shall be written inside the function as function definition and function
call shall be placed inside the constraint block
• Functions shall be called before constraints are solved, and their return values shall be
treated as state variables.
class packet;
if(e_addr < 4)
s_addr = 0;
else
s_addr = e_addr - 4;
endfunction
module func_constr;
initial begin
packet pkt;
pkt = new();
repeat(3) begin
pkt.randomize();
end
end
endmodule
class packet;
if(e_addr < 4)
s_addr = 0;
else
s_addr = e_addr - 4;
endfunction
endclass
module func_constr;
initial begin
packet pkt;
pkt = new();
repeat(3) begin
pkt.randomize();
end
end
endmodule
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
class packet;
endclass
module soft_constr;
initial begin
packet pkt;
pkt = new();
repeat(2) begin
$display("\taddr = %0d",pkt.addr);
end
end
endmodule
class packet;
endclass
module soft_constr;
initial begin
packet pkt;
pkt = new();
repeat(2) begin
$display("\taddr = %0d",pkt.addr);
end
end
endmodule
© Cranes Varsity V1-2020-21 85/ 123
System verilog www.cranesvarsity.com
Bidirectional Constraints
• else b == 0; }
class packet;
constraint a_value { a == b + c; }
endclass
module bidirectional_constr;
initial begin
packet pkt;
pkt = new();
repeat(5) begin
pkt.randomize();
end
end
endmodule
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
class pakcet;
rand bit a;
endclass
• Writing below constraint will direct solver to solve 'a' first, so more frequently a will
take value of 1.
class packet;
rand bit a;
endclass
module inline_constr;
initial begin
packet pkt;
pkt = new();
repeat(10) begin
pkt.randomize();
end
end
endmodule
• Value of a = 0, b = 6
Value of a = 0, b = 3
Value of a = 1, b = 0
Value of a = 0, b = 15
Value of a = 0, b = 7
Value of a = 0, b = 2
Value of a = 0, b = 15
Value of a = 0, b = 4
Value of a = 0, b = 7
Value of a = 0, b = 11
• this example is without solve before constraint, so we can see the simulation result that
the occurrence of value a == 1 is less.
• this example is to solve before constraint, so we can see the simulation result that the
occurrence of value a == 1 is more than without solve before constraint.
• $urandom( )
$urandom( )
The function returns a new 32-bit random number each time it is called. The number shall
be unsigned.
• The seed is an optional argument that determines the sequence of random numbers
generated. The seed can be an integral expression. for a particular seed, the same value
will get generated.
module system_funcations;
initial begin
addr1 = $urandom();
addr2 = $urandom(89);
addr3 = {$urandom(),$urandom()};
data = $urandom * 6;
Chapter-4
System verilog based Coverage
The main goal of this course is to help you to achieve the objective of the functional coverage
and design.
Bins
Cross
Transition
Under system verilog we have not only the assertion based verification,at the same time
we have another sub language, that is cover key word.
So not only you have verified the properties but also make sure that the property has been
covered so for all low level temporal domain condition u need to use the cover which is
part of the system verilog.
The second part of the coverage is using covergroup and cover point features which is part of
the functional based coverage verification.
Cross 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
This is only as good as the code written for it. Say you have 10 features mentioned in the design
document, and you have some hoe overlooked /missed or were not aware of the 3 features, You
will write functional coverage code for only 7 of them. If all the 7 have been hit in the tests,
you might come to the conclusion that all the the features are covered. So you need to make
sure that all the the required information from the design specification is included in the
functional coverage block.
Functional Coverage
Functional coverage is a user-defined metric that measures how much of the design
specification has been exercised in verification.
The type definition is written once, and multiple instances of that type can be created in
different contexts.
Similar to a class, once defined, a covergroup instance can be created via the new()operator.
A covergroup can be defined in a module, program, interface, or class.
Module tb;
Bit[3:0]addr;
endmodule
Addr can take 16 values, while data can take 4 values. So , there is some thing to monitor these
two variables in a simulation and report what values of addr and data have been exercised.
The good part is that there are option in simulator to dump out such coverage details into a
single a file so that it can be reviewed after the simulation has finished.
Class packet;
Endfunction
Covergroup covgrp;
Coverpoint addr {
bins a={0};
Bins b={[1:3]};
Coverpoint data;
Endgroup
Endclass
So from the above code let me clear about coverpoint, bins etc.So coming to the point of
program - program started with class . under class properties and methods are declared.
Multiple covergroups can be created to sample the same variable with the different set of
bins.
Bins are said to be hit/covered when the variables recahes the corresponding values. So
that bins b is hit when the addr takes either 1,2,or3 values.
Now let discuss about coverpoint which is written under the covergroup.
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.
Program main;
Covergroup covgrp;
A:coverpoint addr;
Endgroup
Covgrp covgrp_inst=new():
Initial
Foreach (values[I])
Begin addr=values[I];
Covgrp_inst.sample();
End
Endmodule
In the above example, we are sampleing the cover point "addr". The cover point is named "a" .
In the Coverage report you will see this name. A cover group "covgrp" is defined and its
instance "covgrp_inst" is created. The value of "addr" is sampled when covgrp_inst.sample()
method is called. Total possible values for addr are 0,1,2,3,4,5,6,7. The variable "addr" is
assigned only values 3,5,6. The coverage engine should report that only 3 values are covered
and there are 8 possible values.
Coverage should be triggered to sample the coverage values. Sampling can be done using
End-point of a sequence
….…
….…
….…
Endgroup
The above example defines a covergroup named "covgrp". This covergroup will be
automatically sampled each time there is a posedge on "clk" signal.
Class coverage ;
Covergroup covgrp;
….
endgroup
Function new();
Endfunction
Endclass
Module tb_top();
Initial begin
Cov.covgrp.smaple();End
endmodule
Sampling can also be done by calling explicitly calling .sample() method in procedural code.
This is used when coverage sampling is required based on some calculations rather than events.
Coverage Bins:
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.
Lets do an example :
Module cov;
Logic clk;
Logic wr_rd;
C1:coverpoint addr;
C2:coverpoint ar_rd;
Covergroup:cg
Cg cover_inst=new():
….
Endmodule
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.
© Cranes Varsity V1-2020-21 95/ 123
System verilog www.cranesvarsity.com
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])
begin
y = values[i];
cg_inst.sample();
end
endprogram
In the above example, the auto_bin_max is declared as 4. So, the total possible values are
divided in 4 parts and each part correspoits to one bin.
The total possible values for variable "y" are 8. They are divided in to 4 groups.
Varible 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.
Coverage report:
--------------------
VARIABLE : cover_point_y
Expected : 4
Covered : 3
Percent: 75.00
Uncovered bins
------------------
auto[0:1]
Covered bins
© Cranes Varsity V1-2020-21 96/ 123
System verilog www.cranesvarsity.com
------------------
auto[2:3]
auto[4:5]
auto[6:7]
For Enum data type, the numbers of bins are equal to the number of elements of enum data
type. The bin identifiers are the enum member name.
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 members
A,B,C and D. Variable Y is assigned only 3 Enum members A,B and C.
Coverage report:
---------------------
VARIABLE : cover_point_y
Expected : 4
Covered : 3
Percent: 75.00
Uncovered bins
--------------------
auto_D
Covered bins
© Cranes Varsity V1-2020-21 97/ 123
System verilog www.cranesvarsity.com
--------------------
auto_C
auto_B
auto_A
Explicit bins:
BINS DECLARATION:
module cov;
Logic [3:0]addr;
Logic ar_rd;
Bins b2[3]={11,12};
Bins b3 ={[30:40],[50:60],77};
Bins b4[]={[25:36],[90:96],123};
Bins b5 ={200:$};
Endgrp:cg
Cg cover_inst=new();
endmodule
Bins b2[3]={11:20}; // crerates 3 bins b2[0],b2[1],b2[3]. and 10 possibles values are distributed
as follows (11,12,13),(14,15,16),(17,18,19,20) respectively
Bins b5 ={200:$}; // bins b5 incremented for addr =200 to max value ie255
default bin; // catches the values of the coverage point that do not lie within any of the defined
bins.
Array Of Bins:
To create a separate bin for each value (an array of bins) the square brackets, [], must follow
the bin name.
program main;
bit [0:2] y;
bit [0:2] values[$]= '{3,5,6};
covergroup cg;
cover_point_y : coverpoint y {
bins a[] = {[0:7]};
}
endgroup
cg cg_inst = new();
initial
foreach(values[i])
begin
y = values[i];
cg_inst.sample();
end
endprogram
In the above example, bin a is array of 8 bins and each bin associates to one number between 0
to 7.
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
© Cranes Varsity V1-2020-21 99/ 123
System verilog www.cranesvarsity.com
Covered bins
-------------------
a_3
a_5
a_6
To create a fixed number of bins for a set of values, a number can be specified inside the square
brackets.
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])
begin
y = values[i];
cg_inst.sample();
end
endprogram
In the above example, variable y is 4 bit width vector. Total possible values for this vector are
16.
But in the cover point bins, we have giving the interested range as 0 to 7. So the coverage report
is calculated over the range 0 to 7 only. In this example, we have shown the number bins to be
fixed to size 4.
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]
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
foreach(values[i])
begin
y = values[i];
© Cranes Varsity V1-2020-21 101/ 123
System verilog www.cranesvarsity.com
cg_inst.sample();
end
endprogram
In the above example, 2 bins are created for covering the transition of point "y" from 3 to 4 and
other for 5 to 6.
The variable y is given the values and only the transition 5 to 6 is occurring.
Coverage report:
--------------------
VARIABLE : cover_point_y
Expected : 2
Covered : 1
Percent: 50.00
Uncovered bins
------------------
tran_34
Covered bins
----------------
tran_56
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
© Cranes Varsity V1-2020-21 102/ 123
System verilog www.cranesvarsity.com
y = values[i];
cg_inst.sample();
end
endprogram
In the above example, bin trans creates 4 bin for covering 3=>5,4=>5,3=>6 and 4=>6.
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.
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
Coverage report:
--------------------
VARIABLE : cover_point_y
Expected : 3
© Cranes Varsity V1-2020-21 103/ 123
System verilog www.cranesvarsity.com
Covered : 2
Percent: 66.66
Uncovered bins
------------------
auto[0]
Excluded/Illegal bins
-------------------------
ig
auto[1]
auto[2]
auto[3]
auto[4]
auto[5]
Covered bins
----------------
auto[6]
auto[7]
Illegal Bins
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();
initial
foreach(values[i])
begin
y = values[i];
© Cranes Varsity V1-2020-21 104/ 123
System verilog www.cranesvarsity.com
cg_inst.sample();
end
endprogram
Result:
------------
ERROR
Illegal state bin ib of coverpoint cover_point_y in
covergroup cg got hit with value 0x7
Cross Coverage
Cross allows keeping track of information which is received simultaneous on more than one
cover point. Cross coverage is specified using the cross construct.
program main;
bit [0:1] y;
bit [0:1] y_values[$]= '{1,3};
bit [0:1] z;
bit [0:1] z_values[$]= '{1,2};
covergroup cg;
cover_point_y : coverpoint y ;
cover_point_z : coverpoint z ;
cross_yz : cross cover_point_y,cover_point_z ;
endgroup
cg cg_inst = new();
initial
foreach(y_values[i])
begin
y = y_values[i];
z = z_values[i];
cg_inst.sample();
end
endprogram
In the above program, y has can have 4 values 0,1,2 and 3 and similarly z can have 4 values
0,1,2 and 3. The cross product of the y and z will be 16 values
(00),(01),(02),(03),(10),(11)........(y,z)......(3,2)(3,3) .
Only combinations (11) and (32) are generated.
© Cranes Varsity V1-2020-21 105/ 123
System verilog www.cranesvarsity.com
Covered bins
-----------------
cover_point_y cover_point_z
auto[3] auto[2]
auto[1] auto[1]
Covergroup cover port(ref bit[2:0]port,input int mid); // passing cover group arguments
Coverpoint port{
Bins lo={[0:mid-1]};
Bins hi={[mid:$]};
Endgroup
Coverport cpa,cpb;
Initial begin
End
SYSTEM TASKS
SystemVerilog provides the following system tasks and functions to help manage coverage data
collection.
$set_coverage_db_name ( name ) :
Sets the filename of the coverage database into which coverage information is saved at the end
of a simulation run.
$load_coverage_db ( name ) :
Load from the given filename the cumulative coverage information for all coverage group
© Cranes Varsity V1-2020-21 106/ 123
System verilog www.cranesvarsity.com
types.
$get_coverage ( ) :
Returns as a real number in the range 0 to 100 the overall coverage of all coverage group types.
This number is computed as described above.
State
Transition
Cross correlation
Coverage attributes
class coverage;
base_packet pkt;
option.per_instance=1;
};
coverpoint pkt.rst;
//coverpoint pkt.dataframe;
coverpoint pkt.tx_strt;
coverpoint pkt.rx_strt;
coverpoint pkt.dout;
coverpoint pkt.baudclk;
coverpoint pkt.count;
//coverpoint pkt.y;
endgroup
function new();
endfunction
this.pkt=pkt;
endtask
endclass
From the above example - coverage is written within class and endclass
Cross Coverage
• Cross Coverage is specified between the cover points or variables. Cross coverage is
specified using the cross construct.
bit [3:0] a, b;
c1: coverpoint a;
c2: coverpoint b;
endgroup : cg
bit [3:0] a, b;
aXb : cross a, b;
endgroup
Cross coverage
class trasaction;
endclass
Transaction tr;
covergroup covport;
a: coverpoint tr.a;
b: coverpoint tr.b;
cross a,b;
endgroup
Chapter-5
What is assertion?
Why it is used ?
Assertion based verification means how the design will be verified by using assertion and then
we will use typically system verilog language to write assertion code.
Introduction to Assertion:
Assertion is the simply check. In order to check the design we need to have some important
behaviour or specification that design should obey. These are specified requirement.
What is assertion?
It is an embedded check in the code.This code will be either added in the design file or in
the test bench file or written separately or it could be associated with design file. In general
an assertion is added to vast to specific set of condition.
So we can say
An assertion is a check embedded in design or bound to a design unit during the simulation.
An assertion’s sole purpose is that design things to be implemented and what designer is
implemented. Which means it should ensure the consistency between the designer’s
intention and what is implemented.
It will watch
forbidden behaviour or
expected behaviour.
For the first case when we use for the reporting forbidden behaviour it will flag error for the
specific condition or sequence has violated in simulation.So it is common usage of assertion.
But same set of assertion can also be used to check whether expected behaviour is accurate in
the design or in other words to cover that specific scenario or sequence has occur in the design.
When req1 and req2 are on then next cycle grant1 will be accepted but grant2 will not be
accepted. So it is not boolean formula, it is a spam over time. Request1 and request2 will on in
one cycle but next cycle grant1 will be on but grant2 will not be on. So for each time spam it is
boolean but overall through time spam it is sequence.
So these specification are captured by assertion. These scenarios are interesting and has to be
verified. When you simulate the test bench then we just put the behaviour into our hand and
check that behaviour are matching or not when design simulates.
Apart from that assertion can also be used for collection of coverage.
Next question is who should write the assertion RTL designer or verification engineer?
Answer is design engineer or verification engineer both are comfortable to write the assertion.
Immediate Assertions
Concurrent Assertions
Immediate Assertions:
Syntax:
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
Now let me explain about action block
action_block;
The statement associated with else is called a fail statement and is executed if the
expression evaluates to false
Since the assertion is a statement that something must be true, the failure of an assertion
shall have a severity associated with it.
Other severity levels can be specified by including one of the following severity system
tasks in the fail statement:
If an assertion fails and no else clause is specified, the tool shall, by default call $error.
Let me take one simple one example of immediate assertion:
assert(a&&b)
Module assertion_ex;
Bit clk,a,b;
Always #5 clk=~clk;
Initial begin
a=1;
b=1;
#15 b=0;
© Cranes Varsity V1-2020-21 112/ 123
System verilog www.cranesvarsity.com
b=1;
a=0;
#20 a=1;
#10;
$finish;
End
So from the above example and after simulation we can observe that green line is indicating
pass and and red line is indicating no passing any data.
Concurrent assertion:
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
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);
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".
Sequence seq_1;
@(posedge clk) a==1;
Endsequence
In the above 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.
Sequence seq_1;
@(posedge clk) a||b;
Endsequence
© Cranes Varsity V1-2020-21 114/ 123
System verilog www.cranesvarsity.com
From above example sequence, seq_1 checks that on every positive edge of the clock, either
signal "a" or signal "b" is high. If both the signals are low, the assertion will fail.
Sequence Expressions
By defining arguments in a sequence definition, the same sequence can be re-used for similar
behavior.
In SVA, clock cycle delays are represented by a "##" sign. For example, ##2 means 2 clock
cycles.
Sequence seq_1;
a ##2b;
Endsequence
Property p;
@(posedge clk)seq
Endproperty
A_1:assert property (p);
Forbidding a property
Calling a property with a clock definition from within the assert statement is not allowed.
A_3:assert property(@(posedge clk)p);
The above example is not allowed.
© Cranes Varsity V1-2020-21 115/ 123
System verilog www.cranesvarsity.com
Sequence seq;
@(posedge clk) a##2 b;
Endsequence
Property p;
Not seq;
Endproperty
A_1:assert property(p);
From the above example I can conclude that sequence checks that if signal "a" is high on a
given positive edge of the clock, then after 2 clock cycles, signal "b" shall not be high. The
keyword "not" is used to specify that the property should never be true.
Implication Operator
Sequence seq;
@(posedge clk) a##2 b;
Endsequence
If we want the sequence to be checked only after “a” is high, this can be achieved by using
the implication operator.
The implication is equivalent to an if-then structure. The left-hand side of the implication
is called the "antecedent" and the right-hand side is called the "consequent." The antecedent is
the gating condition. If the antecedent succeeds, then the consequent is evaluated.
The implication construct can be used only with property definitions. It cannot be used in
sequences.
OVERLAPPED IMPLICATION
Non-overlapped implication
Overlapped implication
|->.
Property p;
Endproperty
A:assert property(p);
Non-overlapped implication
If there is a match on the antecedent, then the consequent expression is evaluated in the next
clock cycle.
Below property checks that, if signal "a" is high on a given positive clock edge, then signal "b"
should be high on the next clock edge.
Property p;
Endproperty
A:assert property(p);
Property p;
Endproperty
A:assert property(p);
Below property checks that, if signal "a" is high on a given positive clock edge, then signal "b"
should be high in the same clock cycle or within 4 clock cycles.
Property p;
Endproperty
a:assert property(p);
Property p;
Endproperty
a:assert property(p);
From above example i can say that 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.
Repetition Operators
Propertyp;
@(posedge clk) a|-> ##1 b ##1b;
Endproperty
a:assert property(p);
The above property checks that, if the signal “a” is high on given posedge of the clock, the
signal “b” should be high for 3 consecutive clock cycles.
The Consecutive repetition operator is used to specify that a signal or a sequence will match
continuously for the number of clocks specified.
Syntax
Propertyp;
@(posedge clk) a|-> ##1 b[*2];
Endproperty
© Cranes Varsity V1-2020-21 118/ 123
System verilog www.cranesvarsity.com
a:assert property(p);
SVA Methods
$rose
returns true if the least significant bit of the expression changed to 1. Otherwise, it returns false.
Sequence seq_rose;
Endsequence
Sequence seq_rose checks that the signal "a" transitions to a value of 1 on every positive edge
of the clock. If the transition does not occur, the assertion will fail.
$fell
returns true if the least significant bit of the expression changed to 0. Otherwise, it returns false.
Sequence seq_rose;
Endsequence
Sequence seq_fell checks that the signal "a" transitions to a value of 0 on every positive edge
of the clock. If the transition does not occur, the assertion will fail.
$stable
returns true if the least significant bit of the expression changed to 0. Otherwise, it returns false.
Sequence seq_rose;
Endsequence
Sequence seq_stable checks that the signal "a" is stable on every positive edge of the clock. If
there is any transition occurs, the assertion will fail.
$past
provides the value of the signal from the previous clock cycle.
Below Property checks that, in the given positive clock edge, if the “b” is high, then 2 cycles
before that, a was high.
Property p;
Endproperty
A:assert property(p);
module tb;
bit a;
bit clk;
int i;
sequence s_a;
endsequence
assert property(s_a);
initial begin
for(i=0;i<10;i++)
a=$random;
@(posedge clk);
$display("a=%d",$time,a);
end
// $finish;
Endmodule
$onehot(expression)
o checks that only one bit of the expression can be high on any given clock edge.
$onehot0(expression)
o checks only one bit of the expression can be high or none of the bits can be high
on any given clock edge.
$isunknown(expression)
o checks if any bit of the expression is X or Z.
$countones(expression)
o counts the number of bits that are high in a vector.
Assert statement a_1 checks that the bit vector "state" is one-hot.
Assert statement a_2 checks that the bit vector "state" is zero one-hot.
Assert statement a_3 checks if any bit of the vector "bus" is X or Z.
Assert statement a_4 checks that the number of ones in the vector "bus" is greater than one.
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.
Properety p;
@(posedge clk)
endproperty
a:assert property(p);
From the above example we can conclude that 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.
module tb1;
© Cranes Varsity V1-2020-21 121/ 123
System verilog www.cranesvarsity.com
bit a,b;
bit clk;
sequence s_a;
endsequence
assert property(s_a);
// $display("assertion pass!",$time);
initial begin
@(posedge clk);
a<=$random;
b<=$random;
// $finish;
end
end
endmodule