Verification
UVM Configuration Database (uvm_config_db): Enabling Flexible and Reusable Verification Environments
![]()
Introduction
As verification environments grow in complexity, components often require access to configuration information such as interface handles, protocol settings, timeout values, address ranges, operating modes, and environment-specific parameters. Passing such information through constructors or manually distributing it across the hierarchy quickly
becomes difficult to manage and maintain.
The Universal Verification Methodology (UVM) addresses this challenge through the UVM Configuration Database (uvm_config_db). It provides a centralized mechanism for sharing configuration information between testbench components while preserving modularity and reusability.
The configuration database allows higher-level components, such as tests and environments, to configure lower-level components without requiring direct knowledge of their implementation details. Instead of hardcoding values or creating tight dependencies between components, information can be distributed dynamically through hierarchical
configuration settings.
The uvm_config_db is built on top of the UVM Resource Database and is one of the most frequently used mechanisms in UVM testbenches. It is widely used for passing virtual interface handles, agent configuration objects, protocol parameters, environment settings, and runtime controls.
A strong understanding of uvm_config_db is essential for building scalable, configurable, and reusable verification environments.
Why Do We Need uvm_config_db?
Consider an environment containing multiple agents, drivers, monitors, scoreboards, and sequences. Each component may require access to common configuration information.
Without uvm_config_db, verification engineers often resort to:
- Global variables.
- Hardcoded parameter values
- Constructor-based parameter passing
- Direct handle sharing
These approaches introduce several challenges:
- Increased coupling between components
- Reduced reusability
- Difficult maintenance
- Poor scalability for large projects
The configuration database eliminates these problems by providing a hierarchical mechanism for distributing configuration information throughout the testbench.
The key advantages include:
- Improved reusability
- Better modularity
- Easier maintenance
- Centralized configuration management
- Support for test-specific customization
Basic Methods of uvm_config_db
The two primary methods used in most environments are:
1. set()
Used to place information into the configuration database.
Syntax
uvm_config_db #(type)::set(
cntxt,
inst_name,
field_name,
value
);
Example
uvm_config_db #(int)::set(
this,
“*”,
“timeout”,
1000
);
This stores the value 1000 under the field name timeout.
2. get()
Used to retrieve information from the configuration database.
Syntax
uvm_config_db #(type)::get(
cntxt,
inst_name,
field_name,
value
);
Example
int timeout;
if(!uvm_config_db #(int)::get(
this,
“”,
“timeout”,
timeout))
begin
`uvm_fatal(“CFG”,”Timeout not found”)
end
The value stored in the database is copied into the variable timeout.
Understanding the Arguments
cntxt
Defines the starting point for the configuration search.
Examples:
this
null
uvm_root::get()
Using this restricts the search relative to the current component.
Using null performs an absolute search.
inst_name
Specifies the hierarchy path.
Examples:
“*”
“env.agent*”
“env.agent.driver”
“”
The wildcard (*) allows configuration values to be applied to multiple instances.
field_name
Represents the configuration key.
Examples:
“vif”
“cfg”
“is_active”
“timeout”
value
The actual object or data being stored.
Examples:
virtual interface
configuration object
integer
string
enum
Passing Virtual Interfaces Using uvm_config_db
One of the most common uses of uvm_config_db is passing virtual interfaces from the top-level module into UVM components.
Top Module
module top;
my_if vif();
initial begin
uvm_config_db #(virtual my_if)::set(
null,
“*”,
“vif”,
vif
);
run_test();
end
endmodule
Driver
class my_driver extends uvm_driver #(my_txn);
virtual my_if vif;
function void build_phase(
uvm_phase phase);
if(!uvm_config_db #(virtual my_if)::get(
this,
“”,
“vif”,
vif))
begin
`uvm_fatal(“NOVIF”,
“Interface not found”)
end
endfunction
endclass
This technique completely decouples the driver from the top-level module.
Test
Passing Configuration Objects
Instead of setting individual variables one by one, UVM commonly uses configuration objects.
Configuration Class
class agent_cfg extends uvm_object;
bit is_active;
int timeout;
`uvm_object_utils(agent_cfg)
endclass
Test
agent_cfg cfg;
cfg = agent_cfg::type_id::create(“cfg”);
cfg.is_active = UVM_ACTIVE;
cfg.timeout = 500;
uvm_config_db #(agent_cfg)::set(
this,
“env.agent*”,
“cfg,”
cfg
);
Agent
agent_cfg cfg;
if(!uvm_config_db #(agent_cfg)::get(
this,
“”,
“cfg”,
cfg))
begin
`uvm_fatal(“CFG”,
“Agent config missing”)
end
This approach simplifies management of large numbers of related settings.
Real-Time Application 1: Active and Passive Agents
In a typical SoC verification environment, the same agent may operate in two modes:
- Active Mode
- Driver present
- Sequencer present
- Generates traffic
- Passive Mode
- Monitor only
- Observes DUT activity
Using uvm_config_db, the test can dynamically select the operating mode.
cfg.is_active = UVM_PASSIVE;
uvm_config_db #(agent_cfg)::set(
this,
“env.axi_agent”,
“cfg”,
cfg
);
The agent behavior changes without modifying its source code.
Real-Time Application 2: Multi-Protocol Verification
Consider a reusable VIP supporting:
- Driver present
- Sequencer present
- Generates traffic
A configuration object may contain:
cfg.protocol = AXI;
cfg.data_width = 64;
cfg.addr_width = 32;
Different tests can configure protocol behavior dynamically.
The same verification environment can support multiple protocols using only configuration changes.
Real-Time Application 3: Error Injection Testing
Many projects require fault injection.
Examples:
- Parity errors
- ECC errors
- Protocol violations
- Timeout conditions
A test can enable error injection through configuration settings.
cfg.enable_error = 1;
cfg.error_rate = 10;
Drivers and sequences retrieve these settings through uvm_config_db and automatically
adjust their behavior.
No source code modifications are required.
Configuration Lookup Mechanism
When a component calls get(), UVM searches using the following order:
1. Exact instance match
2. Hierarchical parent match
3. Wildcard match
4. Global match
The closest matching entry has the highest priority.
For example:
set(null,”*”,”timeout”,1000);
set(null,
“env.agent.driver”,
“timeout”,
500);
The driver receives:
timeout = 500;
because the specific path overrides the wildcard entry.
Debugging Configuration Problems
Configuration issues are among the most common UVM debugging challenges.
Useful techniques include:
uvm_top.print_topology();
and
uvm_config_db #(int)::dump();
Common mistakes:
- Incorrect hierarchy path
- Typographical errors in field names
- Calling get() before set()
- Incorrect data types
- Missing wildcard usag
Best Practices
- Store configuration values in dedicated configuration objects.
- Use meaningful field names.
- Perform get() operations in build_phase().
- Always check the return value of get().
- Use wildcards carefully.
- Avoid excessive global settings.
- Keep configuration ownership in test classes.
- Use configuration objects instead of many individual settings.
Conclusion
The UVM Configuration Database is one of the most important mechanisms in modern UVM testbenches. It provides a flexible and scalable way to distribute configuration information throughout the verification hierarchy while maintaining component independence and reusability.
Through the set() and get() methods, verification engineers can pass virtual interfaces, configuration objects, protocol settings, runtime controls, and environment parameters without introducing tight coupling between components.
Whether configuring active/passive agents, supporting multiple protocols, enabling error injection, or managing large SoC verification environments, uvm_config_db plays a central role in creating reusable and maintainable verification architectures.
A thorough understanding of configuration database usage, lookup rules, debugging techniques, and best practices enables engineers to build highly configurable testbenches
that can easily adapt to evolving verification requirements.
75,221
SUBSCRIBERS
Subscribe to our Blog
Get the latest VLSI news, updates, technical and interview resources



