UNIT-2
Introduction to System Verilog
Dr. A. Sai Kumar
Assistant Professor
VNR VJIET
saikumar_a@[Link]
7013251431
VERIFICATION
IMPORTANCE OF
VERIFICATION
• Bug escapes to silicon can be
costly including re-spin
• 70 % of design cycles is spent in
verifying design
• Ever increasing complexity of
designs makes this harder
• Hence Verification is always on
critical path for any product design
System Verilog
• Hardware Description Languages (HDL) like Verilog and VHDL are used to
describe hardware behavior so that it can be converted to digital blocks
made up of combinational gates and sequential elements.
• In order to verify that the hardware description in HDL is correct, there is a
need for a language with more features in OOP that will support complicated
testing procedures and is often called a Hardware Verification Language.
• System Verilog is an extension of Verilog with many such verification
features that allow engineers to verify the design using complex testbench
structures and random stimuli in simulation.
System Verilog
• Back in the 1990's, Verilog was the primary language to verify functionality
of designs that were small, not very complex and had less features.
• As design complexity increases, so does the requirement of better tools to
design and verify it.
• System Verilog is far superior to Verilog because of its ability to perform
constrained random stimuli, use OOP features in testbench construction,
functional coverage, assertions among many others.
System Verilog
• Verification is the process of ensuring that a given hardware design works as
expected.
• Chip design is a very extensive and time consuming process and costs millions
to fabricate. Functional defects in the design if caught at an earlier stage in the
design process will help save costs. If a bug is found later on in the design
flow, then all of the design steps have to be repeated again which will use up
more resources, money and time.
• System Verilog can be considered an extension of Verilog (the most popular
HDL), and it makes sense to verify a Verilog design in System Verilog. Also
System Verilog supports OOP which makes verification of designs at a higher
level of abstraction possible.
System Verilog
Test Bench
• A testbench allows us to verify the functionality of a design through
simulations. It is a container where the design is placed and driven with
different input stimulus.
1. Generate different types of input stimulus
2. Drive the design inputs with the generated stimulus
3. Allow the design to process input and provide an output
4. Check the output with expected behavior to find functional defects
5. If a functional bug is found, then change the design to fix the bug
6. Perform the above steps until there are no more functional defects
Components of Test bench
Components of Test bench
Key features in System Verilog:
• System Verilog is referred to as the first Hardware Description and
Verification Language (HDVL) in the industry because it integrates
features from C (Python) and C++ with those from Hardware
Description Languages (HDL) such as Verilog and VHDL.
• Functional Coverage: Tracks the progress of verification scenarios.
Functional coverage is a System Verilog tool that measures how much
of a design's functionality has been exercised during a verification
phase. It helps ensure that a test has covered the necessary scenarios and
situations to prove it is working correctly
Key features in System Verilog:
• Class Properties: Allows for object-oriented programming
techniques.
• Multi-Dimensional Arrays: Offers static and dynamic arrays for
flexible data handling.
• Direct Programming Interface: Enables interaction between System
Verilog and other programming languages.
Advantages of using System Verilog over
Verilog for Verification
• Design Capabilities:Verilog is primarily used for digital circuit
design, while System Verilog provides extended capabilities for
designing digital circuits. System Verilog offers additional constructs,
such as classes, interfaces, and packages, to describe complex
hardware structures. It also provides better support for verification,
with constructs like assertions and coverage models.
• Data Types:Data types are crucial in hardware design for representing
and manipulating data in digital circuits. SystemVerilog offers a wider
range of data types, including user-defined and enumerated types,
packed and unpacked arrays, associative arrays, and queues.
• Object-Oriented Programming:System Verilog has superior support
for object-oriented programming (OOP) compared to Verilog, making
code more organized and easier to read. With System Verilog,
designers can encapsulate functionality into objects and classes,
including abstract classes and interface classes.
• Assertions:System Verilog provides built-in support for assertions,
while Verilog does not. Assertions are statements that check for certain
conditions in the design, helping to catch design errors early in the
development process. This is an important feature for verification.
• Unified Language: System Verilog is a unified hardware design,
specification, and verification language that includes all the features of
Verilog, along with additional features for design and verification.
This makes it easier for designers and verification engineers to use a
single language for the entire design flow, from design to verification.
Data Types in System Verilog
System Verilog offers many improved data structures compared with
Verilog. System Verilog introduces new data types with the following
benefits.
• Two-state: better performance, reduced memory usage
• Queues, dynamic and associative arrays: reduced memory usage, built-
in support
• Classes and structures: support for abstract data structures
• Unions and packed structures: allow multiple views of the same data
• Strings: built-in string support
• Enumerated types: code is easier to write and understand
2 State Data types:
• Two-state data types, only have two possible values (0 or 1), which
makes simulation faster and more efficient.
• Additionally, two-state data types are more consistent with the
behavior of digital hardware, which only has two possible states. This
makes it easier to write and understand Verilog code that accurately
models hardware behavior.
• The simplest type is the bit , which is always unsigned. There are four
signed 2-state types: byte, shortint, int , and longint.
Examples:
bit b;//one bit unsigned
bit [31:0]a;32-bit unsigned integer
int i;//32-bit signed integer
int unsigned ui;//32-bit unsigned integer
byte b8;//8-bit signed integer;
short int s;//16-bit signed integer
long int l;//64-bit signed integer
real r;//double precision floating point number
4 State Data types:
Data types that can store X and Z values along with zero and one are called
4 state data types.
To use datatypes which are signed as unsigned,declare the variables using
unsigned keyword.
Example:
integer i4;//32-bit signed integer
time t;//64-bit unsigned integer
$time(); return current simulation time in fixed point format
$realtime(); return current simulation time in floating point format
`timescale 1ns/1ps `timescale 1ns/1ps
module tb; module tb;
time fix_time=0; realtime real_time=0;
initial begin initial begin
#12; #12.23;
fix_time=$time; real_time=$realtime;
$display("Current simulation time is $display("Current simulation time is
%0t",fix_time); %0t",real_time);
end end
endmodule endmodule
Logic Data type:
• The one thing in Verilog that always leaves new users scratching their
heads is the difference between a reg and a wire .
• When driving a port, which should you use? How about when you are
connecting blocks?
• System Verilog improves the classic reg data type so that it can be
driven by continuous assignments, gates, and mod ules, in addition to
being a variable.
• It is given the synonym logic as some people new to Verilog thought
that reg declared a digital register, and not a signal.
• System Verilog introduces a new 4-state data type called logic that can be driven in
both procedural blocks and continuous assign statements
Example:
module top(input a,b,c, output y); module fa(
logic temp; input a,b,cin,
output s,c);
always @*
logic t1,t2,t3;
begin ha h1(a,b,t1,t2);
if(sel==1'b0) ha h2(t1,cin,s,t3);
temp=a; assign c=t2|t3;
else endmodule
temp=b;
end
assign y=temp;
endmodule
USER DEFINED DATA TYPE:
• Verilog 2001 does not allow users the freedom to extend net and
variable types to create their own data types for some specific purpose.
SystemVerilog introduces user-defined data types like those present in
the ‘C’ programming language. Here users can create and manipulate
their own complex data types for specific purposes like simulation,
emulation etc.
• User-defined types allow new type definitions to be created from
existing data types. A ‘typedef’ declaration is used to define a user-
defined type as similarly done in the ‘C’ programming language
Make your own types using typedef,Use typedef to get C compatibility
• typedef shortint short;
• typedef longint long
• typedef real double;
• typedef shortreal float;
Example:
typedef int unsigned unsint; // Define a new 32-bit unsigned 2-state
integer type
typedef bit [31:0] uint; // Equivalent to the above definition – a new
32-bit // unsigned 2-state integer type
unsint a, b; // Declaring variables with the new ‘unsint’ type uint c, d; //
a, b, c and d are 32-bit unsigned 2-state integers
Characteristics of User-defined Data Types:
• They can be defined locally or in a package.
• All of System Verilog’s data types can be extended with user-defined
type declarations.
• The new type names are intended to provide additional descriptive
information for the object declarations that use them.
ENUMERATED DATA TYPE:
• An enumerated type in System Verilog allows one to create a named set of
related but unique constants. Verilog 2001 has text macros for names and
parameters to define constants, but relating both of them is extremely difficult.
• Enumeration/Enum is a data type which assigns names to the integer constants.
These are used to simplify the code and make it easier to read and manage. Also,
Enum is synthesizable in System Verilog and thus can be used for design as well
as test bench code.
• An enumerated type allows you to create a set of related but unique constants
such as states in a state machine or opcodes.
• The simplest enumerated type declaration contains a list of constant names and
one or more variables as shown:
enum {RED,BLUE,GREEN} color;
Verilog:
reg [1:0]state;
parameter NO=0,HB=1,MB=2,SB=3;
System Verilog:
enum {NO,HB,MB,SB} state;
// Create data type for values 0, 1, 2
typedef enum {INIT, DECODE, IDLE} fsmstate_e;
fsmstate_e pstate, nstate;
initial begin
case (pstate)
// declare typed variables
IDLE:nstate = INIT;
INIT:nstate=DECODE;
default: nstate = IDLE;
endcase
$display ("Next state is %s", [Link]());
end
Defining enumerated data types:
• The actual values default to int starting at 0 and then increase. You can choose
your own enumerated values.
Example:
typedef enum{INIT, DECODE=2, IDLE} fsmtype_e;
• If any name does not have an assigned value, then it automatically takes the
incremented value of the previous name.
Incorrectly specifying enumerated values
• typedef enum {FIRST=1, SECOND, THIRD} ordinal_e;
ordinal_e position;
Correctly specifying enumerated values
• typedef enum {BAD_0=0, FIRST=1, SECOND, THIRD} ordinal_e;
ordinal_e position;
Note that an enumeration name cannot start with a number.
enum {1WAY, 2TIMES, SIXPACK=6} e_formula;//compilation error
enum {ONEWAY, TIMES2, SIXPACK=6} e_formula;
module tb;
typedef enum {TRUE, FALSE} e_true_false;
initial begin
e_true_false answer;
answer = TRUE;
$display ("answer = %s", [Link]);
end
endmodule
Output: answer = TRUE
Code:
typedef enum {RED, BLUE, GREEN} color_e;
module tb;
initial begin
color_e color;
color = [Link];
do
begin
$display ("Color = %0d/%s", color, [Link]());
color=[Link];
end
while (color != [Link]);
end
endmodule
Routines for Enumerated Types:
System Verilog provides several functions for stepping through
enumerated types.
function enum first(): Returns the value of the first member of the
enumeration
function enum last(): Returns the value of the last member of the
enumeration
function enum next(int unsigned N = 1): Returns the Nth-next
enumeration value (default is the next one) starting from the current
value of the given variable
function enum prev(int unsigned N = 1): Returns the Nth-previous
enumeration value (default is the previous one) starting from the current
value of the given variable
function int num(): Returns the number of elements in the given enumeration.
function string name(): Returns the string representation of the given enumeration
value. If the given value is not a member of the enumeration, the name() method
returns the empty string.
STRUCTURES
• A structure can contain different members of different data types.
• An array contains elements of the same data type. This makes
structures different from an array.
• Does not supports inheritance, polymorphism.
• Supports data abstraction.
• A structure can contain elements of different data types which can be
referenced as a whole or individually by their names.
SYNTAX:
struct { <Data type> <member 1>;
<Data type> <member 2>;
...; } <struct_name>;
Example1:
struct {
addr_t SrcAdr;
addr_t DstAdr;
data_t Data; } Pkt;
[Link] = SrcAdr;
if ([Link] == [Link])
Usage of typedef:
The typedef keyword allows creating multiple sets of information with
different reference handles.
Example:
typedef struct { bit [7:0] opcode;
bit [23:0] addr;
} instruction;
instruction IR1,IR2;
[Link] = 1;
[Link] = 2;
Packed Structures:
• Consists of bit fields, which are packed together in memory without
gaps– They are easily converted to and from bit vectors.
• Similar to a packed array, if memory allocated for variables in
structure is contiguous, then it is called a packed structure.
• The packed keyword is used to declare a packed structure.
• In a packed structure, if any data type is 4-state, then the complete
structure is treated as 4-state structure.
• Only packed data types are allowed in packed structures.
Example:
struct packed {
bit Valid;
byte Tag;
bit [15:0] Addr;
} Entry;
iTag = [Link];
iAddr = [Link];
iValid = [Link];
Unpacked structures:
A structure is unpacked by default and can be defined using the struct
keyword and a list of member declarations can be provided within the
curly brackets followed by the name of the structure.
UNIONS:
• Unions are similar to structures that can contain different data types members
except they share the same memory location. Hence, it is memory efficient
data structure. But it also restricts the user to use one member at a time.
• Unions can also be declared as packed, but in the packed union, all the
elements must be of same size.
Syntax:
union
{ <Data type> <member 1>;
<Data type> <member 2>; ...; }
<union_name>;
Packed Unions:
typedef logic [7:0] byte_t;
typedef struct packed {
logic [15:0] opcode;
logic [1:0] Mod;
…
logic [2:0] Base;
} Instruction_t;
typedef union packed {
byte_t [3:0] bytes;
Instruction_t fields;
} Instruction_u;
Instruction_u inst;
[Link] = 16’hDEAD;
[Link][1] = 8’hBE;
inst[7:0] = 8’hEF;
inst == 32’hDEADBEEF;
CLASS TYPES
• A class is a user-defined data type that contains a collection of data
items and a set of subroutines that operate on that data. These data
items in a class are referred to as class properties, and its subroutines
are called methods.
• A class is like a template or blueprint that defines the structure and
behavior of objects. Once a class is defined, it can be used to create
multiple objects that share the same structure but can have different
data.
CLASS TYPES
SYNTAX:
class class_name;
<data type 1 / property 1 declaration>;
:
<data type p / property p declaration>;
<(method 1) task 1 / function 1 declaration>;
:
<(method q) task q / function q declaration>;
endclass
Example:
class int_operations;
//Properties
int i;
int j;
//Methods 2 properties i and j are of type int
task addprint();
$display(“i + j = %d”, i+j); 3 methods called
endtask addprint(), mulprint() and
task mulprint(); subprint()
$display(“i * j = %d”, i*j);
Endtask
task subprint();
$display(“i - j = %d”, i-j);
endtask
endclass
Properties and Methods:
Properties: These are variables that hold the state of the class. For
example, if you define a class representing a car, the properties might
include speed, color, and model.
Methods: These are functions or tasks that define the behavior of the
class. In the car example, methods might include start(), accelerate(), or
stop().
Class Objects: Objects are instances of a class type. When a class is
instantiated, the object is created, and memory is allocated for its
properties.
Features of Class Types:
Encapsulation: Bundles both data and behavior together.
Inheritance: One class type can extend another class, inheriting its
properties and methods.
Polymorphism: Allows different classes to define the same method in
different ways.
Abstraction: Hides implementation details and exposes only essential
features to the outside world.
Reusability: You can define class types once and reuse them
throughout your code.
Appends the ‘n’ individual string operands together. The
operands can be of string type or can be string literals.
The concatenation operator ({}) is used to combine
multiple signals or variables into a single signal. It is
denoted by curly braces {}.
Syntax: {signal1, signal2, ..., signalN}
The width of the resulting signal is the sum of the widths of
the concatenated signals.
Concatenation
Operators:
wire [3:0] a = 4'b1101;
wire [1:0] b = 2'b10;
wire [5:0] result;
assign result = {a, b}; // Concatenates a and b, result =
6'b110110
The replication operator is used to duplicate (or replicate)
a signal multiple times. It is written as n{} where n is the
number of times the expression inside {} should be
replicated.
Syntax:{n{signal}}
This creates n copies of the signal, concatenated together.
The width of the resulting signal is n times the width of
signal.
Replication wire [1:0] x = 2'b01;
Operators: wire [5:0] result;
assign result = {3{x}}; // Replicates x three times, result
= 6'b010101
Here, x is 2 bits wide, and using 3{x} replicates x three
times, resulting in a 6-bit signal: 010101.
Example:
wire [2:0] y = 3'b101;
wire [7:0] result;
assign result = {2{y}, 2'b11}; // Replicates y twice and concatenates
with 2'b11, result = 8'b10110111
Here, y is 3 bits wide, and the expression 2{y} replicates y twice,
making it 101101. This is then concatenated with 2'b11 to form the 8-
bit signal 10110111.
PROCEDURAL BLOCKS:
• In System Verilog, procedural blocks define how the behavior of a
design evolves over time, based on the change in signals.
• These blocks are fundamental to modeling sequential logic, event-driven
simulation, and testbenches.
• Procedural blocks contain sequential statements that execute within the
block, unlike continuous assignments which update concurrently.
• There are two main types of procedural blocks in System Verilog:
Initial blocks
Always blocks
Initial Block:
The initial block is executed only once at the start of the simulation. It's
commonly used in testbenches for initialization, stimulus generation, or
one-time setups (like reset signals).
Syntax:
initial begin
// Sequential procedural statements
end
Always Block:
The always block executes continuously during simulation. It triggers
every time an event (based on the sensitivity list) occurs. It is used to
describe both combinational and sequential logic.
Types of always Blocks:
• Combinational Logic (always_comb)
• Sequential Logic (always_ff)
• General Event Control (always @(*) or always @(sensitivity list))
Combinational Logic Block (always_comb):
• This block is specifically for combinational logic. It automatically
determines the sensitivity list (i.e., it reacts to changes in any of its
inputs).
Syntax:
always_comb begin
// Combinational logic
end
Example:
always_comb begin
sum = a + b; // Combinational logic: sum always equals a + b
end
Sequential Logic Block (always_ff):
The always_ff block is used for sequential logic where the behavior
depends on a clock or other control signals (flip-flop behavior). This
block requires that the sensitivity list include only a clock (and optionally
a reset).
Syntax:
always_ff @(posedge clk or negedge reset_n) begin
if (!reset_n)
q <= 0; // Asynchronous reset
else
q <= d; // Flip-flop behavior: q takes value of d at each clock edge
end
Example:
always_ff @(posedge clk) begin
if (reset)
count <= 0; // Reset the counter
else
count <= count + 1; // Increment on every clock edge
end
General always Block (always @(*) or always @(sensitivity list))
• This is the most flexible always block. The sensitivity list
(@(sensitivity list)) defines when the block should be triggered. Using
@(*) automatically creates a sensitivity list for all the signals used in
the block, making it combinational.
Syntax:
always @(posedge clk or posedge reset) begin
// Sequential or combinational logic
end
Example:
always @(posedge clk or posedge reset) begin
if (reset)
out <= 1'b0;
else
out <= in;
end