UVM RAL: The Register Layer
Verifying registers by name, with a mirror you can trust
Every modern block has dozens or hundreds of configuration and status registers. Poking them with raw bus transactions and remembering addresses by hand does not scale and does not survive a spec change. The UVM Register Abstraction Layer (RAL) lets you read and write registers by name, while keeping a model of what each register should currently hold. It builds a class model of the map: a uvm_reg per register, grouped into a uvm_reg_block, with a uvm_reg_field per field. For every field it tracks a desired value (what you intend to write, set by set() and flushed by update()) and a mirror value (what RAL believes hardware currently holds).
Front-door vs back-door access
| Access | Path | Cost | Use it for |
|---|---|---|---|
| Front door | Real bus cycles via the adapter and sequencer | Slow, realistic | Verifying the bus access path itself |
| Back door | Direct hierarchical poke or peek into the RTL register | Instant, zero cycles | Fast setup of state and golden checks |
// Inside a sequence body(); reg model handle is 'regmodel'
uvm_status_e status;
bit [31:0] rdata;
regmodel.ctrl.write(status, 32'h0000_0003); // front-door: drives bus cycles
regmodel.ctrl.read(status, rdata); // front-door read-back
regmodel.ctrl.read(status, rdata, UVM_BACKDOOR);// back-door: zero sim time
regmodel.ctrl.enable.set(1'b1); // update only the DESIRED value of a field
regmodel.ctrl.update(status); // writes to HW only if desired != mirrorBuilt-in register tests
The biggest payoff is the predefined sequences that exercise the map for you. Point them at the model and they generate and self-check the stimulus, so you do not hand-write hundreds of poke-and-compare lines.
- uvm_reg_hw_reset_seq - checks every register reads its specified reset value.
- uvm_reg_bit_bash_seq - writes and reads back each writable bit to find stuck or aliased bits.
- uvm_reg_access_seq - confirms front-door and back-door agree, catching address-decode bugs.
The mirror is what makes RAL a checker, not just an addressing convenience. After a front-door write, get_mirrored_value() holds the predicted contents, so a later read can be compared automatically. Combine a back-door peek (the truth) with a front-door read (the path under test) and you verify the access path and the storage in one step.
If RTL changes a register without RAL knowing - hardware sets a status bit, or a clear-on-read field fires - the mirror goes stale and later checks produce false mismatches. Tell RAL about such behavior: model each field access policy (RO, W1C, RC, and so on) correctly, and use a predictor with explicit prediction driven by the monitor so the mirror stays honest.