0% found this document useful (0 votes)
33 views129 pages

By SCVN Reddy

Uploaded by

Juyaal Premises
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
33 views129 pages

By SCVN Reddy

Uploaded by

Juyaal Premises
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 129

RTL TO GDS

Article-21
System Verilog
(For Design Verification)

Semiconductor
Industry

Written By-
DAY-51
SYSTEM VERILOG: REFERENCE GUIDE
#100DAYSRTL

What is System Verilog:-


• System Verilog is a combined hardware description language
and Hardware verification language
• System Verilog is an extensive set of enhancements to the
IEEE
• 1364 Verilog-2001 standards
• It has features inherited from Verilog HDL, VHDL, C, C++
History and Evolution of System Verilog:-
• Verilog (IEEE standard 1364)
✓ Began in 1983 as a proprietary language
✓ Opened to the public in 1992
✓ Became an IEEE standard in 1995 (updated in 2001 and
2005)
✓ Between 1983 and 2005 design sizes increased
dramatically
• System Verilog (IEEE standard 1800)
✓ Originally intended to be the 2005 update to Verilog
✓ Contains hundreds of enhancements and extensions to
Verilog
✓ Published in 2005 as a separate document
✓ Officially superseded Verilog in 2009
✓ Updated with more features in 2012 (IEE 1800 2012
standard)
Why is System Verilog:-

System Verilog-User View:-


System Verilog has 5 major parts
1. SVD – System Verilog for Design:-Features supporting
Design
2. SVTB – System Verilog for Test benches:- Test bench specific
Features
3. SVA – System Verilog Assertions:- Features for temporal and
concurrent assertions
4. SVDPI – SV Direct Programming Interface:- For better
C/C++ Integration
5. SVAPI – SV Application Programming Interface:-For better
Coverage/Assertion integration
Verilog Vs System Verilog :-

Why not VHDL ? :-


VHDL Lacks
✓ Constrained Random Generation
✓ Functional Coverage
✓ Assertions
Specman E/Vera
✓ Used with VHDL and Verilog for Constrained Random
generation and Functional Coverage
PSL (Property Specification Language)
✓ Used for Assertions
▪ Learning 1 language (System Verilog) is better than learning 2
languages (Specman E/Vera and PSL)
System Verilog Testbench Architecture:-
DAY-52
#100DAYSRTL

Predefined Datatypes:-

• 2 Valued :- Digits : 0 or 1
• 4 Valued :- Digits : 0 or 1 or X or Z
Code Practising:-
• 2 Valued Data Type:-
4 Valued Data Type:-

Console:-
2 Valued Data Type:-

4 Valued Data Type:-

Integer Data Types:-

Signed/Unsigned Integers:-
• byte, shortint, int, integer and longint defaults to signed
▪ Use unsigned to represent unsigned integer value
Example: int unsigned a;
• bit, reg and logic defaults to unsigned
• To create vectors, use the following syntax:
✓ Eg:- logic [1:0] L; // Creates 2 bit logic vector
• To use these types as unsigned, user has to explicitly declare
it as unsigned.
✓ Eg:-int unsigned a;
String Data Types:-
• In Verilog, string literals are packed arrays of a width that is a
multiple of 8 bits which hold ASCII values.
• In Verilog, if a string is larger than the destination string
variable, the string is truncated to the left, and the leftmost
• characters will be lost.
• System Verilog adds new keyword "string" which is used to
declare string data types unlike verilog.
• String data types can be of arbitrary length and no truncation
occurs.
Code Practising:-

Console:-

; Default value :Null


User defined Datatypes:-
Systemverilog allows the user to define datatypes.
There are different ways to define user defined datatypes.
1. Class
2. Enumarations.
3. Struct
4. Union.
5. Typedef
DAY-53
#100DAYSRTL

String:-
• In Verilog, string literals are packed arrays of a width that is a
multiple of 8 bits that hold ASCII values.
• In Verilog, if a string is larger than the destination string
variable, the string is truncated to the left, and the leftmost
characters will be lost.
• System Verilog adds a new keyword "string" which is used to
declare string data types, unlike Verilog.
• System Verilog String data types can be of arbitrary length
and no truncation occurs.
Methods:-
1. str.len() :- returns the length of the string, i.e., the number of
characters in the string.
2. str.putc(i, c) :-replaces the ith character in str with the given
integral value.
3. str.getc(i) :-returns the ASCII code of the ith character in str.
4. str.toupper() :-returns a string with characters in str
converted to uppercase.
5. str.tolower() :-returns a string with characters in str converted
to lowercase.
6. str.compare(s) :-compares str and s, and returns a value. This
comparison is case-sensitive.
7. str.icompare(s) :-compares str and s, and returns a value.
This comparison is case-insensitive.
8. str.substr(i, j) :-returns a new string that is a substring
formed by index i through j of str.
9. str.atoi() :-returns the integer corresponding to the ASCII
decimal representation in str
10. str.atoreal() :-returns the real number corresponding to the
ASCII decimal representation in str.
11. str.itoa(i) :-stores the ASCII decimal representation of i
into str (inverse of atoi).
12. str.hextoa(i) :-stores the ASCII hexadecimal representation
of i into str (inverse of atohex).
13. str.bintoa(i) :-stores the ASCII binary representation of i
into str (inverse of atobin).
14. str.realtoa(r) :-stores the ASCII real representation of r into
str (inverse of atoreal).
Code Practising:-
Result:-
DAY-54
#100DAYSRTL

Enumerations:-
• Need for variables that have a limited set of possible values
that can be usually referred to by name.
• There's a specific facility, called an enumeration in System
Verilog .
• Enumerated data types assign a symbolic name to each legal
value taken by the data type.
Syntax:-
▪ enum <data-type> {<elements>} <name>;
▪ enum {IDLE, SETUP, ACCESS} state; // example 1
▪ enum bit[1:0] {IDLE, SETUP, ACCESS} state; // example 2
In the above example, the Enum type state has 3
elements, IDLE, SETUP and ACCESS. By default, the first
element is Enum gets the value of 0 and the value increments for
other following elements. Values can be manually assigned to
Enum elements as shown below. If the value is only defined for
the first element, the following elements get incremented value
unless otherwise stated
Eg:-
▪ enum {IDLE=6, SETUP, ACCESS} state; // example 3 - IDLE=6, SETUP=7, ACCESS=8
▪ enum {IDLE=6, SETUP=9, ACCESS} state; // example 3 - IDLE=6, SETUP=9, ACCESS=10
▪ enum {IDLE=6, SETUP=9, ACCESS=14} state; // example 4 -IDLE=6,SETUP=9, ACCESS=14
Some other important points:-
1. Enums can be used as a data type only when the typedef
keyword is used to define the enum. Otherwise, it’s a simple
variable.
2. Elements defined inside Enum can be referenced directly. It
will return the value that it holds.
3. Elements having the same name cannot be defined inside 2
different enums. It is because the element of an enum has
visibility in the entire block inside which the enum is defined.
▪ enum bit[2:0] { RED , BLUE } color_1;
▪ enum bit[2:0] { RED , GREEN } color_2; // Will show error
▪ enum bit[2:0] { VOILET , GREEN } color_2; // Will work fine
If the value for an element is not mentioned explicitly it will
automatically take the incremented value of the previous element
for which the value is mentioned.
Methods:-
Enum provides various in-built system functions that can be
used to iterate within elements of the Enum. Let’s see these in-
built functions in detail.
1. first() – return the value of the first element of the Enum
2. last() – returns the value of the last element of the Enum
3. prev(int N) – returns the value of the Nth element before the
current element of Enum
4. next(int N) – returns the value of the Nth element after the
current element of Enum
5. num() – returns the number of element in the Enum
6. name() – returns the name of the element
Code Practising:-
Enum using Typedef:-
Result:-

Enum without Typedef:-

Result:-
DAY-55
#100DAYSRTL

Introduction:-
Structures and unions are special data types
which are used to group variables having different data types. We
have seen that arrays also provide the grouping of various
variables or elements. But in arrays, the data type of each element
is the same, whereas structure and unions can have elements
having different data types
Structure:-
A structure is a collection of elements having
different data types. These elements can be accessed as a whole
or individually. Like Enums these can be used to make user-
defined data types. When a structure is declared, the memory is
allocated for all the elements.
Syntax:-
<typedef> struct { <element1>; <element2>; ... } <name>;
Code practising :-
Result:-

Like the arrays, a structure can also be packed or


unpacked. This concept of a packed and unpacked structure is
exclusive to System Verilog. All structures are by default
unpacked in nature.
Code practising :-

Result:-

Packed Vs Unpacked Stracture:-

In a packed structure, we can only use a packed


data type. For example, a string cannot be used inside a packed
structure. Also, all array types except a packed array cannot be
used inside the packed address
Union:-
Unions are like structures, but in a union, we can only
access one element at a time. When unions are declared the
memory is allocated only for the largest data type.
Syntax:-
<typedef> union { <element1>; <element2>; ... } <name>;
Code practising :-

Result:-

Structure vs Union:-

Unions can also be declared as packed, but in the


packed union, all the elements should be of the same size. I do
not find packed union useful as all members have the same size
and also store the same value at a given time. Thus, a packed
union can be replaced with a simple data type variable.
Tagged Unions:-
We have seen that the unions in System Verilog
are not very useful as the value changed for one variable is
reflected in other variables defined inside the union. System
Verilog introduced a new concept of tagged unions. In a tagged
union, we can assign a tag to a particular variable of any data
type. Using this tag we can know that union is currently used to
store which variable. This is useful when we want to have a
packet that can store different values at different times
Syntax:-
<typedef>union tagged{<element1>;<element2>;.. }<name>;
DAY-56
#100DAYSRTL

Introduction:-
In Verilog, we have seen that only static arrays
can be created. Static arrays have a major drawback as the size of
the arrays once defined cannot be changed. This wasted a lot of
memory space as at times the entire size of the array is not used.
Dynamic arrays were introduced in the System Verilog along
with a few other array constructs like associative arrays and
queues.
Packed Array:-
Packed arrays can be considered as a single
dimensional memory, in which the index i represents the ith bit
of the memory. Packed arrays can only be used with data types
having width of one bit, i.e., only logic, bit, reg can be used. Any
other data type cannot be used.

In the figure below, we see that all the data are closely packed
with each address or index having one bit data. Thus, we cannot
use multiple bits data type such as int, byte, etc to declare a
packed array.
Syntax:-
bit [<index of MSB>:<index of LSB>] <identifier>;
Multidimensional Packed Arrays:-
In System Verilog, packed arrays can be of multiple dimensions.
Multiple dimensions should not be confused with the physical
layout. Physically it will be single dimension only

So, multi-dimensional packed array just means that the single


block of 1-D memory is split into different blocks inside the
simulator. This can be beneficial when the size of packed array is
large.
Code Practising:-

Result:-
Unpacked Arrays:-
Unpacked arrays can be considered as a 2-dimensional memory.
A 2 -dimensional memory means that each address of the
memory can hold one or more than one bits of data, i.e., there is
a width of memory. In simpler terms, it is the same type of array
we are acquainted with in other programming language like C or
Java. Unpacked arrays can be used with any data types, even 1bit
data types.

Syntax:-
bit <identifier> [<index of MSB>:<index of LSB>];
Multidimensional UnPacked Arrays:-
Just as the packed array, unpacked arrays can also be of multiple
dimensions. Again, physically it can be visualized as 2-
dimensional matrix which is split in various blocks

Array slicing and Assignment:-


Array slicing is the same as that of the packed arrays.
While assigning unpacked arrays, we must keep in mind that each
index will hold certain number of bits and the assignment should
be made keeping in that mind.We use loops or ‘{} operator to
assign elements to an unpacked array. Loops will be discussed
later, thus that method will be explained in future articles. In this
article we will focus on the operator method. ‘{} represents a
element thus for arrays of multiple dimension, the ‘{} operator is
nested within the same operator.
Code Practising:-

Result:-
Mixed Arrays:-
Mixed arrays are the combination of packed and unpacked array.
In most of the cases it will not be possible to use the inbuilt data
types for array creation. In these cases, we can combine both the
types in single array.

Code Practising:-

Result:-
DAY-57
#100DAYSRTL

Introduction:-
An array is several memory addresses grouped. Thus, before
entering the data into the array, the size of the array needs to be
defined so that the compiler knows how much memory it needs
to allocate. But in the case of the dynamic array the size of the
array is known only during the run time. This makes it very hard
for the simulator to assign continuous memory addresses.
Static Arrays:-
In static arrays, the size of the array is known in the compilation
time. This makes it possible for the simulator to ensure that a
continuous chunk of memory is allocated for the arrays. Also, as
the size is defined in the compile-time, it is not possible to change
the size of the array later on during run-time. Thus these are
known as static arrays.
Syntax:-
• <datatype> [<packed_arr_size>] <identifier> [<unpacked_arr_sizes>]
• <datatype> <identifier> [<unpacked_arr_sizes>]
Code Practising:-
Result:-

Dynamic Arrays:-
In dynamic arrays, the size of the array is known only in the run-
time, which makes it difficult for the simulator to ensure that a
continuous chunk of memory is allocated to the array. The size of
the array can be easily changed during the run time thus giving it
the name dynamic arrays
Syntax:-
• <datatype> <identifier>[] = ‘{<elements of array>};
• <datatype> <identifier>[];
• <identifier>[] = new [<size of array>];
Note :-
Packed array can not be a dynamic array. As discussed earlier
packed arrays must have a continuous memory chunk which is
not ensured in dynamic arrays. Also if a mixed array is declared
only the unpacked part of the array can be dynamic.
▪ bit [] arr ; // illegal.
▪ bit [7:0] arr[]; //Legal
Code Practising:-
Result:-

Static Vs Dynamic Array:-


DAY-58
#100DAYSRTL

Introduction:-
Associative arrays are an extension of dynamic arrays which
provide more flexibility in the way in which data can be stored.
In associative arrays, the index can be of any data type including
strings which makes it very beneficial for certain scenarios.
Associative Arrays:-
• Associative arrays are a special type of dynamic arrays in
which the memory is not allocated immediately when the array
is declared. Instead, the memory is allocated as and when data
is stored in the array. As the memory is not allocated
immediately the allocated memory is not continuous, which
makes it slower than dynamic arrays.
• This can be compared to key: value pairs in another language.
The index can be used as a key to get the value stored. The
index can be referred to as a key to get the value stored.
• Also, the key data type should not necessarily be an int, but it
can be any data type including string or real
Syntax:-
• [value datatype] [arr_name] [index datatype];
Code Practising:-
Result:-

Important Note:-
Associative arrays are very useful when we want to model
memories on the test bench.
This is because memories are arrays having a large number of
elements. If the dynamic array is used, then the memory will be
allocated immediately after the array is defined which can lead to
system failures. In an associative array, the memory will be
allocated only when some value is stored in a particular key.
Thus the memory requirement in the associative array will be on
a need basis
Methods:-
1. int num() - returns the number of values or entries stored in
the associative array.
2. int size () - Also returns the number of values stored in the
associative array. Returns 0 for empty array
3. int delete([key]) - If the key is passed to this function then the
value associated with the key is deleted. If no key is provided,
then it deletes the entire array.
4. int exists(key) - checks whether a value is associated with the
given key or not. If no value is present, it returns 0.
5. int first (ref key) - assigns the key variable passed with the
first key of the associative array. If the array is empty 0 is
returned
6. int last(ref key) - assigns the key variable passed with the last
key of the associative array. If the array is empty 0 is returned.
7. int next(ref key) - assigns the key variable passed with the
key which comes just after the specified key. If the array is
empty or if the specified key is last, 0 is returned.
8. int prev(ref key) - assigns the key variable passed with the
key which comes just before the specified key. If the array is
empty or if the specified key is first, 0 is returned.
Code Practising:-

Result:-
Dynamic Array inside Associative Array :-
Code Practising:-

Result:-

Associative Array inside Dynamic Array :-


Code Practising:-

Result:-
DAY-59
#100DAYSRTL

Introduction:-
The queue is a special data type in System Verilog that works on
the principle of FIFO (First in First Out). Thus, the element that
is stored first in the queue is retrieved first, just as the case in the
real-life queue.
Queues:-
• Queues are based on the concept of a linked list in which the
elements consist of 2 parts. 1st part is the value that needs to
be stored, and the 2nd part is the address of the next element of
the list. If the element is the last one, then the 2nd part is null
otherwise it points to the next item.
• Queue in system Verilog, handles all the address-related
operations internally which makes using queue a lot easier.
Queue like an associative array has no specific size and the size
grows and shrinks dynamically depending upon the number of
elements stored. But in queues, the index is continuous in
nature, unlike the associative arrays.
Concept of push and pop:-
• As discussed, queues work on the concept of FIFO, i.e., first in
first out. This means that a new element can be added at the
end of the queue. Also, the element which is first in queue
means that it was inserted earlier than other elements and thus
this element will be removed from the queue first.
• Push in queue means inserting a new element at the end of the
queue.
• Pop in queue means getting the first element present in the
queue and removing it from the queue.

Syntax:-
• <element datatype> <queue_name> [$];
Code Practising:-

Result:-

Important Note:-
Using the $symbol for adding new elements in the queue may not
produce the same result in different simulators. Thus, it is
recommended to use the built-in functions to add or remove
elements from a queue so that the output is the same on all
simulators.
Methods:-
1. int size() - returns the number of elements present in the
queue.
2. element_t pop_front() - returns the first element present in
the queue and deletes it.
3. element_t pop_back() - returns the last element present in the
queue and deletes it.
4. void push_front(element_t item) - Inserts the item in the first
position of the queue. Index of all other item shifts by 1.
5. void push_back() - inserts the item in the last position of the
queue. All other items present in the queue are unaffected.
6. void insert(int index, element_t item) - inserts the item in the
specified index.
7. void delete([int index]) - if index is provided as input, it
deletes the item present in specific index otherwise it delete
the entire queue.
Code Practising:-

Result:-
Example:-
• Let’s suppose there is a process that samples data and sends it
to the processing unit. It is not necessary that the data sent by
the sampling unit would be processed immediately.
• In this scenario we don’t know exactly how many elements we
need to store thus dynamic array is not a good option. Also, an
associative array is not good for this scenario as we don’t need
the elements after the element has been processed. In the case
of an associative array, the size will increase, and it is slower.
• Thus, queues are the best option for this scenario as the
sampling unit can push data once it has sampled it and the
processing unit can pop it whenever it can process the data.
Code Practising:-

Result:-
DAY-60
#100DAYSRTL

Introduction:-
The queue is a special data type in System Verilog that works on
the principle of FIFO (First in First Out). Thus, the element that
is stored first in the queue is retrieved first, just as in the case of
the real-life queue.
With Keyword:-
Basically, with keyword is used to pass a condition. This keyword
is used with a function to put some constraint for the argument
that we are passing as the function. These keywords are not only
used with the array manipulation functions but also with some
other constructs which we will see later in this series.
Syntax:-
function_name([argument]) with ([argument condition]);
Ordering Functions:-
1. reverse():-This function reverses the order of the array. This
means that the first element will be shifted to the last position
and the last element will come to the first position.
2. sort():-This function sorts the array in the ascending order.
This can be used in conjunction with the keyword.
3. rsort():-This function sorts the array in descending order. This
also supports the keyword optionally.
4. shuffle():-Randomly changes the order of the elements present
in the array.
Note:- We cannot use the keyword with reverse and shuffle functions.
Code practicing:-

Result:-

Searching Functions:-
find():-This function returns all the elements which satisfy a given
condition.
find_index():-Returns the index of all the elements which satisfy
a given condition. This is somewhat similar to find() but returns
the index instead of actual elements.
find_first():-returns the first element which satisfies the given
condition.
find_first_index():-returns the index of the first element which
satisfies the given condition.
find_last():-returns the last element that satisfies the given
condition.
find_last_index():-returns the index of the last element which
satisfies the given condition.
Note:- The “with” clause is important with all these functions.
Code practicing:-

Result:-

Some Other functions:-


1. min():-Returns the smallest value of the array
2. max():-Returns the largest value of the array
3. unique():-Returns the array in which all the duplicate values are
removed.
4. unique_index():-Return the array of indices that contains a
unique value.
5. sum():-Returns the sum of all array elements
6. product():-Returns the product of all array elements
7. and():-Returns the bitwise AND (&) of all array elements
8. or():-Returns the bitwise OR (|) of all array elements
9. xor():-Returns the bitwise XOR (^) of all array elements
Code practicing:-

Result:-
Result:-
DAY-61
#100DAYSRTL

“Introduction”:-
• Improperly coded Verilog case statements can frequently cause
unintended synthesis optimizations or unintended latches.
These problems, if not caught in pre-silicon simulations or gate-
level simulations, can easily lead to a non-functional chip. The
new System Verilog unique and priority keywords are designed
to address these coding traps.
• The System Verilog unique and priority modifiers are placed
before an if, case, casez, casex.
• With the if…else statement, the System Verilog unique or
priority keyword is placed only before the first if but affects all
subsequent else if and else statements.
“Unique”:-
Unique causes a simulator to add run-time checks that will report
a warning if any of the following conditions are true:
1. More than one if/case item matches the case expression
2. No if/case item matches the case expression, and there is no
default case/else
Firstly, by adding the System Verilog unique keyword, the
designer asserts that only one case item can match at a time. the
unique keyword tells the tool that all valid case items have been
specified and can be evaluated in parallel. Synthesis is free to
optimize the case items that are not listed.
“Code Practising”:-
//

“Result”:-

“Code Practising”:-

“Result”:-

“Priority”:-
The priority keyword instructs all tools that support System
Verilog that each selection item in a series of decisions must be
evaluated in the order in which they are listed, and all legal cases
have been listed.
Unique causes a simulator to add run-time checks that will report
a warning if any of the following conditions are true:
1. If the case/if expression does not match any of the case/if item
expressions, and there is no default case/else
“Code Practising”:-

“Result”:-
“Code Practising”:-

“Result”:-
DAY-62
#100DAYSRTL

“Introduction”:-
Loops are statements that help to perform repetitive tasks by
writing them once. In testbench, loops are very important as we
must perform lots of repetitive tasks such as sampling a signal
after a certain duration. So, this sampling should happen
repeatedly until the simulation ends.
“Types Of loops”:-
1. Finite loop – this type of loop will repeat for certain number
until some conditions are not met. Once the condition evaluates
to be false it will move out of the loop and execute the
statements present after loop.
2. Infinite loop – this type of loop basically run for infinite
iterations or until the simulation ends. In this type of loops either
there is no condition evaluation, or the condition evaluates to
true every time. Infinite loops can be exited with the help of
break statement if required. Infinite loops should be used with
great care because using it in a wrong way can lead to
unexpected results or also hang the simulation.
“Forever”:-
This is an infinite loop, just like while (True) .
Note that your simulation will hang unless you include a time
delay inside the forever block to advance simulation time
Code practicing:-

Result:-

“Repeat”:-
Used to repeat statements in a block a certain number of times.
Code practicing:-

Result:-
“While”:-
It'll repeat the block as long as the condition is true
Code practicing:-

Result:-

“For Loop”:-

“For loop”:-
It'll repeat the block as long as the condition is true
Code practicing:-

Result:-

“For Loop”:-
“Do While”:-
Repeats the given set of statements at least once, and then loops
as long as the condition is true
Code practicing:-

Result:-

“Foreach”:-
Used mainly to iterate through all elements in an array
Code practicing:-

Result:-
DAY-63
#100DAYSRTL

“Introduction”:-
Often we find certain pieces of code to be repetitive and
called multiple times within the RTL. They mostly do not
consume simulation time and might involve complex
calculations that need to be done with different data values. In
such cases, we can declare a function/task place the repetitive
code inside the function/task, and allow it to return the result.
This will reduce the number of lines in the RTL drastically since
all you need to do now is to do a function call and pass the data
on which the computation needs to be performed.
“Function”:-
The purpose of a function is to return a value that is to be used
in an expression. A function definition always starts with the
keyword function followed by the return type, name, and port list
enclosed in parentheses. Verilog knows that a function definition
is over when it finds the end function keyword. Note that a
function shall have at least one input declared and the return type
will be void if the function does not return anything.
“Automatic Function”:-
The keyword automatic will make the function reuse and
items declared within the task are dynamically allocated rather
than shared between different invocations of the task.This will be
useful for recursive functions and when the same function is
executed concurrently by N process when forked.
“Declaration”:-

function [7:6] sum;

“Function Rules”:-
• A function cannot contain any time-controlled statements like
#, @, wait, posedge, negedge
• A function cannot start a task because it may consume
simulation time, but can call other functions
• A function should have at least one input
• A function cannot have non-blocking assignments or force-
release or assign-design
• A function cannot have any triggers
• A function cannot have an output or input
Code practicing:-

Result:-
“Recursive Functions”:-
Functions that call itself is called recursive function
Code practicing:-

Result:-

“Task”:-
A function is meant to do some processing on the input and
return a single value, whereas a task is more general and can
calculate multiple result values and return them using the output
and inout type arguments. Tasks can contain simulation time-
consuming elements such as @, posedge, and others.
“Declarations”:-
“Automatic Task”:-
The keyword automatic will make the task reentrant,
otherwise, it will be static by default. All items inside automatic
tasks are allocated dynamically for each invocation and not
shared between invocations of the same task running
concurrently. Note that automatic task items cannot be accessed
by hierarchical references.
“Static Task”:-
If a task is static, then all its member variables will be shared
across different invocations of the same task that has been
launched to run concurrently static, then all its member variables will be shared across diff
“Static vs Automatic”:-
• If the task is made automatic, each invocation of the task is
allocated a different space in simulation memory and behaves
differently.
• If the task is made static, each invocation of the task is
allocated a same space in simulation memory and behaves
identically
Code practising:-
Result:-

“Task rules”:-
• A task can contain time-controlled statements like #, @, wait,
posedge, negedge.
• A task can start a task.
• A task can have any number of inputs, outputs, and inout ports.
• A task can have non-blocking assignments, force-release, and
assign-design.
• A task can have any number of triggers.
• A task can have any number of outputs and inout ports.

“Function Vs Task”:-
DAY-64
#100DAYSRTL

“Introduction”:-
System Verilog enables versatile argument passing in
functions and tasks. It supports passing by value, reference, and
position, facilitating diverse data handling methods. Additionally,
it allows default argument values, offering flexibility. These
features empower efficient hardware description and verification
methodologies within System Verilog designs.
“Argument pass by value”:-
• The argument-passing mechanism works by copying each
argument into the subroutine area.
• If any changes to arguments within the subroutine, those
changes will not be visible outside the subroutine.
Code practicing:-

Result:-
“Argument pass by reference”:-
• In pass-by-reference, a reference to the original argument is
passed to the subroutine.
• As the argument within a subroutine is pointing to an original
argument, any changes to the argument within the subroutine
will be visible outside.
• To indicate argument pass by reference, the argument
declaration is preceded by keyword ref
Code practicing:-

Result:-

Note:-
Any modifications to the argument value in a pass-by-reference
can be avoided by using the const keyword before ref, any attempt
to change the argument value in the subroutine will lead to a
compilation error.
“Default Argument Values”:-
• The default value can be specified to the arguments of the
subroutine.
• In the subroutine call, arguments with a default value can be
omitted from the call.
• If any value is passed to an argument with a default value, then
the new value will be considered.
Code practicing:-

Result:-

“Argument pass by value”:-


In argument pass by name, arguments can be passed in any
order by specifying the name of the subroutine argument.
Code practicing:-

Result:-
DAY-65
#100DAYSRTL

“Introduction”:-
System Verilog provides support for parallel or concurrent
threads through fork-join construct. Multiple procedural blocks
can be spawned off at the same time using fork and join. There
are variations to fork-join that allow the main thread to continue
executing the rest of the statements based on when child threads
finish.
“Fork-Join”:-
• The join statements are executed only after completing all the
fork statements
• The statements in the join and fork executed concurrently
“Code Practising”:-
“Result”:-

“Fork-Join any”:-
• The join statements are executed if at least one statement in the
fork is executed completely
“Code Practising”:-

“Result”:-
“Fork-join_none”:-
• The join statements are executed without depending on fork
statements
“Code Practising”:-

“Result”:-
DAY-66
#100DAYSRTL

“Introduction”:-
In System Verilog IPC(Inter process communication), when
creating multiple processes that run simultaneously, they might
need to communicate or share resources. To facilitate this, System
Verilog introduced tools like mailboxes and semaphores.
Mailboxes, specifically, are useful in test benches where various
components run in separate processes and need a way to
communicate with each other.
“Mailbox”:-
Mailboxes are like a direct line of communication between two
parallel processes. Picture them as a real mailbox: just like how
you send and receive letters, in a mailbox, there's a sender and a
receiver. The receiver can only get mail when the sender sends it.
If the mail hasn’t arrived yet, the receiver has two options. They
can wait for the mail or they can go and do other tasks and then
later check for the .Similarly, if the mailbox is full the sender can't
add new mail until there's space available.
“Establishing IPC via Mailbox”:-
There will be a parent process which will start the sub-process.
Mailbox is defined and declared inside the parent process. This
mailbox handle can then be used by the sub-processes to
communicate with each other.

“Methods of mailbox”:-
1. new() - This function creates a new instance of the mailbox and
returns the handle. If no parameter is passed unbounded mailbox is
created else bounded mailbox is created which can store max
number of elements as specified.
2. put() – This is a blocking task and is used to write some data to the
mailbox. If the mailbox is full it will wait for the mailbox to have
some space.
3. try_put() - This is a non-blocking function. This will try to write a
message in the mailbox. If the mailbox is full or due to some reason
it cannot write it will return a status value of 0 or else return a
positive value.
4. get() – This is a blocking task and is used to get data from the
mailbox. This method also deletes the data from the mailbox after
retrieving it.
5. try_get() – Same as get() method but this is non-blocking function.
The function returns positive number if data is retrieved from the
mailbox else returns zero.
6. peek() – This is similar to the get() method in nature but this task
does not delete the data from the mailbox. As the name suggests it
just peeks into the mailbox and gets back data without changing
any contents of the mailbox
7. try_peek() – Similar to peek() method but is non-blocking
function. Returns a positive number if any data can be retrieved
from the mailbox else returns 0.
8. num() – This function returns the number of data elements that are
currently present in mailbox.
Code Practising:-

Result:-

“Parameterized Mailbox”:-
Parameterized mailboxes offer a solution by being more specific.
They work like a labeled container, where you define the type of data
that can be sent. Just as a package marked with clear instructions on
its content, parameterized mailboxes allow senders to only send data
of a specified type. This restriction prevents mismatched data and
potential errors, ensuring that the receiver is always prepared to
handle the expected content.
“Mailbox Vs Queue”:-
✓ The queue is an array, memory can be operated like a FIFO or
LIFO using the non-blocking methods, whereas the Mailbox is
a class that can be used to communicate between TB
components for sharing the transactions or data.
✓ Mailbox has both blocking and non-blocking methods. Mailbox
is implemented with queues and semaphores.
DAY-67
#100DAYSRTL

“Introduction”:-
We have seen that in System Verilog various processes can run
in parallel. This can create a problem if 2 processes access some
variables. Semaphore provides a solution to this problem.
semaphores can also help in synchronization of different
processes mainly used in test bench design where different
components of the test bench need to be synchronized with each
other.
“Semaphore”:-
Semaphores are basically a way to prevent unintended access
to shared variables by different processes. This can be considered
as a bucket having keys. The process will first need to get a key
from this bucket and then only it can continue to execute the
remaining code lines. If there are no keys left in the bucket, the
process will have to wait until a key is back in the bucket.
semaphore sem;
sem = new();

“Methods of Semaphore”:-
1. new(int key count = 0)- This method creates a new handle of
semaphore. This handle will be used to get or put keys back
into the semaphore. The number of keys stored by semaphore
can be passed as an argument.
2. get(int keyCount = 1)- This method gets the number of keys
passed as an argument from the semaphore. If the mentioned
number of keys is not present in the semaphore then it will
wait for the specified number of keys to be available in the
semaphore.
3. try_get(int keyCount = 1) - this is a non-blocking function
that returns 0 if the number of keys is not available it will
return 1. This will not wait for the number of keys to be
available.
4. put(int key count = 1) - this is a task that will put the
specified number of keys back into the semaphore. This is also
a blocking method that will block the execution of further
statements until the specified number of keys are returned to
the semaphore.
Code practicing:-

Result:-
Note:-
In semaphore, the no of keys given inside the new is just the initial
no of keys. More no of keys can be added to the semaphore
pushing put() task. If the no of keys inside put() is more than what
we have removed from the semaphore the total no of keys gets
increased as seen in the below code.
Code practicing:-

Result:-
DAY-68
#100DAYSRTL

“Introduction”:-
Events in System Verilog, similar to Verilog, are static entities.
However, System Verilog has improved upon the basic
functionalities of events. Think of events as markers or flags that
help control the flow of actions in your code. They're like signals
that trigger specific actions to occur in your program or hardware
design. They've got a few enhancements in System Verilog,
making them more versatile and powerful for managing the
execution sequence in your code.
“Events”:-
✓ Events act like flags that help two different tasks or processes
in a program or hardware design to work together smoothly.
They make sure these tasks stay in sync, just like a countdown
timer used by two people to start an activity together.
✓ In System Verilog, you can 'raise' an event using “->” or “->>”
to signal that something has happened, while you can 'listen' for
that event using @ or wait() to make sure you don't proceed
until that event has been 'raised'.
event ev;
-> ev;

✓ Named events can be triggered using -> or ->> operator


✓ Processes can wait for an event using @ operator or .triggered
Code Practising:-

Result:-

“-> Vs ->>”:-
➢ (Non-blocking Event Control)->: It schedules the event to
trigger, but does not wait for the event to be processed
immediately. It's like leaving a note or a message about the
event but continuing with other tasks without waiting for it to
be handled right away.
➢ (Blocking Event Control) ->>: It schedules the event and then
waits for it to be processed before moving on to the next task.
It's like sending a message and then waiting until the receiver
acknowledges it before continuing with your own tasks.
➢ Both -> and ->> are used to trigger events. The difference lies
in whether the current process waits for the event to be
processed immediately (->>) or not (->).
“@ Vs wait”:-
➢ An event's triggered state persists throughout the time step, until
simulation advances. Hence if both wait for the event and the
trigger of the event happen at the same time there will be a race
condition and the triggered property helps to avoid that.
➢ A process that waits on the triggered state always unblocks,
regardless of the order of wait and trigger.
Code Practising:-

Result:-

“Wait Order”:-
Waits for events to be triggered in the given order, and issues an
error if any event executes out of order.
wait_order(a,b,c)
Code Practising:-

Result:-
DAY-69
#100DAYSRTL

“Introduction”:-
In System Verilog, a language used for complex design testing,
they added Object-Oriented Programming (OOP) concepts. This
means they included a way to build components that can inherit
characteristics from other components and have more flexible
behaviors. In traditional Verilog, the components, called modules,
couldn't do this, making it harder to reuse them efficiently for
complex tests.
“OOPs”:-
✓ System Verilog, primarily an HDL for hardware design,
incorporates certain Object-Oriented Programming (OOP)
features but not all.
✓ OOP, inspired by real-world objects, simplifies coding by
resembling real objects. Key OOP features include Inheritance,
Polymorphism, Encapsulation, and Data Abstraction, found in
languages like C++, C#, and Java.
✓ In System Verilog, supported OOP elements include Single and
Multi-level Inheritance, Function Overriding, Virtual Classes,
and Virtual Functions.
✓ These features allow defining blueprints called "classes" that
specify an object's properties and behaviors.
For example, a car, an object created from a car blueprint (class),
shares common attributes like wheels, brakes, and steering. Yet,
individual cars have unique features like color and configuration.
Exploring these OOP features through real-life examples, such as
cars and their varying properties, helps us understand how classes
define objects and their distinct characteristics.

“Class and Objects”:-


✓ Class is a blueprint that defines the properties and behavior of
an object. In OOP classes are the entity that encapsulates all the
data and methods.
✓ Objects are the unique entity created from class. Objects are
dynamic in nature, i.e., it is created dynamically during runtime.
✓ Parent class can be known as base class or super class.
Similarly, child class is known as derived class and sub class.
“Inheritance”:-
This is the property of OOP by virtue of which a class can
inherit properties and behaviour of another class called parent or
base class. The child or derived class can add more property or
behaviour on the base class.

“Polymorphism”:-
Poly means many and morph means form. Thus, polymorphism is
a concept in which the same method can act differently in a child
class or when inputs are different. OOPs provide us with two ways
to enable polymorphism – function overloading and function
overriding.
“Abstraction”:-
Data Abstraction means hiding unnecessary and representing only
what is necessary for the user basically that particular use case.

“Encapsulation”:-
This is a property by which we can bundle all the data and methods
into one unit. This also helps in black boxing a unit where users
can focus more on using the unit without knowing the underlying
process or complexity.
DAY-70
#100DAYSRTL

“Introduction”:-
System Verilog introduces class and object-oriented
programming paradigms to hardware description languages,
facilitating modular design, encapsulation, and reusability in
hardware development. Classes define structures, behaviors, and
hierarchies, while objects instantiate these classes, enabling robust
and efficient design methodologies in System Verilog.
“Class”:-
• Class is a blueprint that defines the properties and behavior of
an object.
• The class encapsulates properties and methods in a single entity.
In System Verilog, all classes are dynamic in nature by default

• A class will define all the properties and methods that will be
present in the object
Eg:-
“Object”:-
• Objects are a unique entity of the class.
• They are created dynamically whenever needed and destroyed
when their need is over

“Constructors”:-
• Constructors are in-built methods that are called to create a new
object
• Basically, when we use new() to create a new class this acts as
a constructor.
• In contrast to a default constructor, a parameterized constructor
allows specific properties to be defined upon object creation.

• Note:-Constructors are special methods used to create objects


so unlike a normal method, constructors don’t have a return
type. In the example mentioned above please note there is no
return type for function new.
“Destructors”:-
• These are just the opposite of constructors and are called when
we want to destroy an object.
• In SV, we can’t manually destroy objects and thus destructors
are not present in System Verilog
“this keyword”:-
this keyword represents the current object. This can be used to
specifically point to properties that belong to the current object.

Code Practising:-

Result:-

“Automatic”:-
When a method is automatic in nature these variables won’t be
allocated memory when we create an object but rather when the
methods are called. Once the method call is over the memory is
released.
Code Practising:-

Result:-

If we have a fork_join inside a for loop and we are using the loop
variable inside fork_join then changes made by any one of the
processes to that loop variable will be reflected on all other
processes. But if we declare that variable as automatic, then all
processes will have individual memory space for that variable, and
thus, changes in the variable won't be reflected in other processes.
“Static”:-
• Static keyword is used to make a method or class static in nature.
• Static methods would share internal variables between different
method calls. Thus, if we set some internal value of the method
to some value, it will be reflected on all other method calls.
• Similarly, we can use static keyword for class as well. This makes
class of static nature and thus can be used without making objects
Code Practising:-

Result:-

An object of another class Packet2 inside class Packet. The object


of class Packet2 is static in nature, thus it can be observed that the
object handle pkt in Packet class points to the same address and
no new object is created for each new object of Packet.
DAY-71
#100DAYSRTL

“Introduction”:-
In System Verilog, inheritance serves as a pivotal feature
enabling the creation of hierarchical relationships among classes.
This concept allows derived classes to inherit properties and
behaviours from base classes, promoting code reusability,
modularity, and efficient design in hardware description and
verification methodologies.
“Inheritance”:-
• This is the property of OOP by virtue of which a class can
inherit properties and behaviour of another class called parent
or base class.
• The child or derived class can add more properties or behaviour
to the base class.
“Child Class or Sub Class”:-
• Subclasses, like children, inherit traits from parent classes.
• In verification, we often start with a basic reference class and
gradually add more features to build a stronger base class.
• It's similar to how kids inherit characteristics from their parents
and grow with added attributes over time
class <class name> extends <base_class_name>;
endclass
“Super Keyword”:-
• Super keyword is kind of like this keyword except it is used to
access property or method present in the parent class.
class abc extends xyz;
function test();
super.test1();
endfunction
endclass

• Note:-It is not necessary to use the super keyword when the


method name is unique b/w parent and child class. Super
keyword is mainly used when method names are common in
parent and child or when we do function overriding which we
will learn later.
• When a constructor of the child class is called it automatically
calls the new class of the parent class, i.e., super.new() is by
default the first thing called inside the constructor of child class
“Single inheritance”:-
• In Single inheritance there was a child class and parent class.
“Code Practising”:-
“Result”:-

“Multi-level Inheritance”:-
• In multi-level inheritance child class can also be the parent of
another child
• In multi-level inheritance it is not allowed to reach a class
higher than the immediate parent class. This means that
super.super.new() or similar is not allowed.
• In multi-level inheritance it is not allowed to reach a class
higher than the immediate parent class. This means that
super.super.new() or similar are not allowed.

“Code practicing”:-
“Result”:-
DAY-72
#100DAYSRTL

“Introduction”:-
In System Verilog, polymorphism is primarily achieved
through function overriding, enabling varied function
definitions in child classes, known as static polymorphism.
Parameterized classes also offer versatility by allowing different
class behaviors based on parameters. However, function
overloading, a means of polymorphism, isn't supported in the
latest System Verilog version (IEEE 1800-2008), restricting
dynamic polymorphism. This language leans towards static
polymorphism through overriding and parameterization, steering
away from runtime-defined function behaviors, and emphasizing
compile-time decision-making for function execution.
“Polymorphism”:-
• Polymorphism means many forms. Polymorphism in System
Verilog provides the ability for 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.
“Virtual”:-
• In SV, to override a function present in parent class, we need to
use virtual keyword in the function declaration present in parent
class.
• Note:-It is not necessary for the child class to have the virtual
keyword, but if we intend to create a child class from this class
then we must use virtual keyword to enable function overriding.
“Code Practising”:-

“Result”:-
“Code practising”:-

“Result”:-
DAY-73
#100DAYSRTL

“Introduction”:-
System Verilog has a feature called virtual classes that can be
used for data abstraction. These classes are like templates that can
be used to create other classes. They define common behavior
and interfaces for their subclasses but leave some details to be
implemented by the subclasses. However, virtual classes cannot
be directly used to create objects. Instead, they are used as base
classes for other classes. Think of them as a blueprint for creating
other classes. The subclasses can then be used to create objects.
This way, you can create a hierarchy of classes that share
common behaviors and interfaces.
“Abstraction”:-
• An abstract class sets out the prototype for the sub-classes.
• An abstract class cannot be instantiated, it can only be derived.
• An abstract class can contain methods for which only a
prototype and no implementation, just a method declaration.
“Code practising”:-

“Result”:-

“Code practising”:-

“Result”:-

“Pure Virtual Method”:-


• These are special kinds of method definitions that can only be
used inside a virtual class.
• By using a pure keyword with the method definition we do not
need to write the body of the method inside the virtual class.
• The method body needs to be defined by all the sub-classes
which are derived from an abstract class.
• If a sub-class does not provide an implementation of the pure
virtual function then there will be a compilation error.
“Code Practising”:-

“Result”:-
DAY-74
#100DAYSRTL

“Introduction”:-
Encapsulation is a programming practice that involves the
concealment of data within a class, making it exclusively
accessible through the class's methods. This technique effectively
safeguards the data (along with internal methods) within the
"capsule" of the class, thereby limiting access solely to
authorized users, typically the methods of the class.
“Encapsulation”:-
Frequently, we utilize Base Classes or Base Class libraries offered
by third-party sources. Typically, the Class Members in these
libraries are inherently public, allowing direct access from outside
the Class. However, there are instances where the providers of
these Base Classes might impose restrictions on how external
entities can access the Class members. This is implemented as a
safety and security measure to prevent unauthorized alterations
to internal states and logic. These restrictions are put in place to
fortify the integrity of the Class and uphold its intended
functionality, promoting a more controlled and secure
environment for the users and maintainers of the code.
Class Members can be declared with the following two Qualifiers:
• Local: It is available only to methods inside the class. Further,
these local members are not visible within subclasses.
• Protected: It is a property or method that has all of the
characteristics of a local member, except that it can be inherited;
it is visible to subclasses.
“Local”:-
• External access to the class members can be avoided by
declaring members as local, Within the class is allowed
• Any violation could result in a compilation error.

“Code Practising”:-

“Result”:-

“Code Practising”:-

“Result”:-
“Protected”:-
• In some use cases, it is required to access the class members
only by the derived class’s, this can be done by prefixing the
class members with the protected keyword.
• Any violation could result in a compilation error.
“Code Practising”:-

“Result”:-

“Code Practising”:-
“Result”:-
DAY-75
#100DAYSRTL

“Introduction”:-
Explore System Verilog's prowess in designing complex digital
systems, focusing on its dynamic randomization feature. From
syntax insights to practical examples, this article navigates the
basics, revealing how controlled randomness enhances flexibility
and aids in uncovering design flaws. Stay tuned for advanced
constraint discussions.
“Randomization”:-
• System Verilog employs randomization to assign unpredictable
values to variables or objects, serving a dual purpose.
• It generates dynamic inputs for the DUT and introduces
diversity into testbench elements such as monitors and
checkers.
• This process enhances code coverage and unveils elusive corner
cases, unraveling unexpected behaviors for comprehensive
testing.
• Test benches demand extensive stimuli for the DUT, making
directed scenarios impractical and prone to missing corner
cases.
• Randomization offers a succinct solution, enabling the creation
of unpredictable and realistic test scenarios without extensive
code.
• To declare a variable as random we use rand or randc keyword
“rand”:-
• The rand keyword means that the variable or object can take
any value within its range
• the same value may repeated until the possible random values
have been used.
“randc”:-
• The randc keyword means that the variable or object can take
any value within its range, but not the same value until the
possible random values have been used.
• Using randc ensures that we get unique random values.
“randomize()”:-
• every class incorporates the built-in "randomize" method,
facilitating variable randomization. If this method remains
uninvoked, variables retain their default values.
• This design choice permits the utilization of random variables
with specified values without randomization. Moreover, the
"randomize" method doubles as an error indicator by returning
the randomization status.
• This feedback proves invaluable, offering insights into
unsuccessful randomization caused by conflicting constraints or
solver-related issues, enabling effective error handling in the
design and verification process.
“Code practising”:-
“Result”:-

“Disable randomization”:-
• We can disable randomization for any of the random variables
using the rand_mode() method. This ensures that we have finer
granularity in randomizing variables and randomization for
some variables can be enabled/disabled for specific scenarios.
• <var>.rand_mode(0); will disable the randomization
• <var>.rand_mode(1); will enable randomization for variable

“Code practising”:-
“Result”:-

“Static Randomization”:-
SV also provides a static randomization function which can be
called from any class and can be used to randomize variables. It is
different from the normal randomization function as in this we
explicitly pass the variables which we want to randomize. Even
variables which are declared as random can be used with this static
function.
“Code Practising”:-

“Result”:-
DAY-76
#100DAYSRTL

“Introduction”:-
Constraints are a pivotal facet of randomization. Constraints
serve as the avenue through which we articulate specific
conditions or limitations on the randomness imbued in our
values. Given the expansive nature of this subject, we've opted
for a phased approach, unraveling the intricacies of constraints
across multiple articles.
“Constraints”:-
During randomization, it might require to randomize the variable
within a range of values or with an inset of values or other than a
range of values. this can be achieved by using constraints inside
the operator. With the System Verilog inside operator, random
variables will get values specified within the inside block.
• values within the inside block can be variable, constant, or
range
• the inside block is written with an inside keyword followed by
curly braces {}
“Constraint Blocks”:-
• Constraint blocks are class members like tasks, functions, and
variables
• Constraint blocks will have a unique name within a class
• Constraint blocks consist of conditions or expressions to limit
or control the values for a random variable
• Constraint blocks are enclosed within curly braces { }.
• Constraint blocks can be defined inside the class or outside the
class like extern methods, a constraint block defined outside
the class is called an extern constraint block
“Code Practising”:-

“Result”:-

“Code Practising”:-

“Result”:-
“Constraint Inheritance”:-
• Like class members, constraints also will be inherited from
parent class to child class.
• Constraint blocks can be overridden by writing constraint
blocks with the same name as in the parent class
“Code Practising”:-

“Result”:-

“Constraints inside”:-
• values within the inside block can be variable, constant or
range
• the inside block is written with an inside keyword followed by
curly braces {}
constraint addr_range { addr inside { ... }; }

• the range is specified by [ ]


constraint addr_range { addr inside { [5:10]}; }
• set of values are specified by ‘comma’,
constraint addr_range { addr inside { 1,3,5,7,9}; }

• it is allowed to mix range and set of values


constraint addr_range { addr inside {1,3,[5:10],12,[13:15]};}

“Code Practising”:-

“Result”:-
DAY-77
#100DAYSRTL

“Introduction”:-
Constraints are a pivotal facet of randomization. Constraints
serve as the avenue through which we articulate specific
conditions or limitations on the randomness imbued in our
values. Given the expansive nature of this subject, we've opted
for a phased approach, unraveling the intricacies of constraints
across multiple articles.
“Dist Constraints”:-
• Constraint provides control on randomization, from which the
user can control the values on randomization.
• It would be good if it's possible to control the occurrence or
repetition of the same value on randomization.
• It is possible, with a dist operator, that some values can be
allocated more often to a random variable.
• This is also known as weighted distribution.
• dist is an operator, it takes a list of values and weights,
separated by := or :/ operator

“:= Operator”:-
The “:= operator” assigns the specified weight to the item, or if
the item is a range, specified weight to every value in the range.
“:/ Operator”:-
The “:/ operator” assigns the specified weight to the item, or if
the item is a range, specified weight/n to every value in the range.
where n is the number of values in the range.

“Code Practising”:-

“Result”:-
“Implication if else Constraints”:-
The implication operator can be used to declare conditional
relations between two variables.
• implication operator is denoted by the symbol ->.
• The implication operator is placed between the expression and
constraint.
• If the expression on the LHS of implication operator (->) is
true, then the only constraint on the RHS will be considered
“Code practising”:-

“Result”:-

“Code Practising”:-
“Result”:-

“foreach loop Constraint Blocks”:-


• SystemVerilog supports using the foreach loop inside a
constraint block.
• using the for each loop within the constraint block will make it
easy to constrain an array.
• The foreach loop iterates over the elements of an array, so
constraints with the foreach loop are called Iterative constraints

“Code Practising”:-

“Result”:-
“Constraint modes”:-
• The constraint_mode() method can be used to disable any
particular constraint block.
• By default, the constraint_mode value for all the constraint
blocks will be 1.
• constraint_mode() can be used as follow,
✓ addr_range.constraint_mode(0); //disable
✓ packet.addr_range.constraint_mode(0);
“Static Constraints”:-
• A constraint block can be defined as static, by including a static
keyword in its definition. static constraint addr_range { addr >
5; }
• Any mode change of static constraint will afect in all the
objects of same class type
“Code Practising”:-

“Result”:-
DAY-78
#100DAYSRTL

“Introduction”:-
System Verilog revolutionized hardware description languages
by introducing powerful assertion constructs. These built-in
assertions, including constraints, streamline the creation of
intricate designs, enhancing readability and fostering consistency
in System Verilog code. This advancement facilitates the
seamless development of complex hardware systems with
improved reliability and efficiency.
“Assertions”:-
• In hardware verification, checkers traditionally focus on
validating design functionality by comparing outputs to
expected results.
• However, they often fall short in assessing design behavior.
Assertions become crucial in such cases.
• For instance, if a specification mandates that an output toggles
precisely after 2 clock cycles of a valid input, assertions enable
precise behavior verification.
• By embedding assertions in the testbench, designers can ensure
adherence to specified temporal and logical conditions,
enhancing the verification process.
• This approach goes beyond mere output validation, providing
a robust means to verify intricate behavioral requirements and
promoting more comprehensive and accurate verification
methodologies in hardware design.
“Advantages of Assertions”:-
✓ Precision in Issue Localization: Assertions capture design
flaws at their source, minimizing debugging time.
✓ Targeted Debugging: Assertion failures identify specific
signals, streamlining the debugging process.
✓ Functional Coverage: Assertions serve as effective tools for
covering complex behavioral properties.
✓ Formal Verification Integration: Assertions play a crucial
role in Formal verification, a distinct and assertion-centric
approach.
“Different Assertions Languages”:-
➢ PSL (Property Specification Language) – based on IBM Sugar
➢ Synopsys OVA (Open Vera Assertions) and OVL (Open Vera)
➢ Assertions in Specman
➢ 0-In (0–In Assertions)
➢ SystemC Verification (SCV)
➢ SVA (System Verilog Assertions)
“System Verilog Assertions”:-
Prior to System Verilog, different assertion languages were used
due to which there was no uniformity in the assertion constructs.
There was a need to natively support assertions in HDL itself due
to the increasing complexity of the verification.
o System Verilog merges benefits from different assertion
languages into one, thus giving the best from all languages.
o Due to native support of assertions in SV, assertions can be
added to the design and testbench directly without needing to
add special interface.
o SVA is easy to learn and implement.
“Immediate Assertions”:-
An immediate assertion is a type of instruction that tells a
simulator how to check the correctness of a design under test
(DUT). It follows the simulation event semantics, which means
it will be evaluated in the event regions based on how assertion
is used. It is written as a procedural statement, and it is executed
like any other statement in a procedural block.
• Immediate assertion as a basic statement that is evaluated for a
single time.
assert(expression)pass_statement[else fail_statement]

• The expression is non-temporal, and it is treated as a condition


in an if statement.
• The pass_statement is executed if the expression is true, and
the fail_statement is executed if the expression is false.
• The else block is optional, but it can be used to specify the
severity level of the assertion failure.
“Concurrent Assertions”:-
Sequence is the basic building block of concurrent assertions in
SV. A sequence is a series of Boolean expressions that specify the
order and timing of events that form a property. A sequence can
be written as a simple sequence, which consists of a single
expression, or as a complex sequence, which combines multiple
expressions with operators.
➢ Property:- A property is a logical expression that describes a
condition or a sequence of events that should hold true for the
design. We can use sequence in a property or even directly use
an expression, if the expression is simple.
➢ Assert directives:-As we have seen assertion can be used in
formal verification as well as coverage, thus there are multiple
assert directives provided by SV.
➢ assert: This statement specifies that a given property of the
design should always be true in simulation. If the property
evaluates to false, the assertion fails, and an error message is
generated.
➢ assume: This statement specifies that a given property is an
assumption that guides the formal verification tools to generate
input stimulus. The assumption is not checked in simulation,
but it can be used to constrain random variables or generate
cover points.
➢ cover: This statement evaluates a given property for functional
coverage. If the property evaluates to true, a cover point is hit,
and a coverage report is generated.
➢ restrict: This statement specifies that a given property is a
constraint on formal verification computations. The property is
ignored by simulators, but it can be used to prune unreachable
states or avoid invalid scenarios.
➢ Delay operator:-Concurrent assertions have temporal
expressions, thus we need some way to provide delay in terms
of the clock for the expression. ## is the clock cycle delay
operator. The delay provided by this operator is not based on
time scale but rather based on the clock which is inferred by
the assertion property.
Eg:- ##1 means delay of one clock cycle

“Code Practising”:-
DAY-79
#100DAYSRTL

“Implication Operator”:-

➢ In the above sequence, we can observe that the sequence starts


on every positive edge of the clock and it looks for “a” to be
high on every positive clock edge. If the signal “a” is not high
on any given positive clock edge, an error is issued by the
checker.
➢ If we want the sequence to be checked only after “a” is high,
this can be achieved by using the implication operator.
➢ The implication is equivalent to an if-then structure. The left-
hand side of the implication is called the “antecedent” and the
right-hand side is called the “consequent”
➢ The antecedent is the gating condition. If the antecedent
succeeds, then the consequent is evaluated.
➢ The implication construct can be used only with property
definitions. It cannot be used in sequences.
“Overlapped Implication”:-
• The overlapped implication is denoted by the symbol |->.
• If there is a match on the antecedent, then the consequent
expression is evaluated in the same clock cycle.
• Below property checks that, if signal “a” is high on a given
positive clock edge, then signal “b” should also be high on the
same clock edge.

“Code Practising”:-

“Result”:-

“Non-Overlapped Implication”:-
• The non-overlapped implication is denoted by the symbol |=>.
• If there is a match on the antecedent, then the consequent
expression is evaluated in the next clock cycle.
• Below property checks that, if signal “a” is high on a given
positive clock edge, then signal “b” should be high on the next
clock edge.
“Code Practising”:-

“Result”:-

“Implication with a sequence”:-


The below property checks that, if the sequence seq_1 is true
on a given positive edge of the clock, then start checking the seq_2
(“d” should be low, 2 clock cycles after seq_1 is true).

“Timing Windows in Assertions”:-


Below property checks that, if signal “a” is high on a given
positive clock edge, then within 1 to 4 clock cycles, the signal “b”
should be high.
“Repetation Operators”:-

Using repetation operator we can write it as

Examples:-

“go to repetition”:-
the go-to repetition operator is used to specify that a signal will
match the number of times specified not necessarily on a
continuous clock cycle
Eg:-

➢ property checks that, if the signal “a” is high on a 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
DAY-80
#100DAYSRTL

“Assertions Methods”:-
System Verilog has some inbuild methods for the purpose of
assertions
• $rose:-It returns true if the least significant bit of the signal
changed to 1. Otherwise, it returns false
➢ Eg:- Sequence seq_rose checks that the signal “a” transitions
to a value of 1 on every positive edge of the clock. If the
transition does not occur, the assertion will fail

• $fell:- It returns true if the least significant bit of the signal


changed to 0. Otherwise, it returns false
➢ Eg:-Sequence seq_fell checks that the signal "a" transitions to
a value of 0 on every positive edge of the clock. If the
transition does not occur, the assertion will fail.

• $stable:- It returns true if the value of the expression don’t


change. Otherwise, it returns false
➢ Eg:- Sequence seq_stable checks that the signal "a" is stable
on every positive edge of the clock. If there is any transition
occurs, the assertion will fail
• $past:-It provides the value of the signal from the previous
clock cycle
➢ Eg:- Property checks that, in the given positive clock edge, if
the “b” is high, then 2 cycles before that, a was high.

“Code Practising”:-

• $past construct with clock gating:- The $past construct can be


used with a gating signal on a given clock edge, the gating
signal has to be true even before checking for the consequent
condition.
➢ Eg:- Property checks that, in the given positive clock edge, if
the “b” is high, then 2 cycles before that, a was high only if the
gating signal "c' is valid on any given positive edge of the
clock.

• $onehot:- checks that only one bit of the expression can be high
on any given clock edge.
• $onehot:-It checks only one bit of the expression can be high
or none of the bits can be high on any given clock edge.

• $isunknown:- It checks if any bit of the expression is X or Z.

• $countones:- It counts the number of bits that are high in a


signal

• 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.
➢ Eg:- property checks that, if the signal “a” is high on a 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

• Ended:- while concatenating the sequences, the ending point of


the sequence can be used as a synchronization point. This is
expressed by attaching the keyword "ended" to a sequence
name.
➢ Eg:-property checks that, sequence seq_1 and SEQ_2 match
with a delay of 2 clock cycles in between them. the end point
of the sequences does the synchronization
DAY-81
#100DAYSRTL

“Aim”:-Writing the assertions for a simple up down counter


“RTL Code”:-

“Conditions to be checked”:-
➢ Reset property:- When rst==0 then count==0;
➢ Up count property:- when udbar=1 then count=count+1;
➢ Down count property:- when udbar=1 then count=count+1;
➢ Load property:- when load==1 then count==load;
➢ 0 to F property:-in case of down counter if count==0; then next
value should be F
➢ F to 0 property:- in case of Up counter if count==F; then next
value should be 0
“Assertions Code”:-

“Some Insights”:-
o RTL Designers wrote the Assertions used to test the
Microarchitecture Design Specification and the internal Chip
level interfaces, illegal combinations.
o But they don't write it within the RTL code instead they wrote
it outside the module as a separate file and then use the keyword
“bind” to map those Assertions within RTL code.
o Sometimes RTL designers use the “assume” keyword as a part
of Assertions to check several design-related features.
Verification Engineers generally put the Assertions within the
“interface” or inside a “monitor” or use a separate file as
“assertions.sv” to increase the observability of the design.
o Verification Engineers wrote the Assertions related to inter-
module interfaces, at full chip level/block level, and used it as a
Checker to verify the design-related features and performance.
DAY-82
#100DAYSRTL

“Introduction”:-
We can generate an infinite number of random scenarios for the
design under test, but we need to stop our verification at some
point in time and consider the design to be verified. Coverage
gives us that metric which can be used to say verification is
complete. This article will be more focused on the concepts of
coverage and thus will be the same for HDLs like System Verilog,
VHDL, etc.
“Coverage in verification”:-
• Coverage is a metric that measures how well the design under
test (DUT) has been verified by the testbench.
• Coverage helps us identify the gaps in the verification process
and ensure that the DUT meets the specifications and
requirements
• Coverage is important because it provides feedback on the
quality and completeness of the verification process.
• Without coverage, it is difficult to know if the testbench has
covered all the features and scenarios of the DUT, or if there are
any missing or redundant tests
“Code Coverage”:-
• Code coverage is a measure of how much of the code in the
DUT has been executed by the testbench.
• It also helps us detect any dead or unreachable code in DUT.
This helps optimize the design to remove any redundant code.
• Code coverage can also help us optimize the verification
process by reducing the number of tests or increasing the
efficiency of the tests.
• With code coverage we can know if some codes have been
executed or not by our stimulus.
• If there are multiple stimuli executing the same code, we can
remove some redundant tests, similarly, we can add new stimuli
if some code is not getting executed.

➢ Statement Coverage:- The percentage of executable


statements in the DUT that have been executed at least once by
the testbench. This helps us understand if there is some
unreachable code or if there is some redundant code in the
design.
➢ Branch Coverage:- The percentage of branches (if-else, case,
etc.) in the DUT that have been taken by the testbench.
Basically, it covers whether all the branches in the if-else
construct are getting executed or not. Branch coverage implies
statement coverage, but not vice versa.
➢ Expression Coverage:- The percentage of expressions (logical,
arithmetic, etc.) in the DUT that have been evaluated to all
possible values by the testbench. This basically covers whether
the operands in an expression have taken all possible values or
not.
➢ Toggle Coverage:- The percentage of bits or signals in the DUT
that have changed their values from 0 to 1 or 1 to 0 by the
testbench. Toggle coverage generally slows down the
simulation time for a complex design and thus as a trade-off, it
can sometimes be disabled.
➢ FSM Coverage:- The percentage of states and transitions in the
FSMs in the DUT that have been visited by the testbench.
Note:-Code coverage can be collected using tools such as
simulators or code analyzers. Thus, code coverage does not
require any extra coding as needed in functional coverage. The
tool automatically generates a code coverage report if code
coverage commands are used in the simulation.
“Functional Coverage”:-
• Functional coverage is a measure of how well the functionality
of the DUT has been verified by the testbench. Functional
coverage is based on the specifications and requirements of the
DUT, not on its implementation.
• In System Verilog, functional coverage can be defined by using
cover-points and bins, which specify what values or ranges of
values of certain signals or variables are of interest for
verification.
Note:- Functional coverage cannot be automatically generated
by a tool. All the coverage related codes are added as part of the
verification plan.
DAY-83
#100DAYSRTL

“Functional Coverage”:-
Functional coverage measures what functionalities/features of
the design have been exercised by the tests. This can be useful in
constrained random verification (CRV) to know what features
have been covered by a set of tests in a regression. Functional
coverage is a user-defined metric that measures how much of the
design specification has been exercised in verification.
“Coverage Model”:-
• The coverage model is defined using the Covergroup construct.
• The covergroup construct is a user-defined type. The type
definition is written once, and multiple instances of that type
can be created in different contexts.
• Similar to a class, once defined, a cover group instance can be
created via the new()operator. A covergroup can be defined as a
module, program, interface, or class.
• Each covergroup specification can include,
• A clocking event that synchronizes the sampling of coverage
points
✓ A set of coverage points
✓ Cross coverage between coverage points
✓ Optional formal arguments
✓ Coverage options
“Bins”:-
• A coverage point can be an integral variable or an integral
expression. Each coverage point is associated with a “bin”. On
each sample clock simulator will increment the associated bin
value.
• The bins will automatically be created or can be explicitly
defined.
“Automatic Bins(Implicit Bins)”:-
• An automatically single bin will be created for each value of the
coverpoint variable range. These are called automatic, or
implicit, bins.
• For an “n” bit integral coverpoint variable, a 2𝑛 number of
automatic bins will get created.

• Below are the bins, will get created automatically,


o for addr: c1.auto[0] c1.auto[1] c1.auto[2] … c1.auto[255]
o for wr_rd: c2.auto[0]
“Explicit bins”:-
• “bins” keyword is used to declare the bins explicitly to a variable.
• A separate bin is created for each value in the given range of
variable or a single/multiple bins for the rage of values.
• Bins are explicitly declared within curly braces { } along with the
bins keyword followed by bin name and variable value/range,
immediately after the coverpoint identifier.
Result:-
bins b1 = {0,2,7 }; //bin “b1” increments for addr = 0,2 or 7
bins b2[3] = {11:20};//creates three bins b2[0],b2[1] and b2[3].and The 11 possible values are //distributed as follows:
(11,12,13),(14,15,16) and (17,18,19,20) respectively.
bins b3 = {[30:40],[50:60],77}; //bin “b3” increments for addr = 30-40 or 50-60 or 77
bins b4[] = {[79:99],[110:130],140};//creates three bins b4[0],b4[1] and b4[3] with values 79-99,50-60 and 77 respectively
bins b5[] = {160,170,180};//creates three bins b5[0],b5[1] and b5[3] with values 160,170 and 180 respectively
bins b6 = {200:$}; //bin “b6” increments for addr = 200 to max value i.e, 255.
default bin;// catches the values of the coverage point that do not lie within any of the defined bins.

“Bins for Transition”:-


• The transition of coverage point can be covered by specifying
the sequence,
value1 => value2
• It represents transition of coverage point value from value1 to
value2.
• sequence can be single value or range,
value1 => value2 => value3 ….
range_list_1 => range_list_2
“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.

“Illegal Bins”:-
• A set of values or transitions associated with a coverage point
can be marked as illegal by specifying them as illegal_bins.
DAY-84
#100DAYSRTL

“Cross Coverage”:-
• Cross Coverage is specified between the cover points or
variables. Cross coverage is specified using the cross construct.
• Expressions cannot be used directly in a cross; a coverage point
must be explicitly defined first.
• The cross-coverage allows having a cross-product (i.e. cartesian
product) between two or more variables or coverage points
within the same covergroup.
• In simple words, cross-coverage is nothing but a set of cross-
products of variables or coverage points.

✓ In the above example, each coverage point has 16 bins,


namely auto[0]…auto[15].
✓ The cross of a and b (labeled aXb), therefore, has 256 cross
products, and each cross product is a bin of aXb.
• The coverage group cov has the same number of cross-products
as the previous example, but in this case, one of the coverage
points is the expression b+c, which is labeled BC.

“Code Practising”:-

“iff Constructs”:-
• The expression within the iff construct provides feasibility to
exclude the coverpoint in the coverage if an expression is
evaluated as false.

“Code Practising”:-
“bins of”:-

✓ In the above example, coverage points cp1 and cp2 include a


set of cover bins for variables var1 and var2. The cp1_X_cp2
denotes the cross product of var1 and var2 with specified cross-
bins.
✓ If no additional cross bins were specified (i.e. cp1_X_cp2:
cross var1, var2), then it would have resulted in 9 cross
products listed as:

✓ The cross bin xy1: It results in 3 cross products listed as

✓ The cross bin xy2: It results in 3 cross products listed as

✓ The cross bin xy3: It results in 1 cross-product listed as

✓ The cross bin xy4: It results in 5 cross products listed as


DAY-85
#100DAYSRTL

“Transaction”:-
It contains
✓ variables for all ports (DUT) except Global Signals
✓ modifiers for input ports
✓ Constrains for variables
✓ Methods→Printing Values, Copy
“Generator”:-
✓ It performs Randomization for transaction method
✓ It Sends transactions to the driver
✓ It Sense event from Scoreboard and Driver
“Driver”:-
✓ It Receives transactions from the generator
✓ It applies reset to DUT
✓ It applies transactions to DUT with an interface
“Monitor”:-
✓ It Capture DUT response
✓ It Sends a response transaction to the scoreboard
✓ It also controls data to be sent for a specific operation
“Scoreboard”:-
✓ It Receives transactions from the monitor
✓ Store transaction: array, Queue, Associative Array, etc
✓ Compare with expected result
“Environment Class”:-
✓ It holds all classes together
✓ It Schedules different process
✓ It connects Mailbox, Events
“Transaction”:-
✓ It has all the ports of DUT defined with logic
✓ It is dynamic in nature
THANK YOU !

The VLSI Voyager

You might also like