system verilog
system verilog
1
Semi Design
2
Semi Design
3
Semi Design
Design
(DUT)
DUT
Apply input Get the
(Design
stimulus output
Under Test)
4
Semi Design
3. DUT output will be compared with reference model output.
equal
Reference Compare
inputs = = outputs
DUT
(Design
Under Test)
4. Compare the DUT output with expected result, If there are equal the
design is bug free.
5
Semi Design
Not equal
Referenc Compare
e inputs != outputs
DUT
(Design
Under Test)
6. If there is a failure, need to fix the issue and re-verify the Design
6
Semi Design
Semi Design
8
Semi Design
Example : Linear Testbench
12
Semi Design
interface
generator driver DUT
transaction
Scoreboard monitor
transaction
14
Semi Design
Semi Design
Shortint - 16bits
int - 32bits
Signed Data types longint - 64bits
byte - 8bits
integer - 32bits
bit - User defined size
logic - Identical to reg
Unsigned Data types Reg - User defined size
time - 64bit
17
Semi Design
String Methods:
str.len() It returns the length of the string, i.e., the number of characters
in the string.
str.putc(i, c) It replaces the ith character in str with the given integral value.
str.getc(i) It returns the ASCII code of the ith character in str.
18
str.toupper() returns a string with characters in str converted to uppercase.
Semi Design
str.tolower() It returns a string with characters in str converted to lowercase.
str.compare(s) It compares str and s, and return value. This comparison is case
sensitive.
str.icompare(s) It compares str and s, and return value .This comparison is case
insensitive.
str.substr(i, j) It returns a new string that is a substring formed by index i
through j of str.
str.atoi() It returns the integer corresponding to the ASCII decimal
representation in str.
str.atoreal() It returns the real number corresponding to the ASCII decimal
representation in str.
str.itoa(i) It stores the ASCII decimal representation of i into str (inverse
of atoi).
str.hextoa(i) It stores the ASCII hexadecimal representation of i into str 19
(inverse of atohex).
Semi Design
// Example using String methods
module str_method;
string X;
string Y;
// Simulation results:
initial begin
4
X = "TEST ";
h
Y = "Bench";
test
$display(" %d ",X.len() );
BENCH
$display(" %s ",Y.getc(4) );
-18
$display(" %s ",X.tolower);
-32
$display(" %s ",Y.toupper);
ST
$display(" %d ",Y.compare(X) );
$display(" %d ",X.compare("test") );
$display(" %s ",X.substr(2,3) );
end
endmodule
20
Semi Design
String Operators
SystemVerilog provides a set of operators that can be used to manipulate
combinations of string variables and string literals.
1. Equality Operator:
Checks whether the two strings are equal. Result is 1 if they are equal
and 0 if they are not.
21
Semi Design
end
endprogram
25
Semi Design
5. Replication:
end
endprogram
26
Semi Design
1. Class.
2. Enumarations.
3. Struct.
4. Union.
5. Typedef.
27
Semi Design
enum {a=0, b=5, c, d=6} alphabet; // Syntax error: c and d are both assigned 6
Enumarated Methods:
29
Semi Design
// Example code for enum methods
module enum_method;
typedef enum {red,blue,green} colour;
colour c;
initial
begin // Simulation results:
c = c.first(); red
$display(" %s ",c.name); Blue
c = c.next(); green
$display(" %s ",c.name); blue
c = c.last();
$display(" %s ",c.name);
c = c.prev();
$display(" %s ",c.name);
end
endmodule 30
Semi Design
// Simulation results: 31
a value is 123
Semi Design
my_data.a = 321;
$display(" a value is %d ",my_data.a); 32
Semi Design
Byte b XXXXXXXXXX
Integer a
0………7……….15………..23…………..31
34
Semi Design
Now we saw logic and wire are closer. Wire (net) is used when driven by
multiple drivers, where as logic is used when it is driven by only one driver.
logic just holds the last value assigned to it, while a wire resolves its value based
on all the drivers.
logic a; 35
Semi Design
Arrays
Arrays are classified into :
1. Fixed-sized arrays (static arrays)
whose size cannot change once their declaration is done.
2. Dynamic arrays
which can be resized.
3. Associative arrays
Associative arrays give you another way to store information. When
the size of the collection is unknown or the data space is sparse, an
associative array is a better option. 38
Semi Design
Static Arrays
Fixed arrays are classified as:
1. Packed arrays
2. Unpacked arrays
1. Packed arrays:
"Packed array" to refer to the dimensions declared before the object name
2. UnPacked arrays:
"unpacked array" refers to the dimensions declared after the object name. 39
Semi Design
wire arr [31:0]; // 1-dimensional Unpacked array
wire arr [32][4:0]; // 2-dimensional Unpacked array
integer arr [7:0][0:31][15:0]; // 3-dimensional unpacked array of integers
reg [31:0] arr1 [0:255]; // unpacked array of 256 registers each
reg [31:0] arr2 [256]; // register is packed 32 bit wide
bit arr[1:2][1:4][1:3] bit [1:3] arr [1:2][1:4] bit [1:3][1:4] arr [1:2]
Dynamic Arrays
Verilog does not allow changing the dimensions of the array once it is declared.
Most of the time in verification, we need arrays whose size varies based on the
some behavior. For example Ethernet packet varies length from one packet to
other packet. In verilog, for creating Ethernet packet, array with Maximum packet
size is declared and only the number of elements which are require for small
packets are used and unused elements are waste of memory.
To overcome this deficiency, System Verilog provides Dynamic Array. A
dynamic array is unpacked array whose size can be set or changed at runtime
unlike verilog which needs size at compile time.
41
Semi Design
Declaration of Dynamic Array:
integer d_arr [ ];
integer multi_d_arr[ ][ ];
New[]:The built-in function new allocates the storage and initializes the
newly allocated array elements either to their default initial value.
0 1 2 3 4
integer d_arr = new [5];
0 1 2 3 4 5 6 7 8 9
0 1 2 3 4 5 6 7 8 9
4 3 2 1 0
module dynamic_array();
integer arr[]; d_arr[ ]
initial
begin 8
arr = new[4]; // Simulation results:
$display(d_arr.size); 5 4
arr[1] = 8; 8
arr[3] = 5; 0
arr = new[8] (arr);
$display(d_arr.size);
d_arr.delete;
$display(d_arr.size);
end
endmodule 44
Semi Design
Associative Arrays
Dynamic arrays are useful for dealing with contiguous collections of
variables whose number changes dynamically. Associative arrays give you
another way to store information. When the size of the collection is
unknown or the data space is sparse, an associative array is a better option.
In Associative arrays Elements Not Allocated until Used. Index Can Be of
Any Packed Type, String or Class. Associative elements are stored in an
order that ensures fastest access.
In an associative array a key is associated with a value.
46
Semi Design
module associative_array;
int a_array[*]; // array declaration
int i;
initial begin
repeat(3) begin
a_array[i] = i*2; //allocating array and assigning value to it
i=i+4;
end
//num() –Associative array method
$display("\tNumber of entries in a_array is %0d",a_array.num());
foreach(a_array[i])
$display("\ta_array[%0d] \t = %0d",i,a_array[i]);
end
endmodule
48
Semi Design
// Simulation results:
Number of entries in a_array is 3
a_array[0] = 0
a_array[4] = 8
a_array[8] = 16
49
Semi Design
Semi Design
Queues
A queue is a variable-size, ordered collection of homogeneous elements.
Queues can be used to model a last in, first out buffer or first in, first out buffer.
Queues support insertion and deletion of elements from random locations using an
index.
Queue Methods:
size() method returns the number of items in the queue. If the queue is
empty, it returns 0.
insert() method inserts the given item at the specified index position.
delete() method deletes the item at the specified index.
pop_front() method removes and returns the first element of the queue.
pop_back() method removes and returns the last element of the queue.
push_fornt() method inserts the given element at the front of the queue.
51
push_back() method inserts the given element at the end of the queue.
Semi Design
module queues;
byte qu [$] ;
initial begin
qu.push_front(2);
qu.push_front(12); // Simulation results:
qu.push_front(22); 5
qu.push_back(11); 22
qu.push_back(99); 99
$display(" %d ",qu.size() ); 3
$display(" %d ",qu.pop_front() ); 0
$display(" %d ",qu.pop_back() );
$display(" %d ",qu.size() );
qu.delete;
$display(" %d ",qu.size() );
end
endmodule 52
Semi Design
Semi Design
Casting
Verilog is loosely typed . Assignments can be done from one data type to other
data types based on predefined rules.The compiler only checks that the destination
variable and source expression are scalars. Otherwise, no type checking is done at
compile time. Systemverilog has complex data types than Verilog. It's necessary
for SystemVerilog to be much stricter about type conversions than Verilog, so
Systemverilog provided the cast(`) operator.
1. Static casting
2. Dynamic casting.
54
Semi Design
Static Casting
A data type can be changed by using a cast ( ` ) operation. In a static cast, the
expression to be cast shall be enclosed in parentheses that are prefixed with the
casting type and an apostrophe. If the expression is assignment compatible with the
casting type, then the cast shall return the value that a variable of the casting type
would hold after being assigned the expression.
55
Semi Design
Dynamic Casting
SystemVerilog provides the $cast system task to assign values to variables that
might not ordinarily be valid because of differing data type. $cast can be called as
either a task or a function.
56
Semi Design
initial begin
$cast (myCent, 10 + 5 + 10);
$display ("Money = %s", myCent.name());
end
endmodule
// Simulation results:
Money = QUARTER
57
Semi Design
Semi Design
program Pro_TB();
initial
forever @(posedge DUT.clk)
$display("Program_based_TB : A = %b\n", DUT.A); 61
endprogram
Semi Design
Semi Design
Fork Join
A Verilog fork...join block always causes the process executing the fork
statement to block until the termination of all forked processes. With the addition
of the join_any and join_none keywords, SystemVerilog provides three choices
for specifying when the parent (forking) process resumes execution.
63
Semi Design
fork fork fork
64
Join [all] Join any Join none
Semi Design
fork join_all : The parent process blocks until all the processes spawned by this fork
complete.
program main();
initial begin
#(10);
$display(" BEFORE fork time = %d ",$time );
program main();
initial begin
#(10);
$display(" BEFORE fork time = %d ",$time );
fork // Simulation results:
begin # (20); $display("time = %d # 20 ",$time ); BEFORE fork time = 10
end time = 15 # 5
begin #(10); $display("time = %d # 10 ",$time ); time = 15
end Outside the main fork
begin #(5); $display("time = %d # 5 ",$time ); Killed the child processes
end
join_any
$display(" time = %d Outside the main fork ",$time );
disable fork;
$display(" Killed the child processes"); 69
end
endprogram
Semi Design
Semi Design
Semaphore
Conceptually, a semaphore is a bucket. When a semaphore is allocated, a bucket
that contains a fixed number of keys is created. Processes using semaphores
must first procure a key from the bucket before they can continue to execute. If
a specific process requires a key, only a fixed number of occurrences of that
process can be in progress simultaneously. All others must wait until a sufficient
number of keys is returned to the bucket. Semaphores are typically used for
mutual exclusion, access control to shared resources, and basic synchronization.
Semaphore is a built-in class that provides the following methods:
new() Create a semaphore with a specified number of keys
put() Obtain one or more keys from the bucket
get() Return one or more keys into the bucket
71
try_get() Try to obtain one or more keys without blocking
Semi Design
program main ;
semaphore sema = new(1);
initial begin
repeat(2)
begin sema.get(1);
fork $display("2: Got the Key");
////////// PROCESS 1 //////////////// #(10); //Do some work
begin sema.put(1);
$display("1: Waiting for key"); $display("2: Returning back key ");
sema.get(1); #(10);
$display("1: Got the Key"); end
#(10); // Do some work join
sema.put(1); end #1000;
$display("1: Returning back key "); end
#(10); endprogram
end
////////// PROCESS 2 ////////////////
begin 72
$display("2: Waiting for Key");
Semi Design
// Simulation results:
1: Waiting for key
1: Got the Key
2: Waiting for Key
1: Returning back key
2: Got the Key
2: Returning back key
1: Waiting for key
1: Got the Key
2: Waiting for Key
1: Returning back key
2: Got the Key
2: Returning back key
73
Semi Design
Semi Design
Mailbox
A mailbox is a communication mechanism that allows messages to be exchanged
between processes. The process which wants to talk to another process posts the
message to a mailbox, which stores the messages temporarily in a system defined
memory object, to pass it to the desired process.
75
Semi Design
1. Generic Mailbox:
The default mailbox is type-less. that is, a single mailbox can send and
receive data of any type.
2. Parameterized mailbox:
Parameterized mailbox is used to transfer a data of particular type.
76
Semi Design
Mailbox methods():
Blocking means it will wait until packet available where as non blocking means it
doesn’t wait. Suppose that you have a mailbox in that you don’t have any
message. So blocking method will wait until a message will come in mailbox. On 77
other hand non blocking will not wait for the same.
Semi Design
program main ; task get_packets();
mailbox my_m; integer i, packet;
initial begin begin
my_m= new(); for (i=0; i<10; i++)
if (my_m) begin
begin my_m.get(packet);
fork $display("Got packet %d @time
put_packets(); %d", packet, $time);
get_packets(); task put_packets(); end
#10000; integer i; end
join_any begin endtask
end for (i=0; i<10; i++) endprogram
#(1000); begin #(10);
$display("END of Program"); my_m.put(i);
end $display("Done putting packet %d
@time %d",i, $time);
end
end 78
endtask
Semi Design
// Simulation results
Done putting packet 0 @time 10
Got packet 0 @time 10
Done putting packet 1 @time 20
Got packet 1 @time 20
Done putting packet 2 @time 30
Got packet 2 @time 30 Done putting packet 7 @time 80
Done putting packet 3 @time 40 Got packet 7 @time 80
Got packet 3 @time 40 Done putting packet 8 @time 90
Done putting packet 4 @time 50 Got packet 8 @time 90
Got packet 4 @time 50 Done putting packet 9 @time 100
Done putting packet 5 @time 60 Got packet 9 @time 100
Got packet 5 @time 60 END of Program
Done putting packet 6 @time 70
Got packet 6 @time 70
79
// Example for mailbox Semi Design
class generator;
rand transaction t1;
mailbox g2d; //declaring mailbox
task main();
repeat(repeat_count) begin
t1 = new();
if( !t1.randomize() )
$fatal("Gen:: trans randomization failed");
g2d.put(t1);
end
-> ended; //triggering indicatesthe end of generation
endtask 80
endclass
Semi Design
class driver; task main;
//used to count the number of transactions forever begin
int no_transactions; transaction t1;
g2d.get(t1);
//creating virtual interface handle @(posedge v_i.clk);
virtual intf v_i; v_i.valid <= 1;
v_i.a <= t1.a;
//creating mailbox handle v_i.b <= t1.b;
mailbox g2d; @(posedge v_i.clk);
v_i.valid <= 0;
//constructor t1.c <= v_i.c;
function new(virtual intf v_i,mailbox @(posedge v_i.clk);
g2d); t1.display("[ Driver ]");
//getting the interface no_transactions++;
this.v_i = v_i; end
//getting the mailbox handles endtask
from environment endmodule
this.g2d = g2d; 81
endfunction
Semi Design
Semi Design
Events
An identifier declared as an event data type is called a named event. Named event is
a data type which has no storage. In verilog, a named event can be triggered
explicitly using "->" . Verilog Named Event triggering occurrence can be recognized
by using the event control "@" .
Triggered:
The "triggered" event property evaluates to true if the given event has been
triggered in the current time-step and false otherwise. If event_identifier is
null, then the triggered event property evaluates to false. Using this
mechanism, an event trigger shall unblock the waiting process whether the
wait executes before or at the same simulation time as the trigger operation.
83
Triggered: Semi Design
module tri;
event e;
initial // Simulation results
repeat(4) e is FALSE at 10
begin e is triggered at 20
#20; e is TRUE at 20
->e ; e is FALSE at 30
$display(" e is triggered at %t ",$time); e is triggered at 40
end e is TRUE at 40
initial e is FALSE at 50
#100 $finish; e is triggered at 60
always begin #10; e is TRUE at 60
if(e.triggered) e is FALSE at 70
$display(" e is TRUE at %t",$time); e is triggered at 80
else e is TRUE at 80
$display(" e is FALSE at %t",$time); e is FALSE at 90
end 84
endmodule
Semi Design
Wait():
module wait_ex;
event a;
initial
repeat(4) // Simulation results
#20 -> a; 20 ONE :: EVENT A is triggered
20 TWO :: EVENT A is triggered
always begin 40 ONE :: EVENT A is triggered
@a; 40 TWO :: EVENT A is triggered
$display($time, " ONE :: EVENT A is triggered " ); 60 ONE :: EVENT A is triggered
end 60 TWO :: EVENT A is triggered
80 ONE :: EVENT A is triggered
always begin 80 TWO :: EVENT A is triggered
wait(a.triggered);
$display($time, " TWO :: EVENT A is triggered ");
#1;
end
85
endmodule
Semi Design
Merging events:
module merg_ex;
event a,b;
initial
begin
#20 -> a;
#20 -> b; // Simulation results
#20 -> a; 20 EVENT A is triggered
end 40 EVENT B is also triggered
60 EVENT A is triggered
always@(a)
$display($time, " EVENT A is triggered ");
always@(b)
$display($time, " EVENT B is also triggered ");
86
endmodule
Semi Design
Wait_order:
module main;
event e1,e2,e3;
initial
begin
#10; -> e1; -> e2; -> e3;
#10; -> e3; -> e1; -> e2;
#10; -> e3; -> e2; -> e3;
// Simulation results
end
10 Events are in order
10 Events are out of order
always
10 Events are out of order
begin
wait_order(e1,e2,e3)
$display($time, " Events are in order ");
else
$display($time, " Events are out of order ");
end
87
endmodule
Semi Design
Semi Design
Interface
The communication between blocks of a digital system is a critical area. In Verilog,
modules are connected using module ports. For large modules, this is not productive as
it involves
• Manually connecting hundreds of ports may lead to errors.
• Detailed knowledge of all the port is required.
• Difficult to change if the design changes.
• More time consuming.
• Most port declaration work is duplicated in many modules.
In Verilog, the communication between blocks is specified using module ports.
SystemVerilog adds the interface construct which encapsulates the
communication between blocks. An interface is a bundle of signals or nets
through which a testbench communicates with a design. A virtual interface is a
variable that represents an interface instance. this section describes the interface, 89
interface over traditional method and virtual interface.
Semi Design
Interface construct
The interface construct is used to connect the design and testbench.
Above diagram shows connecting design and testbench without interface.
addr
W_en
90
clk clk
Semi Design
Below diagram shows connecting design and testbench with interface.
92
Semi Design
Connecting testbench and design without interface construct:
module tbench_top;
module memory ( clk, addr, reg clk;
wr_rd, wdata, rdata); reg [7:0] w_addr;
input clk; reg w_wr_rd;
input [7:0] addr; reg [7:0] w_wdata;
input wr_rd; reg [7:0] w_rdata;
input [7:0] wdata; wire [7:0] rdata;
output [7:0] rdata;
…… // DUT instance
endmodule memory dut(
.clk(clk),
.addr(w_addr),
.wr_rd(w_wr_rd),
.wdata(w_wdata),
.rdata(r_data)
); 93
endmodule
Semi Design
Connecting testbench and design with interface construct:
module memory ( clk, addr,
wr_rd, wdata, rdata); module tbench_top;`
input clk; //Interface instance
input [7:0] addr; mem_intf intf();
input wr_rd;
input [7:0] wdata; //DUT(Design Under Test)
output [7:0] rdata; instance
…… memory dut(
endmodule .clk(intf.clk),
.addr(intf.addr),
interface mem_intf; .wr_rd(intf.wr_rd),
logic clk; .wdata(intf.wdata),
logic [7:0] addr; .rdata(intf.rdata));
logic wr_rd;
logic [7:0] wdata; endmodule
logic [7:0] rdata;
94
endinterface
Semi Design
Interface Example:
Writing interface:
interface intf;
endinterface
Interface declaration:
//DUT instance
adder DUT (.a(i_i.a), .b(i_i.b), .c(i_i.c) );
i_i.a = 6;
i_i.b = 4;
i_i.c = i_i.a + i_i.b;
// Simulation results
Value of a = 6, b = 4
Sum of a and b, c = 10 96
Semi Design
Semi Design
Virtual interface
A virtual interface is a variable that represents an interface instance.
• The virtual interface must be initialized before using it. i.e, Virtual interface
must be connected/pointed to the actual interface.
• Accessing the uninitialized virtual interface result in a run-time fatal error.
• Virtual interfaces can be declared as class properties, which can be initialized
procedural or by an argument to new().
• Virtual interface variables can be passed as arguments to the tasks, functions,
or methods.
• All the interface variables/Methods can be accessed via a virtual interface
handle. i.e virtual_interface.variable
98
Semi Design
Syntax for virtual interface:
// Syntax for Virtual interface
virtual interface_name instance_name;
99
Semi Design
Accessing interface signal using a virtual interface handle
Modport
System Verilog Modport. The Modport groups and specifies the port
directions to the wires/signals declared within the interface. modports are
declared inside the interface with the keyword modport.
• By specifying the port directions, modport provides access restrictions.
• The keyword modport indicates that the directions are declared as if inside
the module.
• Modport wire declared with input is not allowed to drive or assign, any
attempt to drive leads to a compilation error.
• The Interface can have any number of modports, the wire declared in the
interface can be grouped in many modports.
• Modpports can have, input, inout, output, and ref.
101
Semi Design
Declaration of Modport:
interface i_i;
logic x;
logic y;
//modport delcaration
modport driver (input x, output y);
modport monitor (input x, input y);
endinterface
driver modport:
It groups the signals x and y with the access direction input and output
respectively
monitor modport:
It groups the signals x and y with the access restricted to input for both the 10
signals. As the monitor need only monitoring the signals, driving access is 2
restricted by specifying direction as input.
Semi Design
Modport example:
interface intf();
logic [3:0] a;
logic [3:0] b; // Simulation results:
logic [6:0] c; Port 'a' of modport 'driver' has
been restricted as an input port.
modport driver (input a, b, output c); Input ports cannot be driven.
endinterface Port 'b' of modport 'driver' has
been restricted as an input port.
task run; Input ports cannot be driven.
vif.driver.a = 6;
vif.driver.b = 4;
Clocking blocks
SystemVerilog adds the clocking block that identifies clock signals, and captures
the timing and synchronization requirements of the blocks being modeled. A
clocking block assembles signals that are synchronous to a particular clock, and
makes their timing explicit. The clocking block is a key element in a cycle-based
methodology, which enables users to write testbenches at a higher level of
abstraction. Simulation is faster with cycle based methodology.
Depending on the environment, a testbench can contain one or more clocking
blocks, each containing its own clock plus an arbitrary number of signals. These
operations are as follows:
• Synchronous events
• Input sampling
• Synchronous drives 10
5
Semi Design
Syntax for Clocking block:
In the above example, the first line declares a clocking block called cb that is to
be clocked on the positive edge of the signal clk. The second line specifies that
by default all signals in the clocking block shall use a 10ns input skew and a 2ns
output skew by default. The next line adds three output signals to the clocking
block: read, enable and addr. The fourth line adds the signal data to the clocking
block as input. Fourth line also contains negedge which overrides the skew ,so
that data is sampled on the negedge of the clk.
10
6
Semi Design
Skew
If an input skew is specified then the signal is sampled at skew time units
before the clock event. If output skew is specified, then output (or inout)
signals are driven skew time units after the corresponding clock event. A
skew must be a constant expression, and can be specified as a parameter.
Cycle delay:
The ## operator can be used to delay execution by a specified number of
clocking events, or clock cycles. What constitutes a cycle is determined by the
default clocking in effect of module, interface, or program.
10
9
Semi Design
Semi Design
Introduction to OOP
Unlike procedural programming, here in the OOP programming model programs are
organized around objects and data rather than actions and logic. Objects represent
some concepts or things and like any other objects in the real Objects in programming
language have certain behavior, properties, type, and identity. In OOP based language
the principal aim is to find out the objects to manipulate and their relation between
each other. OOP offers greater flexibility and compatibility then procedural language
like verilog.
Objects are key to understanding object-oriented technology. Look around right now
and you'll find many examples of real-world objects: your system, your desk, your
chair.
Real-world objects share two characteristics: They all have state and behavior.
System have state (name, color) and behavior (playing music,switch off).
Identifying the state and behavior for real-world objects is a great way to begin 111
thinking in terms of object-oriented programming.
Semi Design
SystemVerilog is a object oriented programming and to understand the functionality of
OOP in SystemVerilog, we first need to understand several fundamentals related to
objects. These include class, method, inheritance, encapsulation, abstraction,
polymorphism etc.
Class:
It is the central point of OOP and that contains data and codes with behavior. In
SystemVerilog OOPS , everything happens within class and it describes a set of
objects with common behavior. The class definition describes all the properties,
behavior, and identity of objects present within that class.
Object:
Objects are the basic unit of object orientation with behavior, identity. As we
mentioned above, these are part of a class but are not the same. An object is
expressed by the variable and methods within the objects. Again these variables
and methods are distinguished from each other as instant variables, instant methods
and class variable and class methods.
112
Semi Design
Methods:
We know that a class can define both attributes and behaviors. Again attributes are
defined by variables and behaviors are represented by methods. In other words,
methods define the abilities of an object.
Inheritance:
This is the mechanism of organizing and structuring program. Though objects are
distinguished from each other by some additional features but there are objects that
share certain things common. In object oriented programming classes can inherit
some common behavior and state from others. Inheritance in OOP allows to define
a general class and later to organize some other classes simply adding some details
with the old class definition. This saves work as the special class inherits all the
properties of the old general class and as a programmer you only require the new
features. This helps in a better data analysis, accurate coding and reduces
development time.
113
Semi Design
Abstraction:
The process of abstraction in SystemVerilog is used to hide certain details and only
show the essential features of the object. In other words, it deals with the outside
view of an object.
Encapsulation:
This is an important programming concept that assists in separating an object's
state from its behavior. This helps in hiding an object's data describing its state
from any further modification by external component. In SystemVerilog there are
three different terms used for hiding data constructs and these are public, private
and protected . As we know an object can associated with data with predefined
classes and in any application an object can know about the data it needs to know
about. So any unnecessary data are not required by an object can be hidden by this
process. It can also be termed as information hiding that prohibits outsiders in
seeing the inside of an object in which abstraction is implemented.
114
Semi Design
Polymorphism:
It describes the ability of the object in belonging to different types with specific
behavior of each type. So by using this, one object can be treated like another and in
this way it can create and define multiple level of interface. Here the programmers
need not have to know the exact type of object in advance and this is being
implemented at runtime.
115
Semi Design
Class
A class is the implementation of an abstract data type . It defines attributes and
methods which implement the data structure and operations of the abstract data
type, respectively. Instances of classes are called objects. Consequently, classes
define properties and behavior of sets of objects.
Object:
An object is an instance of a class. It can be uniquely identified by its name and it
defines a state which is represented by the values of its attributes at a particular
time.
class simple ;
int i, j; obj_1 = new();
task printf(); obj_2 = new();
$display( i , j ); obj_1.i = 2;
// Simulation results:
endtask obj_1.j = 5;
2 5
endclass obj_2.i = 4;
4 0
obj_1.printf();
program main; obj_2. printf();
initial begin end
simple obj_1; endprogram 117
simple obj_2;
Semi Design
Declaration of objects:
//Example of declaration objects:
Packet pkt;
Driver driv;
If you declare pkt like this, its value will be undetermined until an object is
actually created and assigned to it using the new method. Simply declaring a
reference variable does not create an object. For that, you need to use the new
operator. You must assign an object to pkt before you use it in your code.
Otherwise, you will get a compiler error.
Creating objects:
This
‘this’ keyword is used to refer to class properties. this keyword is used to
unambiguously refer to class properties or methods of the current instance. this is a
pre-defined class handle referring to the object from which it is used,
calling this.variable means object.variable.
12
0
Semi Design
class packet;
byte a
Compiler gets confused on which is the class
byte b;
variable
function void data(byte a, b);
a = a;
b = b; Using this will solve the issue
endfunction this.a = a;
this.b = b;
endclass
121
class packet; Semi Design
bit [31:0] addr;
bit [31:0] data;
bit write;
string pkt_type;
// simulation result
addr = 0
data = 0
write = 0
pkt_type =
12
3
class packet; // simulation result Semi Design
bit [31:0] addr; addr = 10
bit [31:0] data; data = ff
bit write; write = 1
string pkt_type; pkt_type = GOOD_PKT
Inheritance
Inheritance:
Inheritance is the mechanism which allows a class A to inherit properties of a
class B. We say ``A inherits from B''. Objects of class A thus have access to
attributes and methods of class B without the need to redefine them. The
following definition defines two terms with which we are able to refer to
participating classes when they use inheritance.
Subclass (or) child class (or) extended class (or) derived class:
12
If class A inherits from class B, then A is called subclass of B. 5
Semi Design
The idea of inheritance is simple but powerful: When you want to create a new class
and there is already a class that includes some of the code that you want, you can
derive your new class from the existing class. In doing this, you can reuse the fields
and methods of the existing class without having to write (and debug!) them yourself.
12
7
Semi Design
Overriding: class parent;
task printf();
$display(" THIS IS PARENT CLASS ");
endtask endclass
class subclass extends parent;
task printf();
// simulation result $display(" THIS IS SUBCLASS ");
THIS IS PARENT CLASS endtask endclass
THIS IS SUBCLASS
program main;
initial begin
parent p;
subclass s;
p = new();
s = new();
p.printf();
s.printf(); 12
end endprogram 8
Semi Design
Super: class parent;
task printf();
The super keyword is used from $display(" THIS IS PARENT CLASS ");
within a derived class to refer to endtask
members of the parent class. It is endclass
necessary to use super to access class subclass extends parent;
members of a parent class when task printf();
those members are overridden by super.printf();
the derived class. endtask
endclass
Encapsulation
The technique of hiding the data within the class and making it available only
through the methods, is known as encapsulation.
Because it seals the data (and internal methods) safely inside the “capsule” of
the class, where it can be accessed only by trusted users (i.e., by the methods
of the class).
By default all the members and methods of a class are accessible from
anywhere using the object handle, sometimes this could corrupt the class
members values, which should not be touched at all.
Access control rules that restrict the members of a class from being used
outside the class, this is achieved by prefixing the class members with the
keywords,
• Local
13
• Protected 3
Semi Design
Local class members:
External access to the class members can be avoided by declaring members as
local.
Any violation could result in a compilation error.
class parent_class;
local bit [31:0] a;
The local variable declared inside the class is trying
function new(bit [31:0] r_i); to access from outside the class by using object
a = r_i + 10; handle.
endfunction As the variable is declared as local, which leads to a
compilation error.
function display();
$display("tmp_addr = %0d",a);
endfunction // simulation result
endclass Error- Illegal class variable access
testbench.sv, Local member ‘a’ of
module encapsulation; class 'parent_class' is not visible to
initial begin scope 'encapsulation'.
parent_class p_c = new(5);
p_c.a = 20; //Accessing local variable outside the class
p_c.display(); 13
end 5
endmodule
Accessing a Local variable within the class (allowed ) Semi Design
class parent_class;
local bit [31:0] a;
The local variable declared inside the class is being
function new(bit [31:0] r_i); accessed inside the class. as it is allowed, no
a = r_i + 10; compilation error is observed.
endfunction
function display();
$display("tmp_addr = %0d",a);
endfunction // simulation result
endclass tmp_addr = 15
module encapsulation;
initial begin
parent_class p_c = new(5);
p_c.display();
end 13
endmodule 6
Accessing a Protected variable outside the class ( not allowed ) Semi Design
class parent_class;
protected bit [31:0] a;
module encapsulation;
function new(bit [31:0] r_i);
initial begin
a= r_i + 10;
parent_class p_c = new(5);
endfunction
child_class c_c = new(10);
function display();
// variable declared as protected cannot be
$display("tmp_addr = %0d",a);
accessed outside the class
endfunction
p_c.a= 10;
endclass
p_c.display();
class child_class extends parent_class;
end
function new(bit [31:0] r_i);
endmodule
super.new(r_i);
endfunction
In the above example, The protected variable declared inside the class is
trying to access from outside the class by using object handle.
As the variable is declared as protected, which leads to a compilation
error.
// simulation result
Error- Illegal class variable access testbench.sv, Protected
member ‘a' of class 'parent_class' is not visible to scope
'encapsulation'.
13
8
Accessing a Protected variable in the extended class (allowed ) Semi Design
class parent_class;
protected bit [31:0] a;
function new(bit [31:0] r_i); module encapsulation;
a= r_i + 10; initial begin
endfunction child_class c_c = new(10);
In the above example, The protected variable declared inside the class is
being accessed inside the extended class. as it is allowed, no compilation
error is observed.
// simulation result
tmp_addr = 21
14
0
Semi Design
Abstract class
SystemVerilog class declared with the keyword virtual is referred to as
an abstract class.
Abstract classes are those which can be used for creation of handles. However their
methods and constructors can be used by the child or extended class. The need for
abstract classes is that you can generalize the super class from which child classes
can share its methods. The subclass of an abstract class which can create an object
is called as "concrete class".
module virtual_class;
initial begin
packet p;
p = new();
end
endmodule
// simulation result
virtual_class, "p = new();" Instantiation of the object 'p' can not be done
because its type 'packet' is an abstract base class. Perhaps there is a 14
derived class that should be used. 2
Semi Design
Deriving Virtual class:
virtual class packet;
bit [31:0] addr;
endclass
An abstract class is derived and
class extended_packet extends packet; written extend the class and creating
function void display; it.
$display("Value of addr is %0d", addr);
endfunction
endclass // simulation result
Value of addr is 10
module virtual_class;
initial begin
extended_packet p;
p = new();
p.addr = 10;
p.display();
14
end endmodule 3
Semi Design
Virtual methods():
1. Virtual Functions:
A function declared with a virtual keyword before the function keyword is
referred to as virtual Function
// Syntax for virtual functions
virtual function function_name;
// Function definition
endfunction
2. Virtual Tasks:
Task declared with a virtual keyword before the task keyword is referred to as
virtual task
// Syntax for virtual functions
virtual task task_name;
// task definition
endtask 14
4
Semi Design
Method without virtual keyword:
class vir_ex;
function void display; module virtual_class;
$display("Inside base_class"); initial begin
endfunction vir_ex v_e;
endclass child c;
The method inside the base class is declared without a virtual keyword, on
calling method of the base class which is pointing to the extended class
will call the base class method.
14
5
Semi Design
Method with virtual keyword:
class vir_ex;
virtual function void display; module virtual_class;
$display("Inside base_class"); initial begin
endfunction vir_ex v_e;
endclass child c;
The method inside the base class is declared with a virtual keyword, on
calling method of the base class which is pointing to an extended class will
call the extended class method.
14
6
Semi Design
Polymorphism
Polymorphism means many forms. Polymorphism in SystemVerilog provides an
ability to an object to take on many forms.
Method handle of super-class can be made to refer to the subclass method, this
allows polymorphism or different forms of the same method.
Example of polymorphism:
class A
14
class B_1 class B_2 class B_2 7
Semi Design
1. Let’s write the base_class with a method display()
class base_class;
virtual function display();
$display("Inside base class");
endfunction
endclass
2. Writing three extended classes of base_class, with display method overridden in it.
class ext_class_1 extends base_class;
function display();
$display("Inside extended class 1");
endfunction
endclass
class ext_class_3 extends base_class;
class ext_class_2 extends base_class; function display();
function display(); $display("Inside extended class 3");
$display("Inside extended class 2"); endfunction 14
endfunction endclass 8
endclass
Semi Design
3. Create an object of each extended class
base_class b_c[3];
b_c[0] = ec_1;
b_c[1] = ec_2;
b_c[2] = ec_3;
14
9
Semi Design
class base_class;
virtual function void display();
$display("Inside base class");
endfunction
endclass
base_class b_c[3];
b_c[0] = ec_1;
b_c[1] = ec_2; // simulation result
b_c[2] = ec_3; Inside extended class 1
Inside extended class 2
Inside extended class 3
b_c[0].display();
b_c[1].display();
b_c[2].display();
end
151
endmodule
Semi Design
Parameterized Classes
Parameterized classes are same as the parameterized modules in the verilog.
parameters are like constants local to that particular class.
The parameter value can be used to define a set of attributes in class. default values can
be overridden by passing a new set of parameters during instantiation. this is called
parameter overriding.
class packet #(parameter int ADDR_WIDTH = 32,DATA_WIDTH = 32);
bit [ADDR_WIDTH-1:0] address;
bit [DATA_WIDTH-1:0] data ;
packet pkt; –> creates pkt handle with default
ADDR_WIDTH and DATA_WIDTH values.
function new();
The default parameter value can be overridden when
address = 10;
the class is instantiated.
data = 20;
packet #(32,64) pkt; –> creates pkt handle with 15
endfunction
ADDR_WIDTH = 32 and DATA_WIDTH = 64. 2
endclass
Semi Design
Pass a data type to a class:
function new();
address = 10;
data = 20; packet pkt; –> address and data type is int
endfunction packet #(bit [31:0]) pkt; –> address and data type
endclass is bit [31:0]
15
3
Semi Design
Constants
Constant class:
An instance of a class (an object handle) can also be declared with the const
keyword.
// Example
const class_name object = new(3,3,4);
In other words, the object acts like a variable that cannot be written. The arguments
to the new method must be constant expressions. The members of the object can be
written (except for those members that are declared const).
15
4
Semi Design
Global Constant:
Global constant class properties include an initial value as part of their declaration.
They are similar to other const variables in that they cannot be assigned a value
anywhere other than in the declaration.
class A ;
const int i = 10;
endclass
class A ; class A ;
const int i; const int i;
function new(); function new();
i = 20; i = 20;
endfunction i++;
endclass endfunction
endclass
program main ;
A my_a;
// simulation result // simulation result
initial begin
20 Instance constants assignment can
my_a = new();
only be done once 15
$display(my_a.i); 6
end endprogram
Semi Design
Static
A static property is a class variable that is associated with the class, rather than
with an instance of the class. This means that when it is changed, its change is
reflected in all instances of the class. Static properties are declared with the static
keyword. If you need to access a static property inside a class, you can also use
the magic keywords "this" and "super", which resolve to the current class and the
parent of the current class, respectively. Using "this" and "super" allows you to
avoid having to explicitly reference the class by name.
15
7
Semi Design
class A ;
static int i;
endclass
program main ;
A obj_1;
A obj_2;
initial begin
obj_1 = new();
obj_2 = new();
obj_1.i = 123;
$display(obj_2.i);
end
endprogram
// simulation result
123 15
8
class A ; Semi Design
static task incr(); // simulation result
int j; //automatic variable Static task - static task with automatic
j++; variables
$display("J is %d",j); J is 1
endtask J is 1
endclass J is 1
J is 1
program main ; J is 1
A obj_1; A obj_2;
initial begin
$display("Static task - static task with automatic variables");
obj_1 = new();
obj_2 = new();
obj_1.incr();
obj_2.incr();
obj_1.incr();
obj_2.incr();
15
obj_1.incr(); 9
end endprogram
Semi Design
class A ;
int j;
static task incr(); A static method has no access to nonstatic members
j++; (class properties or methods), but it can directly
$display("J is %d",j); access static class properties or call static methods
endtask of the same class. Access to nonstatic members or to
endclass the special this handle within the body of a static
method is illegal and results in a compiler error.
program main ;
A obj_1;
A obj_2; // simulation result
initial begin A static method has no access to nonstatic
obj_1 = new(); members (class properties or methods)
obj_2 = new();
obj_1.incr();
obj_2.incr();
end 16
endprogram 0
Semi Design
Copy
The terms "deep copy" and "shallow copy" refer to the way objects are copied, for
example, during the invocation of a copy constructor or assignment operator.
class B;
int i;
endclass In the above example, both objects are pointing to
same memory. The properties did not get copied.
program main; Only the handle is copied.
initial begin
B b1; B b2; // simulation result
b1 = new(); 123
b1.i = 123;
b2 = b1;
$display( b2.i ); 161
end
endprogram
Semi Design
Shallow Copy:
A shallow copy of an object copies all of the member field values.
class B; This works well if the fields are values, but may not
int i; be what you want for fields that point to
endclass dynamically allocated memory. The pointer will be
copied. but the memory it points to will not be
program main; copied -- the field in both the original object and the
initial begin copy will then point to the same dynamically
B b1; B b2; allocated memory, which is not usually what you
b1 = new(); want. The assignment operator make shallow copies.
b1.i = 123;
b2 = new b1; // simulation result
b2.i = 321; 123
$display( b1.i ); 321
$display( b2.i );
end 16
endprogram 2
class A; Semi Design
int i;
endclass In the above example, the varible i is
class B; changed to which is inside the object of .
A a; This changes in seen in also because both
endclass the objects are pointing to same memory
location.
program main;
initial begin
B b1; B b2; // simulation result
b1 = new(); 123
b1.a = new(); 123
b1.a.i = 123; 321
b2 = new b1; 321
$display( b1.a.i );
$display( b2.a.i );
b1.a.i = 321;
$display( b1.a.i ); 16
$display( b2.a.i ); 3
end endprogram
Semi Design
Deep Copy:
A deep copy copies all fields, and makes copies of dynamically allocated memory
pointed to by the fields. To make a deep copy, you must write a copy constructor and
overload the assignment operator, otherwise the copy will point to the original, with
disasterous consequences.
endprogram
Semi Design
Class Resolution operator allows access to static members (class properties and
methods) from outside the class, as well as access to public or protected elements of
super classes from within the derived classes.
16
5
Semi Design
class packet;
bit [31:0] addr;
static bit [31:0] id; A static member of the class is accessed
outside the class by using class resolution
function display(bit [31:0] a,b); operator ::
$display("Values are %0d %0d",a,b);
endfunction
endclass // simulation result
Values are 20 10
module sro_class;
int id=10;
initial begin
packet p;
p = new();
packet::id = 20;
p.display(packet::id,id);
end
endmodule 16
6
Semi Design
Null
The Null is perhaps the most "intelligent" pattern of all. It knows exactly what to
do all the time, every time. Its does nothing. The Null is somewhat difficult to
describe, since it resides in an abstract hierarchy tree, having no particular place
at all, but occupying many roles. It is somewhat like the mathematical concept of
zero: it is a placeholder, but is in itself nothing, and has no value. Null Object is a
behavioral pattern designed to act as a default value of an object in most OOPs
tools. These references need to be checked to ensure they are not null before
invoking any methods, because one can't invoke anything on a null reference; this
tends to make code less readable. If you forgot to create an object anew passed it
to method, where the method has some operation on the object, the simulation
fails. So , If the method is expecting an object , then check weather the object is
created or not else take necessary action. The advantage of this approach over a
working default implementation is that a Null Object is very predictable and has 16
no side effects. 7
Semi Design
class B;
task printf();
$display(" Hi ");
endtask
endclass
External Declaration
Class methods and Constraints can be defined in the following places:
• inside a class.
• outside a class in the same file.
• outside a class in a separate file.
The extern qualifier indicates that the body of the method (its implementation) or
constraint block is to be found outside the declaration.
NOTE : class scope resolution operator :: should be used while defining.
16
9
Semi Design
class B;
extern task printf();
endclass
17
0
Semi Design
Semi Design
Introduction
Historically,verification engineers used directed test bench to verify the functionality
of their design.Rapid changes have occurred during the past decades in design and
verification.High Level Verification Languages (HVLS) such as e, System
c,Vera,SystemVerilog have become a necessity for verification environments.
Constraint Random stimulus generation is not new. Everybody uses verilog and
VHDL at very low level abstraction for this purpose. HVLS provide constructs to
express specification of stimulus at high level of abstraction and constraint solver
generates legal stimulus.
Writing constraints at higher level of absctraction,makes the programming closer
to specation.
A constraint language should support:
• Expressions to complex scenarios. 17
• Felxibility to control dynamically. 2
• Combinational and sequential constraints.
Semi Design
Verilog CRV
Constrained Random Stimulus Generation In Verilog:
Verilog has system function $random, which can be used to generate random input
vectors. With this approach,we can generate values which we wouldnt have got, if
listed manually. In this topic I would like to discuss what natural things happening
behind $random and how we use it in different manners.
17
3
Semi Design
module Tb();
integer address; We have seen how to generate random
initial begin numbers.But the numbers randge from -
repeat(5) (2**32 -1) to 2 **32. Most of the time,
#1 address = $random; the requirement is dont need this range.
end For example, take a memory. The
address starts from 0 to some 1k or
initial 1m.Generating a random address which
$monitor("address = %0d;",address); DUT is not supporting is meaning less.
endmodule In verilog there are no constructs to
constraint randomization. Following
// simulation result example demonstrated how to generate
address = 303379748; random number between 0 to 10.Using %
address = -1064739199; operation,the remainder of any number is
address = -2071669239; always between 0 to 10.
address = -1309649309;
17
address = 112818957; 4
Semi Design
module Tb();
integer add_1;
// simulation result
initial begin
add_1 = 8;
repeat(5)
add_1 = 4294967287;
begin #1;
add_1 = 4294967295;
add_1 = $random % 10;
add_1 = 9;
end
add_1 = 9;
end
initial
$monitor("add_1 = %0d",add_1);
endmodule
17
5
Semi Design
module Tb();
integer add_2; The above example shows the generation
reg [31:0] add_1; of numbers from 0 to N. Some
integer add_3; specification require the range to start
initial begin from non Zero number. MIN +
repeat(5) {$random} % (MAX - MIN ) will
begin #1; generate random numbers between MIN
add_1 = $random % 10; and MAX.
add_2 = {$random} %10 ;
add_3 = $unsigned($random) %10 ; // simulation result
end add_3 = 7;add_2 = 7;add_1 = 8
end add_3 = 7;add_2 = 7;add_1 = 4
add_3 = 1;add_2 = 2;add_1 = 4
initial add_3 = 7;add_2 = 8;add_1 = 9
$monitor("add_3 = %0d;add_2 = %0d;add_1 = add_3 = 9;add_2 = 2;add_1 = 9
%0d",add_3,add_2,add_1);
endmodule
17
6
Semi Design
177
Semi Design
module Tb();
integer add; All the random numbers generated above
initial are 32 bit vectors, which is not always
begin the same requirement. For example, to
repeat(5) generate a 5 bit and 45 bit vector random
begin #1; number, the following method can be
if( $random % 2) used.
add = 40 + {$random} % (50 - 40) ;
else
// simulation result
add = 90 + {$random} % (100 - 90) ;
add = 97
$display("add = %0d",add);
add = 47
end
add = 47
end
add = 42
endmodule
add = 49
17
8
Semi Design
module Tb();
integer num_1,num_2,tmp; All the above examples show that the
initial random numbers are integers only. In
begin verilog there is no special construct to
repeat(5) generate a random real number.The
begin following method shows generation of
num_1 = ($random / 3)*3; random real numbers.
num_2 = ($random / 5)*5;
$display("num_1 = %d,num_2 = %d",num_1,num_2);
end
end
endmodule
// simulation result
num_1 = 303379746,num_2 = -1064739195
num_1 = -2071669239,num_2 = -1309649305
num_1 = 112818957,num_2 = 1189058955
num_1 = -1295874969,num_2 = -1992863210 17
9
num_1 = 15983361,num_2 = 114806025
Semi Design
module Tb();
integer num_1,num_2,num_3;
real r_num; To generate random real number , system
initial begin function $bitstoreal can also be used.
repeat(5)
begin #1;
num_1 = $random;
num_2 = $random;
num_3 = $random;
r_num = num_1 + ((10)**(-(num_2)))*(num_3);
$display("r_num = %e",r_num);
end // simulation result
end r_num = -2.071669e+03
endmodule r_num = 2641.189059e+013
r_num = 976361.598336e+01
r_num = 57645.126096e+02
r_num = 24589.097015e+0 18
0
Semi Design
module Tb();
real r_num;
initial begin
repeat(5)
begin #1;
r_num = $bitstoreal({$random,$random});
$display("r_num = %e",r_num);
end
end
endmodule
SystemVerilog CRV
SystemVerilog Constrained Random Stimulus Generation:
We have seen how to get random values and constrain them. These constraints are at
very low level of abstraction. Todays verification needs a better way to describe the
constraints. SystemVerilog has randomization constructs to support todays
verification needs.
Following are the features of SystemVerilog which support Constraint Random
Verification (CRV) :
1) Constraints : Purely random stimulus takes too long to generate interesting
scenarios. Specify the interesting subset of all possible stimulus with constraint blocks.
These are features provided by SystemVerilog for constraining randomness. Random
variable generated in verilog Boolean expressions, foreach (for constraining elements
18
of array), set membership, inline constraints, rand case, rand sequence, Conditional 6
constraints and implication constraints.
Semi Design
2) Randomization : random function, constrained and unconstrained randomization,
uniform distribution, weighted distribution, weighted range, weighted case, pre
randomization, post randomization, declaration of random variable and non
repeating sequence.
In verilog only system functions like $random are used for stimulus generation. In
SystemVerilog, constraint random stimulus can be generated in following ways.
18
7
Random Number Generator System Functions: Semi Design
module Tb();
integer unsigned address;
// simulation result
initial begin
address = 3468265955;
repeat(5)
address = 541037099;
begin
address = 3836988758;
address = $urandom();
address = 3611785217;
$display("address = %d;",address);
address = 978699393;
end
end
endmodule
18
8
Semi Design
$urandom_range:
The $urandom_range() function returns an unsigned integer within a specified
range. The syntax for $urandom_range() is as follows: function int unsigned
$urandom_range( int unsigned maxval,int unsigned minval = 0 ); The function
shall return an unsigned integer in the range of maxval ... minval.
19
0
Semi Design
191
Semi Design
19
2
Semi Design
module scope;
integer Var;
initial begin
for ( int i = 0;i<7;i++);
if( randomize(Var))
$display(" Randomization sucsessfull : Var = %0d ",Var);
else
$display("Randomization failed");
$finish;
end // simulation result
endmodule Randomization sucsessfull : Var = -826701341
Randomization sucsessfull : Var = 541037099
Randomization sucsessfull : Var = -457978538
Randomization sucsessfull : Var = -683182079
Randomization sucsessfull : Var = 978699393
Randomization sucsessfull : Var = 717199556
Randomization sucsessfull : Var = 1114265683
19
3
Scope randomize function gives better control over the
$random, as it allows to add constraints using inline
module scope; constraints and constraint solver gives valid solution.
integer Var; Variables which are in the constraint block and not
integer MIN; passed as arguments to randomize() function are not
initial begin randomized. In the following example Variable Var is
MIN = 50; randomized and MIN is not randomized.
for ( int i = 0;i< 100 ; i=i+1)
if( randomize(Var) with { Var < 100 ; Var > MIN ;})
$display(" Randomization sucsessfull : Var = %0d Min = %0d",Var,MIN);
else
$display("Randomization failed"); // simulation result
$finish; Randomization sucsessfull : Var = 94 Min = 50
end Randomization sucsessfull : Var = 69 Min = 50
endmodule Randomization sucsessfull : Var = 53 Min = 50
Randomization sucsessfull : Var = 71 Min = 50
Randomization sucsessfull : Var = 51 Min = 50
Randomization sucsessfull : Var = 78 Min = 50 19
Randomization sucsessfull : Var = 95 Min = 50 4
Semi Design
Randomizing Objects:
Generating random stimulus within objects :
SystemVerilog allows object-oriented programming for random stimulus generation,
subjected to specified constraints. During randomization, variables declared as rand
or randc inside class are only considered for randomization. Built-in randomize()
method is called to generate new random values for the declared random variables.
program s_s; // simulation result
class Simple; Randomization sucsessfull : Var = -82993358
rand integer Var; Randomization sucsessfull : Var = -112342886
endclass Randomization sucsessfull : Var = -867551972
Simple obj; Randomization sucsessfull : Var = -34537722
initial begin obj = new(); Randomization sucsessfull : Var = 1977312553
repeat(5)
if(obj.randomize())
$display(" Randomization successful : Var = %0d ",obj.Var);
else
$display("Randomization failed"); 19
end 5
endprogram
Semi Design
Random Unpacked Structs:
SystemVerilog allows unpackedstructs to be declared as rand for randomization. Only
members of struct which are declared as rand or randc are only randomized. randc is
not allowed on unpacked structs. If Struct is not declared as rand, solver considers it as
state variable.
class Rand_struct;
typedef struct { randc int Var1; int Var2; } Struct_t;
rand Struct_t Str; // To randomize Var1 and Struct_t type has to declared as rand
endclass
program stru_rand_6;
Rand_struct RS ;
initial begin // simulation result
RS = new(); Var1 : -430761355
repeat(5) Var1 : 424439941
if(RS.randomize()) Var1 : -1129955555
$display(" Var1 : %d",RS.Str.Var1); Var1 : 1781908941
end Var1 : -752252755 `
19
endprogram 6
Semi Design
program ran_c;
class Ch; Simillar to struct, the same can be achived using class
rand int Var1; by calling the randomize() function on the object,
int Var2; which is created by using class.
endclass
class R_c;
rand Ch obj; // To randomize Var1,Class_t type has to declared as rand function
function new();
obj = new(); // simulation result
endfunction Var1 : 733126180 Var2 : 0
end Var1 : -119008195 Var2 : 0
Var1 : 342785185 Var2 : 0
R_c RC = new(); Var1 : 679818185 Var2 : 0
initial repeat(5) Var1 : -717162992 Var2 : 0
if(RC.randomize())
$display(" Var1 : %0d Var2 : %0d",RC.obj.Var1,RC.obj.Var2);
endprogram 19
7
Semi Design
Semi Design
Randomization
Randomization is the process of making something random; SystemVerilog
randomization is the process of generating random values to a variable. Verilog
has a $random method for generating the random integer values. This is good for
randomizing the variables alone, but it is hard to use in case of class object
randomization. for easy randomization of class properties, SystemVerilog
provides rand keyword and randomize() method.
19
9
Semi Design
Random Variable
The class variables which get random values on randomization are called random
variables. In order to make variables as random variables, Class variables need to
be declared using the rand and randc type-modifier keywords.
Following types can be declared as rand and randc,
• singular variables of any integral type
• arrays
• arrays size
• object handle’s
20
0
Semi Design
rand keyword:
Variables declared with the rand keyword are standard random variables. Their values
are uniformly distributed over their range.
//Syntax:
rand bit [3:0] A;
A is a 4-bit unsigned integer with a range of 0 to 15. on randomization this variable
shall be assigned any value in the range 0 to 15 with equal probability.
randc keyword:
randc is random-cyclic. For the variables declared with the randc keyword, on
randomization variable values don’t repeat a random value until every possible value
has been assigned.
//Syntax:
randc bit wr_rd;
In order to randomize the object variables, the user needs to call randomize()
method. 20
1
//Example:
object.randomize();
Semi Design
class packet;
rand bit [2:0] addr1;
randc bit [2:0] addr2;
endclass
// simulation result
addr1 = 6 addr2 = 4
module rand_methods;
addr1 = 4 addr2 = 3
initial begin
addr1 = 2 addr2 = 0
packet pkt;
addr1 = 6 addr2 = 6
pkt = new();
addr1 = 1 addr2 = 7
repeat(5) begin
pkt.randomize();
$display("\taddr1 = %0d \t addr2 = %0d",pkt.addr1,pkt.addr2);
end
end addr1 – takes the random value on every randomization
endmodule addr2 – takes the random value on every randomization, but takes
random value until every possible value has been assigned
20
2
Semi Design
Randomization Methods
SystemVerilog randomization provides a built-in method randomize. The
randomize() method generates random values for all the active random variables of
an object, subject to the active constraints. Variables declared with the rand keyword
will get random values on the object.randomize() method call.The randomize()
method returns 1 if the randomization is successful i.e on randomization it’s able to
assign random values to all the random variables, otherwise, it returns 0.
20
3
Semi Design
20
5
Semi Design
program pre_rand;
class simple;
function void pre_randomize;
$display(" PRE_RANDOMIZATION ");
endfunction
In the extended class EXTEND_1, when overiding the builtin functions, parent
class functions are not called. In the extended class EXTEND_2, super.methods
are called which invokes the parent class methods also.
20
9
The pre_randomize() and post_randomize() methods are not virtual. Semi Design
However because they are automatically called by the randomize() method, which is
virtual, they appear to behave as virtual methods. This example demonstrates that these
functions are not virtual but simulation results show that, it executed extended class
definition functions. Extended class object is created and assigned to base class object.
Calls to pre_randomize and post_randomize calls in object B ,executed the extended
class definitions.
class Base;
function void pre_randomize;
$display(" BASE PRE_RANDOMIZATION ");
endfunction
virtual function void post_randomize;
$display(" BASE POST_RANDOMIZATION ");
endfunction class Extend extends Base;
endclass function void pre_randomize;
$display(" EXTEND PRE_RANDOMIZATION ");
endfunction
function void post_randomize; 21
0
$display(" EXTEND POST_RANDOMIZATION ");
endfunction endclass
Semi Design
program pre_post_17;
Base B = new();
Extend E = new();
initial begin
B=E;
void'(B.randomize());
void'(E.randomize());
end
endprogram
// simulation result
There should be compilation error
// simulation result
BASE PRE_RANDOMIZATION
EXTENDED PRE_RANDOMIZATION
EXTENDED POST_RANDOMIZATION
randomization done
21
5
Semi Design
Disable randomization
The variable declared without rand or randc will not get random values on
randomization. what if for some reason it is required not to generate a random value
for a random variable. Yes, it is possible to disable the randomization of a variable
by using the systemverilog randomization method rand_mode.
rand_mode methods:
The rand_mode() method is used to disable the randomization of a variable declared
with the rand/randc keyword.
• rand_mode(1) means randomization enabled
• rand_mode(0) means randomization disabled
• The default value of rand_mode is 1, i.e enabled
21
6
Semi Design
• Once the randomization is disabled, it is required to make rand_mode(1) enable
back the randomization
• rand_mode can be called as SystemVerilog method, the randomization
enables/disable status of a variable can be obtained by calling
vairble.rand_mode().
• The rand_mode method returns 1 if randomization is enabled else returns 0
// rand_mode syntax
<object_hanlde>.<variable_name>.rand_mode(enable);
//enable = 1, randomization enable
//enable = 0, randomization disable
21
7
randomization disable examples: Semi Design
module rand_methods;
initial begin
packet pkt;
pkt = new(); // simulation result
addr = 110 data = 116
//calling randomize method
pkt.randomize();
class packet;
rand byte addr; In the example,
rand byte data; The class packet has random variables addr and
endclass data, randomization is disabled for a variable addr,
module rand_methods; on randomization only data will get random value.
initial begin The addr will not get any random value.
packet pkt; rand_mode() method is called in a display to know
pkt = new(); the status.
Constraint Block
Constraint block contains declarative statements which restrict the range of variable or
defines the relation between variables. Constraint programming is a powerful method
that lets users build generic, resuble objects that can be extended or more constrained
later. constraint solver can only support 2 state values. If a 4 state variable is used,
solver treates them as 2 state variable.. Constraint solver fails only if there is no
solution which satisfies all the constraints. Constraint block can also have nonrandom
variables, but at least one random variable is needed for randomization. Constraints are
tied to objects. This allows inheritance, hierarchical constraints, controlling the
constraints of specific object.
// Synatx:
constraint <constraint_block_name> { <condition/expression>;
...
22
<condition/expression>; } 1
Semi Design
Constraint Inheritance:
Like class members, constraints also will get inherited from parent class to child class.
Constraint blocks can be overridden by writing constraint block with the same name as
in parent class.
In the example below,
Constraint to an addr > 5 of the parent class is overridden with constraint addr < 5 in
child class.
class packet;
rand bit [3:0] addr;
constraint addr_range { addr > 5; }
endclass
module cons;
initial begin
packet pkt1;
// simulation result
packet2 pkt2;
pkt1:: addr = 14
pkt1:: addr = 10
pkt1 = new();
pkt1:: addr = 9
pkt2 = new();
pkt1:: addr = 8
repeat(5) begin
pkt1:: addr = 9
pkt1.randomize();
$display("\tpkt1:: addr = %0d",pkt1.addr);
pkt2:: addr = 0
end
pkt2:: addr = 1
repeat(5) begin
pkt2:: addr = 2
pkt2.randomize();
pkt2:: addr = 0
$display("\tpkt2:: addr = %0d",pkt2.addr);
pkt2:: addr = 2
end
end
endmodule 22
3
Semi Design
class Base;
rand integer Var;
constraint range { Var < 100 ; Var > 0 ;}
endclass
program inhe_31;
Extended obj;
initial begin
obj = new();
for(int i=0 ; i < 100 ; i++)
if(obj.randomize())
$display(" Randomization sucsessfull : Var = %0d ",obj.Var);
else
$display("Randomization failed"); 22
end 4
endprogram
Semi Design
// simulation result
Randomization sucsessfull : Var = 91
Randomization sucsessfull : Var = 93
Randomization sucsessfull : Var = 77
Randomization sucsessfull : Var = 68
Randomization sucsessfull : Var = 67
Randomization sucsessfull : Var = 52
Randomization sucsessfull : Var = 71
Randomization sucsessfull : Var = 98
Randomization sucsessfull : Var = 69
Adding new constraints in the derived class, can change the solution space.
Solver has to solve both constraints defined in base class and derived class. In
the example given below, Constraint range_1 defines the range that Var is
between 0 to 100.Constraint range_2 limits the Var to be greater than 50 and
solver has to solve both the constraints and the solution space is between 50 to
22
100. 5
Semi Design
class Base;
rand integer Var;
constraint range_1 { Var < 100 ; Var > 0 ;}
endclass
end endprogram
Semi Design
// simulation result
Randomization sucsessfull : Var = 100
Randomization sucsessfull : Var = 100
Randomization sucsessfull : Var = 100
Randomization sucsessfull : Var = 100
Randomization sucsessfull : Var = 100
Randomization sucsessfull : Var = 100
Randomization sucsessfull : Var = 100
Randomization sucsessfull : Var = 100
Randomization sucsessfull : Var = 100
22
8
Semi Design
class Base;
rand integer Var;
constraint range_1 { Var < 100 ; Var > 0 ;}
endclass
class Extended extends Base;
constraint range_2 { Var > 50 ;}
endclass
program inhe_34;
Extended obj_e;
Base obj_b;
initial begin obj_e = new();
obj_b = obj_e;
for(int i=0 ; i < 10 ; i++)
if(obj_b.randomize())
$display(" Randomization sucsessfull : Var = %0d ",obj_b.Var);
else
$display("Randomization failed");
end 22
endprogram 9
Semi Design
// simulation result
Randomization sucsessfull : Var = 91
Randomization sucsessfull : Var = 93
Randomization sucsessfull : Var = 77
Randomization sucsessfull : Var = 68
Randomization sucsessfull : Var = 67
Randomization sucsessfull : Var = 52
Randomization sucsessfull : Var = 71
Randomization sucsessfull : Var = 98
Randomization sucsessfull : Var = 69
Randomization sucsessfull : Var = 70
23
0
Semi Design
Inline Constraint
Inline constraints allows to add extra constraints to already existing constraints which
are declared inside class. If you have constraints already defined for variable var,
solver solves those constraints along with the in-line constraints.
class inline;
rand integer Var;
constraint default_c { Var > 0 ; Var < 100;}
endclass
program inline_p_35;
inline obj;
initial begin obj = new();
repeat(5)
if( obj.randomize() with { Var == 50;})
$display(" Randodmize sucessful Var %d ",obj.Var); 23
1
else $display(" Randomization failes");
end endprogram
Semi Design
// simulation result
Randodmize sucessful Var 50
Randodmize sucessful Var 50
Randodmize sucessful Var 50
Randodmize sucessful Var 50
Randodmize sucessful Var 50
23
2
Semi Design
Global Constraint
SystemVerilog allows to have constraints between variables of different objects. These
are called global constraints. Using the hierarchy notation, constraints can be applied
on variables of different objects. When object is randomized, so are the contained
objects and all other constraints are considered simultaneously.
23
3
Semi Design
class child;
rand int Var1;
endclass
class parent;
rand child child_obj;
rand int Var2;
constraint global_c { Var2 < child_obj.Var1 ;}
function new();
child_obj = new(); // simulation result
endfunction Var1 = 903271284 ,Var2 = -1102515531
endclass Var1 = 2112727279 ,Var2 = -838916208
program random_37; Var1 = 1614679637 ,Var2 = 1572451945
initial for(int i=0;i<5; i=i+1) Var1 = 1284140376 ,Var2 = -373511538
begin Var1 = 463675676 ,Var2 = -516850003
parent parent_obj = new();
void'(parent_obj.randomize ());
$display(" Var1 = %0d ,Var2 = %0d ",parent_obj.child_obj.Var1,parent_obj.Var2 ); 23
end endprogram 4
Semi Design
Constraint Mode
Disabling Constraint Block:
SystemVerilog supports to change the status of constraint block dynamically. To
change the status of a Constraint block, built in constraint_mode() method is
used. By default all the constraint blocks are active. When it is called as task, the
arguments to the task determines the operation to be performed. If the arguments
are 0 or 1, then all the constraints blocks are effected .
23
5
Semi Design
class rand_mo;
rand integer Var1; // simulation result
rand integer Var2; Var1 : 20 Var2 : 10
constraint Var_1 { Var1 == 20;} Var1 : 733126180 Var2 : -119008195
constraint Var_2 { Var2 == 10;} Var1 : 20 Var2 : 10
endclass
program rand_mo_p_38;
rand_mo obj = new();
initial begin
void'(obj.randomize()); //By default all constraints are active.
$display(" Var1 : %d Var2 : %d ",obj.Var1,obj.Var2);
obj.constraint_mode(0); //Both constraints Var_1 and Var_2 are turned off.
void'(obj.randomize());
$display(" Var1 : %d Var2 : %d ",obj.Var1,obj.Var2);
obj.constraint_mode(1); //Both constraints Var_1 and Var_2 are turned on.
void'(obj.randomize());
$display(" Var1 : %d Var2 : %d ",obj.Var1,obj.Var2); 23
end endprogram 6
Semi Design
Randomization Controlability
Controlability :
Additional to the controllability feauters supported by SystemVerilog, following
are more points with which controlabiity can be achieved. In the following
example, MACROS MIN_D and MAX_D are defined. Set the MIN and MAX
values in the pre_randomize as shown. As MIN_D and MAX_D are macros, they
can be assigned from command line. Biggest disadvantage for the method shown
below is dynamic controllability.
23
7
Semi Design
`define MAX_D 100
`define MIN_D 50
class Base;
rand integer Var;
integer MIN,MAX;
constraint randge { Var < MAX ; Var > MIN ;}
function void pre_randomize ();
this.MIN = `MIN_D;
this.MAX = `MAX_D;
$display( " PRE_RANDOMIZE : MIN = %0d , MAX = %0d ",MIN,MAX);
endfunction
endclass
program inhe_42;
Base obj;
initial begin obj = new();
for(int i=0 ; i < 100 ; i++) if(obj.randomize())
$display(" Randomization sucsessfull : Var = %0d ",obj.Var);
else 23
$display("Randomization failed"); 8
end endprogram
// simulation result Semi Design
PRE_RANDOMIZE : MIN = 50 , MAX = 100
Randomization sucsessfull : Var = 91
PRE_RANDOMIZE : MIN = 50 , MAX = 100
Randomization sucsessfull : Var = 93
PRE_RANDOMIZE : MIN = 50 , MAX = 100
Randomization sucsessfull : Var = 77
PRE_RANDOMIZE : MIN = 50 , MAX = 100
Randomization sucsessfull : Var = 68
PRE_RANDOMIZE : MIN = 50 , MAX = 100
Randomization sucsessfull : Var = 67
PRE_RANDOMIZE : MIN = 50 , MAX = 100
Randomization sucsessfull : Var = 52
PRE_RANDOMIZE : MIN = 50 , MAX = 100
Randomization sucsessfull : Var = 71
PRE_RANDOMIZE : MIN = 50 , MAX = 100
Randomization sucsessfull : Var = 98….etc
As in this example,a single object is created and randomized 100 times. Due to 23
this,pre_reandomize is called 100 times, which may not be preferred. By assigning the values9
while declaration itself this can be avoided. Simpler way to achieve the above logic.
Semi Design
`define MAX_D 100
`define MIN_D 50
class Base;
rand integer Var;
integer MIN = `MIN_D;
integer MAX = `MAX_D;
constraint range { Var < MAX ; Var > MIN ;}
endclass
program inhe_43;
Base obj;
initial begin
obj = new();
for(int i=0 ; i < 100 ; i++)
if(obj.randomize())
$display(" Randomization sucsessfull : Var = %0d ",obj.Var);
else $display("Randomization failed");
end 24
endprogram 0
Semi Design
// simulation result
Randomization sucsessfull : Var = 91
Randomization sucsessfull : Var = 93
Randomization sucsessfull : Var = 77
Randomization sucsessfull : Var = 68
Randomization sucsessfull : Var = 67
Randomization sucsessfull : Var = 52
Randomization sucsessfull : Var = 71
Randomization sucsessfull : Var = 98
Randomization sucsessfull : Var = 69
Randomization sucsessfull : Var = 70
With the above approach also, dynamic controlability is lost. For dynamic
controllability, define a task, pass this values as arguments when ever the
changed is needed.
24
1
class Base; Semi Design
rand integer Var;
integer MIN = 10,MAX = 20; // Define default values,If function set is not
called,with this it will work
constraint randge {Var < MAX ; Var > MIN ;}
task set (integer MIN,integer MAX);
this.MIN = MIN;
this.MAX = MAX;
$display( " SET : MIN = %0d , MAX = %0d ",MIN,MAX);
endtask
endclass if(obj.randomize())
program inhe_44; $display(" Randomization sucsessfull : Var = %0d ",obj.Var);
Base obj; else
initial begin $display("Randomization failed");
obj = new(); obj.set(50,100) ;
obj.set(0,100) ; for(int i=0 ; i < 5 ; i++)
for(int i=0 ; i < 5 ; i++) if(obj.randomize())
$display(" Randomization sucsessfull : Var = %0d ",obj.Var);
else 24
$display("Randomization failed"); 2
end endprogram
Semi Design
// simulation result
SET : MIN = 0 , MAX = 100
Randomization sucsessfull : Var = 24
Randomization sucsessfull : Var = 68
Randomization sucsessfull : Var = 43
Randomization sucsessfull : Var = 11
Randomization sucsessfull : Var = 4
SET : MIN = 50 , MAX = 100 #
Randomization sucsessfull : Var = 52
Randomization sucsessfull : Var = 71
Randomization sucsessfull : Var = 98
Randomization sucsessfull : Var = 69
Randomization sucsessfull : Var = 70
Static Constraints
SystemVerilog static constraints are similar to static class properties. A constraint
block can be defined as static by including the static keyword in its definition.
constraint block with the static keyword followed by constraint keyword is called as a
static constraint. the static constraint is shared across all the class instances.
•only the mode change of static constraint will get affected in all the instances
of a class
•mode change is enable or disable of a constraint by constrain_mode() method
•a static class can be enabled or disabled by any object handle of its class, mode
change with one object handle will reflect all other objects of same class type
// Syntax
static constraint constraint_name { ....; } 24
4
Semi Design
Non-static constraint:
In the below example,
The class packet has two instances pkt1 and pkt2. constraint addr_range is defined
to control the value of random variable addr.
On randomization, pkt1.addr and pkt2.addr will take value based on the constraint.
The constraint is disabled using a pkt2 handle. As constraint is non-static only for
pkt2 constraint will get disabled. On randomization, pkt1.addr will get value based
on the constraint.
24
5
class packet; Semi Design
rand bit [7:0] addr;
constraint addr_range { addr == 5; }
endclass
module static_constr;
initial begin
packet pkt1; packet pkt2;
pkt1 = new(); pkt2 = new();
$display("Before disabling constraint");
pkt1.randomize();
$display("\tpkt1.addr = %0d",pkt1.addr);
pkt2.randomize();
$display("\tpkt2.addr = %0d",pkt2.addr);
pkt2.addr_range.constraint_mode(0);
$display("After disabling constraint");
pkt1.randomize();
$display("\tpkt1.addr = %0d",pkt1.addr);
pkt2.randomize();
24
$display("\tpkt2.addr = %0d",pkt2.addr); 6
end
Semi Design
// simulation result
Before disabling constraint
pkt1.addr = 5
pkt2.addr = 5
After disabling constraint
pkt1.addr = 5
pkt2.addr = 134
24
7
Semi Design
class packet;
rand bit [7:0] addr;
static constraint addr_range { addr == 5; }
endclass
module static_constr;
initial begin
packet pkt1; packet pkt2;
pkt1 = new(); pkt2 = new();
$display("Before disabling constraint");
pkt1.randomize();
$display("\tpkt1.addr = %0d",pkt1.addr);
pkt2.randomize();
$display("\tpkt2.addr = %0d",pkt2.addr);
pkt2.addr_range.constraint_mode(0);
$display("After disabling constraint");
pkt1.randomize();
$display("\tpkt1.addr = %0d",pkt1.addr);
pkt2.randomize(); 24
$display("\tpkt2.addr = %0d",pkt2.addr); 8
end endmodule
Semi Design
// simulation result
Before disabling constraint
pkt1.addr = 5
pkt2.addr = 5
After disabling constraint
pkt1.addr = 22
pkt2.addr = 134
The example below is the same as the above example, the only change is the
constraint is made as static.
The constraint is disabled by using one of the object handles. as the constraint
is static in nature, the constraint will get disabled for both the objects.
24
9
Semi Design
Constraint Expression
A constraint_expression is any SystemVerilog expression or one of the constraint
specific operators( -> (Implication) and dist). Functions are allowed to certain
limitation. Operators which has side effects are not allowed like ++,--.
Set Membership:
A set membership is a list of expressions or a range. This operator searches for the
existences of the value in the specified expression or range and returns 1 if it is
existing.
25
0
Semi Design
class C_e;
rand integer Var;
constraint range { Var inside {0,1,[50:60],[90:100]}; }
function void post_randomize();
$write("%0d__",Var);
endfunction
endclass
program set;
// simulation result
C_e obj = new();
50__57__60__93__100__94__90__1__54__1
initial
00__
repeat(10)
void'(obj.randomize());
endprogram
25
1
Semi Design
If you want to define a range which is outside the set, use negation.
class C_e;
rand bit [0:2] Var;
constraint range { !( Var inside {0,1,5,6});}
function void post_randomize();
$write("%0d__",Var);
endfunction
endclass
program set;
C_e obj = new();
// simulation result
initial
7__4__4__4__7__2__2__3__2__7__
repeat(10)
void'(obj.randomize());
endprogram
25
2
Semi Design
class set_mem;
rand bit [0:2] Var;
endclass
Engineers often mistaken that set
membership operator is used only in
program set;
constraint block. It can also be used in other
set_mem obj = new();
scopes also.
initial begin
obj.Var = 1;
repeat(10) // simulation result
begin Var = 4
void'(obj.randomize()); Var = 5
while ( obj.Var inside {[1:5]}) Var = 1
begin Var = 1
$display("Var = %0d",obj.Var); Var = 2
break; Var = 2
end
end
end endprogram 25
3
Semi Design
Bidirectional Constraints
SystemVerilog constraints are solved bidirectionally, which means constraints on all
random variables will be solved parallel.
Consider a constraint example,
class packet;
rand bit [3:0] a;
rand bit [3:0] b;
rand bit [3:0] c;
constraint a_value { a == b + c; }
constraint b_value { b > 6; }
constraint c_value { c < 8; }
endclass
module bidirectional_constr;
initial begin
packet pkt;
pkt = new();
repeat(5)
begin
pkt.randomize();
$display("Value of a = %0d \tb = %0d \tc =%0d",pkt.a,pkt.b,pkt.c); 25
end end 5
endmodule
Semi Design
Value of a should be sum of b and c, b should be greater than 6 and c
should be less than 8. so in this case constraint solver will choose a
value to ‘a’ in such a way that it should be sum of b and c, also ‘b’ and
‘c’ should satisfies their constraint.
// simulation result
Value of a = 8 b = 8 c =0
Value of a = 0 b = 14 c =2
Value of a = 14 b = 14 c =0
Value of a = 6 b = 15 c =7
Value of a = 13 b = 11 c =2
Value of a = 8 b = 8 c =0
Value of a = 0 b = 14 c =2
Value of a = 14 b = 14 c =0
Value of a = 6 b = 15 c =7
Value of a = 13 b = 11 c =2
25
6
Bidirectional constraint example 2: Semi Design
class packet;
rand bit a;
rand bit b;
constraint a_value { a == 1; }
constraint b_value { if(a == 0) b == 1;
else b == 0; }
endclass
module bidirectional_const;
initial begin
packet pkt;
pkt = new();
pkt.randomize() with { b == 1; };
$display("Value of a = %0d \tb = %0d",pkt.a,pkt.b);
end
endmodule
25
7
Semi Design
In aboveexample,
Generation of value for b is depending on value of a.
i.e if(a == 0) b = 1;
this condition can be re-written as,
if(b == 1) a = 0;
but there is a constraint for ‘a’ that value for ‘a’ should be always ‘1’.
so ‘b’ should not take value of ‘1’ (to satisfy constraint if(a == 0) b ==
1;)
What if we make ‘b’ value as ‘1’ with inline constraint?
// simulation result
Constraints are inconsistent and cannot be solved.
Please check the inconsistent constraints being printed
above and rewrite them.
25
8
Semi Design
Variable ordering
Solve before is the constraint property. solve before is used inside the constraint
block to specify the order of constraint solving. If the variables are dependent, due
to the bidirectional nature of constraints value of one variable will influence the
value of another variable.
• solve before constraints are used to force the constraint solver to choose the order
in which constraints are solved.
• constraint solver will give equal weight-age to all the possible values. i.e On
multiple randomization solver should assign all the possible values.
25
9
Solve before constraint example: Semi Design
module inline_constr;
initial begin
packet pkt;
pkt = new();
repeat(10)
begin
pkt.randomize();
$display("\tValue of a = %0d, b = %0d",pkt.a,pkt.b);
end
end 26
0
endmodule
Semi Design
Iterative Constraints
Iterative constraints allow Constraining individual elements of fixed-size, dynamic,
associative arrays or queue. foreach construct specifies iteration over the each
elements of array.
NOTE: Remember while randomizing each element of array also array should be
declared as random variable otherwise randomization wont happen.
26
4
// Example program Semi Design
class Eth_pt;
rand byte Payload[] ;
Soft Constraints
SystemVerilog constraints declared with the keyword soft is called as soft
constraints. any conflict between class constraint and inline constraint leads to a
randomization failure, from this it is clear that it is not possible to override the class
constraint by inline constraint. Some test scenarios demand to override the
constraints, this can be done by writing a soft keyword in class constraint.
A soft constraint is a constraint on a random variable, which allows overriding the
constraint.
// Syntax
constraint c_name { soft variable { condition }; }
26
6
Semi Design
Example of real-time soft constraint:
26
7
Example without soft constraint: Semi Design
Unique Constraints
SystemVerilog constraint defined with the keyword unique is called as a unique
constraint. On randomization, unique values to set of variables or unique elements to
an array can be generated by using unique constraints.
Unique constraint allows us to,
• Generate unique values across the variables
• Generate unique elements in an array (Fixed Size Array, Dynamic Array,
Associative array and Queue)
// Syntax
constraint c_name { unique {variable's/array}; }
27
0
Unique constraint example: Semi Design
class u_e;
rand bit [3:0] var_1,var_2,var_3;
rand bit [7:0] array[6];
constraint varis_c {unique {var_1,var_2,var_3};}
constraint array_c {unique {array};}
function void display();
$display("var_1 = %p",var_1); On randomization unique values to
$display("var_2 = %p",var_2); a variable var_1, var_2, var_3 can
$display("var_3 = %p",var_3); be obtained by writing unique
$display("array = %p",array); constraints. Also, a unique
endfunction constraint is written to an array to
endclass get unique array elements.
program u_e_r;
u_e pkt;
initial begin // simulation result
pkt = new(); pkt.randomize(); var_1 = 8 var_2 = 14 var_3 = 11 27
pkt.display(); array = '{'h81, 'h7b, 'h4, 'h47, 'he1, 'h17} 1
end endprogram
unique array of elements example: Semi Design
class u_e;
rand bit [31:0] array[10];
constraint array_c {unique {array};
foreach(array[i]) array[i] < 10;} Unique elements for an array is
generated by using a unique
function void display(); keyword. Also considered that the
$display("array = %p",array); value of elements is less than 10.
endfunction
endclass
program u_e_r;
u_e pkt;
initial begin
pkt = new(); // simulation result
pkt.randomize(); array = '{'h5, 'h7, 'h8, 'h1, 'h6, 'h9, 'h2, 'h3, 'h4, 'h0}
pkt.display();
end 27
endprogram 2
Semi Design
Note:
To see the difference, remove “unique {array};” and execute.
Below is the result on removing the “unique {array};” from constraint.
array = '{'h8, 'h4, 'h3, 'h2, 'h3, 'h0, 'h4, 'h8, 'h6, 'h2}
27
3
Semi Design
Rand case
randcase is a case statement that randomly selects one of its branches. The randcase
item expressions are non-negative integral values that constitute the branch
weights. An item weight divided by the sum of all weights gives the probability of
taking that branch. Randcase can be used in class are modules. The randcase
weights can be arbitrary expressions, not just constants.
// Example:
randcase
3 : x = 1;
1 : x = 2;
4 : x = 3;
endcase
27
4
Semi Design
// Example:
module rand_case;
integer x;
integer cnt_1,cnt_2,cnt_3;
initial begin
cnt_1 = 0; cnt_2=0; cnt_3 = 0;
repeat(100000) begin
randcase
3 : x = 1;
1 : x = 2;
4 : x = 3;
endcase
if(x == 1) cnt_1++;
else if(x == 2) cnt_2++;
else if(x ==3) cnt_3++;
end $display("count_1 =%0d count_2 =%0d count_3 =%0d ",cnt_1,cnt_2,cnt_3);
$display("Probability of count_1 =%0f count_2 =%0f count_3 =%0f
",(cnt_1/100000.0),(cnt_2/100000.0),(cnt_3/100000.0)); 27
end 5
endmodule
Semi Design
The sum of all weights is 8; therefore, the probability of taking the first branch is
0.375, the probability of taking the second is 0.125, and the probability of taking the
third is 0.5. If a branch specifies a zero weight, then that branch is not taken. The sum
of all weights (SUM) is computed (negative values contribute a zero weight). If SUM
is zero or exceeds (2*32-1), no branch is taken. Each call to randcae statement will
return a random number in the range from 0 to SUM. $urandom_range(0,SUM) is used
to generate a random number. As the random numbers are generated using $urandom
are thread stable, randcase also exhibit random stability.
// simulation result
count_1 =37578 count_2 =12643 count_3 =49779
Probability of count_1 =0.375780 count_2 =0.126430 count_3 =0.497790
27
6
Semi Design
Rand sequence
The random sequence generator is useful for randomly generating sequences of
stimulus. For example, to verify a temporal scenario, a sequence of packets are
needed. By randomizing a packet, it will generate most unlikely scenarios which
are not interested. These type of sequence of scenarios can be generated using
randsequence. A randsequence grammar is composed of one or more productions.
Production items are further classified into terminals and nonterminals. A terminal
is an indivisible item that needs no further definition than its associated code block.
27
7
Semi Design
// Example:
module rs();
initial begin
repeat(5)
begin
randsequence( main )
main : one two three ;
one : {$write("one");};
two : {$write(" two");};
three : {$display(" three");};
endsequence
end
end
endmodule
27
8
Semi Design
The production main is defined in terms of three nonterminals: one, two and three.
Productions one,two and three are terminals. When the main is chosen, it will select
the sequence one, two and three in order.
// simulation result
one two three
one two three
one two three
one two three
one two three
27
9
Semi Design
Random production:
// Example:
module rs();
initial
repeat(8)
randsequence( main )
main : one | two | three ;
one : {$display("one");};
two : {$display("two");};
three: {$display("three");};
endsequence
endmodule
28
0
Semi Design
Results show that one, two and three are selected randomly.
// simulation result
three
three
three
three
one
three
two
two
28
1
Semi Design
Semi Design
Coverage
Coverage is used to measure tested and untested portions of the design. Coverage
is defined as the percentage of verification objectives that have been met.
There are two types of coverage metrics,
1. Code Coverage
2. Functional Coverage
28
3
Semi Design
Code Coverage:
• Code coverage measures how much of the “design Code” is exercised.
• This includes the execution of design blocks, Number of Lines, Conditions, FSM,
Toggle and Path.
• The simulator tool will automatically extract the code coverage from the design
code.
Functional Coverage:
Functional coverage is a user-defined metric that measures how much of the
design specification has been exercised in verification.
There are two types of functional coverage,
• Data-oriented Coverage – Checks combinations of data values have
occurred. We can get Data-oriented coverage by writing Coverage groups,
coverage points and also by cross coverage
• Control-oriented Coverage – Checks whether sequences of behaviors have
occurred. We can get assertion coverage by writing SystemVerilog
28
Assertions 4
Semi Design
Cover group
The covergroup construct encapsulates the specification of a coverage model.
Each covergroup specification can include the following components:
28
5
Semi Design
A Cover group is defined between key words covergroup & endgroup. A
Covergroup Instance can be created using the new() operator.
// Syntax
covergroup cg;
... ... ...
endgroup
cg cg_inst = new;
28
6
Semi Design
Sample
cg cg_inst = new;
initial // or task or function or always block
begin
...
...
cg_inst.sample();
...
...
end
Cover Points
A covergroup can contain one or more coverage points. A coverage point can be an
integral variable or an integral expression. A coverage point creates a hierarchical
scope, and can be optionally labeled. If the label is specified then it designates the
name of the coverage point.
28
9
Semi Design
// Syntax In the above example, we are
program main; sampling the cover point "y". The
bit [0:2] y; cover point is named
bit [0:2] values[$]= '{3,5,6}; "cover_point_y" . In the Coverage
report you will see this name. A
covergroup cg; cover group "cg" is defined and its
cover_point_y : coverpoint y; instance "cg_inst" is created. The
endgroup value of "y" is sampled when
cg_inst.sample() method is called.
cg cg_inst = new(); Total possible values for Y are
initial 0,1,2,3,4,5,6,7. The variable "y" is
foreach(values[i]) assigned only values 3,5,6. The
begin y = values[i]; coverage engine should report that
cg_inst.sample(); only 3 values are covered and there
end are 8 possible values.
endprogram
29
0
Semi Design
Coverage Filter
The expression within the iff construct specifies an optional condition that disables
coverage for that cover point. If the guard expression evaluates to false at a sampling
point, the coverage point is ignored.
// Syntax
covergroup cg;
coverpoint cp_varib iff(!reset); // filter condition
endgroup
In the preceding example, cover point varible "cp_varib" is covered only if the
value reset is low.
29
1
Semi Design
Coverage Bins
A coverage-point bin associates a name and a count with a set of values or a
sequence of value transitions. If the bin designates a set of values, the count is
incremented every time the coverage point matches one of the values in the set. If
the bin designates a sequence of value transitions, the count is incremented every
time the coverage point matches the entire sequence of value transitions.
Bins can be created implicitly or explicitly.
29
2
Semi Design
Implicit Bins
While define cover point, if you do not specify any bins, then Implicit bins are created.
The number of bins creating can be controlled by auto_bin_max parameter.
// Example:
program main;
bit [0:2] y;
bit [0:2] values[$] = '{3,5,6};
covergroup cg;
cover_point_y : coverpoint y { option.auto_bin_max = 4 ; }
endgroup
cg cg_inst = new();
initial foreach(values[i]) In the above example, the auto_bin_max is declared as 4.
begin So, the total possible values are divided in 4 parts and each
y = values[i]; part correspoits to one bin. The total possible values for 29
cg_inst.sample(); variable "y" are 8. They are divided in to 4 groups. 3
end endprogram
Bin[0] for 0 and 1 Semi Design
Bin[1] for 2 and 3
Bin[2] for 4 and 5
Bin[3] for 6 and 7
Variable Y is assigned values 3,5 and 6. Values 3,5 and 6 belongs to bins
bin[1],bin[2] and bin[3] respectively. Bin[0] is not covered.
// simulation result
Coverage report:
--------------------
VARIABLE : cover_point_y
Expected : 4
Covered : 3
Percent: 75.00
Uncovered bins
------------------
auto[0:1]
Covered bins
------------------ 29
4
auto[2:3] auto[4:5] auto[6:7]
Semi Design
// Example:
typedef enum { A,B,C,D } alpha;
program main;
alpha y;
alpha values[$] = '{A,B,C};
covergroup cg;
cover_point_y : coverpoint y;
endgroup
cg cg_inst = new();
initial
foreach(values[i])
begin
y = values[i];
cg_inst.sample();
end
endprogram
In The above example, the variable "y" is enum data type and it can have 4 enum 29
5
members A,B,C and D. Variable Y is assigned only 3 Enum members A,B and C.
Semi Design
// simulation result
Coverage report:
---------------------
VARIABLE : cover_point_y
Expected : 4
Covered : 3
Percent: 75.00
Uncovered bins
--------------------
auto_D
Covered bins
--------------------
auto_C
auto_B
auto_A
29
6
Semi Design
Explicit Bins
Explicit bin creation is recommended method. Not all values are interesting or relevant
in a cover point, so when the user knows the exact values he is going to cover, he can
use explicit bins. You can also name the bins.
29
7
Semi Design
// Example:
program main;
bit [0:2] y;
bit [0:2] values[$] = '{3,5,6};
covergroup cg;
cover_point_y : coverpoint y {
bins a = {0,1};
bins b = {2,3}; In the above example, bins
bins c = {4,5}; are created explicitly. The
bins d = {6,7}; } bins are named a,b,c and d.
endgroup
cg cg_inst = new();
initial
foreach(values[i])
begin y = values[i];
cg_inst.sample();
end 29
endprogram 8
Semi Design
// simulation result
Coverage report:
-------------------
VARIABLE : cover_point_y
Expected : 4
Covered : 3
Percent: 75.00
Uncovered bins
--------------------
a
Covered bins
--------------------
b
c
d
29
9
Array Of Bins: Semi Design
To create a separate bin for each value (an array of bins) the square brackets, [], must
follow the bin name.
// Example:
program main;
bit [0:2] y;
bit [0:2] values[$] = '{3,5,6};
covergroup cg;
cover_point_y : coverpoint y{
bins a[] = {[0:7]}; In the above example, bin a
} is array of 8 bins and each
endgroup bin associates to one number
cg cg_inst = new(); between 0 to 7.
initial foreach(values[i])
begin
y = values[i];
cg_inst.sample();
end 30
endprogram 0
Semi Design
// simulation result
Coverage report:
--------------------
VARIABLE :
cover_point_y
Expected : 8
Covered : 3
Percent: 37.50
Uncovered bins
-------------------
a_0
a_1
a_2
a_4
a_7
Covered bins
-------------------
a_3 a_5 a_6 30
1
To create a fixed number of bins for a set of values, a number can be Semi Design
specified inside the square brackets.
// Example:
program main;
bit [0:3] y;
bit [0:2] values[$] = '{3,5,6};
covergroup cg;
cover_point_y : coverpoint y { bins a[4] = {[0:7]}; }
endgroup
cg cg_inst = new();
initial
foreach(values[i]) In the above example, variable y is 4 bit width vector.
begin y = values[i]; Total possible values for this vector are 16. But in the
cg_inst.sample(); cover point bins, we have giving the interested range as 0
end to 7. So the coverage report is calculated over the range 0
endprogram to 7 only. In this example, we have shown the number
bins to be fixed to size 4.
30
2
Semi Design
// simulation result
Coverage report:
--------------------
VARIABLE : cover_point_y
Expected : 4
Covered : 3
Percent: 75.00
Uncovered bins
-------------------
a[0:1]
Covered bins
------------------
a[2:3]
a[4:5]
a[6:7]
30
3
Default Bin: Semi Design
The default specification defines a bin that is associated with none of the defined
value bins. The default bin catches the values of the coverage point that do not lie
within any of the defined bins. However, the coverage calculation for a coverage
point shall not take into account the coverage captured by the default bin.
// Example:
program main;
bit [0:3] y;
bit [0:2] values[$] = '{3,5,6};
covergroup cg;
cover_point_y : coverpoint y {
bins a[2] = {[0:4]};
bins d = default; }
endgroup
cg cg_inst = new(); In the above example, we have specified only 2 bins to
initial cover values from 0 to 4. Rest of values are covered in
foreach(values[i]) default bin d which is not using in calculating the
begin y = values[i]; coverage percentage. 30
cg_inst.sample(); 4
end endprogram
Semi Design
// simulation result
Coverage report:
--------------------
VARIABLE : cover_point_y
Expected : 2
Covered : 1
Percent: 50.00
Uncovered bins
------------------
a[0:1]
Covered bins
----------------
a[2:4]
Default bin
-----------------
d
30
5
Semi Design
Transition Bins
Transitional functional point bin is used to examine the legal transitions of a value.
SystemVerilog allows to specifies one or more sets of ordered value transitions of
the coverage point.
Type of Transitions:
• Single Value Transition
• Sequence Of Transitions
• Set Of Transitions
• Consecutive Repetitions
• Range Of Repetition
• Goto Repetition
• Non Consecutive Repetition
30
6
Single Value Transition: Semi Design
Single value transition is specified as:
value1 => value2
// Example:
program main;
bit [0:3] y;
bit [0:2] values[$] = '{3,5,6};
covergroup cg;
cover_point_y : coverpoint y {
bins tran_34 = (3=>4);
bins tran_56 = (5=>6);
}
endgroup
cg cg_inst = new();
initial In the above example, 2 bins are created for covering the
foreach(values[i]) transition of point "y" from 3 to 4 and other for 5 to 6.
begin The variable y is given the values and only the transition
y = values[i]; 5 to 6 is occurring. 30
cg_inst.sample(); 7
end endprogram
Semi Design
// simulation result
Coverage report:
--------------------
VARIABLE : cover_point_y
Expected : 2
Covered : 1
Percent: 50.00
Uncovered bins
------------------
tran_34
Covered bins
----------------
tran_56
30
8
Sequence Of Transitions: Semi Design
A sequence of transitions is represented as:
value1 => value3 => value4 => value5
// Example:
program main;
bit [0:3] y;
bit [0:2] values[$] = '{3,5,6};
covergroup cg;
cover_point_y : coverpoint y {
bins tran_345 = (3=>4>=5);
bins tran_356 = (3=>5=>6);
}
endgroup In this case, value1 is followed by value3, followed by
cg cg_inst = new(); value4 and followed by value5. A sequence can be of any
initial arbitrary length.
foreach(values[i]) In the above example, 2 bins re created for covering the
begin y = values[i]; transition of point "y" from 3 to 4 to 5 and other for 3 to 5 to
cg_inst.sample(); 6. The variable y is given the values and only the transition 3 30
end to 5 to 6 is occurring. 9
endprogram
Semi Design
// simulation result
Coverage report:
--------------------
VARIABLE : cover_point_y
Expected : 2
Covered : 1
Percent: 50.00
Uncovered bins
------------------
tran_345
Covered bins
----------------
tran_356
31
0
Set Of Transitions : Semi Design
A set of transitions can be specified as:
range_list1 => range_list2
// Example:
program main;
bit [0:3] y;
bit [0:2] values[$] = '{3,5,6};
covergroup cg;
cover_point_y : coverpoint y {
bins trans[] = (3,4=>5,6);
}
endgroup
cg cg_inst = new();
initial
foreach(values[i])
begin
y = values[i];
cg_inst.sample(); 311
end endprogram
Semi Design
// simulation result
Coverage report:
--------------------
VARIABLE : cover_point_y
Expected : 4
Covered : 1
Percent: 25.00
Uncovered bins
------------------
tran_34_to_56:3->6
tran_34_to_56:4->5
tran_34_to_56:4->6
Covered bins
----------------
tran_34_to_56:3->5
31
2
Consecutive Repetitions : Semi Design
Consecutive repetitions of transitions are specified using
trans_item [* repeat_range ]
// Example:
program main;
bit [0:3] y;
bit [0:2] values[$] = '{3,3,3,4,4};
covergroup cg;
cover_point_y : coverpoint y {
bins trans_3 = (3[*5]);
bins trans_4 = (4[*2]);
}
endgroup
cg cg_inst = new();
initial
foreach(values[i])
begin
y = values[i]; 31
cg_inst.sample(); 3
end endprogram
Semi Design
// simulation result
Coverage report:
--------------------
VARIABLE : cover_point_y
Expected : 2
Covered : 1
Percent: 50.00
Uncovered bins
------------------
trans_3
Covered bins
----------------
trans_4
31
4
Range Of Repetition: Semi Design
An example of a range of repetition is:
3 [* 3:5] is the same as 3=>3=>3, 3=>3=>3=>3, 3=>3=>3=>3=>3
// Example:
program main;
bit [0:3] y;
bit [0:2] values[$] = '{4,5,3,3,3,3,6,7};
covergroup cg;
cover_point_y : coverpoint y {
bins trans_3[] = (3[*3:5]);
}
endgroup
cg cg_inst = new();
initial
foreach(values[i])
begin
y = values[i];
cg_inst.sample(); 31
end 5
endprogram
Semi Design
// simulation result
Coverage report:
--------------------
VARIABLE : cover_point_y
Expected : 3
Covered : 1
Percent: 33.33
Uncovered bins
------------------
tran_3:3[*3]
tran_3:3[*5]
Covered bins
----------------
tran_3:3[*4]
31
6
Goto Repetition: Semi Design
The goto repetition is specified using: trans_item [-> repeat_range]. The required
number of occurrences of a particular value is specified by the repeat_range. Any
number of sample points can occur before the first occurrence of the specified
value and any number of sample points can occur between each occurrence of the
specified value. The transition following the goto repetition must immediately
follow the last occurrence of the repetition. For example: 3 [-> 3] is the same as
...=>3...=>3...=>3
31
7
Semi Design
// Example:
program main;
bit [0:3] y;
bit [0:2] values[$] = '{1,6,3,6,3,6,3,5};
covergroup cg;
cover_point_y : coverpoint y {
bins trans_3 = (1=>3[->3]=>5);
}
endgroup A goto repetition followed by an additional value is
cg cg_inst = new(); represented as follows: 1 => 3 [ -> 3] => 5 is the same as
initial 1...=>3...=>3...=>3 =>5
foreach(values[i])
// simulation result
begin y = values[i];
Coverage report:
cg_inst.sample();
--------------------
end
VARIABLE : cover_point_y
endprogram
Expected : 1
Covered : 1 31
8
Percent: 100.00
Non Consecutive Repetition: Semi Design
31
9
Semi Design
// Example:
program main;
bit [0:3] y;
bit [0:2] values[$] = '{1,6,3,6,3,6,5};
covergroup cg;
cover_point_y : coverpoint y {
bins trans_3 = (1=>3[=2]=>5);
}
A nonconsecutive repetition followed by an additional value
endgroup
is represented as follows:
cg cg_inst = new();
1 => 3 [=2] => 5 is the same as 1...=>3...=>3...=>5
initial
foreach(values[i]) // simulation result
begin Coverage report:
y = values[i]; --------------------
cg_inst.sample(); VARIABLE : cover_point_y
end Expected : 1
endprogram Covered : 1 32
Percent: 100.00 0
Semi Design
Wildcard Bins
By default, a value or transition bin definition can specify 4-state values. When a bin
definition includes an X or Z, it indicates that the bin count should only be
incremented when the sampled value has an X or Z in the same bit positions. The
wildcard bins definition causes all X, Z, or ? to be treated as wildcards for 0 or 1
(similar to the ==? operator).
For example:
// Example
wildcard bins g12_16 = { 4'b11?? };
The count of bin g12_16 is incremented when the sampled variable is between 12
and 16:
1100 1101 1110 1111
32
1
Semi Design
// Example:
program main;
reg [0:3] y;
reg [0:3] values[$] = '{ 4'b1100,4'b1101,4'b1110,4'b1111};
covergroup cg;
cover_point_y : coverpoint y {
wildcard bins g12_15 = { 4'b11?? } ;
}
endgroup // simulation result
cg cg_inst = new(); Coverage report:
initial --------------------
foreach(values[i]) VARIABLE : cover_point_y
begin Expected : 1
y = values[i]; Covered : 1
cg_inst.sample(); Percent: 100.00
end Covered bin
endprogram ---------------
g12_15 32
Number of times g12_15 hit : 4 2
Similarly, transition bins can define wildcard bins. For Semi Design
example:
// Example
wildcard bins T0_3 = (2'b0x => 2'b1x);
The count of transition bin T0_3 is incremented for the following transitions (as
if (0,1=>2,3)): 00 => 10 , 00 => 11, 01 => 10 , 01 => 11
32
3
Semi Design
// Example:
program main;
reg [0:1] y;
reg [0:1] values[$] = '{ 2'b00,2'b01,2'b10,2'b11};
covergroup cg;
cover_point_y : coverpoint y {
wildcard bins trans = (2'b0X => 2'b1X );
}
endgroup // simulation result
cg cg_inst = new(); Coverage report:
initial --------------------
foreach(values[i]) VARIABLE : cover_point_y
begin y = values[i]; Expected : 1
cg_inst.sample(); Covered : 1
end Percent: 100.00
endprogram Covered bin
---------------
trans Number of times trans hit : 1 (01 => 10) 32
4
Semi Design
Ignore Bins
A set of values or transitions associated with a coverage-point can be explicitly
excluded from coverage by specifying them as ignore bins.
32
5
Semi Design
// Example:
program main;
bit [0:2] y;
bit [0:2] values[$] = '{1,6,3,7,3,4,3,5};
covergroup cg;
cover_point_y : coverpoint y {
ignore_bins ig = {1,2,3,4,5};
}
endgroup
cg cg_inst = new();
initial
foreach(values[i])
begin y = values[i];
cg_inst.sample();
end
endprogram
32
6
Semi Design
// simulation result
Coverage report:
--------------------
VARIABLE : cover_point_y
Expected : 3 In the above program, total possible
Covered : 2 values for y are 0 to 7. Ignore_bins
Percent: 66.66 specified to Ignored values between 1 to
Uncovered bins 5. So the Expected values are 0,6 and 7.
------------------ Out of these expected values, only 6 and 7
auto[0] are generated.
Excluded/Illegal bins
-------------------------
auto[1] auto[2]
auto[3] auto[4]
auto[5]
Covered bins
–---------------
auto[6] auto[7] 32
7
Semi Design
Illegal Bins
A set of values or transitions associated with a coverage-point can be marked as
illegal by specifying them as illegal_bins. All values or transitions associated with
illegal bins are excluded from coverage. If an illegal value or transition occurs, a
runtime error is issued.
32
8
Semi Design
// Example:
program main;
bit [0:2] y;
bit [0:2] values[$] = '{1,6,3,7,3,4,3,5};
covergroup cg;
cover_point_y : coverpoint y {
illegal_bins ib = {7};
}
endgroup
cg cg_inst = new(); // simulation result
initial ------------
foreach(values[i]) ** ERROR **
begin Illegal state bin ib of coverpoint
y = values[i]; cover_point_y in covergroup cg got hit with
cg_inst.sample(); value 0x7
end
endprogram 32
9
Semi Design
Cross Coverage
Cross Coverage is specified between the cover points or variables. Cross coverage is
specified using the cross construct.
Cross allows keeping track of information which is received simultaneous on more
than one cover point.
Expressions cannot be used directly in a cross; a coverage point must be
explicitly defined first.
33
0
Cross coverage by cover_point name: Semi Design
// Example:
bit [3:0] a, b;
covergroup cg @(posedge clk);
c1: coverpoint a;
c2: coverpoint b;
c1Xc2: cross c1,c2;
endgroup : cg In the above example, each coverage
point has 16 bins, namely
auto[0]…auto[15]. The cross of a and b
Cross coverage by the variable name:
(labeled aXb), therefore, has 256 cross
// Example: products, and each cross product is a bin
bit [3:0] a, b; of aXb.
covergroup cov @(posedge clk);
aXb : cross a, b;
endgroup
33
1
Semi Design
Coverage Options
Coverage options control the behavior of the covergroup, coverpoint, and cross.
1. at_least
2. auto_bin_max
3. cross_auto_bin_max
33
2
Semi Design
1. at_least
A minimum number of hits for each bin. A bin with a hit count that is less than the
number is not considered covered. the default value is ‘1’.
2. auto_bin_max
A maximum number of automatically created bins when no bins are explicitly defined for
a coverpoint. the default value is ‘64’.
3. cross_auto_bin_max
A maximum number of automatically created cross product bins for a cross. there is no
default value, it is unbounded.
// Example:
covergroup cg @(posedge clk);
c1: coverpoint addr { option.auto_bin_max = 128;}
c2: coverpoint wr_rd { option.atleast = 2;}
c1Xc2: cross c1, c2 { option.cross_auto_bin_max = 128;}
endgroup : cg
33
3
Semi Design
Semi Design
Introduction
SystemVerilog adds features to specify assertions of a system. An assertion
specifies a behavior of the system. Assertions are primarily used to validate the
behavior of a design. In addition, assertions can be used to provide functional
coverage and generate input stimulus for validation.
The evaluation of the assertions is guaranteed to be equivalent between simulation,
which is event-based, and formal verification, which is cycle-based.
SystemVerilog allows assertions to communicate information to the test bench and
allows the test bench to react to the status of assertions without requiring a separate
application programming interface (API) of any kind
33
5
Semi Design
Advantages Of Assertion:
• Improving Observability.
• Reduces the debug time.
• Bugs can be found earlier and are more isolated.
• Controllable severity level.
• Can interact with C functions.
• Describe the Documentation and Specification of the design.
33
6
Semi Design
33
7
Immediate Assertions: Semi Design
// Syntax
label: assert(expression) action_block;
• The optional statement label (identifier and colon) creates a named block
around the assertion statement
• The action block is executed immediately after the evaluation of the assert
expression
• The action_block specifies what actions are taken upon success or failure of the
assertion
// action_block
pass_statement; else fail_statement;
33
8
Semi Design
• The pass statement is executed if the expression evaluates to true
• The statement associated with else is called a fail statement and is executed if the
expression evaluates to false
• Both pass and fail statements are optional
• Since the assertion is a statement that something must be true, the failure of an
assertion shall have a severity associated with it. By default, the severity of an
assertion failure is an error.
• Other severity levels can be specified by including one of the following severity
system tasks in the fail statement:
$fatal is a run-time fatal.
$error is a run-time error.
$warning is a run-time warning, which can be suppressed in a tool-specific
manner.
$info indicates that the assertion failure carries no specific severity.
• If an assertion fails and no else clause is specified, the tool shall, by default call
$error.
33
9
Semi Design
// Example:
always @(posedge clk) assert (a && b);
Condition (a && b) will be checked at every posedge of the clock, failure in the
condition leads to an assertion failure.
34
0
Concurrent Assertions: Semi Design
Concurrent assertions check the sequence of events spread over multiple clock
cycles.
• The concurrent assertion is evaluated only at the occurrence of a clock tick
• The test expression is evaluated at clock edges based on the sampled values of
the variables involved
• It can be placed in a procedural block, a module, an interface or a program
definition
// Example
c_assert: assert property(@(posedge clk) not(a && b));
The Keyword differentiates the immediate assertion from the concurrent assertion
is “property.”
34
1
Semi Design
Event Simulation
The Problem of race condition exists if the SVA is sampling the signals exactly at
specified event. So in SystemVerilog , the language has very clear semantics to avoid
race condition while evaluating SVA.
Updates to IEEE STD 1800-20051 divide the SystemVerilog time slot into 17
ordered regions, nine ordered regions for the execution of SystemVerilog
statements and eight ordered regions for the execution of PLI code. The purpose of
dividing a time slot into these ordered regions is to provide predictable interactions
between the design and testbench code.
34
2
Semi Design
Use of Event scheduling:
Every change in the state of a net or variable in the system description being
simulated is considered an update event. When an update event is executed, all
the processes that are sensitive to those events are considered for evaluation
known as an evaluation event.
Examples of processes include, initial, always, always_comb, always_latch,
and always_ff procedural blocks, continuous assignments, asynchronous tasks,
and procedural assignment statements.
A single time slot is divided into multiple regions where events can be
scheduled. This event scheduling supports obtaining clear and predictable
interactions that provide for the ordering of particular types of execution.
This allows properties and checkers to sample data when the design under test is in
a stable state. Property expressions can be safely evaluated, and testbenches can
react to both properties and checkers with zero delay, all in a predictable manner.
This same mechanism also allows for non-zero delays in the design, clock
propagation, and/or stimulus and response code to be mixed freely and consistently
with cycle-accurate descriptions. 34
3
Semi Design
34
4
Semi Design
Preponed region:
The values of variables that are used in concurrent assertions are sampled in the
Preponed region. (Evaluation is done at observed region). Preponed region is
executed only once in each time slot, immediately after advancing simulation time.
Pre-active region:
The Pre-active region is specifically for a PLI callback control point that allows for
user code to read and write values and create events before events in the Active
region are evaluated
Active region:
The Active region holds current events being evaluated and can be processed
in any order.
• Execute all module blocking assignments.
• Evaluate the Right-Hand-Side (RHS) of all nonblocking assignments and
schedule updates into the NBA region.
• Execute all module continuous assignments
34
• Evaluate inputs and update outputs of Verilog primitives. 5
• Execute the $display and $finish commands
Inactive region: Semi Design
The Inactive region holds the events to be evaluated after all the active events are
processed. In this region #0 blocking assignments are scheduled.
Pre-NBA region:
The Pre-NBA region is specifically for a PLI callback control point that allows for
user code to read and write values and create events before the events in the NBA
region are evaluated
Non-blocking Assignment Events region (NBA):
The principal function of this region is to execute the updates to the Left-Hand-Side
(LHS) variables that were scheduled in the Active region for all currently executing
non-blocking assignments.
Post-NBA region:
The Post-NBA region is specifically for a PLI callback control point that allows
for user code to read and write values and create events after the events in the
NBA region are evaluated 34
6
Observed region: Semi Design
The principal function of this region is to evaluate the concurrent assertions using the
values sampled in the Preponed region. A criterion behind this decision is that the
property evaluations must only occur once in any clock triggering time slot. During
the property evaluation, the pass/fail code shall be scheduled in the Reactive region
of the current time slot.
Post-observed region:
The Post-observed region is specifically for a PLI callback control point that allows
for user code to read values after properties are evaluated (in Observed or earlier
region).
Re-Inactive Events region:
In this region #0 blocking assignments in a program process are scheduled.
34
7
Semi Design
Reactive region:
The code specified in the program block, and pass/fail code from property
expressions, are scheduled in the Reactive region. The principal function of
this region is to evaluate and execute all current program activity in any order
Execute all program blocking assignments.
Execute the pass/fail code from concurrent assertions.
Evaluate the Right-Hand-Side (RHS) of all program non-blocking assignments
and schedule
Execute all program continuous assignments
Execute the $exit and implicit $exit commands
Postponed Region:
The principal function of this region is to execute the $strobe and $monitor
commands that will show the final updated values for the current time slot. This
region is also used to collect functional coverage for items that use strobe
sampling.
34
8
Semi Design
34
9
Semi Design
Assert property
Create Property
Create sequence
expressions
Create Boolean
Expressions
35
0
Boolean expressions: Semi Design
// Syntax
sequence name_of_sequence;
……
endsequence
Property:
A number of sequences can be combined logically or sequentially to create more
complex sequences. SVA provides a keyword to represent these complex 35
sequential behaviors called “property”. 1
Semi Design
// Syntax
property name_of_property;
test expression or
complex sequence expressions
endproperty
Assert:
The property is the one that is verified during a simulation. It has to be asserted to
take effect during a simulation. SVA provides a keyword called “assert” to check
the property.
// Syntax
assertion_ name: assert_property( property_name );
35
2
Semi Design
SVA Sequence
Boolean expression events that evaluate over a period of time involving
single/multiple clock cycles. SVA provides a keyword to represent these events called
“sequence”.
Boolean logic doenot have the concept of time. Temporal logic is boolean logic with
time as one more dimention. Sequence allows us to define temporal nature of the
signals using temporal expressions. Sequences can be composed by concatenation,
analogous to a concatenation of lists. The concatenation specifies a delay, using ##,
from the end of the first sequence until the beginning of the second sequence. ##
indicates cycle delay.
35
3
SVA Sequence example: Semi Design
In the below example the sequence seq_1 checks that the signal “a” is high on every
positive edge of the clock. If the signal “a” is not high on any positive clock edge,
the assertion will fail.
// Example
sequence seq_1;
@(posedge clk) a==1;
endsequence
35
4
Semi Design
Sequences with timing relationship:
Fixed Delay:
In SVA, clock cycle delays are represented by a “##” sign. For example, ##2 means 2
clock cycles.
Below sequence checks for the signal “a” being high on a given positive edge of the
clock. If the signal “a” is not high, then the sequence fails. If signal “a” is high on any
given positive edge of the clock, the signal “b” should be high 2 clock cycles after
that. If signal “b” is not asserted after 2 clock cycles, the assertion fails.
// Example
sequence seq;
@(posedge clk) a ##2 b;
endsequence
35
5
Semi Design
35
6
Semi Design
Zero Delay:
The delay ##0 indicates that the beginning of the second sequence is at the same clock
tick as the end of the first sequence. This can also be archived using boolean expressions
&& .
// Example
sequence seq;
@(posedge clk) sig1 ##0 sig2;
endsequence
This specifies that sig1 shall be true on the current clock tick, and sig2 shall be
true on the same clock tick.
35
7
Semi Design
Properties
A property defines a behavior of the design. A property can be used for verification as
an assumption, a checker, or a coverage specification. Sequences are often used to
construct properties. usage of sequences in properties brakes down the complexity.
Sequence can be reused across various properties.
A property can be declared in any of the following:
A module
An interface
A program
A clocking block
A package
A compilation-unit scope
35
8
Semi Design
Properties constructs:
1. Disable iff
2. Implication (if ..else)
3. overlapping implication (|->)
4. Non overlapping implication(||->)
1. Disable iff:
In certain design conditions, we don’t want to proceed with the check if some
condition is true. this can be achieved by using disable iff.
Below property checks that, if the signal “a” is high on given posedge of the
clock, the signal “b” should be high for 3 clock cycles followed by “c” should
be high after ”b” is high for the third time. During this entire sequence, if
reset is detected high at any point, the checker will stop.
35
9
Semi Design
// Example
property p;
@(posedge clk)
disable iff (reset) a |-> ##1 b[->3] ##1 c;
endproperty
a: assert property(p);
// Example
property p(bit x, bit y);
##1 x |-> ##[2:10] y;
//antecedent |-> consequent
endproperty
The left-hand operand sequence_expr is called the antecedent, while the right-hand
operand property_expr is called the consequent. if antecedent is false, then
consequent is not cared and property is considered as vacuous success. if 36
antecedent is True and if consequent is false then property is considered as false. if 0
antecedent is True and if consequent is true then property is considered as true.
Semi Design
Overlap Implication:
Consequent expression is evaluated on the same clock of antecedent.
// Example
a |-> b
36
1
Semi Design
Non Overlapping Implication :
Consequent expression is evaluated on the next clock of antecedent
// Example
a ||-> b
36
2
Assertion Control System Tasks: Semi Design
$assertoff : It shall stop the checking of all specified assertions until a subsequent
$asserton. An assertion that is already executing, including execution of the pass or
fail statement, is not affected.
$asserton: It shall reenable the execution of all specified assertions. When invoked
with no arguments, the system task shall apply to all assertions. When the task is
specified with arguments, the first argument indicates levels of the hierarchy,
consistent with the corresponding argument to the Verilog $dumpvars system task.
Subsequent arguments specify which scopes of the model to control. These
arguments can specify entire modules or individual assertions.
36
3
Semi Design
Boolean System Function:
DPI C++
From long time , Users have needes a simple way of communication to foreign
languages from verilog. VPI and PLI are not easy interfaces to Use . Users need
detailed knowledge of PLI and VPI even for a simple program. Most of the time, users
do not need the sophisticated capabilities of VPI and PLI. DPI also permits C/C++
code to wait for Verilog events and C/C++ tasks and functions can be disabledfrom
SystemVerilog. SystemVerilog introduces a new foreign language interface called the
Direct Programming Interface (DPI).
The DPI provides a very simple, straightforward, and efficient way to connect
SystemVerilog and foreign language code unlike PLI or VPI.
36
6
Semi Design
DPI developed based on the donations from Synopsys "DirectC interface". DPI
consists of two separate layers: the SystemVerilog layer and a foreign language layer.
Both sides of DPI-C are fully isolated. Which programming language is actually used
as the foreign language is transparent and irrelevant for the System-Verilog side of
this interface. Neither the SystemVerilog compiler nor the foreign language compiler
is required to analyze the source code in the others language.
SystemVerilog DPI (Direct Programming Interface) is an interface which can be
used to interface SystemVerilog with foreign languages. These Foreign languages
can be C, C++, SystemC as well as others.
DPI allows the user to easily call functions of other language from SystemVerilog
and to export SystemVerilog functions, so that they can be called in other languages.
Advantage of DPI is, it allows to make use of the code exists in other languages.
36
7
Semi Design
DPI Import and export methods:
Import Method:
Export methods:
36
8
DPI Declaration: Semi Design
Import Declaration:
// Example
import “DPI-C” function int calc_parity (input int a);
Export Declaration:
// Example
export “DPI-C” my_cfunction = function myfunction;
36
9
SystemVerilog DPI Example: Semi Design
// Example
// SystemVerilog File
module dpi_tb;
export "DPI-C" function sv_method;
import "DPI-C" context function void c_method();
initial
begin
$display("Before calling C Method"); // C++ file
c_method(); #include stdio.h
$display("After calling C Method"); #include iostream
end #include svdpi.h
function void sv_method(); using namespace std;
$display(" [SV-Prog] Hello World...!"); extern "C" void sv_method();
endfunction extern "C" void c_method() {
endmodule printf(" [C-Prog] Hello World...!\n");
sv_method();
} 37
1
Semi Design
// simulation result
Before calling C Method
[C-Prog] Hello World...!
[SV-Prog] Hello World...!
After calling C Method
37
2
Semi Design
Semi Design
Test bench
Testbench or Verification Environment is used to check the functional
correctness of the Design Under Test (DUT) by generating and driving a
predefined input sequence to a design, capturing the design output and comparing
with-respect-to expected output.
37
4
Semi Design
interface
generator driver DUT
transaction
Scoreboard monitor
transaction
37
5
Semi Design
TestBench Components: Semi Design
2 :1 Multiplexer
a [0:1]
2 : 1 MUX out
DUT
reset
sel
37
9
Semi Design
Verilog programming for 2:1 Mux
module mux2_1(a0, a1, reset, sel, out);
input [2:0] a0, a1;
input reset, sel;
output reg [2:0]out;
always @ (*)
begin
if(!reset)
if(sel)
out = a1;
else
out = a0;
else
out = 3'd0;
end
endmodule 38
0
Semi Design
Getting started with test bench
Transaction Class:
• Fields required to generate the stimulus are declared in the transaction
class.
• Transaction class can also be used as a placeholder for the activity
monitored by the monitor on DUT signals.
• So, the first step is to declare the ‘Fields‘ in the transaction class.
• Below are the steps to write the transaction class.
38
1
Semi Design
class transaction;
38
2
Semi Design
Generator Class:
Generator class is responsible for,
• Generating the stimulus by randomizing the transaction class
• Sending the randomized class to driver
38
3
class generator; main task, generates(create and
randomizes) the repeat_count
rand transaction t1; number of transaction packets and
int repeat_count; puts into mailbox
endinterface
38
5
Driver Class: Semi Design
Receive the stimulus generated from the generator and drive to DUT by
assigning transaction class values to interface signals.
class driver;
38
6
task reset; Semi Design
wait(vir.reset);
$display("[Driver] ----- Reset Started -----"); task main;
vir.a0 <= 0; forever begin
vir.a1 <= 0; transaction t1;
vir.sel <= 0; g2d.get(t1);
wait(!vir.reset);
$display("[Driver] ----- Reset Ended -----"); vir.a0 <= t1.a0;
endtask vir.a1 <= t1.a1;
vir.sel <= t1.sel;
#1;
Adding a reset task, which t1.out = vir.out;
initializes the Interface
signals to default values. t1.display("<< Driver >>");
no_of_transactions++;
Adding a main task to drive end
the transaction packet to the endtask
interface signal. endclass
38
7
Semi Design
Monitor class:
• Samples the interface signals and converts the signal level activity to the
transaction level.
• Send the sampled transaction to Scoreboard via Mailbox.
• Below are the steps to write a monitor.
38
8
Semi Design
class monitor;
39
0
Semi Design
class scoreboard;
task main;
mailbox m2s; transaction t1;
int no_of_transactions; forever begin
m2s.get(t1);
function new(mailbox m2s); no_of_transactions++;
this.m2s = m2s; t1.display("[Scoreboard]");
endfunction if (((t1.sel) &&
(t1.out==t1.a1))|((!t1.sel) &&
(t1.out==t1.a0)))
Declaring the mailbox and variable to keep $display ("result correct");
count of transactions, connecting handle else $display ("result wrong");
through the constructor. end
endtask
logic to compare the received result with
the expected result endclass
39
1
Semi Design
Environment class:
Environment is container class contains Mailbox, Generator and Driver.
Creates the mailbox, generator and driver shares the mailbox handle across the
Generator and Driver.
39
2
class environment; Semi Design
generator g1;
driver d1;
monitor m1;
scoreboard s1;
mailbox g2d;
mailbox m2s; In Construct Method, Create
virtual intf vir; - Mailbox
function new(virtual intf vir); - Generator
this.vir = vir; - Driver
and pass the interface handle
g2d = new(); through the new() method.
m2s = new();
g1 = new(g2d);
d1 = new(vir, g2d);
m1 = new(vir, m2s);
39
s1 = new(m2s); 3
endfunction
Semi Design
task pre_test();
d1.reset();
endtask For better accessibility.
Generator and Driver activity can be divided and
task test(); controlled in three methods.
fork - pre_test() – Method to call Initialization. i.e, reset
g1.main(); method.
d1.main(); - test() – Method to call Stimulus Generation and
m1.main(); Stimulus Driving.
s1.main(); - post_test() – Method to wait the completion of
join_any generation and driving.
endtask
task post_test();
wait(g1.ended.triggered);
wait(g1.repeat_count == d1.no_of_transactions);
wait(g1.repeat_count == s1.no_of_transactions); 39
endtask 4
Semi Design
task run;
pre_test();
test();
post_test(); // not required
$finish; Add a run task to call the above methods.
endtask
endclass
39
5
Semi Design
Test:
Test code is written with the program block.
The test is responsible for,
• Creating the environment.
• Configuring the testbench i.e, setting the type and number of transactions to
be generated.
• Initiating the stimulus driving.
39
6
Semi Design
environment e1;
- Declare and Create an environment.
initial begin
- Configure the number of transactions to
e1 = new(i_i);
be generated
e1.g1.repeat_count = 10;
- Initiating the stimulus driving
e1.run();
end
endprogram
39
7
Semi Design
TestBench Top:
• This is the topmost file, which connects the DUT and TestBench.
• TestBench top consists of DUT, Test and Interface instances.
• The interface connects the DUT and TestBench.
39
8
Semi Design
`include "header.svh"
module testbench_top;
bit reset;
initial begin
reset = 1;
#5 reset = 0; - Declare and Generate the clock and reset.
end - Create Interface instance.
- Create Design Instance and Connect
intf i_i(reset); Interface signals.
test t1(i_i);
mux2_1
d1(.a0(i_i.a0),.a1(i_i.a1),.reset(i_i.reset),.se
l(i_i.sel),.out(i_i.out));
initial begin
$dumpfile("dump.vcd");
$dumpvars; 39
end 9
endmodule
Semi Design
Header.sv file
`include "interface.sv"
`include "transaction.sv"
`include "generator.sv" It includes all .sv files in header.sv
`include "driver.sv"
`include "monitor.sv"
`include "scoreboard.sv"
`include "environment.sv"
`include "random_test.sv"
40
0
Semi Design
// simulation result
[Driver] ----- Reset Started -----
[Driver] ----- Reset Ended -----
[Generator] # KERNEL: -------------------------
# KERNEL: ------------------------- # KERNEL: - Monitor
# KERNEL: - a0 = 3, a1 = 0, sel = 0 # KERNEL: -------------------------
# KERNEL: - out = 0 # KERNEL: - a0 = 2, a1 = 6, sel = 1
# KERNEL: ------------------------- # KERNEL: - out = 6
# KERNEL: ------------------------- # KERNEL: -------------------------
# KERNEL: - [Driver] # KERNEL: -------------------------
# KERNEL: ------------------------- # KERNEL: - [Scoreboard]
# KERNEL: - a0 = 2, a1 = 6, sel = 1 # KERNEL: -------------------------
# KERNEL: - out = 6 # KERNEL: - a0 = 2, a1 = 6, sel = 1
# KERNEL: ------------------------- # KERNEL: - out = 6
# KERNEL: -------------------------
# KERNEL: result correct
# KERNEL: -------------------------
40
---- 1
Semi Design
SystemVerilog TestBench Example — D - Flipflop
Let’s Write the SystemVerilog TestBench for the simple design “D - Flipflop”.
Design specification:
D - Flipflop
Q
D D - FF
DUT
Qn
clock reset
40
2
Semi Design
Verilog programming for D - Flipflop
module d_ff(D, clk, reset, Q, Qn);
input D, clk, reset;
output reg Q;
output Qn;
assign Qn = ~ Q;
endmodule 40
3
Semi Design
Getting started with test bench
Transaction Class:
• Fields required to generate the stimulus are declared in the transaction
class.
• Transaction class can also be used as a placeholder for the activity
monitored by the monitor on DUT signals.
• So, the first step is to declare the ‘Fields‘ in the transaction class.
• Below are the steps to write the transaction class.
40
4
Semi Design
class transaction;
rand bit D;
bit Q, Qn;
40
6
Semi Design
class generator;
transaction t1,t2;
40
7
Semi Design
function new(mailbox g2d,event ended);
this.g2d = g2d;
t1=new();
this.ended=ended;
endfunction
task main();
repeat (repeat_count)
begin main task, generates(create and
if (t1.randomize()) randomizes) the repeat_count
begin number of transaction packets and
t1.display("<< Generator >>"); puts into mailbox
t2 = t1.do_copy;
g2d.put(t2);
end else
$fatal("Gen:: trans randomization failed");
end
-> ended; 40
endtask 8
endclass
interface intf(input logic clk, reset); Semi Design
logic D;
logic Q;
logic Qn;
Receive the stimulus generated from the generator and drive to DUT by
assigning transaction class values to interface signals.
mailbox g2d;
41
2
Semi Design
`define MON v_i.cb_m.cb
class monitor;
41
4
Semi Design
class scoreboard;
41
5
Semi Design
Environment class:
Environment is container class contains Mailbox, Generator and Driver.
Creates the mailbox, generator and driver shares the mailbox handle across the
Generator and Driver.
41
6
class environment; Semi Design
generator g1;
driver d1;
monitor m1;
scoreboard s1;
mailbox g2d;
mailbox m2s; In Construct Method, Create
virtual intf vir; - Mailbox
function new(virtual intf vir); - Generator
this.vir = vir; - Driver
and pass the interface handle
g2d = new(); through the new() method.
m2s = new();
g1 = new(g2d);
d1 = new(vir, g2d);
m1 = new(vir, m2s);
41
s1 = new(m2s); 7
endfunction
Semi Design
task pre_test();
d1.reset();
endtask For better accessibility.
Generator and Driver activity can be divided and
task test(); controlled in three methods.
fork - pre_test() – Method to call Initialization. i.e, reset
g1.main(); method.
d1.main(); - test() – Method to call Stimulus Generation and
m1.main(); Stimulus Driving.
s1.main(); - post_test() – Method to wait the completion of
join_any generation and driving.
endtask
task post_test();
wait(g1.ended.triggered);
wait(g1.repeat_count == d1.no_of_transactions);
wait(g1.repeat_count == s1.no_of_transactions); 41
endtask 8
Semi Design
task run;
pre_test();
test();
post_test(); // not required
$finish; Add a run task to call the above methods.
endtask
endclass
41
9
Semi Design
Test:
Test code is written with the program block.
The test is responsible for,
• Creating the environment.
• Configuring the testbench i.e, setting the type and number of transactions to
be generated.
• Initiating the stimulus driving.
42
0
Semi Design
environment e1;
- Declare and Create an environment.
initial begin
- Configure the number of transactions to
e1 = new(i_i);
be generated
e1.g1.repeat_count = 10;
- Initiating the stimulus driving
e1.run();
end
endprogram
42
1
Semi Design
TestBench Top:
• This is the topmost file, which connects the DUT and TestBench.
• TestBench top consists of DUT, Test and Interface instances.
• The interface connects the DUT and TestBench.
42
2
Semi Design
`include "header.svh"
module testbench_top; - Declare and Generate the clock and reset.
- Create Interface instance.
bit clk; - Create Design Instance and Connect
bit reset; Interface signals.
`include "interface.sv"
`include "transaction.sv"
`include "generator.sv" It includes all .sv files in header.sv
`include "driver.sv"
`include "monitor.sv"
`include "scoreboard.sv"
`include "environment.sv"
`include "random_test.sv"
42
4
Semi Design
// simulation result
# KERNEL: << Driver >>
# KERNEL: ---- Reset started ----
# KERNEL: << Driver >>
# KERNEL: ---- Reset ended ----
# KERNEL: - << Monitor >>
# KERNEL: << Generator >>
# KERNEL: -------------------------
# KERNEL: -------------------------
# KERNEL: - D = 1
# KERNEL: - D = 1
# KERNEL: - Q = 1, Qn = 0
# KERNEL: - Q = 0, Qn = 0
# KERNEL: -------------------------
# KERNEL: -------------------------
# KERNEL: -------------------------
# KERNEL: - << Driver >>
# KERNEL: - << scoreboard >>
# KERNEL: -------------------------
# KERNEL: -------------------------
# KERNEL: - D = 1
# KERNEL: - D = 1
# KERNEL: - Q = 1, Qn = 0
# KERNEL: - Q = 1, Qn = 0
# KERNEL: -------------------------
# KERNEL: -------------------------
# KERNEL: result correct
# KERNEL: ------------------------- 42
5