UVM RAL – Register Implementation with Reserved Bits

Modeling a 32-bit register containing multiple fields and reserved bits.

Overview

In real designs, registers often contain valid fields along with reserved bits allocated for future expansion.

In this example, we model a 32-bit register containing:

  • en → 1 bit at position 0
  • mode → 3 bits starting at position 1
  • addr → 8 bits starting at position 4
  • data → 16 bits starting at position 12

The remaining 4 bits are reserved. Reserved bits do not require a uvm_reg_field declaration.

Register Bit Mapping

Total Width = 32 bits

  • Bit [0] → en
  • Bits [3:1] → mode
  • Bits [11:4] → addr
  • Bits [27:12] → data
  • Remaining bits → Reserved

Step 1 – Extend uvm_reg


class reg3 extends uvm_reg;
  `uvm_object_utils(reg3)

Every register must extend uvm_reg and be registered with the UVM factory.

Step 2 – Declare Valid Fields Only


rand uvm_reg_field en;
rand uvm_reg_field mode;
rand uvm_reg_field addr;
rand uvm_reg_field data;

Reserved bits are not modeled using uvm_reg_field.

Step 3 – Constructor


function new (string name = "reg3");
  super.new(name,32,UVM_NO_COVERAGE); 
endfunction

The total register width must be 32 bits, even though some bits are reserved.

Step 4 – Build and Configure Fields

We configure fields using positional arguments:


function void build; 

  en = uvm_reg_field::type_id::create("en");   
  en.configure(this, 1, 0, "RW", 0, 0, 1, 1, 1); 

  mode = uvm_reg_field::type_id::create("mode");   
  mode.configure(this, 3, 1, "RW", 0, 0, 1, 1, 1); 

  addr = uvm_reg_field::type_id::create("addr");   
  addr.configure(this, 8, 4, "RW", 0, 0, 1, 1, 1); 

  data = uvm_reg_field::type_id::create("slv_cntrl");   
  data.configure(this, 16, 12, "RW", 0, 0, 1, 1, 1); 

endfunction

The LSB position must exactly match the DUT bit layout.

Complete Working Example


`include "uvm_macros.svh"
import uvm_pkg::*;

class reg3 extends uvm_reg;
  `uvm_object_utils(reg3)

  rand uvm_reg_field en;
  rand uvm_reg_field mode;
  rand uvm_reg_field addr;
  rand uvm_reg_field data;
  
  function new (string name = "reg3");
    super.new(name,32,UVM_NO_COVERAGE); 
  endfunction
  
  function void build; 
    
    en = uvm_reg_field::type_id::create("en");   
    en.configure(this,1,0,"RW",0,0,1,1,1); 
    
    mode = uvm_reg_field::type_id::create("mode");   
    mode.configure(this,3,1,"RW",0,0,1,1,1); 
    
    addr = uvm_reg_field::type_id::create("addr");   
    addr.configure(this,8,4,"RW",0,0,1,1,1); 
    
    data = uvm_reg_field::type_id::create("slv_cntrl");   
    data.configure(this,16,12,"RW",0,0,1,1,1); 
    
  endfunction
  
endclass


module tb;
  
  reg3 r3;
  
  initial begin
    r3 = new("r3");
    r3.build();
  end
  
endmodule
Important Note About Reserved Bits

Reserved bits do not require a uvm_reg_field. They are implicitly part of the register width.

The only requirement is that total declared field widths must not exceed the register size.

Run This Example on EDA Playground

Click below to execute this example.

▶ Open on EDA Playground
Summary
  • Registers can contain valid fields and reserved bits.
  • Only valid fields require uvm_reg_field modeling.
  • LSB position defines bit mapping.
  • Total field width must not exceed register size.
  • Reserved bits are automatically handled within register width.