The Verification Horizons Blog will provide an online forum to provide weekly updates on concepts, values, standards, methodologies and examples to assist with the understanding of what advanced functional verification technologies can do and how to most effectively apply them.
Read more posts from Chris Spear at the Verification Horizons Blog.
Introduction
In a previous post, I said that in SystemVerilog, once you specialize a class, you can not make a group of them. Oops! Turns out that UVM does this all this time. You just need to know where to start.
Just to be clear, you are making a group of handles, an array. Every object is separate, and thus cannot organized into an array.

Pool of parameterized handles in SystemVerilog
Where’s my sequencer?
Here is an example of a group of specialized classes. Your design may speak several protocols, so your UVM testbench needs multiple agents. In UVM, an agent speaks one protocol, such as USB or AXI. Inside the agent, a sequencer picks incoming transactions and sends them to the driver. The uvm_sequencer class is specialized for a single flavor of transactions, like this declaration.
// Inside the AXI agent class
uvm_sequencer #(axi_txn) axi_sqr; // A sequencer for AXI transactions
// Inside the USB agent class
uvm_sequencer #(usb_txn) usb_sqr; // A sequencer for USB transactions
How can your testbench organize all those sequencers? What if your testbench declared an array of handles to hold these? Is the following code legal?
uvm_sequencer sqr_array[string];
sqr_array["AXI"] = axi_sqr; // Compile error
sqr_array["USB"] usb_sqr; // Compile error
This won’t compile because when you specialized the class uvm_sequencer, it created a new type, and this is not compatible with the base uvm_sequencer, or the USB specialization. The full example requires a lot of support code, so let’s make a smaller example, without UVM.
Read more on Groups of Class Specializations in SystemVerilog at the Verification Horizons Blog.
Introduction
This is a follow up to last week’s high-level post on the UVM Factory. Now let’s get technical! Here are the SystemVerilog Object-Oriented Programming concepts behind the factory.
What is a type_id?
Last week you saw that your verification project will be more stable if you create objects with the UVM Factory instead of calling the class constructor, new()
.
drv = x_driver::type_id::create(…);
But what is type_id
? Is it the UVM Factory? A class? How about a floor polish and a dessert topping? Actually, it is none of the above; it is just a type.
A riddle wrapped in a macro
What is in the uvm_object_utils
and uvm_component_utils
macros? They are almost identical, except the first assumes the class constructor has one argument, and the second assumes there are two. Let’s focus on a transaction class.
class Txn extends uvm_sequence_item;
`uvm_object_utils(Txn)
function new(string name=”Txn”);
super.new(name);
endfunction
…
endclass/systemverilog>
<p>For this class, the macro defines <courier-code>type_id</courier-code> as follows.</p>
<systemverilog>
typedef uvm_object_registry#(Txn,"Txn") type_id;
You are creating a new object, so the handle is still null, and you can’t call its methods with handle.type_id.create()
. The uvm_object_registry
has static methods, which you call with the class::type_id::create()
syntax.
Read more on UVM Factory Revealed, Part 2 at the Verification Horizons Blog.
Introduction
When you first learn UVM, most of the concepts make sense, even if you are new to Object-Oriented Programming. Except one, the UVM Factory. Why do you need all that extra code, class::type_id::create()
, just to make an object? What’s wrong with just calling new()
? The answer is teamwork!
The Small Problem
Imagine you are trying to verify a design with the X bus protocol. You write UVM testbench components that speak that protocol, including the agent, driver, and monitor. Here is agent code that constructs the driver.
class x_agent extends uvm_agent;
x_driver drv;
function void build_phase(…);
drv = new("drv", this); // Construct the X bus driver
endfunction
endclass.
In the build phase you call new()
. SystemVerilog says that this constructs the object based on the type of the handle on the left side, and so you end up with an x_driver
object. Job done and you didn’t have to type all that type_id::create()
stuff.
But then halfway through the project, your manager says the design must work with the next generation of the protocol, called the Xplus bus. She even gave you the xplus_driver
class that extends x_driver
.
No problem, just add a flag variable and some code and your agent constructs both types. Since the new class extends the original one, you can reuse the drv handle. You can even get fancy with the typed constructor.
Read more on UVM Factory Revealed, Part 1 at the Verification Horizons Blog.
Introduction
UVM is a standard, so that means that every company writes their testbenches the same, universally interchangeable, right? Not exactly. I just got back from teaching in Europe. No matter where the engineers grew up, they all spoke English, each with a different accent. I think that I don’t have an accent, having grown up in Alaska, but my coworkers in Texas and London would disagree. Let’s look at some of the different accents and flavors of UVM.
Why are There 31 Flavors?
I’ll describe some differences and explain a little of why Siemens recommends a particular style. I’m not trying to change anyone’s mind, just help you see why some people prefer chocolate vs. vanilla.
There are almost as many reasons for these different styles as there are styles. Every design is unique, and this influences the testbench. Is there legacy code or is this the first of a new breed? Are the engineers SystemVerilog gurus who know UVM, OVM, VMM, and other TLAs, or is a team of VHDL designers learning just enough verification to get this chip into the lab? Finally, each EDA vendor and toolset has its strengths and thus one might push macros for fast adoption while another recommends a code-heavy approach for fine control over the behavior and best performance. A VIP author or verification consultant might create an innovative style.
Read more on Does Your UVM Flavor Have Sprinkles? at the Verification Horizons Blog.
Introduction
SystemVerilog classes are a great way to encapsulate both variables and the routines that operates on them. What if you want to reuse the methods but change the type of properties? Use a parameter and specialize it!
Definition
In Object-Oriented Programming (OOP), encapsulate variables and routines in a class. A class variable is called a property and a class routine is a method. By grouping them together, the result is more reusable than if they were kept separate.
The First Assignment
Your manager asks you to write a class to represent a stack. When you tell her that SystemVerilog already has a queue that can be used as a LIFO (Last In, First Out), she responds, “Yes, but on the last project, someone kept switching between push_front(), push_back(), and pop_front(), pop_back(), causing testbench bugs. Give me a stack class with just push() and pop().” Phew!
Your first attempt might look like the following, with no error checking.

Pool of Stacks
Read more on Dig a Pool of Specialized SystemVerilog Classes at the Verification Horizons Blog.
Introduction
In the last blog post [SC(SECL1] Farmer Ted asked you to keep track of his animals and you wrote some SystemVerilog classes, using public, protected, and local members. This week you are enhancing the code using the implicit handles, this and super.
Quick definition: implicit means the language / tool creates the member for you. If you had to create it yourself, like the weight property, it would be explicit. Also, what I am calling a “handle” is technically called a “class variable” that holds an “object handle”. Everyone I know says “handle” to refer to the variable.
What is this?
How can your routine access a class-level variable when there is a local variable with the same name? This often happens when a set() method or the constructor initializes a class property with an argument. A common style is to give the argument the same name as the class property, such as weight shown here. If the assignment was just “weight = weight”, both names would refer to the closest definition, which is the routine argument. The solution is to use the implicit handle, this, to assign the class property. The code below won’t work without the “this” handle.

This diagram color codes the scope. Members of the Animal class are in blue including the this handle in the upper right, while names associated with the set_weight_kg() method are in purple.
Read more on SystemVerilog: Implicit handles at the Verification Horizons Blog.
Farmer Ted wants to keep track of the animals on his property and asks you to write the code. Since you have access to Questa SIM, you decide to write the code in SystemVerilog. Start by creating a class for an Animal with a property (variable) to hold its weight. Here is a first start with your class and the first animal.
module farm;
class Animal;
int weight; // In kg
endclass
Animal dolly; // handle to an Animal object
initial begin
dolly = new();
dolly.weight = 100;
$display("dolly weighs %0d", dolly.weight);
end
endmodule
A problem with this code is the units: is weight in pounds, kilograms, ounces, or grams? Yes, there is a comment, but who reads the documentation? By allowing the user to read and write the variable, you are exposing the implementation. If you ever decide to change the units from kilograms to grams, the above code will make a 100-gram animal. That’s a mighty small sheep!
Read more on SystemVerilog: Class Member Visibility at the Verification Horizons Blog.
When I learned the SystemVerilog verification features, one concept had me baffled – virtual interfaces. What are these and why are they needed?
What is an interface?
Start with an interface. Quick summary: Back in Verilog days, a module had ports, which were individual signals. To connect two modules, each with 9 ports, you had to list all 9 signals. This is very error prone.

Test and design modules connected by separate port signals
When you connect your TV to a DVD player, do you connect individual wires? No, you plug an HDMI cable, click, and are done. You don’t even have to know how many wires are in an HDMI cable (20). In SystemVerilog, a bundle of wires is called an interface. In this diagram, the SystemVerilog test module has a single interface port, while the old Verilog design still has individual port signals.
Read more on SystemVerilog: What is a Virtual Interface? at the Verification Horizons Blog.
Introduction
My previous post showed how SystemVerilog class variables can refer to base and derived objects. This post shows you how to use the $cast() system task to copy between base and derived class variables.
Classy Cars
Start with a base class for an automobile with a color property.
class Automobile;
string color;
endclass
Now extend this to make a Pickup class with a bed in the back to carry big things.
class Pickup extends Automobile;
int bed_size;
endclass

Parking lot with an Automobile and Pickup, plus class variables
Read more on Class Variables and $cast at the Verification Horizons Blog.
Introduction
Good OOP style says you should start your project with a common base class (or several). When you want to change its default behavior, extend it to make a new class by overriding methods and adding new properties. Everything in the base class is inherited so anything the base class can do, the extended class can also do. What is the relationship between the class variables that point to an object, and how can you assign between them?
This is the fourth post in a series on OOP and UVM. Here is the previous post on $cast() with enumerated types. You might also want to read this post on Class Variables and Objects. Some people use “handle” for “class variable”. Whatever floats your boat!
Classy Cars
Start with a base class for an automobile. It has the property for the color, and a method drive().
class Automobile;
string color;
task drive();
...
endtask
endclass
This looks handy but sometimes you need to carry something big like a desk – you need a pickup truck! An important measure of a pickup is the size of its bed.
class Pickup extends Automobile;
int bed_size;
endclass
Notice that a Pickup is an Automobile. Everything you can do with an Automobile, like set the color, and call drive(), you can also do with a Pickup.
Read more on Class Variables and Assignments in SystemVerilog at the Verification Horizons Blog.
Introduction
Verilog was always known for its lack of type checking, treating everything as just bits strung together into vectors and arrays. “Compile it and find the problems at run-time.” SystemVerilog introduced new types that require more discipline. If you are new to SystemVerilog, the $cast() method can be mysterious as it checks values at runtime, not types at compile time.
This is the third post in a series on OOP and UVM. Here is the previous post on Verification Class Categories.
Enumerated Type

Traffic light: green, yellow, red
An enumerated variable creates a new type that has a limited set of values, specified by named constants. That sounds boring – how can it help you? If you are modeling a traffic light, you could create an enumerated type for the three states. Make it one-hot so you can connect this type to a port that drives the three bulbs.
Read more on Runtime checks with the $cast() method at the Verification Horizons Blog.
Introduction
What can you describe with Object-Oriented Programming? When I learned OOP, we had cute classes like animals, cars, and houses. That would be fine if I was taking a C++ or Java course, but this is SystemVerilog, and I am verifying hardware designs. What should my classes represent? This post shows two major categories. It also covers concepts that confused me when I first learned UVM, like sequence vs. sequencer.
This is the second post in a series. Here is the first post on Class Variables and Objects.
The UVM Way
UVM testbenches have two major groups of classes: transactions and components, plus minor utilities. All UVM classes are derived from uvm_object. In my last post, I recommended that you give every SystemVerilog object either a unique ID or name. uvm_object has both as seen in its constructor.
class uvm_object;
function new(string name);
m_inst_id = m_inst_count++;
m_leaf_name = name;
endfunction
endclass
This code follows the convention that member variables start with the prefix of “m_”.
Read more on Verification Class Categories at the Verification Horizons Blog.
Introduction
With any large software project, you need to share information and control across widely separated blocks. In the bad old days, this would be done with global variables and routines. In OOP and SystemVerilog, you can do this with classes that have static properties and methods. UVM’s Configuration Database is a great example. But did you know that the DB has a global space inside its pseudo-global space?
You may be familiar with the RTL passing a virtual handle pointer to the test class through the DB as follows.
module hdl_top; // Holds RTL code
import uvm_pkg::*;
xbus_ifc xbus_if(...); // Instantiate the xbus interface
initial
uvm_config_db #(virtual xbus_ifc):: // Pass a virtual ifc
set(null, "uvm_test_top", // to the test object
"xbus_if", xbus_if); // Name: "xbus_if"
... // RTL code
endmodule
The uvm_config_db call has the 3 parts. Read the statement from right to to left.
- The “name”, value pair of what you are accessing in the DB. Your code is easier to understand and understand if you try to make the name string and the variable the same. Here they are both xbus_if.
- The scope, which is a uvm_component handle plus a string. Since the RTL code does not know anything about the test class, it uses a null handle, and “uvm_test_top“, the instance name of the test object.
- Specialization #(virtual xbus_ifc) the data type of the value, which here is a virtual Xbus interface handle.
Read more on The UVM Config DB and Scope at the Verification Horizons Blog.
Introduction
How can you visualize the relationship between classes and objects in SystemVerilog? This is the first post in a series on Object-Oriented Programming in SystemVerilog and UVM. To best absorb this, you should know how to write a class in SystemVerilog. Let’s get started!
When you first learn OOP, it can be easy to mix up class variables and objects. I started when I was, so this was especially hard. Get ready to flex your brain muscles! How are objects like a neighborhood?
For a quick review of the terms in this article, see Dave’s excellent description.
Variables and values
In Verilog, a variable v has a value, 5, so I would say that v has the value 5, a direct relationship.

OOP has a two-step relationship between class variables, properties, and values. As you read this article, I encourage you to fire up your favorite editor, wrap these code examples with module-endmodule and simulate with your favorite tool, stepping through the code with the GUI. Don’t just lean back and read – lean forward and absorb what you see! A true engineer practices their craft and improves their skills.
Read more on SystemVerilog Class Variables and Objects at the Verification Horizons Blog.
What is a UVM transaction?
A transaction in UVM is a class with properties for the signals, such as address and data, plus extra information such as errors or delays. This is great for sending in one piece of stimulus, but you can’t verify a design with a single transaction. You need groups of related transactions.
What is a UVM sequence?
A group of related transactions in UVM is called a sequence, and the individual members are called sequence items. When you write your transaction classes, extend uvm_sequence_item, not uvm_transaction. Here is the OOP hierarchy for these classes, including your transaction class, called tx_item.

Extend your transactions from uvm_sequence_item
Read more on Why are UVM transactions built with uvm_sequence_item? at the Verification Horizons Blog.
In my last webinar I explained what happens when you import a package in SystemVerilog. There were still many questions, so here is a written version.
Please, try these examples on your own system or EDA Playground. Cut and paste the code into SystemVerilog files, compile, and debug. Make mistakes, get messy, and you will learn. If you just listen, or just read this, but never run the code, the concepts will disappear from your mind faster than Comet Neowise.
Another box of sugar
Imagine you are cooking dinner, and need some sugar. What do you do? Reach into the cabinet next to the refrigerator and grab the box. Oops, no box as you used it up last night. So you need to go to the grocery store and buy some more.
A SystemVerilog package is like a grocery store – a place to hold lots of stuff, that you go to when you can’t find something locally.

A USA grocery store
What is a package?
A package holds definitions that you want to share between modules. You might have a parameter, enumerated type, structure, a type definition (typedef), a class, or even a task or function.
Here is a package that defines a data type and a parameter.
// chip_pkg.sv
package chip_pkg;
typedef logic [3:0] data_t;
parameter LIFE = 9;
endpackage
Compile a package
When you compile this with Questa, the code is turned into a binary form in the work library. The compiler can read the binary version much faster than the original code, which is why we import packages rather than including them. The UVM package is 70,000 lines, but the compiled version is imported almost instantaneously.
Import a package
A module accesses the compiled package code by importing it. Here is the chip module that declares some parameters and a variable, and displays a parameter.
// chip.sv
module chip;
import chip_pkg::*; // Wildcard import
parameter INIT_VALUE = 'hFF; // Initial value
data_t my_data = INIT_VALUE; // What are data_t and INIT_VALUE?
initial $display("my_data = 'h%x / 'b%b", my_data, my_data);
parameter LIFE = 42; // Ask Douglas Adams
initial $display("The meaning of life is %0d", LIFE);
endmodule
After my last webinar on SystemVerilog arrays, I received several questions on the differences between arrays and structures, plus how to share declarations across modules. This and more will be revealed at my next webinar on SystemVerilog Structures and Packages. The first half is on structures, covering topics such as when should you pick a packed structure vs. unpacked.
Packages are a great way to organize related definitions, like all the classes for a USB testbench, or the PCI hardware definitions. But what does it mean to import a package? In the second half of the webinar, you will learn the best place to import a package, and how to write code that avoids the problem of the same name defined in multiple packages.
For example, why won’t the following code compile compile, and what is the bug for the RED and GREEN names? Tune in and find out.

Read more on Get Your Bits Together at the Verification Horizons Blog.
You asked and I listened
Thank you everyone who registered and attended my webinar on SystemVerilog arrays. There were many great questions and I’ve answered many of them here. "SystemVerilog arrays" is a big topic and I had to leave out many ideas. There were several questions on Multidimensional Arrays (MDAs), so here is a very short introduction. Copy and paste this code and run on your favorite simulator. Get dirty, make mistakes, debug – you are a verification engineer so figure it out!
Exploring the next dimension
int one[4];
foreach (one[i]) one[i] = i;
The best way to think about MDAs is that they are arrays of arrays. So a two dimensional array like the following is made of 3 arrays, each which has 4 elements.
int two[3][4]; // Short declaration, equivalent to ...

Here is its layout in memory.

You can assign three copies of the one array to it.
two = '{ 3 { one } }; $display("two = %p", two); // '{'{0, 1, 2, 3}, '{0, 1, 2, 3}, '{0, 1, 2, 3}}
Read more on SystemVerilog Multidimensional Arrays at the Verification Horizons Blog.
SystemVerilog has many ways to store your data. Vectors, arrays, structures, classes, and probably several more ways that I don’t remember. There are too many choices to squeeze into even 10 blog posts, so I made a webinar, actually two of them, to help you get organized.
The first webinar focuses on vectors, fixed size arrays, dynamic arrays, queues, associative arrays, and strings. (Yeah, that’s one I forgot.) Here is a sneak peek – a diagram to help you choose between these different types.

Ever stumble across the following code and wondered what it does?
q = array.find(x) with (x>5);
Looks like it is trying to find something greater than 5, but what is that 'x' for, and why does searching an array produce a queue?
Read more on Getting Organized with SystemVerilog Arrays at the Verification Horizons Blog.
Introduction
My previous blog posts were on static and parameterized classes to get you ready for the big game – the UVM Configuration Database or uvm_config_db. When used properly, this is a great way for one component to share a value with another. If the test or environment knows the path to the agent, the DB is efficient. Used improperly and it will bring your simulation to its knees.
Too Many Choices
The DB is that it is based on an associative array with a string index. So each entry is a name-value pair. If you store 100,000 values, the DB has to search these to find the particular value. If the array index values are organized as a tree, searching may require up to 20 string comparisons. Here is the DB with 100,000 entries.

Since this is a parameterized class, each specialization with a different type divides the size of the database. Perhaps half your configuration values are 32-bit integers, and the other half 64-bit values. Each DB access is now looking through half as many values.
Read more on UVM Configuration DB Guidelines at the Verification Horizons Blog.
Introduction
In my last post, you learned how to create a class with a static property. This variable acts like a global variable in that only one copy exists, no matter how many objects you create. This post shows how you can create methods that access those static properties.
Methods
Any class method can read and write these static properties, just like dynamic properties. However, if you declare the method as static, you can call the method without needing to construct an object. Here is the Thing class with a static method to print the count of Thing objects. You can call Thing::print_count(), even if no Thing objects were constructed.
class Thing;
int id; // Dynamic, unique to each object
static int count; // Static, associated with the class
static function void print_count();
$display(“Thing::count = %0d.”, count);
endfunction
// The rest of the class
endclass
Read more on SystemVerilog Static Methods at the Verification Horizons Blog.
Introduction
One of the advantages of creating your testbenches with Object Oriented Programming, as opposed to traditional procedural programming, is that your data and code are contained in a class, reducing the need for global variables. Those are useful, but you need to use them carefully to restrict how they are accessed, to avoid data corruption. Also, you need to create unique names for global variables to avoid conflicts. Is there an OOP way to make a variable that can be accessed across multiple classes, and solves the naming problem?
Object Count
When you debug code with multiple objects, it is handy to have a unique name or ID for each one, so you can easily follow them through system. How can you set the ID automatically? You could have a global variable that counts the number of objects of this type, but you are trying to avoid globals. The OOP solution is a static variable, where the storage is associated with the class declaration, not the multiple objects that are constructed dynamically.
Read more on SystemVerilog Classes with Static Properties at the Verification Horizons Blog.
SystemVerilog allows you to create modules and classes that are parameterized. This makes them more flexible, and able to work on a range of data types instead of just a single one. This concept is widely used in UVM, especially the uvm_config_db configuration database. Try these examples yourself.
Parameterized by value
Let’s start with a simple class with a bit vector. The class has a parameter for the width of the vector. (Good programming practice is to always have a default for your parameters.)
class Vector #(parameter WIDTH=1);
bit [WIDTH-1:0] data;
endclass
You can now declare handles for classes with vectors of various widths.
Read more on SystemVerilog Parameterized Classes at the Verification Horizons Blog.
Or: What I forgot in class
When I first learned UVM, there were many things that baffled me. What was still fuzzy after you took a UVM course?
Here is a diagram with the testbench layers, and orange transactions flowing from the test-level sequence into an agent.
