SystemVerilog is a language just like Verilog and has its own constructs, syntax and features but UVM is a SV framework from which a fully functional testbench can be built. So, UVM is nothing but a hierarchy of SV classes that extensively make use of inheritance and have well defined in-built functions and tasks. There's only one prerequisite to learn UVM, and that is SystemVerilog because SV is the foundation for the tower that is UVM.
The primary advantage of UVM is that you don't have to re-invent the wheel as the methodology specifies and lays out a set of guidelines to follow when creating a testbench structure. This will ensure testbench uniformity between different verification teams, cross-compatability between IP and standalone environment integration, flexibility and ease of maintaining testbenches. A simple example is the way reporting mechanisms are implemented to filter and log messages with various levels such as warning, error and debug. Such a requirement are usually implemented in various ways and formats by different teams based on custom requirements. With UVM, the underlying reporting mechanism has been standardized and made available so that engineers can instead focus on the most important part of their job - design verification.
As with any testbench structure, there are a few key components that matter - driver, monitor, scoreboard, etc. UVM provides us with a skeletal structure with basic methods to connect and setup the testbench and we can modify it to perform the functions that we desire. These are static objects that exist throughout a simulation just like buildings in a city. These components naturally process some kind of data that flows around the environment similar to people and vehicles in the city. They are data objects that appear and disappear at various times in the simulation.
The first and the foremost starting point is to understand the UVM class hierarchy just to understand how important classes are related. Since all verification components are derived from these base classes, they inherit common methods like compare/copy/print and reporting functionality. This is one of the core features of UVM. In SV, you had to write and maintain such functions for each component. So with each layer of inheritance, new features are added into the classes and ultimately you get to use all the goodies if you extend from the leaf node.
There are only two primary branches in the hierarchy. One is to define verification components like driver, monitor and the rest. The other is to define data objects consumed and operated upon by verification components. The first component branch is shown as everything below uvm_report_object, while the data branch is everything below uvm_transaction. But the only main thing to note right now is that all testbench components needs to be derived from the appropriately named UVM classes, while all data objects should be extended from
UVM also introduces the concept of a sequence which is nothing but a container for the actual stimulus to the design. If you put different stimuli into different sequences, it enhances the ability to reuse and drive these sequences in random order to get more coverage and verification results. There is also a separate testbench component to handle the execution of sequences known as a sequencer. Learn more on sequences in How to create and use a sequence.
Digital designs support control registers that can be configured by software, and this has been very challenging in a SystemVerilog testbench, because for each project you had to build a separate set of classes that can store and configure these registers. UVM has an extensive set of classes to make that task relatively simpler and belong to something known as a register model. This is very useful in the verification of IPs that can be reused in various SoC designs.
Another really smart feature is the use of TLM from System C. TLM helps to send data between components in the form of transactions and class objects. It also brings a way to broadcast a packet to its listeners without having to create specific channels and attach to it. Read more on TLM.
| ||Abstract class with no data members or functions. |
| ||Define methods for common operations like copy/compare/print|
| ||Provides interface to reporting facility to print messages (like |
| ||Provides |
Another main feature that verification components inherit from their parent class
uvm_component is Phasing. This enables every component to sync with each other before proceeding to the next phase. Phases are covered in the next chapter. Every component goes through the build phase where it gets instantiated, connects with each other during the connect phase, consumes simulation time during the run phase and stops together in the final phase.
| ||Drive signals to DUT|
| ||Monitor signals at DUT output port|
| ||Create different test patterns|
| ||Contains the Sequencer, Driver and Monitor|
| ||Contains all other verification components|
| ||Checker that determines if test Passed/Failed|
| ||Subscribes to activities of other components|
Data objects can be created as stand alone class items in UVM. They can be used inside sequences to create different scenarios, and even more interesting patterns can be created by randomizing a sequence of sequences. For example, a sequence can be created each for "read" and "write" transaction. They can be used randomly in in sequences to perform R-W-R-W, or R-R-R-W, or W-W-R-R and similar patterns.
| ||Adds timing and recording interface useful for data objects|
| ||Provides both sequence items and sequences to operate in the sequence mechanism|