The basic building blocks for any verification environment are the components (drivers, sequencers, monitors ...) and the transactions (class objects that contain actual data) they use to communicate. From the UVM hierarchy, we can see that most of the classes in UVM are derived from a set of core classes that are described below.



This doesn't have any purpose, but serves as the base class for all UVM classes.


This is an implicit top-level UVM component that is automatically created when the simulation is run, and users can access via the global (uvm_pkg-scope) variable, uvm_top. Please note the following properties of uvm_top (an instance of uvm_root)

  • Any component whose parent is set to null becomes a child of uvm_top.

    class my_component extends uvm_component;
      `uvm_component_utils (my_component)
      function new (string name = "my_component", uvm_component parent); (name, parent);
    class my_env extends uvm_env;
      my_component m_comp0 = new ("m_comp0", null);   // Now, you can access this via uvm_top.m_comp0
  • uvm_top manages the phasing for all components.
  • Use uvm_top to search for components based on their hierarchical name. eg : find ("uvm_top.*.usb_drv0");
  • Use uvm_top to globally configure report verbosity, log files and actions. eg :uvm_top.set_report_verbosity_level_hier (UVM_FULL) would set full verbosity for all components
  • UVM's reporting mechanism is accessible from anywhere outside uvm_component such as in modules and sequences
It's worthwhile to note that uvm_top checks for errors during end_of_elaboration phase and issues a UVM_FATAL error to stop simulation from starting. See Class Definition to know more.


The main role of uvm_object is to provide a set of methods for common operations like create, copy, compare, print and record. Since all major UVCs and transactions are derived from uvm_object, all these functions are available for their use. See class definition to know more


Provides an interface to the UVM reporting facility. All messages, warnings, errors issued by components go via this interface. There's an internal instance of uvm_report_handler which stores the reporting configuration on the basis of which the handler makes decisions on whether the message should be printed or not. Then it's passed to a central uvm_report_server which does the actual formatting and production of messages.

A report has ['ID String', 'Severity', 'Verbosity_Level', 'Text_Message'] and may include ['Filename', 'Line_Number'] from which the message came. If the verbosity level is greater than the configured maximum verbosity level, it is ignored. For example, if the maximum verbosity level is set to UVM_MEDIUM, and you issue a statement like `uvm_info ("STAT", "Status Registers have been updated", UVM_HIGH");, then you will not see this message in the output. By setting UVM_HIGH in the message, you are telling the report_server that you only want the message to be printed out when you want tons of messages printed out. This is useful for debug purposes, and you can set the message level to UVM_HIGH for all debug related messages, while you keep the maximum verbosity level to UVM_MEDIUM. That way you have the ability to switch between output levels.


All major verification components are derived from uvm_component, and already inherits features from uvm_object and uvm_report_object. It has the following interfaces:

  • Hierarchy : defines methods for searching and traversing the component hierarchy. eg: env0.pci0.master1.drv
  • Phasing : defines a phasing system that all components can follow eg : build, connect, run, etc
  • Reporting : defines an interface to the Report Handler, and all messages, warnings and errors are processed through this interface (derived from uvm_report_object)
  • Recording : defines methods to record transactions produced/consumed by component to a transaction database.
  • Factory : defines an interface to the uvm_factory (used to create new components/objects based on instance/type)
Note that uvm_component is automatically seeded if UVM seeding is enabled, but all other objects must be manually reseeded via uvm_object::reseed.


This is an extension of uvm_object and includes a timing and recording interface. Note that simple transactions can be derived from uvm_transaction, but sequence-enabled transactions must be derived from uvm_sequence_item.

Was this article helpful ?