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 – Adapter Methods
Understanding reg_to_bus() and bus_to_reg() in Detail
How Write() Works Internally
When we call a write method inside a register sequence:
temp_reg.write(status, 4);
We provide:
- status → Output status of transaction
- data → Value to be written
We do not provide the address explicitly because it is retrieved automatically from the register block address map.
Updating uvm_reg_bus_op Structure
Calling write() updates the internal structure:
- addr → Taken from address map
- data → Value passed to write()
- kind → UVM_WRITE
- status → Updated after transaction
Example:
- Register offset = 0
- write(status, 4)
Then:
- addr = 0
- data = 4
- kind = UVM_WRITE
reg_to_bus() Method
This method converts the register structure into a bus transaction.
function uvm_sequence_item reg_to_bus(const ref uvm_reg_bus_op rw);
my_transaction tr;
tr = my_transaction::type_id::create("tr");
// Convert operation type
tr.WR = (rw.kind == UVM_WRITE) ? 1 : 0;
// Map address
tr.address = rw.addr;
// Map write data
if (tr.WR)
tr.DIN = rw.data;
return tr;
endfunction
What Happens Here?
- Create bus transaction object
- Convert kind → write signal
- Pass address directly
- During write, pass data to DIN
- Return transaction to driver
During read request, only address is driven. Driver does not process DOUT.
Read Operation Flow
When we call:
temp_reg.read(status, data);
The structure gets:
- addr → from map
- kind → UVM_READ
- data → initially 0
The adapter must convert the bus response back into a register transaction.
bus_to_reg() Method
Converts bus response → register structure.
function void bus_to_reg(uvm_sequence_item bus_item,
ref uvm_reg_bus_op rw);
my_transaction tr;
// Cast to correct type
assert($cast(tr, bus_item));
// Update operation type
rw.kind = (tr.WR) ? UVM_WRITE : UVM_READ;
// Update address
rw.addr = tr.address;
// Capture read data
rw.data = tr.DOUT;
// Update status
rw.status = UVM_IS_OK;
endfunction
What Happens Here?
- Cast generic sequence item to bus transaction
- Convert write signal → kind
- Copy address
- Capture DOUT into rw.data
- Set transaction status
Complete Adapter Data Flow
Write Flow:
write() → uvm_reg_bus_op → reg_to_bus() → Driver → DUT
Read Flow:
DUT → Monitor → Predictor → bus_to_reg() → Update Mirror
The adapter ensures both directions remain synchronized.
Example: Native Memory Interface
Suppose DUT has:
- WR → write enable
- address → register address
- DIN → input data
- DOUT → output data
Adapter simply maps:
- kind → WR
- addr → address
- data (write) → DIN
- DOUT → rw.data (read)
Whether using native memory signals or protocol-based interfaces (APB/AXI), the principle remains the same: correctly map operation type, address, and data.
Summary
- write() and read() update uvm_reg_bus_op.
- reg_to_bus() converts structure → bus transaction.
- bus_to_reg() converts bus response → structure.
- Driver applies transactions to DUT.
- Monitor + predictor update mirror values.
- Adapter is pure translation logic.