What is a UVM agent ?
An agent encapsulates a Sequencer, Driver and Monitor into a single entity by instantiating and connecting the components together via TLM interfaces. Since UVM is all about configurability, an agent can also have configuration options like the type of UVM agent (active/passive), knobs to turn on features such as functional coverage, and other similar parameters.
What are all the types of agents ?
|Active || |
- Instantiates all three components [Sequencer, Driver, Monitor]
- Enables data to be driven to DUT via driver
|Passive || |
- Only instantiate the monitor
- Used for checking and coverage only
- Useful when there's no data item to be driven to DUT
How to find out if a UVM agent is active or passive ?
User-defined agent classes derived from
uvm_agent also has another function called
get_is_active() which will return the state of the requested UVM agent.
// Assume this is inside the user-defined agent class
if (get_is_active()) begin
// Build driver and sequencer
// Build monitor
Steps to create a UVM agent 1. Create a custom class inherited from
uvm_agent, register with factory and call
// my_agent is user-given name for this class that has been derived from "uvm_agent"
class my_agent extends uvm_agent;
// [Recommended] Makes this agent more re-usable
// This is standard code for all components
function new (string name = "my_agent", uvm_component parent = null);
super.new (name, parent);
// Code for rest of the steps come here
2. Instantiate agent components
// Create handles to all agent components like driver, monitor and sequencer
// my_driver, my_monitor and agent_cfg are custom classes assumed to be defined
// Agents can be configured via a configuration object that can be passed in from the test
uvm_sequencer #(my_data) m_seqr0;
3. Instantiate and build components
virtual function void build_phase (uvm_phase phase);
// If this UVM agent is active, then build driver, and sequencer
if (get_is_active()) begin
m_seqr0 = uvm_sequencer#(my_data)::type_id::create ("m_seqr0", this);
m_drv0 = my_driver::type_id::create ("m_drv0", this);
// Both active and passive agents need a monitor
m_mon0 = my_monitor::type_id::create ("m_mon0", this);
//[Optional] Get any agent configuration objects from uvm_config_db
4. Connect agent components together
virtual function void connect_phase (uvm_phase phase);
// Connect the driver to the sequencer if this agent is Active
What does a UVM agent do ?
Usually, it makes sense to create an agent that provides protocol specific tasks to generate transactions, check the results and perform coverage. For example, a UVM agent can be created for the WishBone protocol whose sequencer will generate data items which can be sent to the driver. The driver then converts the data item class object into actual pin level signals and drive them to the DUT. The monitor may passively collect the outputs from the DUT, convert them back into another data item class object and distribute it among all the components in the testbench waiting for the item.