UVM Environment
The UVM environment is a crucial component in a UVM testbench. It acts as a container for agents, scoreboards, and other verification components, providing a structured and organized way to manage the verification environment for a design under verification (DUV). The UVM Environment is a critical part of the Universal Verification Methodology (UVM) that encapsulates all the verification components required for a testbench. The environment class (uvm_env
) provides a structured and hierarchical approach to organizing agents, drivers, monitors, scoreboards, and other testbench components. The environment sets the stage for modular, reusable, and scalable verification setups.
Diagram of UVM Environment
Your Roadmap
+-----------------------+
| UVM Environment |
| |
| +------------------+ |
| | Agent | |
| | +--------------+ | |
| | | Driver | | |
| | +--------------+ | |
| | +--------------+ | |
| | | Monitor | | |
| | +--------------+ | |
| | +--------------+ | |
| | | Sequencer | | |
| | +--------------+ | |
| +------------------+ |
| +------------------+ |
| | Scoreboard | |
| +------------------+ |
| +------------------+ |
| | Coverage Coll. | |
| +------------------+ |
| +------------------+ |
| | Config Objects | |
| +------------------+ |
+-----------------------+
Key Responsibilities of a UVM Environment:
- Agent Instantiation: The environment instantiates one or more
uvm_agent
instances, each responsible for driving and monitoring a specific interface of the DUV. - Component Interconnection: It connects the agents, scoreboards, and other components together, establishing the communication paths within the testbench.
- Configuration: The environment is responsible for configuring its contained components, often using the UVM resource database.
- Coordination: It can implement logic to coordinate the activity of different agents or other components.
Structure of a UVM Environment:
A UVM environment is a class that extends uvm_env
. It typically includes the following:
- `uvm_component_utils Macro: This macro is essential for registering the environment with the UVM factory and enabling other UVM features.
- Component Declarations: Declarations of the agents, scoreboards, and other components that the environment contains.
new()
Constructor: The constructor is used to create an instance of the environment.build_phase()
: This phase is used to create the instances of the contained components.connect_phase()
: This phase is used to establish the connections between the components.
Key Components of UVM Environment
- Environment Class (
uvm_env
): The container for all verification components. - Agents: Include drivers, monitors, and sequencers.
- Scoreboards: Perform data checking and comparison.
- Coverage Collectors: Gather coverage information.
- Configuration Objects: Hold configuration settings for various components.
Diagram 1: Environment Containing Agents and Scoreboard
+-------------+
| Environment |
| (my_env) |
+-------------+
| agent1 |----> DUV Interface 1
| agent2 |----> DUV Interface 2
| scoreboard |
+-------------+
Example Code:
`include "uvm_macros.svh"
class my_env extends uvm_env;
`uvm_component_utils(my_env)
my_agent agent1;
my_agent agent2;
my_scoreboard scoreboard;
function new(string name = "my_env", uvm_component parent = null);
super.new(name, parent);
endfunction
virtual function void build_phase(uvm_phase phase);
super.build_phase(phase);
agent1 = my_agent::type_id::create("agent1", this);
agent2 = my_agent::type_id::create("agent2", this);
scoreboard = my_scoreboard::type_id::create("scoreboard", this);
endfunction
virtual function void connect_phase(uvm_phase phase);
super.connect_phase(phase);
// Connect agents to scoreboard (example)
agent1.monitor.analysis_port.connect(scoreboard.analysis_export);
agent2.monitor.analysis_port.connect(scoreboard.analysis_export);
endfunction
endclass
Diagram 2: Environment Class Structure
+-------------+
| my_env |
+-------------+
| `uvm_comp_ |
| utils(my_env)|
| agent1 |
| agent2 |
| scoreboard |
| new() |
| build_phase()|
| connect_phase()|
+-------------+
Environment Hierarchy:
Environments can be nested within other environments, creating a hierarchical structure that reflects the complexity of the DUV. This allows you to manage complex verification environments in a modular and organized way.
Diagram 3: Nested Environments
+-----------------+
| Top Environment |
+-----------------+
| sub_env1 |
| +-------------+
| | sub_sub_env |
| +-------------+
| sub_env2 |
+-----------------+
Configuration of the Environment:
Environments are often configured using the UVM resource database. This allows you to set parameters that affect the behavior of the environment and its contained components.
Example Configuration using Resource Database:
Code snippet
// In the test:
uvm_resource#(int)::set("uvm_test_top.env.agent1.is_active", 1);
// In the agent's build_phase:
int is_active;
uvm_resource#(int) rsrc = new("uvm_test_top.env.agent1.is_active");
rsrc.get(is_active);
if (is_active) begin
// Configure agent for active mode
end else begin
// Configure agent for passive mode
end
Defining a UVM Environment
1. Environment Class
The environment class is derived from uvm_env
. It contains all the agents, drivers, monitors, and scoreboards necessary for the testbench.
class my_env extends uvm_env;
`uvm_component_utils(my_env)
my_agent agt;
my_scoreboard scb;
function new(string name = "my_env", uvm_component parent = null);
super.new(name, parent);
endfunction
virtual function void build_phase(uvm_phase phase);
super.build_phase(phase);
agt = my_agent::type_id::create("agt", this);
scb = my_scoreboard::type_id::create("scb", this);
endfunction
virtual function void connect_phase(uvm_phase phase);
super.connect_phase(phase);
// Connect agent components
agt.driver.seq_item_port.connect(scb.analysis_export);
endfunction
endclass
2. Agents
Agents are composite components that include drivers, monitors, and sequencers.
class my_agent extends uvm_agent;
`uvm_component_utils(my_agent)
my_driver drv;
my_monitor mon;
my_sequencer seqr;
function new(string name = "my_agent", uvm_component parent = null);
super.new(name, parent);
endfunction
virtual function void build_phase(uvm_phase phase);
super.build_phase(phase);
drv = my_driver::type_id::create("drv", this);
mon = my_monitor::type_id::create("mon", this);
seqr = my_sequencer::type_id::create("seqr", this);
endfunction
virtual function void connect_phase(uvm_phase phase);
super.connect_phase(phase);
drv.seq_item_port.connect(seqr.seq_item_export);
endfunction
endclass