Unit 3
Unit 3
Course Description:
This course gives a student an in-depth introduction to the main System Verilog enhancements to the Verilog hardware
description language (HDL), discusses the benefits of the new features, and demonstrates how design and verification can
be more efficient and effective when using System Verilog constructs.
The course is broken down into two modules: The Design module examines improvements for RTL design and synthesis;
the Verification module explores verification enhancements such as object-oriented design, assertions and randomization.
Prerequisites:
• A working knowledge of Verilog HDL
• The ability to navigate a file system and use a text editor
• A basic understanding of digital hardware design and verification
Unit-3: System Verilog Language Concepts
Some of these were created for designers but are also useful for testbenches.
In this chapter you will learn about the data structures most useful for verification.
System Verilog introduces new data types with the following benefits.
Verilog’s variable types are four-state: each bit is 0,1,X or Z. System Verilog introduces
new two-state data types, where each bit is 0 or 1 only.
You would use these when you do not need X and Z values, for example in test benches and
as for-loop variables.
Using two-state variables in RTL models may enable simulators to be more efficient. Used
appropriately, they should not affect the synthesis results.
System Verilog - Two-state types
System Verilog introduces several two-state data types to improve simula- tor performance and
reduce memory usage, over four-state types. The simplest type is the bit, which is always
unsigned. There are four signed types: byte, shortint, int, and longint.
TYPE Description Example
bit user-defined size bit [3:0] a_nibble;
byte 8 bits, signed byte a, b;
shortint 16 bits, signed shortint c, d;
int 32 bits, signed int i,j;
longint 64 bits, signed Longint lword;
System Verilog takes this a stage further and refines the concept of arrays and permits more
operations on arrays.
In System Verilog, arrays may have either packed or unpacked dimensions, or both. Consider
this example:
For arrays with different types, you must use a cast, and there are rules for how an unpacked type is cast to a
packed type. Unpacked arrays can be any type, such as arrays of reals.
SystemVerilog permits a number of operations on complete unpacked arrays and slices of unpacked arrays.
For these, the arrays or slices involved must have the same type and the same shape – i.e. exactly the same
number and lengths of unpacked dimensions.
The packed dimensions may be different, as long as the array or slice elements have the same number of bits.
System Verilog also includes dynamic arrays (the number of elements may change during
simulation) and associative arrays (which have a non-contiguous range).
To support all these array types, System Verilog includes a number of array querying
functions and methods.
For example, you could use $dimensions to find the number dimensions of an array
variable.
System Verilog - Fixed-Size Arrays
System Verilog offers several flavors of arrays beyond the single-dimension, fixed-size
Verilog-1995 arrays. Many enhancements have been made to these classic arrays.
Verilog requires that the low and high array limits must be given in the declaration.
Almost all arrays use a low index of 0, so System Verilog lets you use the shortcut of just giving the array size,
similar to C:
You can create multidimensional fixed-size arrays by specifying the dimensions after the variable name.
This is an unpacked array; packed arrays are shown later.
The following creates several two-dimensional arrays of integers, 8 entries by 4, and sets the last entry to 1.
Multidimensional arrays were introduced in Verilog-2001, but the compact declarations are new.
System Verilog - Fixed-Size Arrays
System Verilog offers several flavors of arrays beyond the single-dimension, fixed-size
Verilog-1995 arrays. Many enhancements have been made to these classic arrays.
SystemVerilog’s data type system allows you to define quite complex types. To make this kind
of code clear, the typedef facility was introduced. Typedef allows users to create their own
names for type definitions that they will use frequently in their code. Typedefs can be very
convenient when building up complicated array definitions.
The default type is int. You can copy them to and from variables of the enumeration type,
compare them with one another and so on. Enumerations are strongly typed.
You can’t copy a numeric value into a variable of enumeration type, unless you use a type-
cast:
However, when you use an enumeration in an expression, the value you are working with
is the literal’s integer equivalent; so, for example, it’s okay to compare an enumeration
variable with an integer; and it’s okay to use an enumeration value in an integer
expression.
System Verilog - Struct and Union struct {
System Verilog introduces struct and union data int x, y;
types, similar to those in C.
} p;
These include increment (++) and decrement (--), and assignment operators (+=, -=, ...).
The wild equality operators (=== and !==) act like the comparisons in a casex statement, with
X and Z values meaning “don’t care”.
Unbounded Queue
Bounded Queue
//Size-Method
$display("----- Queue_1 size is %0d -----",queue_1.size());
foreach(queue_1[i]) $display("\tqueue_1[%0d] = %0d",i,queue_1[i]);
$display("----- Queue_2 size is %0d -----",queue_2.size());
foreach(queue_2[i]) $display("\tqueue_2[%0d] = %0s",i,queue_2[i]);
//Insert-Method
queue_2.insert(1,"Orange");
$display("----- Queue_2 size after inserting Orange is %0d -----",queue_2.size());
foreach(queue_2[i]) $display("\tqueue_2[%0d] = %0s",i,queue_2[i]);
Queue Methods Example
Unbounded Queue Declaration, Initialization, Size, Insert and Delete Method
module queues_array; //Delete Method
//declaration queue_2.delete(3);
bit [31:0] queue_1[$]; //unbounded queue $display("----- Queue_2 size after Delete is %0d ---",queue_2.size());
string queue_2[$]; foreach(queue_2[i])$display("\tqueue_2[%0d] = %0s",i,queue_2[i]);
end
initial begin
//Queue Initialization: endmodule
queue_1 = {0,1,2,3};
queue_2 = {"Red","Blue","Green"};
//Size-Method
$display("----- Queue_1 size is %0d -----",queue_1.size());
foreach(queue_1[i]) $display("\tqueue_1[%0d] = %0d",i,queue_1[i]);
$display("----- Queue_2 size is %0d -----",queue_2.size());
foreach(queue_2[i]) $display("\tqueue_2[%0d] = %0s",i,queue_2[i]);
//Insert-Method
queue_2.insert(1,"Orange");
$display("----- Queue_2 size after inserting Orange is %0d -----",queue_2.size());
foreach(queue_2[i]) $display("\tqueue_2[%0d] = %0s",i,queue_2[i]);
Queue Methods Example
Unbounded Queue Declaration, Initialization, Size, Insert and Delete Method
module queues_array; //Delete Method
//declaration queue_2.delete(3);
bit [31:0] queue_1[$]; //unbounded queue $display("----- Queue_2 size after Delete is %0d ---",queue_2.size());
string queue_2[$]; foreach(queue_2[i])$display("\tqueue_2[%0d] = %0s",i,queue_2[i]);
end
initial begin
//Queue Initialization: endmodule
queue_1 = {0,1,2,3};
queue_2 = {"Red","Blue","Green"};
//Size-Method
$display("----- Queue_1 size is %0d -----",queue_1.size());
foreach(queue_1[i]) $display("\tqueue_1[%0d] = %0d",i,queue_1[i]);
$display("----- Queue_2 size is %0d -----",queue_2.size());
foreach(queue_2[i]) $display("\tqueue_2[%0d] = %0s",i,queue_2[i]);
//Insert-Method
queue_2.insert(1,"Orange");
$display("----- Queue_2 size after inserting Orange is %0d -----",queue_2.size());
foreach(queue_2[i]) $display("\tqueue_2[%0d] = %0s",i,queue_2[i]);
Queue Methods Example
Unbounded Queue Declaration, Initialization, Size, Insert and Delete Method
module queues_array; //Delete Method
//declaration queue_2.delete(3);
bit [31:0] queue_1[$]; //unbounded queue $display("----- Queue_2 size after Delete is %0d ---",queue_2.size());
string queue_2[$]; foreach(queue_2[i])$display("\tqueue_2[%0d] = %0s",i,queue_2[i]);
end
initial begin
//Queue Initialization: endmodule
queue_1 = {0,1,2,3};
queue_2 = {"Red","Blue","Green"};
//Size-Method
$display("----- Queue_1 size is %0d -----",queue_1.size());
foreach(queue_1[i]) $display("\tqueue_1[%0d] = %0d",i,queue_1[i]);
$display("----- Queue_2 size is %0d -----",queue_2.size());
foreach(queue_2[i]) $display("\tqueue_2[%0d] = %0s",i,queue_2[i]);
//Insert-Method
queue_2.insert(1,"Orange");
$display("----- Queue_2 size after inserting Orange is %0d -----",queue_2.size());
foreach(queue_2[i]) $display("\tqueue_2[%0d] = %0s",i,queue_2[i]);
Queue Methods Example
Queue, push_front(), push_back(), pop_front() and pop_back() Method
Queue Methods Example
Unbounded Queue Declaration, Initialization, Size, Insert and Delete Method
module queues_array; //Pop_front Method
//declaration lvar = queue_1.pop_front();
bit [31:0] queue_1[$]; $display("\tQueue_1 pop_front value is %0d",lvar);
int lvar;
//Pop_back Method
initial begin lvar = queue_1.pop_back();
//Queue Initialization: $display("\tQueue_1 pop_back value is %0d",lvar);
queue_1 = {0,1,2,3}; end
endmodule
//Size-Method
$display("\tQueue_1 size is %0d",queue_1.size());
//Push_front Method
queue_1.push_front(22);
$display("\tQueue_1 size after push_front is %0d",queue_1.size());
//Push_back Method
queue_1.push_back(44);
$display("\tQueue_1 size after push_back is %0d",queue_1.size());
Queue Methods Example
Bounded queue declaration and accessing
initial begin
//Queue Initialization:
queue = {7,3,1};
queue.push_back(10);
queue.push_front(10);
Queue Methods Example
Deleting complete queue
Calling queue.delete() method will delete the complete queue, which leads to the deletion of all the entries
of the queue.
module qu_delete;
//queue declaration
int qu[$];
initial begin
qu.push_back(2);
qu.push_back(13);
qu.push_back(5);
qu.push_back(65);
end
endmodule
System Verilog Processes – fork_join
Fork-Join will start all the processes inside it parallel and wait for the completion of all the processes.
At start of simulation
statements 1 and 2 are
executed sequentially
At start of simulation
statements 1 and 2 are
executed sequentially
At start of simulation
statements 1 and 2 are
executed sequentially
• Input, output, and inout argument values can be passed into and
out of both tasks and functions.
Distinctions Between Tasks and Functions
The following rules distinguish tasks from functions:
– A function must execute in one simulation time unit; a task can contain
time-controlling statements.
– A function cannot enable a task; a task can enable other tasks and
functions.
– A function must have at least one input argument; a task can have zero or
more arguments of any type.
– A function returns a single value; a task does not return a value.
SystemVerilog allows,
– to declare an automatic variable in static functions
– to declare the static variable in automatic functions
– more capabilities for declaring function ports
– multiple statements within a function without requiring a begin…end or fork…join block
– returning from the function before reaching the end of the function
– Passing values by reference, value, names, and position
– default argument values
– function output and inout ports
– the default direction of argument is input if no direction has been specified.
– default arguments type is logic if no type has been specified.
Functions
function arguments in declarations and mentioning directions
function arguments in parentheses
Functions
function with return value with the return keyword
In this example,
arguments in declarations and directions, return
value is specified using the return statement.
Functions
Void function Example
The example shows usage of void function, void function,(function with no return value)
Functions
discarding function return value
The function return value must be assigned to a variable or used in an expression.
Calling a function without return value assigned to a variable can result in a warning message.
SystemVerilog void data type is used to discard a function’s return value without any warning message.
Functions
function call as an expression
Task and Function argument passing
SystemVerilog provides below means for passing arguments to functions and tasks,