Using the Register Layer
Contents are extracted from the Advanced UVM sessions by Verification Academy.
UVM register class access API

The register model has two register variables
- Desired value: For when a field has been updated, but not the hardware
- Mirrored value: Containing the latest known value from the hardware
reg.read() and reg.write()*
- Access the hardware register and update the register database
- Front door access access uses bus agent - takes time and may create side effects
- Back door access is instant (via VPI - Verilog Procedural Interface) and does not cause side effects
- Not used for individual fields
reg.peek() and reg.poke()
Explicit backdoor access to the DUT register and also update the register model
- For backdoor accesses, register model updated with result
- Can be used for individual fields
reg.set() and reg.get()
- Access the desired value directly
Register access method fields

A typical register access only needs a few of the arguments:
spi_rm.ctrl.write(status, wdata, .parent(this));Parent of the register access, which is the sequence that includes the method call
Front-Door access modes
Consume time on the bus (default)
spi_rm.ctrl.write(status, wdata, UVM_FRONTDOOR, .parent(this));
spi_rm.ctrl.read(status, rdata, UVM_FRONTDOOR, .parent(this));UVM reg sequence API alternatively:
Don’t have to specify the parent sequence since it is built in for the register sequence
Recommended to use
write_reg(model.ctrl, status, wdata, UVM_FRONTDOOR);
read_reg(model.ctrl, status, rdata, UVM_FRONTDOOR);
Desired and mirrored values updated at the end of the transaction
- Based on transaction contents and field access mode

Can access individual fields
Only if hardware supports it
- Field = byte lane
Will execute the full read-modify-write flow to the particular register field
Back-Door access modes
Consume no time on the bus
write_reg(model.ctrl, status, wdata, UVM_BACKDOOR);
read_reg(model.ctrl, status, rdata, UVM_BACKDOOR);When using this, the backdoor path must be specified explicitly

Desired and mirrored values updated at the end of the transaction
- Based on transaction contents and field access modes

Can only access full register via backdoor access
Using peek/poke:
poke_reg(model.ctrl, status, wdata);
peek_reg(model.ctrl, status, rdata);Desired and mirrored values updated directly at the end of the transaction
- Poke sets the actual register value
- Peek samples the actual value, which is written to model
Peek/Poke work on fields
Peek and poke don’t care about the access mode of the register
Direct access modes
Access the desired value of the register model directly
Consume no time on the bus
Access the desired value directly
model.ctrl.set(wdata);
model.ctrl.randomize();
rdata = model.ctrl.get();
Use update() method to update actual value
- via front-door:
update_reg(model.ctrl, status, UVM_FRONTDOOR); - or back-door:
update_reg(model.ctrl, status, UVM_BACKDOOR);

If the desired value is different from the actual value, the register model will write the desired value directly to the actual register
The change will be reflected on the mirrored value of the register model also

Mirror method
Read register and update/check mirror value
- via front-door:
mirror_reg(model.ctrl, status, UVM_CHECK, UVM_FRONTDOOR); - via back-door:
mirror_reg(model.ctrl, status, UVM_CHECK, UVM_BACKDOOR);
Check will response with error if the mirrored value different from the actual value
The result of the mirror operation is the mirror value will be the same as the actual value, but if they are different from the beginning then the error will occur
Can be called on field, reg or block

Register sequence base class
Extended these to write register level sequences

Base class provides simpler API for interfacing with the register
Extend the uvm_reg_sequence base class and override the register model type

In this case the 2 operation will be accessed through front-door
Register stimulus: base class

Declare and use the set register model API to set the correct register model for extended register sequences
The set register model must be called after the sequence is created and before the sequence start
The
bodymethod of the base sequence contains additional setup when needed
Register stimulus: Building on the base
First is to call the
super.bodyon the extended register sequence to start the setup from the base class may needThe
set_rmof the base class will be called from the test before starting the extended sequence (div_load_seqin this case), so the register model will be using is known

Register sequence: TX Data Load

Built-in sequences
Sequences are easy to run
- Low overhead to use
- Useful for initial sanity checks on bus connectivity
Access modes are respected
- Read only registers are not bit bashed
- Read only memories are not tested
Memories, Registers or Fields can be opted out of a test
- e.g., Clock enable bit
- Mechanism is to use the
uvm_config_dbto set an attribute for the register

Summary
Register model follows hardware structure
- Fields, Registers, Blocks, Maps
- Internal access -
get(),set(), etc.- Sets up desired value
- External access - Front door and back door
Access layered via model
- Generic sequences adapted to target bus sequences
- Sequence reuse straight-forward
Use the convenience API
- Extend
uvm_reg_sequence write_reg()/read_reg()vswrite()/read()- Don’t have to worry about the
.parent()argument
- Don’t have to worry about the
Recommended to use the
write_regandread_regon theuvm_reg_sequencebase class