A UVM monitor is a passive component used to capture DUT signals using a virtual interface and translate them into a sequence item format. These sequence items or transactions are broadcasted to other components like the UVM scoreboard, coverage collector, etc. It uses a TLM analysis port to broadcast transactions.

uvm_monitor class declaration:

virtual class uvm_monitor extends uvm_component

A user-defined monitor has to be extended from uvm_monitor which is derived from uvm_component.

class <monitor_name> extends uvm_monitor;

uvm_monitor class hierarchy

uvm_monitor hierarchy

Purpose of Monitor

  1. Capture signal level information and translate it into the transaction.
  2. Broadcast transactions to other components using TLM port for coverage collection and checking purposes (scoreboard). It can also control them with enable/ disable knobs if required.
  3. Capture protocol-specific information and forward it to the related scoreboard or checker where protocol check happens

How to create a UVM monitor?

Monitor block diagram
  1. Create a user-defined monitor class extended from uvm_monitor and register it in the factory.
  2. Declare virtual interface handle to retrieve actual interface handle using configuration database in the build_phase.
  3. Declare analysis port to broadcast the sequence items or transactions.
  4. Write standard new() function. Since the monitor is a uvm_component. The new() function has two arguments as string name and uvm_component parent.
  5. Implement build_phase and get interface handle from the configuration database.
  6. Implement run_phase to sample DUT interface using a virtual interface handle and translate into transactions. The write() method sends transactions to the collector component.

UVM Monitor Example

class monitor extends uvm_monitor;
  // declaration for the virtual interface, analysis port, and monitor sequence item.
  virtual add_if vif;
  uvm_analysis_port #(seq_item) item_collect_port;
  seq_item mon_item;
  // constructor
  function new(string name = "monitor", uvm_component parent = null);
    super.new(name, parent);
    item_collect_port = new("item_collect_port", this);
    mon_item = new();
  function void build_phase(uvm_phase phase);
    if(!uvm_config_db#(virtual add_if) :: get(this, "", "vif", vif))
      `uvm_fatal(get_type_name(), "Not set at top level");
  task run_phase (uvm_phase phase);
    forever begin
      // Sample DUT information and translate into transaction