0% found this document useful (0 votes)
217 views

SV Concepts

Uploaded by

6R1A0427 Smruti
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)
217 views

SV Concepts

Uploaded by

6R1A0427 Smruti
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/ 76

Verification using SystemVerilog

-- Preetham Lakshmikanthan

© Mirafra Technologies 1
Table of Contents
1. Introduction to SV

2. Commonly Used Terminologies in SV

3. Data Types

4. Object-Oriented Programming (OOP) Concepts

5. SV Stratified Event Queue/Scheduler

6. SV Tasks and Functions

© Mirafra Technologies 2
Table of Contents Continued…
7. Verification Specific SV Constructs

8. Functional Coverage

9. Verification Plan and SV Testbench Architecture

10. Modelling Testbench Blocks for the RAM Design

11. Assertions

12. Direct Programming Interface (DPI)

© Mirafra Technologies 3
References
1. SystemVerilog for Verification: A Guide to Learning the Testbench
Language Features
Author(s): Chris Spear and Greg Tumbush
ISBN-10: 1461407141
ISBN-13: 978-1461407140
Publisher: Springer Publications (3rd Edition 2012)
Weblink: http://www.chris.spear.net/systemverilog/default.htm

2. www.testbench.in – SystemVerilog Tutorial


Weblink: http://www.testbench.in/SV_00_INDEX.html

© Mirafra Technologies 4
References Continued…
3. “SystemVerilog – UNIFIED HARDWARE DESIGN, SPECIFICATION,
AND VERIFICATION LANGUAGE” – The IEEE 1800-2012 LRM
Weblink: http://standards.ieee.org/getieee/1800/download/1800-2012.pdf

4. www.systemverilog.in – SystemVerilog Resources


Weblink: http://www.systemverilog.in/systemverilog_introduction.php

5. Writing Testbenches using SystemVerilog


Author(s): Janick Bergeron
ISBN-10: 1846280230
ISBN-13: 978-0387292212
Publisher: Springer Publications (2006 Edition)
© Mirafra Technologies 5
References Continued…
6. http://www.asic-world.com/systemverilog/tutorial.html – SystemVerilog
Tutorial

7. “ECE 745: ASIC VERIFICATION” – Dr. Meeta Yadav, North Carolina


State University
Weblink:
engineeringonline.ncsu.edu/onlinecourses/coursehomepages/FALL08/ECE745.html

8. Hardware Verification with SystemVerilog: An Object-Oriented


Framework
Author(s): Mike Mintz and Robert Ekendahl
ISBN-10: 0313262322
ISBN-13: 978-0313262326
Publisher: Springer Publications (2007 Edition)
© Mirafra Technologies 6
References Continued…
9. SystemVerilog Assertions Handbook, 3rd Edition … for Dynamic and
Formal Verification
Author(s): Ben Cohen, Srinivasan Venkataramanan, Ajeetha Kumari and Lisa Piper
ASIN: B0096CEVQM
Publisher: VhdlCohen Publishing

10. Verification Suite using SystemVerilog – A Complete Testbench Example


Weblink: http://wiki.usgroup.eu/wiki/public/tutorials/svverification

© Mirafra Technologies 7
1. Introduction to SystemVerilog (SV)

© Mirafra Technologies 8
Need for Verification

Today, the verification effort takes almost 70% of the total design cycle time. This stringent verification is needed

• Due to the complex functionality of present-day designs that could lead to more bugs
– Increase in features lead to an increase in logic functionality – more gates and flip-flops
– Multiple clocks and deeper pipelines are being introduced to improve performance
– Numerous power states are being added in designs to save energy

• To avoid bug escapes to silicon, which otherwise requires costly re-spins


– In 1994, Intel Corporation spent $475 million to replace flawed Pentium chips that had a floating point division bug

• To verify numerous interfaces and bus transactions present in SoCs, due to the integration of multiple
functional components on the chip

• To validate millions of lines of code written using different languages


– RTL is written in VHDL, testbenches in Verilog and functional models are coded in C

© Mirafra Technologies 9
Need for Verification Continued…
Verification Gap - the big challenge confronting the industry

Hardware Verification Languages


such as SystemVerilog are used
to reduce the verification gap

Diagram Reference:

Warren A. Hunt Jr.: Introduction: Special


Issue on Microprocessor Verifications.
Formal Methods in System Design 20(2):
135-137 (2002)

© Mirafra Technologies 10
Deliverables of an RTL Verification Engineer
– Develop a verification plan by reviewing the design specification
• Done by the verification lead by extracting features from the design specification
– Design and develop the various testbench components in the verification
environment
• These components must be bug free and designed in such a way that they are usable at
both the block level as well as the full-chip level
– Understand the working of various IPs, Bus Protocols and Interconnection
Architectures to develop concise and complete test-cases to achieve the coverage
goals
– Maintain the verification environment and append test-cases to the repository in
order to enhance the coverage
– Develop scripts to automate job submission for regressions and analyze reports
– Find bugs in the RTL code and report them to the RTL designer. A key point to note
is that it is not the job of a verification engineer to fix the bugs found
© Mirafra Technologies 11
Limitations of Verilog for Verification
 Weak randomization
o No constructs to easily constrain randomization.
For e.g.: Consider the case of a RAM with 1024 locations. Random numbers in Verilog are generated in the signed
range of values from -(2**32 – 1) to (2**32). Randomly generating addresses for testing of the RAM DUV is of no use
unless the address is constrained in the 0 to 1023 range.

 Limited constructs for handling large data for complex designs


o Verilog does not allow changing the dimensions of an array once it is declared.
For e.g.: Consider the case of network packets that vary in size from one packet to the next. In Verilog, an array
with the maximum packet size is declared. Hence, for smaller packets some elements are unused, which is a waste of
memory.

 Complicated way of validating the functionality of a design and capturing


the designer’s intent
o No pre-defined constructs to automatically capture the designer’s intent or to validate the functionality of a design.
For e.g.: It is extremely difficult to code and automatically validate a common bus request and its corresponding
grant functionality. Try coding and validating {if ‘request’ signal is true in the current clock tick, ‘grant’ signal must be true
anytime within the next 4 clock ticks and then the ‘request’ signal becomes false immediately following ‘grant’} in Verilog.
© Mirafra Technologies 12
Limitations of Verilog for Verification Continued…

 Lack of standardized interfaces or hooks to easily connect testbenches to


the DUV
o Ports and clocks are connected via port maps and these occur at all places where instantiations are done. No
unique interface is present in Verilog to help standardize this.

 Code re-use is very minimal, requiring repeating similar code for different
tests
o Lack of an Object Oriented Programming approach severely limits the amount of code that can be re-used in
Verilog.

 No way of the verifying functional coverage of any design as only code


coverage is allowed by the IEEE 1364-2001 standard
o Although 100% line coverage, path coverage, expression coverage and toggle coverage is achieved for a design, it
still does not mean that 100% functionality of the design has been covered.

© Mirafra Technologies 13
Slide ref. from: “SystemVerilog Introduction & Usage” by Johny Srouji in an IBM Verification Seminar
http://www.research.ibm.com/haifa/Workshops/verification2004/papers/system_verilog_overview-ibm-symposium-johny_srouji.pdf

Features of SV over Verilog

Evolution
of
Language
Features Verilog 2001

14
© Mirafra Technologies
Features of SV over Verilog Continued…
• With SystemVerilog, a complete verification environment can be built with its
new features such as:
– Dynamic data types and dynamic memory allocation
– Interfaces
– Object Oriented Programming (OOP)
– Constraint Randomization
– Functional Coverage constructs
– Assertions

© Mirafra Technologies 15
History of SystemVerilog
• Background:
– It was developed originally by Accellera (www.accellera.org) to dramatically improve productivity in
the design of large gate-count, IP-based, bus-intensive chips
– Originally intended to be the 2005 update to Verilog
– Contains hundreds of enhancements and extensions to Verilog
– It was standardized by IEEE -1800 and published in 2005
– Officially superseded Verilog in 2009
– The current standard is IEEE 1800-2012
• Purpose:
– Is a Hardware Design and Verification Language (HDVL)
– Provides system-extensions to Verilog 2001 (IEEE 1364-2001). The IEEE 1364-2001 Verilog
standard is a proper subset of SystemVerilog.
• Backward Compatibility:
– Backward compatible with Verilog 1995 / Verilog 2001
• Tool Support:
– Supported by most Electronic Design Automation (EDA) tool vendors: Mentor Graphics, Cadence
Design Systems and Synopsys
© Mirafra Technologies 16
2. Commonly Used Terminologies in SV

© Mirafra Technologies 17
Diagram ref. source: http://www.cirrus.com/en/pubs/proBulletin/EP9312_PB.pdf

SoC: System-on-Chip
Definition: System-on-Chip or SoC is an integrated circuit which incorporates all necessary components of
a computing system
Typical components found on an SoC are:
– A microcontroller, microprocessor or DSP core(s);
– Memory blocks including ROM, RAM, EEPROM and flash memory;
– Interconnection buses;
– Timing sources including oscillators and Phase-Locked Loops (PLLs);
– Peripherals including counter-timers, real-time timers and power-on reset generators;
– External interfaces including industry standards such as USB, FireWire, Ethernet, UART and SPI; Timing sources
– Analog interfaces including ADCs and DACs; and
– Voltage regulators and power management circuits.
Interface

Cirrus Logic EP9312


SoC Architecture

Memory

© Mirafra Technologies Read Only Random Access 18


Memory Memory
Testbench
Definition: An RTL testbench is the infrastructure
needed to run RTL verification
Features:
• A testbench is a separate entity from the RTL design
or the Design Under Verification (DUV)
• It is well structured and modular
• It is written in an HDL Testbench
• Any testbench should meet the following objectives: Test
Scoreboard and Checker
– Drive stimulus to the inputs of the RTL design case
– Monitor the response at the output of the RTL design
– Automatically check the response with expected results
– Maintain results along with the associated coverage metrics
Monitor Monitor
– Create warning, error and coverage reports

Typical Functional Blocks of the DUV Response


Generic Testbench Architecture Driver
Instance Generator

© Mirafra Technologies 19
Protocol
Definition: Protocol is a “set of rules” defined that govern the transfer of data as well as control information between
devices. For proper communication to happen, the protocol must define the syntax of data and address formats, and
the semantics of transfer operations which includes the arbitration behavior when device contention occurs.
Features:
• Protocols help eliminate bus contention issues and also help avoid deadlock between devices.
• The transfers or transactions associated with a protocol can be represented with a behavioral model that accepts
signal inputs and produces outputs.
• This behavioral model helps in analyzing the system prior to building and testing the actual hardware. It is
commonly referred to as the Bus Functional Model (BFM) or Transaction Verification Model (TVM).
Consider the various components of a design communicating with each other through a common bus. In such a case,
to ensure that proper communication happens, a bus protocol such as AHB is used. Based on the design’s bandwidth
and other constraints, an appropriate protocol can be chosen. Features of the AHB protocol are listed here:
– AHB stands for Advanced High-performance Bus.
– It is a revised version of the AMBA (Advanced Micro-controller Bus Architecture) protocol from ARM (www.arm.com).
– Supports several bus masters, burst transfers and pipelined operations.
– When multiple components communicate with each other on a common bus in a master-slave configuration, AHB uses an arbitration scheme
to avoid bus contention issues.
– For more information, please refer http://en.wikipedia.org/wiki/Advanced_Microcontroller_Bus_Architecture and also go through the references
and links given on that page.
20
© Mirafra Technologies
Protocol Continued…
An example of the resolution of a bus contention issue in an AMBA AHB based system is explained. The
main components of the system, as seen from the block diagram, are two masters (Master1 and Master2),
a slave and an arbiter. The data transfer between a master and the slave is through a common bus.

© Mirafra Technologies 21
BFM-Bus Functional Model
Definition: The Bus Functional Model or BFM is a behavioral description of the functionality of a given bus protocol

Features:
• The purpose of these models is to simulate system bus transactions prior to building and testing the actual
hardware
• Bus functional models are simplified simulation models that accurately reflect the I/O level behavior of a device
without modeling its internal computational abilities
• A BFM has two interfaces. On one side is a functional interface that accepts transactions and on the other side is
a pin interface that operates the requisite bus protocol. The functionality of the BFM is to bridge those two
interfaces
• BFMs are pre-verified and commonly used in testbenches as drivers and monitors
• Use of BFMs speeds up the process of verification
• For many standard protocols, BFMs are available as off-the-shelf Intellectual Properties (IPs)
• They are non-synthesizable

Examples:
A microprocessor BFM, a RAM BFM, a BFM for the AHB protocol explained on the previous slide. The
bus functional model of a microprocessor would be able to generate Peripheral Component Interconnect (PCI) read
and write transactions to a PCI device model to initialize and test its functionality
22
© Mirafra Technologies
VIP-Verification Intellectual Property
Definition: VIP is an acronym for Verification Intellectual Property. VIPs are a set of completely verified, fully
functional, re-usable and ready to use verification modules that typically consist of BFMs, traffic drivers, protocol
monitors, and functional coverage blocks that easily plug into testbenches.
Characteristics:
• VIPs are standards-compliant, plug and play modules that help in reducing the overall verification time
• They enable verification engineers to completely focus their efforts in verifying designs rather than setting up
complex verification environments
• VIP blocks integrate seamlessly into advanced verification environments, where testbenches are built using a mix
of languages and methodologies like VHDL, Verilog, SystemC and UVM
• In order to support a mix of languages and methodologies, translation wrappers are written resulting in a multiple
layered implementation. This layered approach limits simulation speed
• VIPs are analogous to design IPs or Implementation IPs (IIPs)

The AHB protocol BFM is an example of a VIP which can drive transactions on the AHB bus

DUV

© Mirafra Technologies 23
Regression
Definition: Regression is the process of re-running verification of the DUV DUV RTL
with a known set of test cases. This is done in order to ensure that the Code Change
functionality of the DUV is correct, and that new code changes have not
introduced any new bugs in the design.

Features: Run Regression


• Regressions are run every time the RTL design changes. These changes Test Suite
could be due to:
– New additions and/or modifications that are made to the RTL design
– A bug being fixed in the RTL design
• Ideally, the regression test suite is made up of many small tests, instead Regression
of a few large tests. This helps isolate errors faster. Test(s) Fail Results
• They are regularly run at different phases of the design and verification
cycle. Test(s) Pass
• Regressions should be run before releasing the design for synthesis or
before generating coverage reports to ensure that the design is clean. DUV RTL Code Clean

© Mirafra Technologies 24
Randomization
Definition: Randomization is the process of creating random stimuli.

Consider that all positive 32-bit integers need to be verified for some purpose. The range for this is from 0 to
(2^32)-1. In exhaustive testing, all the 2^32 integer values need to be verified. However, in random testing
only a few random values from the range are verified, as long as they are valid and legal values and satisfy
the coverage metrics. For the above example, the coverage metrics state that 1000 unique representative
positive integers are good enough to verify all the positive 32-bit integers. Then random testing would involve
randomly generating 1000 unique values within the 0 to (2^32)-1 range for verification.

Exhaustive testing, which, in many cases is impossible to do, or takes humongous amounts of time, could
thus be replaced with random testing.

In Verilog, the $random() function is used to generate random numbers. The function returns a new 32-bit
random number each time it is called. This random number is a signed integer - it can be positive or negative.

Randomization can be applied on data and control signals and is extensively used during verification.

Directed testing checks specific features of a design and can only detect expected bugs. Random testing
detects bugs that one did not anticipate.
© Mirafra Technologies 25
Constrained Random Verification
Definition: Verification using automatically generated constrained random stimuli is called as Constrained
Random Verification. The constraints or rules determine the legal values that can be assigned to those
random variables.

Consider a machine whose instructions have an opcode and two 32-bit operands, op_a and op_b. The
constraint here is that it is necessary for ‘op_a’ to only take values less than h’ff, while ‘op_b’ has to only take
values greater than h’ff.
– Generating random numbers for the above example and then constraining them in a Verilog testbench is tedious involving many
lines of code
– Imagine specifying the constraint ((op_a < h’ff) && (op_b > h’ff)) such that the generated random numbers automatically adhere to
those constrained values. Much easier, isn’t it ?

Constrained random verification is a key feature and is used extensively in testbenches


– Helps to achieve better functional coverage and in testing corner cases
– Using this feature drastically reduces simulation time, thereby contributing to the reduction in the verification gap

© Mirafra Technologies 26
Assertion Based Verification (ABV)
Definition: An assertion is a statement that specifies behavior of a design. Verification of a design using
assertions is called as Assertion Based Verification.

Features of Assertions:
• Analogous to assertions used in programming languages like C, C++ or Java
• They are used to:
– Document the functionality of the design
– Check whether the intent of the design is met over simulation time
• They can be specified by:
– The design engineer as part of the RTL design
– The verification engineer as part of the testbench
• An assertion is a behavioral statement that is required to be true, and a directive to verification tools to
verify that this statement holds true

Examples:
1) Assert the bus grant happens not more than 6 clock cycles after the bus request arrives
2) Assert that the divide by zero condition never occurs during the division operation

© Mirafra Technologies 27
3. Data Types

© Mirafra Technologies 28
Overview of Verilog data types

Data Types

• A wire is a net type used to model


Nets Variables physical connections - it does not store
values, but takes the value of its driver

• A reg variable is used to model


storage elements such as latches, flip-
wire reg flops and memories - it stores a value
wand, wor, integer
tri, time
triand, trior real • An integer is a variable of 32-bit width
tri0, tri1, trireg realtime which stores signed values

© Mirafra Technologies 29
Overview of Verilog data types Continued…
 The value set for variables and nets contains 4-values: 0, 1, x, and z
0 — represents a logic zero value or a false condition
1 — represents a logic one value or a true condition
x — represents an unknown logic value
z — represents a high-impedance or open circuit value

 A net or reg declaration without a range specification is considered 1-bit


wide and is known as a scalar. Multiple bit net and reg data types are
declared by specifying a range and are known as vectors

 Verilog data types lead to increased simulation run times and more
memory utilization because they are static in nature - all variables are
alive for the entire simulation time

© Mirafra Technologies 30
New data types in SystemVerilog
The following SV data types were introduced to help in efficient coding of testbenches, in reducing
simulation run times and in reducing memory usage.

 Logic
 Two-state
 int, shortint, longint, bit, byte
 Packed arrays, Unpacked arrays, Mixed Multi-dimensional arrays, Dynamic arrays,
Associative arrays and Queues
 Structures and Unions (Aggregate types)
 Strings (Enhanced from Verilog)
 Events (Enhanced from Verilog)
 User-defined data type
 Enumerated data type
 Classes (explained in detail in the next Chapter)

© Mirafra Technologies 31
Logic
Need for the Introduction of the Definition: The logic data type is a 4-state type that can take values 0, 1, x and z. It
Logic data type in SV can inter-changeably be used in place of the wire and reg data types as long as the
Verilog 2001 has wire and reg data types and users are wire data type does not have multiple drivers.
confused with the rules on their usage. SystemVerilog
has introduced the logic data type which can be used in Syntax : logic variable_name;
place of both the wire and the reg data types, with the
caveat that the wire does not have multiple drivers. Examples:
Verilog 2001: logic rst_n, clk; // 1-bit wide 4-state variables – ‘rst_n’ and ‘clk’
module pl_soc (input wire ip1, input wire ip2, logic [31:0] word32; // A 32-bit wide 4-state variable – ‘word32’
output reg op1, output wire op2);

confusing? confusing? Characteristics of the Logic data type:


simpler! • By default this is an unsigned data type and its initial value is x
SystemVerilog:
module pl_soc (input logic ip1, input logic ip2, • Cannot be driven by multiple drivers. The net data type ‘wire’ is to be used in case of
output logic op1, output logic op2);
multiple drivers.
Verilog 2001:
wire w;
• In addition to being a variable, it can be driven by continuous assignments and gates
assign w = memdata;
• If all signals are declared using the logic type, SystemVerilog infers a variable or net
reg r;
always @*
based on context
r = memdata;

SystemVerilog: Applications of the Logic data type:


// Easier defining everything as logic type
logic w;
• The logic data type can have only one driver and hence can be used to find netlist
assign w = memdata; bugs. If all the signals in a design are declared as logic rather than wires and regs,
logic r; then a compilation error will occur for cases where multiple drivers for a signal are
always @*
r = memdata; present. It makes the code simpler and readable in most cases. 32
Two-State (int, shortint, longint, bit, byte)
Need for the Introduction of Two- Definition: A two-state data type is something that can only take values 0 and 1. int,
State Logic data types in SV shortint, longint, bit and byte are the new 2-state data types introduced in SV. By default
SystemVerilog has introduced several 2-state (0 and 1 int, shortint, longint and byte are signed data types, while bit is an unsigned data type.
value) data types to improve simulator speed and reduce
its memory usage. In comparison, the use of Verilog Syntax : 2_state_data_type variable_name;
2001 4-state (0, 1, x and z value) data types require
additional bits to encode the x and z values, thereby Examples:
slowing down simulation and increasing memory usage
int a; // ‘a’ is a 2-state, 32-bit signed integer
shortint b; // ‘b’ is a 2-state, 16-bit signed integer
Two-State Type Description longint c; // ‘c’ is a 2-state, 64-bit signed integer
bit d; // ‘d’ is a 2-state, single bit value Can count upto 127 as this is a signed data type
int 32-bit size, signed byte e; // ‘e’ is a 2-state, 8-bit signed integer
shortint 16-bit size, signed bit [7:0] f; // ‘f’ is a 2-state, 8-bit unsigned integer Can count upto 255 as this is an unsigned data type

longint 64-bit size, signed Characteristics of Two-State data types:


bit User-defined size, unsigned • Their initial value is 0 and they cannot be used to represent the ‘x‘ un-initialized state
byte 8-bit size, signed • Can assign 4-state values to a 2-state variable - x and z values are automatically
converted to a 0 value
Applications of Two-State data types:
• These data types are mostly used only in The $isunknown() operator is used to check whether any bit of an expression or a
testbenches. Care must be taken to connect 2- variable is ‘x’ or ‘z’. It returns a value 1, if ‘x’ or ‘z’ is found
state variables in a testbench with 4-state
Example:
variables in the DUV. ‘x’ and ‘z’ values received if(!($isunknown(somevar)==1))
from the DUV might automatically be converted $display (“ 2-state variable detected”);
to 0’s in the testbench leading to undesirable else
33
behavior © Mirafra Technologies $display (“ 4-state variable detected”);
Review of the Array data type from Verilog 2001
An array is a collection of elements, all of the same type, and accessed using its name and one or more indices. The array
data type for a net or variable is an aggregate declaration that was either a scalar or a vector

Examples:

reg a[7:0]; // scalar reg ‘a’


wire [0:7] b[7:0]; // Eight-bit wide vector wire ‘b’ indexed from 0 to 7
reg [7:0] memory[0:255]; // Declaration of a ‘memory’ of 256 8-bit registers. The indices are 0 to 255

reg [1:16] rega; // A 16-bit register is not the same


reg mema [1:16]; // as a memory of 16 1-bit registers

Verilog 2001 required that the low and high array limits must be part of the array declaration. SystemVerilog has introduced
the compact array declaration style, where just giving the array size along with the array name declaration is enough

Examples:

 Single-dimension array declaration


int sdarr[0:15]; // Verilog 2001 verbose declaration style – 0 and 15 are the lower and higher array limits
int sdarr[16]; // Same example as above, but using SystemVerilog’s compact declaration style – only the array size (16) is given

 Multi-dimension array declaration


int mdarr[0:7][0:7]; // Verilog 2001 verbose declaration style
int mdarr[8][8]; // Same example as above, SystemVerilog’s compact declaration style

© Mirafra Technologies 34
Packed Arrays
Need for the Introduction of Definition: A packed array is one where the dimensions of the array is declared
Packed Arrays in SV before the array object name
SystemVerilog has introduced packed arrays as a <range (optional)>*
mechanism for sub-dividing a vector into sub-fields, Syntax : <data_type> <range (optional)>* <array_name>; implies 0 or more
which are accessed as array elements. The vector range declarations
can be accessed as a whole (single value) as well Examples:
as individual array elements. A packed 64-bit
register can be accessed as a single entity or as reg single; // A packed 1-bit register
bit [31:0] word_arr; // Packed array of 32-bit vectors
parr[3] parr[2] parr[1] parr[0]
eight 8-bit values or as sixteen 4-bit values.
reg [0:15] myreg; // A packed 16-bit register [7:0] [7:0] [7:0] [7:0]
Characteristics of a Packed Array: logic [3:0][7:0] parr = 32’h0; // Initializing a packed 32-bit vector with
// four 8-bit sub-fields
• It is stored as a contiguous set of bits
• It can be made of only single bit data types (bit, logic, reg), enumerated types (explained later), and recursively other packed
arrays
• If a packed array is declared as signed, then the array viewed as a single vector shall be signed. The individual elements of the
array are unsigned unless they are of a named type declared as signed
• Packed arrays allow arbitrary length integer types; therefore, a 48-bit integer can be made up of 48 bits
• The maximum size of a packed array can be limited, but shall be at least 65536 (2^16) bits
• The following operations can be performed on packed arrays. Assume the declaration of an 8-bit packed array ‘MPA’ for the
examples shown.
– Assignment of an integer value. Example: MPA = 8'b10101010;
– Use of the packed array as an integer in an expression. Example: if ((MPA + 4) > 16) ….. ;
Applications of Packed Arrays:
35
• They are used to store packet structures on which bit-select and part-select operations could be performed
Unpacked Arrays
Need for the Introduction of Definition: An unpacked array is one where the dimensions of the array is declared
Unpacked Arrays in SV after the array object name
SystemVerilog has introduced unpacked arrays so
that one can assign to or manipulate entire arrays Syntax : <data_type> <array_name> <range> ; + <range>+ implies 1 or
at once more range declarations

Examples:
int uparr[0:15][0:31]; // Unpacked array declaration using ranges
int uparr[16][32]; // Same as the above declaration, but using array sizes
real float_point[0:1023]; // Unpacked array of real type
int iuarr[4]=‘{4,3,2,1}; // Initializing an unpacked array of 4 elements
byte banner[0:12] = "hello asics\n"; // String literal assigned to an unpacked array of bytes

Characteristics of an Unpacked Array:


• The unpacked dimensions can be arranged in memory in any way that the simulator chooses – does not have to be contiguous
• They can be of any data type
• If an unpacked array is declared as signed, then this applies to the individual elements of the array, since the whole array
cannot be viewed as a single vector
• The expressions that specify an address range shall be constant integer expressions
• Implementations may limit the maximum size of an unpacked array, but they shall allow least 16777216 (2^24) elements
• They could be fixed-size arrays, dynamic arrays, associative arrays or queues (explained in later slides)
• SystemVerilog simulators store each element on a 32-bit word boundary. An unpacked array, such as the one shown in
following example, stores the values in the lower 8-bits of the 32-bit word boundary, while the upper 24 bits are unused:
© Mirafra Technologies 36
Unpacked Arrays Continued…
Example:
bit upkd_arr[0:2][0:7];

32-bit word boundary


unused space - used space -
upper 24-bits lower 8-bits
upkd_arr[0] 7 65 4 321 0
upkd_arr[1] 7 65 4 321 0
upkd_arr[2] 7 65 4 321 0
31 24 23 16 15 8 7 0

Applications of Unpacked Arrays:


• They are used to model Random Access Memories (RAMs), Read Only Memories (ROMs) and register files where one
element is accessed at a time

© Mirafra Technologies 37
Operations on Arrays
SystemVerilog allows the following operations to be performed on all arrays, packed or unpacked. Assume that arrays X and Y
in the examples below are of the same type and size.

• Reading and writing the entire array. E.g., X = Y

• Reading and writing a slice of the array. E.g., X[0:7] = Y[8:15]

• Reading and writing an element of the array. E.g., X[10] = Y[20]

• Equality operations on the array or slice of the array. E.g., (1) if (X==Y)……
(2) while (X[0:7] != Y[8:15])…..

These are the most commonly used operations on arrays. A few other operations are present, the details of which the learner
can obtain from page 110 of reference [3] - The SystemVerilog IEEE 1800-2012 LRM.

© Mirafra Technologies 38
Mixed Multi-Dimensional Arrays
SystemVerilog allows the mixed use of packed and unpacked dimensions in an array definition
leading to a mixed multi-dimensional array
Example:
logic [2:0][9:0] mymix_array [0:3] [0:5] [0:7]; // Is a mixed 5-dimensional array with 2 packed
// dimensions – [2:0] and [9:0], and 3 unpacked
// dimensions - [0:3], [0:5] and [0:7]

Multi-dimensional array access via indexing must adhere to the following rules:
– All unpacked dimensions are first referenced from the left-most to the right-most dimension in that order
– All packed dimensions are then referenced from the left-most to the right-most dimension in that order

Example:
Left Right Left ….….. Right
logic [2:0][9:0] mymix_array [0:3] [0:5] [0:7];

The 0 index of the array is from the 1st unpacked dimension [0:3]
The 4 index of the array is from the 2nd unpacked dimension [0:5]
The 6 index of the array is from the 3rd unpacked dimension [0:7]
mymix_array [0] [4] [6] [2] [7] = 1’b1; The 2 index of the array is from the 1st packed dimension [2:0]
The 7 index of the array is from the 2nd packed dimension [9:0]
© Mirafra Technologies
39
Mixed Multi-Dimensional Arrays Continued…
Examples to see how different dimensions of mixed arrays are laid out in memory to understand how the array
elements are accessed
bit [0:2]mix_arr1[0:1][0:3];
(Ex1)

3 2 1 0
0
1
0 2

bit [3:0][7:0]mix_arr2[0:2];
(Ex2)
mix_arr2[0][3] mix_arr2[0][0]
mix_arr2[0][1][6]

mix_arr2[0] 7 65 4 3 21 0 7 65 4 3 21 0 7 65 4 3 21 0 7 654 3 21 0
mix_arr2[1] 7 65 4 3 21 0 7 65 4 3 21 0 7 65 4 3 21 0 7 654 3 21 0
mix_arr2[2] 7 65 4 3 21 0 7 65 4 3 21 0 7 65 4 3 21 0 7 654 3 21 0

mix_arr2[1][3][4] mix_arr2[2][2] mix_arr2[1][1] mix_arr2[2][0]


© Mirafra Technologies 40
32-bit word boundary
Dynamic Arrays
Definition: A dynamic array is an unpacked array whose size can be set or changed
Need for the Introduction of at run time. The space for a dynamic array does not exist until the array is explicitly
Dynamic Arrays in SV created at run-time.
The Verilog 2001 array type is a fixed-size array,
which has already been set at compile time. For the Syntax : <data_type> array_name [];
case where the size of the array is not known until
run-time, SystemVerilog has introduced dynamic
arrays that can be allocated and re-sized during Examples:
simulation so that a minimal amount of memory is
used. integer i_dynarr[]; // Dynamic array of integers
bit [31:0] word_dynarr[]; // Dynamic array of 32-bit vectors
integer dd_dynarr[8][]; // Fixed-size unpacked array composed of 8 dynamic sub-arrays of integers
integer md_dynarr[][]; // A dynamic array of dynamic arrays of integers
Characteristics of a Dynamic Array:
• It is declared with empty square brackets []. This means that the array size is not specified at compile time, rather it will
be given later at run time
• The default size of an un-initialized dynamic array is 0
• Dynamic arrays support all variable data types as element types, including arrays
• An out-of-bound access in a dynamic array leads to a run-time error

Applications of Dynamic Arrays:


• Say random control signals need to be generated by the testbench during simulation. If a fixed-size array is used, it
would have to be sized large enough to hold the maximum number of signals possible. In reality, only a subset of control
signals would be used, thus wasting the remaining memory. A dynamic array that can be allocated and re-sized during
simulation will avoid this unnecessary memory allocation. © Mirafra Technologies 41
Dynamic Array Methods

SystemVerilog provides a constructor and built-in methods to manipulate dynamic arrays. The methods or functions are called
after the dynamic array object name with a period “.” between the object name and the function name.

• Constructor new[value]: Sets the size of a dynamic array and initializes its elements or changes the size of the array at
run-time. If the value is zero, the array shall become empty. If the value is negative, then it is an error.

• Function int size(): The size() method returns the current size of a dynamic array or returns zero if the array has not been
created

• Function void delete(): The delete() method empties the array, resulting in a zero-sized array.

© Mirafra Technologies 42
Dynamic Array Methods Continued…
dyn1 dyn2 0
1
Example:
2
int dyn1[], dyn2[]; // Declare 2 dynamic arrays – dyn1 & dyn2 3
int size1;
0
initial 1
begin 2
dyn1=new[4]; // Allocate space for 4 elements
3
size1 = dyn1.size(); // Returns size of dyn1, which is 4

dyn2=dyn1; // Copy the ‘dyn1’ array 5 0


10 1
15 2
dyn2= ‘{5, 10, 15, 20}; // Modify the copy
20 3

dyn1=new[7](dyn2); // Allocate space for 7 elements & copy the existing elements 5 0
10 1
copied elements
15 2
dyn1.delete(); // Delete elements of the dynamic array 20 3
end
4
5 new elements
© Mirafra Technologies dyn1 6 43
Associative Arrays
Need for the Introduction of Definition: An associative array is an unpacked array data-type in SV. It does not have
Associative Arrays in SV any storage allocated until it is used, and the index type used to access elements is not
In addition to being able to handle to a very large
restricted to integers.
address space, SystemVerilog introduces
associative arrays that are used to store sporadic Syntax : <data_type> array_name [index_type];
where, index_type is the data_type to be used or can be the wildcard “*”
or sparse data entries. SV allocates memory for an
element only when data is written into the
associative array. This is a big advantage in that it Examples:
saves tremendous amounts of memory space in integer i_array[*]; // Un-initialized associative array of integers (unspecified index)
comparison with dynamic arrays where the full integer array_s[string] = `{“INIT”:0, “DEEPSLEEP”:30, “FULLPOWER”:10, “MEMSLEEP”:20“, default:-1};
memory is allocated even if only one element is // Initialized associative array of integers, indexed by string
written into it. In Verilog array indices can only be bit [3:0] array_a[int]; // Un-initialized associative array of a 4-bit vector, indexed by int
integer values. However, associative array indices initial
in SV can be of any type. begin
array_a[0] = 4’b0101;
Memory allocation depiction if “array_a” from the array_a[8] = 4’b0111;
example was declared using: array_a[30] = 4’b1101;
array_a[31] = 4’b0110;
end
A standard array (Contiguous) An associative array (Non-Contiguous)
0 4’b0101 0 4’b0101
Memory :::
No memory allocated
allocated for 8 4’b0111 8 4’b0111
:::
for unused
even unused elements
elements :::
30 4’b1101 30 4’b1101
44
31 4’b0110 31 4’b0110 © Mirafra Technologies
Associative Arrays Continued…
Characteristics of an Associative Array:
• It can be stored by the simulator as a hash (lookup) table for extremely fast access of its elements. A hash table
contains an array of groups of elements. A function called hash function generates a unique key to compute the index
into this array, from which the correct array element value is obtained
• Associative array elements are unpacked
• The type of the array index used to access elements is restricted to int, integer, string, class and the wildcard “*”
– For a wildcard associative array, non-integral index values are illegal and a string literal index is automatically cast to a bit vector of equivalent size
• Elements in an associative array can be accessed in a similar way as those in a one-dimensional array
• If an attempt is made to read an invalid (non-existent) associative array entry, then the simulator will issue a warning and
will return the value ‘x’ for a 4-state integral type or a value ‘0’ for a 2-state integral type

Applications of Associative Arrays:


• They are used to model Content Addressable Memories (CAMs)
• Random read or write tests for verification of memories could use associative arrays for storing data only for addresses
which have been written. This would take up significantly much lesser memory than the entire array normally used in
Verilog.

© Mirafra Technologies 45
Examples adapted from source: [3] The SystemVerilog IEEE 1800-2012 LRM, Pages 121 and 122

Associative Array Methods


SystemVerilog provides several built-in methods to manipulate associative arrays as well as iterate over its indices. These
methods or functions are called after the associative array object name with a period “.” between the object name and the
function name. The function arguments (if any) are inputs.
• Function int num() and Function int size(): Return the number of entries in the associative array. If the array is empty, then
return 0.
Example 1:
integer imem[*]; // Un-initialized associative array of integers (unspecified index)
imem[ 2’b3 ] = 1; // Populating element number 2’b3 of imem
imem[ 16’hffff ] = 2; // Populating element number 16’hffff of imem
imem[ 4b’1000 ] = 3; // Populating element number 4’b1000 of imem
$display( "%0d entries\n", imem.num()); // prints "3 entries"

• Function void delete(): The delete() function removes all the elements in the array
• Function void delete(data_type index): Removes the entry at the specified index. If the entry to be deleted does not exist,
the function issues no warning.
Example 2:
integer map[string];
map[ “data" ] = 1;
map[ “address" ] = 2;
map[ “control" ] = 3;
map.delete( “control" ); // Remove entry whose index is “control" from array "map“, i.e., value 3
map.delete(); // Remove all entries from the associative array "map"
© Mirafra Technologies 46
Examples adapted from source: [3] The SystemVerilog IEEE 1800-2012 LRM, Page 122

Associative Array Methods Continued…


• Function int exists(data_type index): Checks if an element exists at the specified index within the given array. It returns 1 if
the element exists, otherwise it returns 0
Example 3:
integer map[string];
integer count = 0;
map[ “data" ] = 1;
map[ “address" ] = 2;
map[ “control" ] = 3;
if(map.exists( “data" )) // Checks to see whether an element exists at the index ‘data’ in array ‘map’.
// In this case the value 3 exists and hence the function returns a 1
count = count + 1;
• Function int first(data_type index): Assigns to the given index variable the value of the first (smallest) index in the associative
array. It returns 0 if the array is empty, and 1 otherwise

Example 4:
string s;
integer map[string];
map[ “address" ] = 1;
map[ “control" ] = 2;
map[ “data" ] = 3;
if(map.first(s)) // Assigns the first index “address” to the string ‘s’ and returns 1 as the array is not empty
$display( "First entry is : map[ %s ] = %0d\n", s, map[s] ); // Display statement is executed to show “First entry is : map[address] = 1”

© Mirafra Technologies 47
Examples adapted from source: [3] The SystemVerilog IEEE 1800-2012 LRM, Page 123

Associative Array Methods Continued…


• Function int last(data_type index): Assigns to the given index variable the value of the final (largest) index in the associative
array. It returns 0 if the array is empty, and 1 otherwise
Example 5:
string s;
integer map[string];
map[ “address" ] = 1;
map[ “control" ] = 2;
map[ “data" ] = 3;
if(map.last(s)) // Assigns the last index “data” to the string ‘s’ and returns 1 as the array is not empty
$display( “Last entry is : map[ %s ] = %0d\n", s, map[s] ); // Display statement is executed to show “Last entry is : map[data] = 3”

• Function int next(data_type index): Finds the smallest index whose value is greater than the given index argument. If there is a
next entry, the index variable is assigned the index of the next entry, and the function returns 1. Otherwise, the index is
unchanged, and the function returns 0
Example 6:
string s;
integer map[string];
map[ “address" ] = 1;
map[ “control" ] = 2;
if(map.first(s)) // Assigns the first index “address” to the string ‘s’ and returns 1 as the array is not empty
do
$display( "%s : %d\n", s, map[s]);
while(map.next(s)); // This do-while loop iterates twice, the first time for “address” and the second time for “control”. 48
// After that the map.next(s) function returns a 0 as there are no more indices, and the loop terminates.
Examples adapted from source: [3] The SystemVerilog IEEE 1800-2012 LRM, Page 123

Associative Array Methods Continued…


• Function int prev(data_type index): Finds the largest index whose value is smaller than the given index argument. If there
is a previous entry, the index variable is assigned the index of the previous entry, and the function returns 1. Otherwise,
the index is unchanged, and the function returns 0
Example 7:
string s;
integer map[string];
map[ “address" ] = 1;
map[ “control" ] = 2;
if(map.last(s)) // Assigns the last index “control” to the string ‘s’ and returns 1 as the array is not empty
do
$display( "%s : %d\n", s, map[s]);
while(map.prev(s)); // This do-while loop iterates twice, the first time for “control” and the second time for “address”.
// After that the map.prev(s) function returns a 0 as there are no more indices, and the loop terminates.

© Mirafra Technologies 49
Queues
Definition: A queue is a variable-size, ordered collection of homogeneous (same type)
Need for the Introduction of
Queues in SV unpacked array elements. It supports constant time access to all its elements as well as
constant time insertion at the beginning and removal at the end of the queue respectively.
The queue data type was introduced in
SystemVerilog to combine the dynamic storage ctrl_names
property and fast access of elements. The main Syntax : <data_type> queue_name [$]; Position 0 Position 1
advantage is that one can add or remove elements
anywhere in a queue, without the storage penalty control enable
of a dynamic array which has to allocate a new
array and copy its entire contents. Also, as done in
a fixed-size array, any element in the queue can be Examples:
accessed directly using an index without any need string ctrl_names[$] = { “control", “enable"}; // An initialized queue of
for accessing elements before it. // strings called “ctrl_names”
// with two elements
integer Q[$] = { 4, 2, 7 }; // An initialized integer queue called “Q”
// containing three integers
byte bytq[$]; // A queue of bytes
Characteristics of a Queue:
Q
• Each element in a queue is identified by a number that represents its position within the
Position 0 Position 1 Position 2
queue, with 0 representing the first, and $ representing the last. In the second example
4 2 7
shown, the integer queue ‘Q’ stores the value 4 at position 0. This is the first element of
the queue. Value 2 is stored at position 1 and finally value 7 is stored at position 2,
which is the last element of the queue
• A queue can have variable length, including a length of zero. This makes the queue
data type an ideal candidate that can be shrunk or grown as elements are deleted or
added to it, without fixing an upper limit on its size 50
© Mirafra Technologies
Queues Continued…
Characteristics of a Queue (Cont’d):
• The empty array literal {} is used to denote an empty queue
• If known, an upper limit index ‘N’ of the queue can be set. This is known as a bounded queue and shall be limited to
have indices not greater than ‘N’ (its size shall not exceed N+1)
– For e.g.: bit limitq[$:255]; // A bounded queue whose maximum size is 256 bits
• SystemVerilog automatically allocates space if the queue runs out of memory when adding additional elements.
Hence, the new[] constructor used in allocating memory for arrays, is never used for queues
• A queue is similar to a one-dimensional unpacked array, except that it grows and shrinks automatically. Therefore,
like arrays, queues can be manipulated using the indexing, concatenation, slicing and equality operators
• Elements of a queue are stored in contiguous locations in memory
– Adding an element to the front of the queue or deleting an element from the back of the queue therefore takes a fixed amount of time
– Adding or deleting an element from the middle of the queue requires shifting the data already present in the queue. The time to do this depends on
the size of the queue

Applications of Queues:
• They are used to model Last In First Out (LIFO) and First In First Out (FIFO) behavior, typically buffers
• Queues are commonly used in various testbench components like scoreboard, monitor, driver – explained further in a
later segment of this course

© Mirafra Technologies 51
Queue Operations
Queues support the same operations that are performed on unpacked arrays. In addition to those, queues also
support the following operations:
• It will resize itself to accommodate any value that is written to it, provided that it is within its maximum bound size
• In a queue slice expression, the slice bounds may be arbitrary integral expressions and are not required to be
constant expressions
• Queues support additional built-in methods described in the next few slides

Consider a queue ‘Q’ whose range is bounded between ‘a’ and ‘b’. The following rules govern queue operators:
• If b > a, then Q[a : b] yields a queue with “b - a + 1” elements
• If a > b, then Q[a : b] yields the empty queue {}
• If a = b, then Q[a : b] is the same as Q[a : a] and it yields a queue with one item, the one at position ‘a’.
• If ‘n’ lies outside Q’s range (n < 0 or n > $), then Q[n:n] yields the empty queue {}
• Q[ a : b ] where a < 0, is the same as Q[ 0 : b ]
• Q[ a : b ] where b > $, is the same as Q[ a : $ ]
• An invalid index value will cause a queue read operation to return the value ‘x’ for a 4-state integral type or a
value ‘0’ for a 2-state integral type
• An invalid index value will cause a queue write operation to be ignored and a run-time warning to be issued
© Mirafra Technologies 52
Examples adapted from source: [3] The SystemVerilog IEEE 1800-2012 LRM, Page 128

Queue Operations Continued…


Examples of queue operations:

int q[$] = {2, 4, 8}; // Initialized integer queue ‘q’ with 3 elements – 2, 4 and 8
int p[$]; // Un-initialized integer queue ‘p’
int e, pos;

e = q[0]; // read the first (left-most) element of ‘q’; ‘e’ gets the value 2
e = q[$]; // read the last (right-most) element of ‘q’; ‘e’ gets the value 8
q[0] = e; // write the value of ‘e’ as the first element in ‘q’
p = q; // copy contents of ‘q’ to ‘p’
q = { q, 6 }; // insert ’6’ at the end of the queue ‘q’ (append the value 6)
q = { e, q }; // insert the value of ’e’ at the beginning of the queue ‘q’ (prepend the value of ‘e’)
q = q[1:$]; // delete the first (left-most) element of ‘q’
q = q[0:$-1]; // delete the last (right-most) element of ‘q’
q = q[1:$-1]; // delete the first and last elements of ‘q’
q = {}; // clear the queue contents, i.e., delete all elements of ‘q’
q = { q[0:pos-1], e, q[pos,$] }; // insert ’e’ in the queue ‘q’ at the position ‘pos’
q = { q[0:pos], e, q[pos+1,$] }; // insert ’e’ in the queue ‘q’ after the position ‘pos’

© Mirafra Technologies 53
Queue Methods
SystemVerilog provides several built-in methods to manipulate queues. These methods or functions are called after the queue
object name with a period “.” between the object name and the function name. The function arguments (if any) are inputs.

• Function int size(): Returns the number of items in the queue. If the queue is empty, it returns 0.
– Q.size() returns 4 for the integer queue, Q[$] = {8, 2, 1, 20}; containing 4 integer values - 8, 2, 1 and 20

• Function void insert (int index, queue_type item): Inserts the given item at the specified index position
– Q.insert (i, e) is equivalent to Q = {Q[0:i-1], e, Q[i:$]}

• Function void delete (int index): Deletes the item from the specified index position
– Q.delete (i) is equivalent to Q = {Q[0:i-1], Q[i+1:$]}
Use of queue
methods enables
• Function queue_type pop_front(): Removes and returns the first element of the queue one to perform
– e = Q.pop_front () is equivalent to e = Q[0]; Q = Q[1:$] queue operations
in a much easier
• Function queue_type pop_back(): Removes and returns the last element of the queue manner
– e = Q.pop_back () is equivalent to e = Q[$]; Q = Q[0:$-1]

• Function void push_front (queue_type item): Inserts the given element at the front of the queue
– Q.push_front (e) is equivalent to Q = {e, Q}

• Function void push_back (queue_type item): Inserts the given element at the end of the queue
– Q.push_back (e) is equivalent to Q = {Q, e} 54
© Mirafra Technologies
Queue Methods Continued…
Examples of queue methods:

integer int_q[$] = {20, 30, 40, 50}; // Initialized integer queue ‘int_q’ with 4 elements – 20, 30, 40 and 50
integer qs, val;
qs = int_q.size(); // The queue ‘int_q’ has 4 elements and hence the size is 4. ‘qs’ gets the value 4.
int_q.push_front(10); // Inserts the value 10 at the beginning of the queue ‘int_q’. Now ‘int_q’ has
// 5 elements – 10, 20, 30, 40 and 50 in that order.
int_q.push_back(60); // Inserts the value 60 at the end of the queue ‘int_q’. Now ‘int_q’ has
// 6 elements – 10, 20, 30, 40, 50 and 60 in that order.
int_q.insert(3, 35); // New element 35 added at index position 3 in the queue ‘int_q’. Now ‘int_q’ has
// 7 elements – 10, 20, 30, 35, 40, 50 and 60 in that order.
int_q.delete(3); // Deletes the element from index position 3 in the queue ‘int_q’. Now ‘int_q’ has
// 6 elements – 10, 20, 30, 40, 50 and 60 in that order.
val = int_q.pop_front(); // Removes and returns the first element of the queue ‘int_q’. ‘val’ now holds the
// value 10, while ‘int_q’ has 5 elements – 20, 30, 40, 50 and 60 in that order.
val = int_q.pop_back(); // Removes and returns the last element of the queue ‘int_q’. ‘val’ now holds the
// value 60, while ‘int_q’ has 4 elements – 20, 30, 40 and 50 in that order.

© Mirafra Technologies 55
Array Classification – Quick Reference
Array Type Example Application(s)

Packed Array bit [31:0] word_arr; // Packed array Such arrays could be used to store packet structures on which bit-
of 32-bit vectors select and part-select operations could be performed
Unpacked Array real float_point[0:1023]; // Such arrays could be used to model Random Access Memories
Unpacked array of real type (RAMs), Read Only Memories (ROMs) and register files where
one element is accessed at a time
Dynamic Array integer i_dynarr[]; // Dynamic array Say random control signals need to be generated by the testbench
of integers during simulation. If a fixed-size array is used, it would have to be
sized large enough to hold the maximum number of signals
possible. In reality, only a subset of control signals would be used,
thus wasting the remaining memory. Hence a dynamic array that
can be allocated and re-sized during simulation will avoid this
unnecessary memory allocation
Associative Array bit [3:0] array_a[int]; // Un- Such arrays could be used to model CAMs. Random read or write
initialized associative array of a 4- tests for verification of memories could use associative arrays for
bit vector, indexed by int storing data only for addresses which have been written
Queue integer Q[$] = { 4, 2, 7 }; // An Such arrays could be used to model Last In First Out (LIFO) and
initialized integer queue called “Q” First In First Out (FIFO) behavior, typically buffers
containing three integers
© Mirafra Technologies 56
Array Locator Methods
These are methods that traverse the array in an unspecified order and search an array for elements or their indices based on
a given search (filter) expression. The array locator methods operate on any unpacked array, including queues, but their
return type is a queue. If no elements satisfy the given filter expression or the array is empty, then an empty queue is
returned. These methods or functions are called after the array object name with a period “.” between the object name and
the function name.
The ‘with’ clause is mandatory in the following methods:
• find() with (filter_expr): Returns all the elements satisfying the given expression
• find_index() with (filter_expr): Returns the indices of all the elements satisfying the given expression
• find_first() with (filter_expr): Returns the first element satisfying the given expression
• find_first_index() with (filter_expr): Returns the index of the first element satisfying the given expression
• find_last() with (filter_expr): Returns the last element satisfying the given expression
• find_last_index() with (filter_expr): Returns the index of the last element satisfying the given expression
For the following methods, the ‘with’ clause can be omitted if the relational operators (<, >, ==) are defined for the element
type of the given array. If the ‘with’ clause is specified, the relational operators shall be defined for the type of the expression.
• min(): Returns the element with the minimum value or whose expression evaluates to a minimum
• max(): Returns the element with the maximum value or whose expression evaluates to a maximum
• unique(): Returns all elements with unique values or whose expression evaluates to a unique value
• unique_index(): Returns the indices of all elements with unique values or whose expression evaluates to a unique
value
© Mirafra Technologies 57
Examples adapted from source: [3] The SystemVerilog IEEE 1800-2012 LRM, Pages 130 and 131

Array Locator Methods Continued…


Examples of Array Locator Methods:
string SA[10], qs[$];
int IA[*], qi[$];
// Find all items in IA that are greater than 30
qi = IA.find(x) with (x > 30);
// Find indices of all items in IA that are equal to 8
qi = IA.find_index with (item == 8);
// Find the first item in SA that is equal to “address”
qs = SA.find_first with (item == “address");
// Find the last item in SA that is equal to “data”
qs = SA.find_last(z) with (z == “data");
// Find the index of last item in SA that is greater than “Z”
qi = SA.find_last_index(p) with (p > "Z");
// Find the smallest item in IA
qi = IA.min;
// Find the string with largest numerical value in SA
qs = SA.max with (item.atoi);
// Find all unique string elements in SA
qs = SA.unique;
// Find all unique strings in upper-case in the array SA
qs = SA.unique(rv) with (rv.toupper);
© Mirafra Technologies 58
Array Ordering Methods
These are methods that change the order of elements in any unpacked array, excluding associative arrays. An important point
to note is that unlike array locator methods, these array ordering methods change the contents of the original array. These
methods or functions are called after the array object name with a period “.” between the object name and the function name.
• reverse(): Reverses the order of the elements in an array. Specifying a ‘with’ clause shall be a compiler error.
• sort(): Sorts the array in ascending order. An optional condition can be specified using the expression in the ‘with’ clause.
• rsort(): Sorts the array in descending order. An optional condition can be specified using the expression in the ‘with’
clause.
• shuffle(): Randomizes the order of the elements in the array. Specifying a ‘with’ clause shall be a compiler error.
Consider an array consisting of
a packet of elements used as
input stimuli in the verification of
a design.
Examples:
Next the array needs to be
Next, the input stimuli needs to sorted in descending order.
be given in a reverse order to int da[] = ‘{10,2,7,3,4,4}; Then the rsort() method is used.
test a particular corner case da.reverse();
during verification. So the // output is {4,4,3,7,2,10}
reverse() method is used. Say the contents of the array
da.sort();
// output is {2,3,4,4,7,10} needs to be randomized after
For exhaustive testing, say the an interrupt. Then the shuffle()
input stimuli need to be given to
da.rsort(); method is used to randomize
the test bench in an ascending // output is {10,7,4,4,3,2} the array.
order. The sort() method is used da.shuffle();
to achieve this. // output is {4,2,4,3,10,7} © Mirafra Technologies 59
Examples adapted from source: [3] The SystemVerilog IEEE 1800-2012 LRM, Page 132

Array Reduction Methods


These are methods that may be applied to any unpacked array of integral values to reduce the array to a single value. The
expression within the optional ‘with’ clause is used to specify the values to use in the reduction. The method returns a single
value of the same type as the array element type or, if specified, the type of the expression in the ‘with’ clause.
• sum(): Returns the sum of all the array elements. If a ‘with’ clause is specified, returns the sum of the values yielded
by evaluating the expression for each array element
• product(): Returns the product of all the array elements. If a ‘with’ clause is specified, returns the product of the
values yielded by evaluating the expression for each array element
• and(): Returns the bit-wise AND ( & ) of all the array elements. If a ‘with’ clause is specified, returns the bit-wise AND
of the values yielded by evaluating the expression for each array element
• or(): Returns the bit-wise OR ( | ) of all the array elements. If a ‘with’ clause is specified, returns the bit-wise OR of the
values yielded by evaluating the expression for each array element
• xor(): Returns the bit-wise XOR ( ^ ) of all the array elements. If a ‘with’ clause is specified, returns the bit-wise XOR
of the values yielded by evaluating the expression for each array element
Examples:

byte da[] = {1,2,3,4};


int ans;

ans = da.sum ; // ans is 10 => 1 + 2 + 3 + 4


ans = da.product ; // ans is 24 => 1 * 2 * 3 * 4
© Mirafra Technologies ans = da.xor with (item + 6); // ans is 12 => 7 ^ 8 ^ 9 ^ 10 60
Structures
Definition: A structure is a user-defined data type that represents a collection of various
Need for the Introduction of
Structures in SV data types that can be referenced as a whole group, or as individual data types which
make up the structure
The big limitation in Verilog is the lack of a data
type that can group a collection of different data
types together. SystemVerilog introduces the Syntax : struct packed(optional) {<data_type> <range(optional)> element1,element2,…;
concept of structures to alleviate this limitation. The <data_type> <range(optional)> element1,element2,…;
concepts are similar to what is available in the ‘C’
programming language. …
} structure_name;

Examples:
packet

struct {byte data_in; 8


logic [31:0] address; data_in
bits
bit [7:0] data_out;} packet; // structure data type, packet containing a collection of byte, logic and bit
// data types respectively address
32
bits
packet ETH; // Defining a variable ETH of the packet structure type
ETH.data_in = 10; // Access of the data_in element using the ETH variable
data_out 8
bits
struct packed {int a;
shortint b;
longint c, d;
bit [7:0] e, f;
byte g;} pack2state; // 2-state variable collection as a packed structure 61
Structures Continued…
Characteristics of a Structure:
• It is a convenient method of handling a group of related data items of different data types under a single name and
stores all the values of the data types it contains
• Each of the constituent members of a structure is called a ‘field’. In the packet structure example shown, data_in,
address and data_out are fields of the packet structure
• By default, structures are unpacked
• A structure is just a collection of data and hence it can be synthesized
• A ‘struct’ data type has a subset of the functionality of the class data type (explained in the next Chapter) – it only
groups data fields together and does not have routines to manipulate such grouped data. Classes are therefore
preferred over structures when writing testbenches

Applications of Structures:
• An ethernet packet can declared as a struct with its constituent elements like packet length, header, footer etc. as fields
of the packet

© Mirafra Technologies 62
Unions
Definition: A union is a data type that can be pictured as a chunk of memory that is used
Need for the Introduction of
Unions in SV to store fields of different data types. Once a new value is assigned to a field, the existing
data is overwritten with the new data.
Unions are similar to structures, but with one major
difference. The size of an object of the union data
type is the size of its largest field. In contrast, the Syntax : union packed(optional) {<data_type> <range(optional)> element1,element2,…;
size of an object of the structure data type is the <data_type> <range(optional)> element1,element2,…;
sum of the size of all its fields put together. Unions …
are therefore more memory efficient than structures
and that is why they were introduced in SV. } union_name;

Examples:
packet

union {byte data_in;


logic [31:0] address; data_in
or
bit [7:0] data_out;} packet; // union data type, packet containing a collection of byte, logic and bit 32
// data types respectively address
or
bits
struct packed {int a;
shortint b; data_out
longint c, d;} ipack2state; // Incomplete 2-state variable collection as a packed structure 32 is the
largest
member
union packed {ipack2state incomplete; // Structure data type used here. Its 2-state data types are incomplete size
bit [7:0] e, f; // Bit and byte data types complete the full list of 2-state data types
byte g;} cpack2state; // Complete 2-state variable collection as a packed union

63
© Mirafra Technologies
Unions Continued…
Characteristics of a Union:
• The declaration of a union is similar to that of a structure and its various fields are referenced the same way as structures
• A union can store only one value – the size of the largest data field in it. Hence the memory usage is reduced
• By default, a union is unpacked
• It can be synthesized

Applications of Unions:
• Unions are useful when frequent reads and writes are done to a register in several different formats – the largest format
determines the storage size.

© Mirafra Technologies 64
Strings
Need for the Enhancement of Definition: A string type is a variable-length ordered collection of characters. The length
Strings in SV of a string is the number of characters in the collection.
Verilog 2001 supports only string literals.
SystemVerilog adds support for string as a built-in Syntax: string variable_name = initial_value(optional);
data type. Also added are a lots of operators and
functions for string manipulation.
Examples:
string soc_name; // Un-initialized string variable ‘soc_name’
string module_name = “video_RAM”; // Initialized string variable
string blp = “BLENDED learning PROgram”;

Characteristics of Strings:
• The memory space for strings is dynamically allocated
• The indices of string variables shall be numbered from 0 to N–1 (where N is the length of the string) so that index 0 is the
first (leftmost) character of the string and index N–1 is the last (rightmost) character of the string
• An un-initialized or empty string is represented with the special value “”. An empty string has 0 length
• An individual character is of type ‘byte’
• Unlike the ‘C’ programming language, there is no “null” character at the end of a SystemVerilog string

Applications of Strings:
• They are used to report the status of verification, to trace how far along in its execution a test case is, and most
importantly to display error messages that helps in debug
65
© Mirafra Technologies
String Operators
SystemVerilog provides a set of operators that can be used to manipulate combinations of string variables and string
literals. They are listed in the table below:

Operator Description
Str1 == Str2 Equality Operation: Checks whether the two string operands are equal. Result is
1 if both strings are composed of the same character sequence and 0 if not
Str1 != Str2 Inequality Operation: This is the exact opposite of the equality operation
Str1 < Str2 Comparison Operation: Returns a 1 if the result of the given comparison is true
Str1 <= Str2
Str1 > Str2
Str1 >= Str2
{Str1,Str2,...,Strn} Concatenation Operation: Appends the ‘n’ individual string operands together.
The operands can be of string type or can be string literals
{multiplier{Str}} Replication Operation: Str is a string literal or a string expression and the
multiplier is an integer ‘N’. The result of this operation is a string containing ‘N’
concatenated copies of Str

Str[index] Indexing Operation: Str is a string literal or a string expression and index is an
integer from 0 to ‘N-1’, where ‘N’ is the number of characters in the string. The
result returned is a byte, which is nothing but the character at the given index 66
© Mirafra Technologies
String Methods
SystemVerilog provides special built-in methods to work with strings. These methods or functions are called after the
string object name with a period “.” between the object name and the function name.

• function int len(): Returns the length of the string, i.e., the number of characters in the string as an integer
value
• function void putc(int i, byte c): Replaces the ith character in the string with character ‘c’
• function byte getc(int i): Returns the ith character of the string
• function string toupper(): Returns a string with characters in the string converted to uppercase. The original
string remains unchanged
• function string tolower(): Returns a string with characters in the string converted to lowercase. The original
string remains unchanged
• function int compare(string s): str1.compare(str2) – compares strings str1 and str2. Return '0' if equal, a
positive value if str1 comes after str2, and a negative value if str1 comes before str2
• function int icompare(string s): str1.icompare(str2) – case insensitive comparison of strings str1 and str2
• function string substr(int i, int j): str.substr(i,j) - returns a new string that is a sub-string consisting of
characters in position i through j in string str
• function integer atoi(): String to integer conversion – returns the integer corresponding to the ASCII decimal
representation of the string
• function void itoa(integer i): Integer to string conversion. This is the inverse of the function atoi()
© Mirafra Technologies 67
String Methods Continued…
Examples of String Methods:
string a = “AEIOU”;
string b = “alonso”;
string c = “123”;
byte subs1;
string subs2, lc, uc;

integer asiz, val;

asiz = a.len(); // asiz is assigned the value 5 as the string ‘a’ initialized to “AEIOU” has 5 characters

subs1 = b.getc(5); // subs1 gets ‘o’ which is the 5th character of string ‘b’ initialized to “alonso”

uc = b.toupper(); // uc gets “ALONSO” which is all uppercase of string ‘b’

lc = a.tolower(); // lc gets “aeiou” which is all lowercase of string ‘a’

subs2 = a.substr(1,3); // subs2 gets “EIO” which is the 1st to 3rd characters of string ‘a’

© Mirafra Technologies 68
Examples adapted from source: [3] The SystemVerilog IEEE 1800-2012 LRM, Page 76

Events
Definition: An event is a powerful means of synchronizing two or more concurrently
Need for the Enhancement of
Events in SV
active processes. This synchronization is done through an object and the event data type
provides a handle it.
Events are used to synchronize processes or
threads. In Verilog 2001 there is a possibility of a Syntax: event event_name = initial_value(optional);
race condition where one process blocks on an
event at the same time that another process
triggers it. SystemVerilog introduces a function to Examples:
check for the triggered status of an event. A
process can wait on this function rather than block event done; // Declare a new event object called done
operation, thereby avoiding the race condition. event redone = done; // Declare redone as an alias to done
event emptyevnt = null; // event variable emptyevnt has no synchronization object

Characteristics of Events:
• The synchronization object referenced by an event variable can be explicitly triggered and waited for.
• When one event variable is assigned another event variable, both event variables refer to the same synchronization object
• When assigned null, the association between the synchronization object and the event variable is broken
• An identifier declared as an event data type is called a named event
• The duration of an event persists throughout the time-step in which it was triggered
• If there is a need to send multiple synchronization notifications in a single time slot, do not use events. Instead use other
built-in synchronization methods like semaphores and mailboxes (explained later in this course)
Applications of Events:
• They are used to synchronize the testbench and the DUV. Sending a burst of data from the testbench and waiting on an
event response from the DUV are some common scenarios encountered. 69
© Mirafra Technologies
Event Operators and Triggered Property
SystemVerilog enhances Verilog events by providing a set of operators that can be used to manipulate events. They
are listed below:
• Operators for triggering an event (-> and ->>)
– Named events are triggered using the -> operator
– Nonblocking events are triggered using the ->> operator
– Triggering an event unblocks all processes currently waiting on that event
• Operator for waiting for an event (@)
– The basic mechanism to wait for an event to be triggered is via the event control operator, @
– ‘@ hierarchical_event_identifier;’ is the syntax and the @ operator blocks the calling process until the given event is triggered
– For a trigger to unblock a process waiting on an event, the waiting process must execute the @ statement before the triggering
process executes the trigger operator, ->. If the trigger executes first, then the waiting process remains blocked

Persistent triggered state: Triggered property


– SystemVerilog can distinguish between the event trigger itself, which is instantaneous, and the event’s triggered state, which persists
throughout the simulation time-step
– The triggered event property allows users to examine this state. The triggered property is invoked as follows:
hierarchical_event_identifier.triggered
The triggered event property evaluates to true if the given event has been triggered in the current time-step and false otherwise

© Mirafra Technologies 70
Examples adapted from source: [3] The SystemVerilog IEEE 1800-2012 LRM, Page 327

Event Operations and Triggered Property Continued…


Persistent triggered state: Triggered property (Cont’d)
– The triggered event property is mostly used with a wait construct as shown below:
wait (hierarchical_event_identifier.triggered)
Using this mechanism, an event trigger shall unblock the waiting process whether the wait executes before or at the same simulation
time as the trigger operation. This prevents any race condition likely to occur.

Examples of Event Operations and Triggered Property:

event done, sync; // declare two new events


event redone = done; // declare redone as an alias to done

task trigg(event ev); // task called “trigg” to trigger some event


-> ev; // trigger ev
endtask
....
....

fork
@ redone; // wait for done through redone
#100 trigg(done); // trigger ‘done’ using the ‘task’ trigg
join

fork
-> sync; // trigger sync
wait (sync.triggered); // wait on the persistent trigger
© Mirafra Technologies join 71
User-defined Data Type
Definition: User-defined types allow new type definitions to be created from existing data
Need for the Introduction of User-
defined Data Type in SV types. A ‘typedef’ declaration is used to define a user-defined type as similarly done in the
‘C’ programming language
Verilog 2001 does not allow users the freedom to
extend net and variable types to create their own Syntax : typedef <base_data_type> <user_defined_type_name>;
data types for some specific purpose.
SystemVerilog introduces user-defined data types
like those present in the ‘C’ programming language. Examples:
Here users can create and manipulate their own typedef int unsigned unsint; // Define a new 32-bit unsigned 2-state integer type
complex data types for specific purposes like typedef bit [31:0] uint; // Equivalent to the above definition – a new 32-bit
simulation, emulation etc. // 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

typedef logic [15:0] bits16; // Defining a new 16-bit type called ‘bits16’
bits16 word1, word2; // These are 2 16-bit words

typedef logic [3:0] nibble; // Defining a new 4-bit type called ‘nibble’
nibble [15:0] vec; // vec is a 64-bit vector made from 16 nibble types
Characteristics of User-defined Data Types:
• They can be defined locally or in a package
• All of SystemVerilog’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
• Sometimes a user-defined type needs to be declared before the contents of the type have been defined. Support for this is
provided by a forward typedef. More information about this can be obtained from page 77 of reference [3], the 72
SystemVerilog IEEE 1800-2012 LRM © Mirafra Technologies
User-defined Data Type Continued…
Applications of User-defined Data Types:
• Most values in a testbench are positive integers and so having a signed integer could cause problems. So the unsigned,
2-state 32-bit integer type ‘uint’ or ‘usint’ (as shown in the example) is used in such testbenches.

© Mirafra Technologies 73
Enumerated Data Type
Definition: Enumerated data types defines a set of named values. It assigns a symbolic
Need for the Introduction of
Enumerated Data Type in SV name to each legal value taken by the data type
An enumerated type in SystemVerilog allows one Syntax : enum enum_base_type(optional) { <enum_name_declaration> = constant_expr(optional),
to create a named set of related but unique <enum_name_declaration> = constant_expr(optional),
Syntax : typedef <base_data_type> <user_defined_type_name>;
constants. Verilog 2001 has text macros for :
names and parameters to define constants, but <enum_name_declaration> = constant_expr(optional)
relating both of them is extremely difficult.
} <enum_type_identifier>;

Examples:
enum {red,amber,green} tlc; // anonymous int type used for a traffic light controller

enum {INIT,START,STOP,FINAL,ABORT} power_ctrl_fsm; // States of a finite state machine


The enumeration index values for INIT, START, // Explicit values defined below to do one-hot encoding
STOP, FINAL and ABORT are 0,1, 2, 3 and 4 enum {idle = 1, start = 2, pause = 4, load = 8, done = 16} onehotstate;
respectively – anonymous int types
// Encoding must match the length of the 3-bit enum data type defined below
enum bit [2:0] {ST0 = 3’b001, ST1 = 3’b010, ST2 = 3’b100} state_encoding;

// Error codes can be stored as an enum declaration


enum logic {underflow, overflow, divbyzero, io_err} error_codes;

If a value is not specified for a name, it gets // Opcodes can be stored as an enum declaration
the value of the previous name in the list enum logic [2:0] {ADD, SUB, MUL, MOV, LD, AND, XOR, NEG} opcode;
incremented by 1. The value of W is 1. X is not
specified and hence it is 1+1, i.e., 2. Similarly Y // Declaring a boolean type below
is 8 and Z is not specified. Hence its value is enum bit {FALSE=1’b0, TRUE=1’b1} boolean;
8+1, i.e., 9 74
enum {W=1, X, Y=8, Z} missing_val; // Missing values for enum names
Enumerated Data Type Continued…
Characteristics of Enumerated Data Types:
• An enumerated type is stored as type ‘int’ unless specified as something else
• This type automatically gives a unique value to every name in the list
• Values default to the ‘int’ type starting at 0 and then incrementing by 1
• If a value is not specified for a name, it gets the value of the previous name in the list incremented by 1
• They are strongly typed, i.e., a variable of type ‘enum’ cannot be directly assigned a value that lies outside the
enumeration set
• Elements of enumerated type variables can be used in numerical expressions. The value used in the expression is the
numerical value associated with the enumerated value

Applications of Enumerated Data Types:


• These can be used to define processor opcodes, error codes and FSM states (as shown in the examples)
• Explicit values can be defined in the enumerated list to allow gray encoding, one-hot encoding etc. (as shown in the
examples)

© Mirafra Technologies 75
Enumerated Type Methods
SystemVerilog provides a set of specialized methods to iterate over and
manipulate the values of enumerated types. These methods or functions are
called after the enumerated object name with a period “.” between the object
name and the function name.
Example of Enumerated Data Type Methods:
• function enum first(): Returns the value of the first member of the
enumeration enum {init,start,stop} fsm_states;
fsm_states ctrl;
• function enum last(): Returns the value of the last member of the int total;

enumeration total = ctrl.num(); // total gets the value 3

• function enum next(int unsigned N = 1): Returns the Nth-next ctrl = ctrl.first();
enumeration value (default is the next one) starting from the current $display("%s",ctrl.name); // Displays ‘init’

value of the given variable ctrl = ctrl.next();


$display("%s",ctrl.name); // Displays ‘start’
• function enum prev(int unsigned N = 1): Returns the Nth-previous
enumeration value (default is the previous one) starting from the ctrl = ctrl.last();
$display("%s",ctrl.name); // Displays ‘stop’
current value of the given variable
ctrl = ctrl.prev();
• function int num(): Returns the number of elements in the given $display("%s",ctrl.name); // Displays ‘start’
enumeration
• function string name(): Returns the string representation of the given
enumeration value. If the given value is not a member of the
© Mirafra Technologies 76
enumeration, the name() method returns the empty string

You might also like