Introduction
Introduction Get started Hello UVM example UVM Phases Part 1 UVM Phases Part 2 UVM Base Classes UVM Object and Core Methods UVM ComponentsBuilding a Testbench
UVM Transaction UVM Sequence UVM Sequencer UVM Driver UVM Monitor UVM Scoreboard UVM Agent UVM Environment UVM TestOther Components
Coverage CollectorExecution Model
UVM Phases ObjectionsCommunication
TLM Basics TLM Blocking Put Port TLM Non-Blocking Put Port TLM Blocking Peek Port Analysis Ports TLM FIFOConfiguration
UVM Factory UVM Config DBRuntime Control
UVM Plusargs Seeds & Reproducibility Verbosity Control Debug Runtime ControlsAdvanced
Virtual Sequences Virtual SequencerUVM RAL
Intro Abstraction Flexibility Comparison Coverage Minimum Requirements Learning Path Register Types First Implementation Register with 2 Fields Register with Reserved Bits Access Policies Part 1 Access Policies Part 2 Access Policies Part 3 Access Policies Part 4 Memory Modeling Register Block Adapter Introduction Adapter Methods Adapter Example Predictor Types Desired and Mirror Values Register Methods Desired Value Mirror ValueUVMArena
Introduction
Introduction Get started Hello UVM example UVM Phases Part 1 UVM Phases Part 2 UVM Base Classes UVM Object and Core Methods UVM ComponentsBuilding a Testbench
UVM Transaction UVM Sequence UVM Sequencer UVM Driver UVM Monitor UVM Scoreboard UVM Agent UVM Environment UVM TestOther Components
Coverage CollectorExecution Model
UVM Phases ObjectionsCommunication
TLM Basics TLM Blocking Put Port TLM Non-Blocking Put Port TLM Blocking Peek Port Analysis Ports TLM FIFOConfiguration
UVM Factory UVM Config DBRuntime Control
UVM Plusargs Seeds & Reproducibility Verbosity Control Debug Runtime ControlsAdvanced
Virtual Sequences Virtual SequencerUVM RAL
Intro Abstraction Flexibility Comparison Coverage Minimum Requirements Learning Path Register Types First Implementation Register with 2 Fields Register with Reserved Bits Access Policies Part 1 Access Policies Part 2 Access Policies Part 3 Access Policies Part 4 Memory Modeling Register Block Adapter Introduction Adapter Methods Adapter Example Predictor Types Desired and Mirror Values Register Methods Desired Value Mirror ValueUVM RAL – Register Block (uvm_reg_block)
Building an address map for registers and memory in UVM RAL.
Why Do We Need a Register Block?
After implementing registers and memory in the verification environment, the next abstraction level is the register block.
A register block is responsible for:
- Holding all register instances
- Holding all memory instances
- Managing address mapping
- Creating the complete DUT address space
In simple terms, the register block connects registers to their addresses.
SoC Addressing Concept
In an SoC, all peripherals share a common base address. Each peripheral has a unique offset address.
Final address = Base Address + Offset
Example:
- Base Address = 0
- Register 1 Offset = 0
- Register 2 Offset = 4
Final addresses:
- Register 1 → 0 + 0 = 0
- Register 2 → 0 + 4 = 4
UVM RAL uses the same principle when building an address map.
Step 1 – Implement the Registers
Assume our DUT contains two 32-bit registers.
Register 1
class reg1 extends uvm_reg;
`uvm_object_utils(reg1)
rand uvm_reg_field ctrl;
function new (string name = "reg1");
super.new(name, 32, UVM_NO_COVERAGE);
endfunction
function void build;
ctrl = uvm_reg_field::type_id::create("ctrl");
ctrl.configure(
.parent(this),
.size(32),
.lsb_pos(0),
.access("RW"),
.volatile(0),
.reset('h0),
.has_reset(1),
.is_rand(1),
.individually_accessible(1)
);
endfunction
endclass
Register 2
class reg2 extends uvm_reg;
`uvm_object_utils(reg2)
rand uvm_reg_field data;
function new (string name = "reg2");
super.new(name, 32, UVM_NO_COVERAGE);
endfunction
function void build;
data = uvm_reg_field::type_id::create("data");
data.configure(
.parent(this),
.size(32),
.lsb_pos(0),
.access("RW"),
.volatile(0),
.reset('h0),
.has_reset(1),
.is_rand(1),
.individually_accessible(1)
);
endfunction
endclass
Step 2 – Create the Register Block
The register block extends uvm_reg_block.
class top_reg_block extends uvm_reg_block;
`uvm_object_utils(top_reg_block)
rand reg1 reg1_inst;
rand reg2 reg2_inst;
function new (string name = "top_reg_block");
super.new(name, UVM_NO_COVERAGE);
endfunction
function void build;
// Create Register 1
reg1_inst = reg1::type_id::create("reg1_inst");
reg1_inst.build();
reg1_inst.configure(this);
// Create Register 2
reg2_inst = reg2::type_id::create("reg2_inst");
reg2_inst.build();
reg2_inst.configure(this);
// Create Address Map
default_map = create_map(
"default_map", // Map name
0, // Base address
4, // Bus width (bytes)
UVM_LITTLE_ENDIAN // Endianness
);
// Add registers to map
default_map.add_reg(reg1_inst, 'h0, "RW");
default_map.add_reg(reg2_inst, 'h4, "RW");
// Finalize model
lock_model();
endfunction
endclass
Important Concepts
- configure(this) is mandatory for every register instance.
- create_map() defines base address, bus width, and endian type.
-
add_reg() requires:
- Register instance
- Offset address
- Access rights (R / W / RW)
-
Field-level access policy (inside
configure()) works together with map-level access rights. - lock_model() is mandatory and prevents further structural changes.
Summary
- Register block connects registers to addresses.
- Base address + offset defines final address.
- create_map() builds the address space.
- add_reg() maps registers to offsets.
- lock_model() finalizes the structure.
Run This Example on EDAPlayground
Click the button below to simulate the UVM Register Block example directly in EDAPlayground.
▶ Run UVM Register Block ExampleSimulator: Questa / Xcelium (UVM Enabled)