0% found this document useful (0 votes)
11 views82 pages

VSLVD Unit 2

The document provides an overview of System Verilog, focusing on built-in data types, arrays, and data structures used in VLSI design. It covers various data types such as nets and variables, as well as different types of arrays including fixed-size, dynamic, associative, and queues. Additionally, it explains linked lists and their structure, highlighting the importance of these concepts in hardware design and verification.

Uploaded by

sooraj Puppala
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)
11 views82 pages

VSLVD Unit 2

The document provides an overview of System Verilog, focusing on built-in data types, arrays, and data structures used in VLSI design. It covers various data types such as nets and variables, as well as different types of arrays including fixed-size, dynamic, associative, and queues. Additionally, it explains linked lists and their structure, highlighting the importance of these concepts in hardware design and verification.

Uploaded by

sooraj Puppala
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/ 82

VERIFICATION

AND SCRIPTING
LANGUAGES FOR
VLSI DESIGN
Dr.Sk.Shoukat Vali
Asst. Professor,
ECE,
VNRVJIET.
UNIT-2: System Verilog-I
• Built-In Data Types
• Fixed-Size Arrays
• Dynamic Arrays
• Associative Arrays
• Queues
• Linked Lists
• User Defined Data types
• Type conversion
• Enumerated data types
• User defined structures
• Procedural statements
• Tasks and Functions
Built-In Data Types
Verilog HDL has two basic data types
(i) Net type
• A net is used to connect parts of a design such as gate primitives and
module instances
• A net type represents a physical connection between structural
elements
(ii) Variable type
• A variable type represents an abstract data storage element. It is
assigned values only within an always statement or an initial
statement, and its value is saved from one assignment to the next
• A variable type has a default value of x.
Net types
• wire
• tri
• wor
• trior
• wand
• triand
• trireg
• tri1
• tri0
• sup
Variable types
There are five different kinds of variable types
• reg : used to model hardware registers since it can hold values
between assignments
• integer : general purpose variable of 32-bit wide and can store integer
• Time: unsigned 64-bit wide and can be used to store simulation time
for debugging purposes
• real : stores floating point values the same way as reg & integer
• realtime: stores time as floating-point quantity
Logic Type
• Instead of choosing reg and wire , declare all your signals as logic
• But if it has multiple drivers, compilation error will occur
• Incase of multiple drivers use wire or tri

0 Logic state 0 - variable/net is at 0 volts

1 Logic state 1 - variable/net is at some


value > 0.7 volts
x or X Logic state X - variable/net has either
0/1 - we just don't know

z or Z Logic state Z - net has high impedance


- maybe the wire is not connected and
is floating
Integer or Basic Data Types - System verilog has a hybrid of both verilog
and C data types
byte - 2-state SystemVerilog data type, 8-bit signed integer or ASCII
character
shortint - 2-state SystemVerilog data type, 16-bit signed integer
int - 2-state SystemVerilog data type, 32-bit signed integer
longint - 2-state SystemVerilog data type, 64-bit signed integer
bit - 2-state SystemVerilog data type, user-defined vector size
logic - 4-state SystemVerilog data type, user-defined vector size
reg - 4-state Verilog data type, user-defined vector size
integer - 4-state Verilog data type, 32-bit signed integer
time - 4-state Verilog data type, 64-bit unsigned integer
Arrays
• An array is a collection of data elements having the same type
• Individual elements are accessed by index using a consecutive range
of integers
• System Verilog offers several flavors of arrays beyond the single-
dimension, fixed size Verilog-1995 arrays.
Arrays can be classified as
• Fixed-Sized Arrays
• Dynamic arrays : can be resized run time.
Fixed-Size Arrays (static arrays)
• size cannot be changed once declared.
Declaring and Initializing Fixed-Size Arrays
• Verilog requires that the low and high array limits must be given in
the declaration
• System-Verilog use the shortcut of just giving the array size, which is
similar to C’s style
E.g.
int data[0:15]; // 16 ints [0]..[15]
int address[16]; // 16 ints [0]..[15]
address[15] = 1; // Set last array element
• You can create multi-dimensional fixed-size arrays by specifying the
dimensions after the variable name
E.g.
int array2 [0:7][0:3]; // Verbose declaration
int array3 [8][4]; // Compact declaration
array2 [7][3] = 1; // Set last array element
• If the code tries to read from an out-of-bounds address, System-
Verilog will return the default value for the array element type.
-an array of 4-state types, such as logic , will return X’s
- an array of 2-state types, such as int or bit , will return 0.
• System-Verilog stores each element on a longword (32-bit) boundary
• So a byte, shortint, and int are all stored in a single longword, while a
longint is stored in two longwords.
E.g.
bit [7:0] unpacked_array[3]; // Unpacked array
Array Literal
• Initialize an array using an array literal (apostrophe followed by the
values in curly braces)
• Using this array literal you can set some or all elements at once.
E.g.
int ascend[4] = ’{0,1,2,3}; // Initialize 4 elements
int decend[5];
int array[2][3] = ’{’{0,1,2}, ’{3,4,5}};
descend = ’{4,3,2,1,0}; // Set 5 elements
descend[0:2] = ’{5,6,7}; // Set first 3 elements
ascend = ’{4{8}}; // Four values of 8
Basic Array Operations — for and Foreach
• for or foreach loop is used to manipulate array
• variable i is declared local to the for loop
module fixed_array;
int a[4];
initial
begin
a='{1,2,3,4};
for(int i=0;i<4;i++)
begin
$display(“\t a[%0d]=%0d",i,a[i]);
$display ("size of array is %d", $size(a) );
end
end
endmodule
foreach
• It specifies iteration over the elements of an array.
• The loop variable is considered based on elements of an array
Syntax:
foreach(<variable>[<iterator>]])
begin
//statement - 1
...
//statement - n
end
E.g.
module foreach_loop;
int a[4];
initial
begin
foreach (a[i])
a[i] = i;
foreach (a[i])
$display("\t Value of a[%0d]=%0d",i,a[i]);
end
endmodule
----output
Value of a[0]=0
Value of a[1]=1
Value of a[2]=2
Value of a[3]=3
Dynamic Arrays
• It can be allocated and resized during simulation so the simulation
consumes a minimal amount of memory.
• Do not specify the array size at compile time; instead, give it at run
time
• dynamic array is declared with empty word subscripts []
• The array is initially empty, so you must call the new[] constructor to
allocate space
• pass the array name to the new[] constructor, the values are copied
into the new elements
E.g.
module dynamic_array;
int a[];
initial
begin
$display("size of array is %d",$size(a));
a=new[4]; //declaring size of array
$display("size of array is %d",$size(a));
a='{1,2,3,4};
for(int i=0;i<4;i++)
begin
$display("a[%0d]=%0d",i,a[i]);
end
a=new[10](a); // to retain the previous element
a.delete(); // to delete the elements of the array
$display("size of array is %d",$size(a));
enmodule
Packed array and Un-packed array
Packed array:
• The array in which the dimensions are declared before the variable
name
• It is guaranteed to be represented as contiguous set of elements with
no unused space
• Packed arrays can be made of only the single bit data types
(bit, logic, reg), enumerated types, and other packed arrays and
packed structures
• These dimensions must be specified in the [msb:lsb] format, not [size]
E.g.
bit [3:0][7:0] bytes; // 4 bytes packed into 32-bits

Fig. packed array layout


Unpacked array
• The dimensions are declared after the variable name
• An unpacked array may or may not be represented as a contiguous
set of bits
• Unpacked arrays can be made of any data type
• System-Verilog accepts a single number, as an alternative to a range,
to specify the size of an unpacked array, like C
E.g.
int Array[8][32]; // is the same as: int Array[0:7][0:31];
E.g.
bit a[3]; // unpacked array declaration
• combination of packed and unpacked array is also used
E.g.
bit [7:0] unpacked_array[3]; // Unpacked array
Associative array
• Dynamic arrays are useful for dealing with contiguous collections of
variables whose number changes dynamically
• When the size of the collection is unknown or the data space is
sparse, an associative array is a better option
• Associative arrays do not have any storage allocated until it is used,
and the index expression is not restricted to integral expressions, but
can be of any type
• An associative array implements a lookup table of the elements of its
declared type
• The data type to be used as an index serves as the lookup key, and
imposes an ordering
E.g.
• In the following picture, the associative array holds the values 0:3, 42,
1000, 4521, and 200,000. The memory used to store these is far less
than would be needed to store a fixed or dynamic array with 200,000
entries,
Syntax: to declare associative array
<data_type> <array_name> [<key_type>];
• The same data type must be used for all of the index values i.e. we can't
mix int types and strings
• we can use any value that we want to index the different elements of an
associative array where sequential integers are used to index different
elements of a dynamic array
• The simulator has to search for the memory location of each element in
the array when we either read or write to it.
• In an associative array, each data we are writing is associated with the
random address & hence array ordering methods are not supported by an
associative array
• As a result of this, associative arrays are less efficient than both static and
dynamic arrays. This normally results in slowly execution times for our test
benches.
Assigning Data to an Associative Array
• Specify both the data and the value of the index
• the general syntax we use to assign data to an associative array using
array literals
<array_name> = '{ <key> : <data>, <key> : <data> };
• <key> field to set the value of the index in the array
• The <data> field is then used to set the value of the data which is written
to the array
E.g.
/ /Create an associative array and initialize it
int example [string] = '{ "age" : 30, "height" : 190 };
example["weight"] = 100; // Add another element to the array
example["age"]; // Read a value from the array
Que
• A Queue is a variable size ordered collection of similar objects
• The size of a queue is variable similar to a dynamic array, but a queue
may be empty with no element and it is still a valid data structure.
• There are two main aspects of a queue that makes it useful for
verification purposes
• First, a queue can have variable length, including a length of zero so it
can shrink or grow as elements are deleted or added without fixing an
upper limit on its size as a regular fixed size array
• The other advantage of having a queue is that it provides a way to
emulate both Last In First Out (LIFO) and First In First Out (FIFO)
behavior that are required in so many ordered transactions
Declaring a Queue
• A queue is declared simply by putting a $ as the size of an array.
Eg.
integer my_q[$];

• We can initializ.e a queue at the place of its variable declaration


E.g.
integer my_q[$] = {1, 3, 5}; // que literals do not use ‘

• setting up an upper limit of index for a queue


E.g.
integer my_q[$:127];

Since index of an array can only be non-negative, the maximum number of


elements for the queue in the above case is 128 (i.e., 0 through 127)
1.my_q[0] refers to the first element of the queue my_q.
2.my_q[$] refers to the last element of my_q (except for a queue
definition)
Operations on Ques
integer prime_q[$] = {2, 3, 5, 7, 11, 13}; // que named as prime_q
integer odd_q[$]; // que with name odd_q

integer elem;

odd_q = prime_q; // odd_q is same as prime_q now


• Adding an element to a queue
prime_q = {prime_q, 17}; //prime_q now has the element 17 to its end
prime_q = {1, prime_q}; // adds 1 to prime_q as its first element
• Deleting elements of a queue
prime_q = prime_q[1:$]; //removes the first element

prime_q = prime_q[0:$-1]; // removes the last.

prime_q = prime_q[lower:upper]; // shrink the queue by lower and


upper values
where lower and upper are the bounds that is within this queue's limits
Inserting elements in a queue
prime_q[$] = {2,3, 5, 7, 11, 13}; //que with “prime_q” name
odd_q[$] = {prime_q[0:3], 9, {prime_q[4:5]};// inserting 9 in the que
// odd_q is now {2,3, 5, 7, 9, 11, 13};

Queue Methods
• provide an easy way of manipulating the queue as well as data inside
the queue.
size()
• This method provides the current size of the queue.
• my_q.size() ; //returns the size of my_q
insert()
• inserts an element in a queue
E.g.
• my_q.insert(i, e); // inserts the element ‘e’ in the location ‘i’ of the queue my_q
• It is equivalent to: my_q = {my_q[0:i-1], e, my-q[i, $]}
delete()
• delete a specified item
E.g.
• my_q.delete(i); // deletes the element at the position ‘i’
• it is equivalent to: my_q = {my_q[0:i-1], my_q[i+1, $]}
pop_front()
• returns the first element (i.e., the 0th element) and then removes it from the
queue
E.g. e = my_q.pop_front(); // returns the first element
it is equivalent to :
e = my_q[0];
my_q = my_q[1, $];
pop_back()
• returns the last element and then removes it from the queue.
E.g. e = my_q.pop_back() ; // returns the last element
It is equivalent of:
e = my_q[$];
my_q = my_q[0, $-1];
push_front()
• inserts an element at the front of a queue
E.g.
my_q.push_front(e) ; // inserts ‘e’ as first element
It is equivalent of:
my_q = {e, my_q};

push_back()
• inserts an element at the end of a queue.
E.g.
my_q.push_back(e); //inserts ‘e’ as last element
It is equivalent of:
my_q = {my_q, e};
Linked list
• A linked list is a linear data structure, in which the elements are not stored
at contiguous memory locations
• The elements in a linked list are linked using pointers
• A linked list consists of nodes where each node contains a data field and a
reference(link) to the next node in the list

• A Doubly Linked List (DLL) contains two pointers along with the data.one
pointer refers to previous element and another refers to next element
• A double linked list is a chain of data structures called nodes
• Each node has 3 members, one points to the next item or points to a
null value if it is last node, one points to the previous item or points
to a null value if it is first node and other has the data
• The disadvantage of the linked list is that data can only be accessed
sequentially and not in random order.
list: A list is a doubly linked list, where every element has a predecessor
and successor.
container:
• A container is a collection of objects of the same type.
• Containers are objects that contain and manage other objects and
provide iterators that allow the contained objects (elements) to be
addressed.
iterator:
• Iterators provide the interface to containers.
• They also provide a means to traverse the container elements.
• Iterators are pointers to nodes within a list.
Procedure to create list
1.Declare list variable

List#(integer) ece; // Object ece is a list of integer

2. Declaring list iterator

List_Iterator#(integer) i; //Object ‘i’ is a list-of-integer iterator


List methods
size(): returns the number of elements stored in the list
empty(): returns 1 if the number elements stored in the list is zero and 0 otherwise.
push_front(): inserts the specified value at the front of the list.
push_back(): inserts the specified value at the end of the list.
front(): returns the data stored in the first element of the list.
back(): returns the data stored in the last element of the list.
pop_front(): removes the first element of the list.
pop_back(): removes the last element of the list.
E.g.
module lists();
List#(integer) List1; //declaring list
List_Iterator#(integer) itor; // declaring iterator
initial
begin
List1 = new(); //allocating new array to the list
$display (" size of list is %d \n",List1.size()); //returns the size of the list
List1.push_back(10); // inserts 10 as last element
List1.push_front(22); //inserts 22 as first element
$display (" size of list is %d \n",List1.size()); // returns the size of list
$display (" poping from list : %d \n",List1.front()); // returns the first ele
List1.pop_front(); // removes the data in the first element
List1.pop_front(); // removes the data in the first element
$display (" size of list is %d \n",List1.size()); // returns the size of the list
List1.push_back(5); // inserts 5 at the end of the list.
List1.push_back(55); // inserts 55 at the end of the list
List1.push_back(555); // inserts 555 at the end of the list
List1.push_back(5555); // inserts 5555 at the end of the list
$display (" size of list is %d \n",List1.size()); //returns the size of the list
end
endmodule
User Defined Data types
• User-defined types allow new type definitions to be created from
existing types
• Once a new type has been defined, variables of the new type can be
declared.
• System-Verilog user-defined types are created using the typedef
keyword, as in C
• A typedef may be used to give a user defined name to an existing
data-type
E.g.
typedef int [7:0] uint; // creating a new datatype
uint a, b; // two variables of type uint
Enumerated data types
• Verilog language does not have enumerated types
• SystemVerilog adds enumerated type declarations to the Verilog language,
using the enum keyword, as in C
• Enumerated types provide a means to declare an abstract variable that can
have a specific list of valid values.
• It is a set of named values
• Each value is identified with a user-defined name, or label.
• Enumerated types can make a model or test program more readable by
providing a way to incorporate meaningful labels for the values a variable
can have. This can make the code more self-documenting and easier to
debug.
E.g.
enum {red,green,blue} RGB;
• The value of the first enumerated type can be specified
-Subsequent types are incremented from the initial value
-The vector size of the type is the size of the initial value
-The default initial value is an integer of 0
Enum methods
<variable name>. name()-returns the string representation of the
variable
<variable name>.first()- returns the value of the first member in the
enumerated list of the specified variable
<>.last()- returns the value of the last member of the variable
<>.next()- returns the value of the next member of the variable
<>.prev()- returns the value of the previous member of the variable
--enumerated data type
--state diagram--start,addr,data,stop module top;
module top; enum {start,addr,data,stop}packet;
enum {start,addr,data,stop}packet; initial
initial begin
begin packet=packet.first();
packet=start; $display("the value of %s is
$display("the value of start is %d",packet.name(),packet);
%d",packet); end
end endmodule
endmodule
Typed enumerated data types:
• An enumerated type declared using typedef is commonly referred to
as a typed enumerated data type
• it is a user-defined Enumerated types
• If typedef is not used, the enumerated type is commonly referred to
as an anonymous enumerated type

E.g.
typedef enum {WAIT, LOAD, READY} states_t;
states_t state, next_state;
Type casting
• Typecasting is converting one data type into another one
• It is also called as data conversion or type conversion
• System-Verilog extends Verilog automatic conversion with a typecast
operator
• Type casting allows the designer to specify that a conversion should
occur at any point during the evaluation of an expression, instead of
part of an assignment
• With type casting, a value can be converted to a new type within an
expression, without any assignment being made
System Verilog provides two types of casting
1. Static (compile time) casting
2. Dynamic casting
Static (compile time) casting
• The static cast operation is a compile-time cast
• The expression to be cast will always be converted during run time,
without any checking that the expression to be cast falls within the
legal range of the type to which the value is cast
• The cast will always be performed, without checking the validity of
the result
E.g.
Syntax: longint a, y;
type’(expression) int r;
y = a + longint'(r**3);
Dynamic casting
• When stronger checking is desired, System-Verilog provides a new
system function, $cast, that performs dynamic, runtime checking on
the value to be cast
• The dynamic cast, $cast , allow us to check for out-of-bounds values
• The $cast system function takes two arguments, a destination
variable and a source variable
Syntax: E.g.
int radius, area;
$cast( dest_var, source_exp );
always @(posedge clock)
$cast(area, 3.154 * radius ** 2);
// result of cast operation is cast
to the type of area
• $cast attempts to assign the source expression to the destination
variable.
• If the assignment is invalid, a run-time error is reported, and the
destination variable is left unchanged.
Structures
• A structure is a collection of variables and/or constants under a single
name.
• The entire collection can be referenced, using the name of the
structure.
• Each member within the structure also has a name, which is used to
select it from the structure.
• System-Verilog adds C-like structures to Verilog
• A structure is declared using the struct keyword. Structure members
can be any variable type, including user-defined types, and any
constant type
• While declaring structure C allows for an optional “tag” after the
struct keyword and before the opening brace but System-Verilog does
not allow a tag Syntax:
struct{ member definition;
member definition;
...
member definition; } one or more structure variables;
E.g.
struct { int a, b; // 32-bit variables
opcode_t opcode; // user-defined type
logic [23:0] address; // 24-bit variable
bit error; // 1-bit 2-state var
} Instruction_Word;
User defined structures
• User-defined types can be created from structures, using the typedef
keyword
• Multiple structure variables with the same constituents can be
created

E.g.
typedef struct { // structure definition
logic [31:0] a, b;
logic [ 7:0] opcode;
logic [23:0] address;
} inst
inst s1,s2 ; // structure allocation
Assigning to structure members
• A value can be assigned to any member of a structure by referencing the name
of the member
always @(posedge clock, negedge resetN)
typedef struct {
logic [31:0] a, b; if (!resetN)
logic [ 7:0] opcode; IW = ’{100, 5, 8’hFF, 0};
logic [23:0] address; else begin --- end
} instr_t;
instr_t IW;
always @(posedge clock, negedge resetN)
if (!resetN) begin IW = ’{address:0, opcode:8’hFF, a:100, b:5};
IW.a = 100; // reference structure member
IW.b = 5;
IW.opcode = 8’hFF;
IW.address = 0;
end
always
• The Verilog always procedural block is an infinite loop that repeatedly
executes the statements within the loop
• This procedural block can contain any number of time controls or
event controls, and the controls can be specified anywhere within the
procedural block
• This block is executed at some particular event and this event is
defined by sensitivity list
E.g.
always @(a, b) // sensitivity list
begin
sum = a + b; diff = a - b; prod = a * b;
end
• Because of the general purpose application of the always procedural block,
the design intent is not readily apparent
• SystemVerilog adds three specialized procedural blocks to reduce the
ambiguity of the Verilog general purpose always procedural block when
modeling hardware
• These specialized procedural blocks act just like any always block, but they
enforce synthesis rules so that the desired logic is created
• These blocks clearly indicate design intent
1. always_comb
2. always_latch
3. always_ff
• The use of always_comb, always_latch, and always_ff procedural blocks
can help eliminate potential modeling errors early in the design process,
before models are ready to synthesize.
E.g.
always_comb always_comb
• Used to indicates intent to model combinatorial logic if (!mode)
y = a + b;
• No sensitivity list is required
else
• It is automatically inferred y = a - b;
• Variables on LHS of assignments cannot be assigned to by other
procedural blocks
• An always_comb procedural block automatically executes one time at
simulation time zero, after all procedural blocks have been activated
• An always_comb procedural block is sensitive to both the signals read
within the block and the signals read by any function called from the
block
E.g.
always_comb
begin
a2 = data << 1;
b2 = decode();
...
end
function decode; // function with no inputs
begin
case (sel)
2'b01: decode = d | e;
2'b10: decode = d & e;
default: decode = c;
endcase
end
endfunction
always_latch
• This is used to indicate that the intent of the procedural block is to
model latched-based logic
• No sensitivity list is required
• It is automatically inferred.
• Variables written in an always_latch procedural block cannot be
written by any other procedural block.
• always_latch always triggers once just after all initial and always
blocks have run to initialize logic correctly.
always_latch
if (enable)
q <= d;
always _ff
• Indicates intent to model sequential flip-flop based logic
• Sensitivity list is required
• Each signal must be specified with either posedge or negedge
• Variables on LHS of assignments cannot be assigned to by other
procedural blocks
• always ff always triggers once just after all initial and always blocks
have run to initalize logic correctly
always_ff @(posedge clk, negedge reset_n)
if(!reset_n)
q <= 1’b0;
else
q <= d;
Tasks and functions
• Tasks and functions are used to reduce code repetition
Task
Tasks are subroutines that can be called anytime in the module they are defined,
but it is possible to define them in a different file and include the file in the module
charachteristics of tasks are:
• Tasks can have any number of inputs and outputs
• The order of inputs/outputs matters when task is called and wired
• Task can include time delays (posedge, #delay, etc)
• Task can call other task or function
• If a variable is declared within the task it is local to the task and can’t be used
outside the task.
• Tasks can drive global variables
• Tasks are called with statements and cannot be used in an expression
• Tasks can use blocking and non-blocking assignments
• Tasks can have zero or many arguments and doesn’t return any value
Syntax
task taskname; E.g. task calling without arguments
input….; module test;
output….; Initial
begin
reg….;
print(); // without argument
staement1; end
statement2; endmodule
….
task print(); // task definition
endtask; $display("TASK");
endtask
E.g. program to explain task usage
module test (a,b,x,y); task convert; //task definition
input [3:0]a,b; input [3:0] ain;
output [3:0]x,y; output [3:0] out;
reg [3:0]x,y; begin
always@(a) out=ain+50;
begin neg(ain);
convert(a,x); //task calling with arguments endtask
end
always@(b) task neg; //task definition
begin inout d;
convert(); //task calling without arguments d=~d;
end endtask;
endmodule
Functions
• Functions can have any number of inputs but only one output.
• The variables declared within the function are local to that function.
• The order of declaration (input/outputs)within the function are
considered and have to be the same as the caller
• function doesn’t include time delays (posedge, #delay, @,etc)
• Functions can use and modify global variables, when no local
variables are used.
• Functions can call other functions, but cannot call tasks
• Non-blocking assignments are not allowed inside a function
• Function can start at 0ns and will return a single value
E.g. function

module functionality();
input a,b,;
output y;
y=sum(a,b); //function calling
function sum(input x,y); //function definition
begin
sum=x+y;
end
endfunction;
endmodule
• System-Verilog makes several enhancements to Verilog tasks and
functions
• These enhancements make it easier to model large designs in an
efficient and intuitive manner
Enhancements to tasks and functions
Implicit task and function statement grouping
• SystemVerilog simplifies task and function definitions by not requiring
the begin...end grouping for multiple statements
• If the grouping is omitted, multiple statements within a task or
function are executed sequentially, as if within a begin...end block
Returning function values
• In Verilog, the return value of a function is set by assigning a value to
the name of the function
• SystemVerilog adds a return statement, which allows functions to
return a value using return, as in C
• To maintain backward compatibility with Verilog, the return value of a
function can be specified using either the return statement or by
assigning to the function name

E.g. function int add_and_inc (input int a, b);


function int add_and_inc (input int a, b); return a + b + 1;
add_and_inc = a + b + 1; endfunction
endfunction
Returning before the end of tasks and functions
• The System-Verilog return statement can be used to exit a task or
function at any time in the execution flow, without having to reach
the end of the task or function
E.g.
function automatic int log2 (input int n);
if (n <=1)
return 1; // abort function
log2 = 0;
while (n > 1)
begin
n = n/2;
log2++;
end
endfunction
Void functions
• SystemVerilog adds a void type, similar to C
• Functions can be explicitly declared as a void type, indicating that
there is no return value from the function
• Void functions are called as statements, like tasks, but have the syntax
and semantic restrictions of functions

E.g.
function void packet ( input a ,output b);
for (int i=0; i<=7; i++)
b=a+i;
endfunction
Passing task/function arguments by name
• SystemVerilog adds the ability to pass argument values to a task or
function using the names of formal arguments, rather than the order
of the formal arguments.
• Named argument values can be passed in any order, and will be
explicitly passed through the specified formal argument
E.g.
always @(posedge clock)
result <= divide(b, a);
function int divide (input int numerator, // SystemVerilog style
denominator); function call
always @(posedge clock)
if (denominator == 0) result <= divide(.denominator(b), .numerator(a) );
begin
$display("Error! divide by zero");
return 0;
End
else
return numerator / denominator;
endfunction
Functions with no formal arguments
• Verilog allows a task to have any number of formal arguments,
including none whereas functions have at least one input formal
argument
• SystemVerilog allows functions with no formal arguments, the same
as with Verilog tasks E.g.
always @*
begin
a1 = data << 1;
b1 = decode();
...
end
Arrays, structures and unions as formal arguments
• SystemVerilog allows unpacked arrays, packed or unpacked structures
and packed, unpacked, or tagged unions to be passed in or out of
tasks and functions
New operators in system verilog
• Increment and decrement operators
• Assignment operators
• Equality operators with don’t care wildcards
• Set membership operator — inside
Increment and decrement operators
• SystemVerilog adds the increment and decrement operators can be
used to either pre-increment/pre-decrement a variable, or to post-
increment/post-decrement a variable.

always_ff @(posedge
clock)
if (!resetN)
count <= 0;
else count++; //
same as count =
count + 1;
E.g.—synthesis guidelines
i++; // synthesizable
if (--i) // not synthesizable
sum = i++; // not synthesizable
Assignment operators
• SystemVerilog adds several additional types of assignment operators to Verilog
• These new operators combine some type of operation with the assignment
Equality operators with don’t care wildcards
Not equal Wild card
Case Wild card operators not Equality
Logical
equality Equality
Equality
operator
operator
• The == logical equality operator will consider any comparison where there
are bits with X or Z values are in either operand to be unknown, and return
a one-bit logic X
• The === case equality operator will perform a bit-wise comparison of the
two operands, and look for an exact match of 0, 1, X and Z values in both
operands
• The != and !== are not-equal operators and invert the results of the
true/false test, returning true if the operands are not equal, and false if
they are equal.
• The ==? , !=? operators, referred to the wildcard equality operator,
performs a bit-wise comparison of its two operands, similar to the ==
logical equality operator.
• With the ==?, !=? a logic X or a logic Z in a bit position of the right-hand
operand is treated as a wildcard that will match any value in the
corresponding bit position of the other operand
Set membership operator — inside
• SystemVerilog adds an operator to test if a value matches anywhere within
a set of values
• This operator uses the keyword, inside
• This operator searches for the existences of the value in the specified
expression or range and returns 1 if it is existing
• the inside operator can simplify comparing a value to several possibilities
E.g.
logic [2:0] a;
if ( a inside {3’b001, 3’b010, 3’b100} ) Equal to
...
….

if ( (a==3’b001) || (a==3’b010) ||
(a==3’b100} ) ...
• In the given example it tests to see if the value of 13 occurs anywhere
in an array called d_array
E.g.
int d_array [0:1023];
if ( 13 inside {d_array} )

You might also like