The UVM Register Abstraction Layer (RAL) is a powerful feature of the Universal Verification Methodology (UVM) that helps manage memory-mapped registers in a testbench. It simplifies register modeling, read/write operations, and checking expected values against actual hardware responses.
This article explores various UVM RAL classes and their methods, including:
uvm_reg_block(Register Blocks)uvm_reg(Registers)uvm_reg_field(Register Fields)uvm_mem(Memory)uvm_reg_map(Register Maps)
We’ll cover their methods, functionality, and examples to help you to integrate them into your UVM environment.
1. uvm_reg_block – Register Block
A register block represents a group of registers or memory within a design. It helps organize registers into hierarchical structures.
Common Methods in uvm_reg_block
| Method | Description |
|---|---|
create_map() | Creates a register map inside the block. |
lock_model() | Locks the register model to prevent further modifications. |
get_registers() | Returns a list of all registers in the block. |
get_memories() | Returns a list of all memory instances in the block. |
get_maps() | Returns all maps associated with the block. |
get_default_map() | Gets the default register map. |
configure() | Configuration for a specific instance. |
add_reg() | Adds a register to the block. |
add_mem() | Adds a memory instance to the block. |
There are some other methods as well. Please refer to UVM class reference manual or UVM cookbook to cover them. Here you can find one.
Example:
class my_reg_block extends uvm_reg_block;
`uvm_object_utils(my_reg_block)
my_reg my_reg1;
uvm_reg_map my_map;
function new(string name = "my_reg_block");
super.new(name, UVM_NO_COVERAGE);
endfunction
virtual function void build();
my_reg1 = my_reg::type_id::create("my_reg1");
my_reg1.configure(this);
my_reg1.build();
my_map = create_map("my_map", 0, 4, UVM_LITTLE_ENDIAN);
my_map.add_reg(my_reg1, 0, "RW");
lock_model();
endfunction
endclass
2. uvm_reg – Register Class
A register represents a memory-mapped hardware register that contains one or more fields.
Common Methods in uvm_reg
| Method | Description |
|---|---|
write() | Writes a value to the register. |
read() | Reads a value from the register. |
mirror() | Compares expected and actual register values. |
reset() | Resets the register fields to their default values. |
get_fields() | Returns a list of fields in the register. |
predict() | Predicts the value of the register based on a write operation. |
There are some other methods as well. Please refer to UVM class reference manual or UVM cookbook to cover them.
Example:
class my_reg extends uvm_reg;
`uvm_object_utils(my_reg)
uvm_reg_field field1, field2;
function new(string name = "my_reg");
super.new(name, 32, UVM_NO_COVERAGE);
endfunction
virtual function void build();
field1 = uvm_reg_field::type_id::create("field1");
field2 = uvm_reg_field::type_id::create("field2");
field1.configure(this, 16, 0, "RW", 0, 16'h0000, 1, 0, 1);
field2.configure(this, 16, 16, "RW", 0, 16'hFFFF, 1, 0, 1);
endfunction
endclass
3. uvm_reg_field – Register Field
A register field represents individual bits or groups of bits within a register.
Common Methods in uvm_reg_field
| Method | Description |
|---|---|
set() | Sets a value to the field. |
get() | Gets the value of the field. |
get_reset() | Returns the default reset value. |
predict() | Predicts the field value after a write operation. |
There are some other methods as well. Please refer to UVM class reference manual or UVM cookbook to cover them.
Example:
initial begin
my_reg my_register = my_reg::type_id::create("my_register");
my_register.build();
// Set and get field values
my_register.field1.set(8'hA5);
$display("Field1 Value: %h", my_register.field1.get());
end
4. uvm_mem – Memory
A memory represents a block of memory-mapped space. It behaves similarly to a register but can handle multiple addresses.
Common Methods in uvm_mem
| Method | Description |
|---|---|
write() | Writes a value to a memory location. |
read() | Reads a value from a memory location. |
get_size() | Returns the memory size. |
get_n_bytes() | Returns the number of bytes per memory entry. |
There are some other methods as well. Please refer to UVM class reference manual or UVM cookbook to cover them.
Example:
class my_mem extends uvm_mem;
`uvm_object_utils(my_mem)
function new(string name = "my_mem");
super.new(name, 256, 32, "RW", UVM_NO_COVERAGE);
endfunction
endclass
5. uvm_reg_map – Register Map
A register map defines address mapping for registers and memories.
Common Methods in uvm_reg_map
| Method | Description |
|---|---|
add_reg() | Maps a register to an address. |
add_mem() | Maps memory to an address range. |
get_reg_by_offset() | Returns the register at a specific address offset. |
set_base_addr() | Sets the base address for the map. |
There are some other methods as well. Please refer to UVM class reference manual or UVM cookbook to cover them.
Example:
my_map = create_map("my_map", 0, 4, UVM_LITTLE_ENDIAN);
my_map.add_reg(my_reg1, 0x100, "RW");
Additional Methods and Utilities
There are some additional methods as well which we will discuss in next articles.
- uvm_reg_adapter: Converts register transactions into bus transactions.
- uvm_reg_predictor: Predicts register values based on transactions.
- uvm_reg_seq: Provides sequences for register operations.
UVM RAL simplifies register modeling and improves testbench efficiency by abstracting low-level register interactions. Understanding and using uvm_reg_block, uvm_reg, uvm_reg_field, uvm_mem, and uvm_reg_map allows for more structured, reusable, and maintainable UVM testbenches.
By using the examples and methods covered in this article, you can integrate RAL effectively into your verification environment. Happy coding!