Deep Dive into UVM Register Model | Agnisys Technology
UVM
Register Model, a key component of the Universal Verification Methodology
(UVM), is a standardized methodology for verifying digital designs. It
provides a framework for creating robust and reusable testbenches in the field
of hardware verification. One essential aspect of UVM is its Register
Abstraction Layer (RAL), which enables efficient verification of register-rich
designs. In this article, we'll take a closer look at the UVM
Register Model and explore its key components and concepts.
Register
Abstraction Layer (RAL)
The UMV Register Layer is designed to model and verify
register-based functionalities in a design. This includes registers,
memory-mapped registers, and the associated fields within those registers. The
primary purpose of RAL is to provide a systematic and efficient way of
accessing and manipulating registers during verification.
RAL Model
in UVM Environment
The UVM
environment is a collection of components, including the generator, sequences,
register model, and other testbench components. It provides a structured and
modular framework for organizing and managing the verification process. The
environment coordinates the generation of stimuli, checking of responses, and
collection of coverage data.
The
generator, often referred to as the register model generator, is responsible
for automatically creating the register model based on a specification provided
by the design team. It takes the register description (register map) of the DUT
and generates the corresponding UVM register model.
Sequences
in the RAL context are sets of register transactions that define specific
operations on the registers, such as read and write operations. Sequences
encapsulate the desired register behavior and are used to generate realistic
test scenarios for the DUT.
The
register model, built using UVM's RAL classes (uvm_reg and uvm_reg_field),
represents the hierarchical structure of registers and their fields within the
DUT. It includes information about register properties, such as names, widths,
access policies, reset values, and more.
The DUT is
the digital design that is being verified. It includes the actual hardware or
digital logic that implements the functionality specified by the design team.
The DUT is the target of the verification process, and the goal is to ensure
that it operates according to its specifications.
Classes of
UVM Register Model
Classes are
part of the UVM Register Abstraction Layer (RAL). These classes are used to
model and verify hardware registers and their fields within the design under
test (DUT). The RAL provides a standardized way to interact with registers and
facilitates the creation of reusable and scalable register verification
environments.
|
Class |
Description |
|
uvm_reg_field |
Used for register field implementation |
|
uvm_reg |
Used to implement design register |
|
uvm_reg_file |
Used to collect a group of registers |
|
uvm_reg_map |
Represents an address map |
|
uvm_mem |
Used to represent memory in design |
|
uvm_reg_block |
Container class to store registers, maps and
memories |
Table 1: Classes of UVM
register model
- uvm_reg_field :
“uvm_reg_field” is a class that is used to model individual fields within a register. They encapsulate the behavior and attributes of specific portions of a register, such as access type (read/write), reset values, and more.
- uvm_reg :
“uvm_reg” is a fundamental unit in the UVM Register Model. It represents a hardware register in the design. Each register has properties such as name, address, and size. Registers are the building blocks that encapsulate the control and status information of a design.
Example
:-
class
Block1_Reg1 extends uvm_reg;
`uvm_object_utils(Block1_Reg1)
rand uvm_reg_field F1;/**/
rand uvm_reg_field F2;/**/
//
Function : new
function
new(string name = "Block1_Reg1");
super.new(name,
32, build_coverage(UVM_NO_COVERAGE));
add_coverage(build_coverage(UVM_NO_COVERAGE));
endfunction
//
Function : build
virtual
function void build();
this.F1
= uvm_reg_field::type_id::create("F1");
this.F1.configure(.parent(this),
.size(16), .lsb_pos(16), .access("RW"), .volatile(0), .reset(16'd0),
.has_reset(1), .is_rand(1), .individually_accessible(0));
this.F2
= uvm_reg_field::type_id::create("F2");
this.F2.configure(.parent(this),
.size(16), .lsb_pos(0), .access("RW"), .volatile(0), .reset(16'd0),
.has_reset(1), .is_rand(1), .individually_accessible(0));
endfunction
endclass
- uvm_reg_block:
“uvm_reg_block”
can contain registers, register files, memories and sub-blocks. Register blocks
are used to organize registers into hierarchical structures. This is
particularly useful for modeling complex designs with multiple levels of
hierarchy. A register block typically represents a module or subsystem in the
design.
Example :-
class Block1_block extends uvm_reg_block;
`uvm_object_utils(Block1_block)
rand
Block1_Reg1 Reg1;
// Function
: new
function
new(string name = "Block1_block");
super.new(name,
UVM_NO_COVERAGE);
endfunction
//
Function : build
virtual
function void build();
//define
default map and add reg/regfiles
default_map=
create_map("default_map", 'h0, 4, UVM_BIG_ENDIAN, 1);
//REG1
Reg1
= Block1_Reg1::type_id::create("Reg1");
Reg1.configure(this,
null, "Reg1");
Reg1.build();
default_map.add_reg(
Reg1, 'h0, "RW");
lock_model();
endfunction
endclass
Register
Sequences and Tests
In UVM register sequences and tests are used to model and verify
the desired behavior of registers and their interactions. Register sequences
define specific sequences of register operations, such as read, write, or
modify operations.
class
my_sequence extends uvm_sequence #(my_register);
`uvm_object_utils(my_sequence)
task
body();
//
Register access operations
endtask
endclass
UVM
Register Layer API
The UVM
Register Layer API also provides a set of methods for performing register
operations, such as reading, writing, and checking register values. Some
commonly used methods include:
- read/write: The normal access APIs are the read()
and write() methods. “read” API is used to read the current value
of a register and the “write” API is used to write a new value to a
register.
- peek/poke: Using the peek() and poke() methods reads
or writes directly to the register respectively, which bypasses the
physical interface.
- get/set: Using the get() and set() methods
reads or writes directly to the desired mirrored value respectively,
without accessing the DUT.
- randomize: Using the randomize() method copies
the randomized value in the uvm_reg_field::value property into the desired
value of the mirror by the post_randomize() method.
- update: Using the update() method invokes
the write() method if the desired value (previously modified using set()
or randomize()) is different from the mirrored value
mirror: Using the mirror() method invokes the
read() method to update the mirrored value based on the readback value.
mirror() can also compare the readback value with the current mirrored value
before updating it.
Conclusion
The UVM Register Model is a powerful feature of the UVM
methodology, providing an effective way to model and verify register-based
designs. By utilizing registers, fields, and register blocks, engineers can
create comprehensive and reusable testbenches for thorough verification of
hardware designs. Understanding the key components and concepts of the UVM
Register Model is crucial for achieving successful and efficient verification
in modern digital design projects.
This
article has provided a glimpse into the UVM Register Model, but there is much
more to explore and understand. As you delve deeper into UVM-based
verification, you'll discover additional features and techniques that
contribute to building robust and scalable testbenches for complex digital
designs.

Comments
Post a Comment