Structure of UVM
UVM, or Universal Verification Methodology, is a widely used standard for verifying digital designs and systems-on-chip (SoCs) in the semiconductor industry. UVM also defines a set of guidelines and best practices for developing testbenches, as well as a methodology for running simulations and analyzing results.
These guidelines make the structure of a UVM test bench a bit different from a regular test bench providing various features which help write complex TBs. In this article, we will explore the basic structure of UVM in more detail and see how it can be used to create effective and efficient testbenches for verifying digital designs and SoCs.
Basic building block of UVM
All pre-defined or user-defined classes in UVM can be categorized as UVM component or UVM Object. These acts as a basic building block upon which the entire UVM is based on.
UVM Components
UVM introduced a concept of components. These components are the class whose objects will be available from the start of the simulation to the end. For example, drivers, monitors, etc. can be considered as components as these will be available in the TB throughout the lifecycle.
As UVM components are available through the test bench lifecycle and represent different components present in testbench, thus all UVM components will follow phase concept. We will learn more about phases in later articles. For now, phases can be considered as a way to synchronize various UVM components.
UVM Objects
In UVM, objects are nothing but a class whose objects won’t be available throughout the test bench lifecycle. Objects will be created whenever they are required and destroyed after that. For example, the transaction classes are UVM objects as the object of these packets are created when required and then destroyed.
AS UVM objects are not available throughout the test bench lifecycle, these do not follow phase.
UVM Factory
In UVM, all the classes (UVM component/ UVM objects) need to be registered with UVM factory. UVM factory can be considered as a factory which will generate all the objects of these classes.
While creating objects in UVM, it is recommended to not use the `new()`` method to create objects. Instead, we should use UVM factory. UVM factory provides lots of other advantages that we will see in future articles dedicated to UVM factory concepts.
Transaction-level modelling
To verify any design, we need to drive various input signals of the DUT and check the output signals. But defining a stimulus directly in terms of signal is challenging as there can be various scenarios. To simplify this, we use an abstract model of the stimulus, which is known as Transaction-level modelling.
Stimulus is created based on this abstraction level and then this is passed to various components of the test bench. The driver will consume these TLM packets and convert them to signal-level stimulus driving various inputs of the DUT.
UVM provides various TLM communication interfaces which help various components communicate with each other in terms of these TLM packets. In UVM, TLM packets are UVM object as these are created whenever a stimulus needs to be sent.
This is just a brief overview of TLM to understand the basic principle behind UVM based test bench. TLM is a very vast topic, and we will see it in more detail in upcoming articles.
Config DB
Test bench can have a lot of knobs to simulate various scenarios. These knobs can be consumed by any of the UVM classes. In big and complex TBs, it becomes very tough to pass these knobs from one class to another as they might not be part of the same hierarchy. To tackle this, UVM introduced the concept of config DB.
Config DB can be understood as a database in which we can add any object from anywhere within our test bench. Once an object is added, these can be accessed from anywhere within the test bench. UVM provides some static methods to add/fetch objects from the config DB.
Config DBs also help in getting the virtual interface handles in different test bench components as we know that the interface is static in nature and thus cannot be instanced inside a class. Thus, we can add the interface handle from the top-level module and get it in our components without need of passing it through various levels of components.
Conclusion
In this article we understood the basic structure of UVM test bench. UVM Components and UVM objects are the basic building blocks for any UVM test bench. Any in-built UVM class or user-defined will either be a UVM component or a UVM object. We have also seen that in UVM to create objects we should not use new() method but use UVM factory instead.
We also understood TLMs in brief and how UVM utilizes it to simplify the stimulus generation and inter-component communication. In the end we saw how config DBs help get the configurations knob easily across the
This article gives a very high-level overview of how UVM works and the bare-minimum concepts which is required to write a UVM test bench. We will be seeing more on these concepts in future articles.