Monthly Archive: August 2014

Aug 07

Quick start UVM – online, free code, tool, documentation

Things have been busy thanks largely to upcoming DVCon India An unintended side effect was that things got silent on this new site/blog/initiative. Sorry to our readers. With no further delays, here comes our friend Victor’s secind instalment on Free UVM, hands-on as a sequel to hugely popular earlier post. Over to Victor:

Having run the simplest of UVM code, time to get into real work. The purpose of this example is two-fold. First, it gives beginners a brief introduction to UVM. Second, and most important, it can serve as a sandbox for future exploration and learning of UVM. For example, when you encounter a UVM feature that you don’t quite understand, add it to this example, click Run, and see what happens.

We will use the following diagram to explain the components of the example.



At the very top, we have the top module. This module contains our synthesizable design and is responsible for starting our UVM test. The design, dut1, is a dummy implementation which simply prints a message when receiving a transaction. The design and testbench worlds communicate through the dut_if interface. Since SystemVerilog interfaces are synthesizable design constructs, our testbench must use a virtual interface, called dut_vif, to drive the pins on the design. A virtual interface is simply a pointer to a static interface instance.


When the top module calls run_test, under the hood the UVM library selects the correct test to run and starts the UVM phase flow (build_phase -> connect_phase -> main_phase). As part of this flow, our verification environment is dynamically created and configured. This testbench contains several classes, with my_testenv, and agent classes nested within each other. It may seem like we have a few too many nested classes with almost nothing in them. However, actual verification environments have a lot more components, so it is good practice to always start with instances of uvm_test and uvm_env. Your future env class may have multiple agents and higher level sequencers to control them.


Our agent extends uvm_agent and contains a sequencer and a driver. UVM agents often also contain a monitor to check the bus level protocol, but a uvm_monitor is not included in this example. The sequencer is a structural UVM component that is created once during the UVM build_phase. The sequencer handles the flow of transaction items from a sequence to the driver. A sequence, on the other hand, can be created as often as needed and at any time throughout the test. Inside our sequence, we create a transaction item, my_transaction, randomize it, and send it to the driver. Our driver has the handle to the interface. Once the driver receives a transaction, it wiggles the proper pins on the interface. In this example, we send 8 random transactions to dut1. Code is live at:


Note: On the EDA Playground example, if you click on “Open EPWave after run” checkbox and re-run, you will see the waveform view of the actual signal transitions over the interface.

If you would like additional detail, a video explanation of this example is available here: UVM Hello World Tutorial on YouTube.


Good luck and happy learning of UVM!