+1 855-VERIFYY
+

How To Create Complex Registers in IDesignSpec

How To Create Complex Registers in IDesignSpec

By: | Tags: , , , , | Comments: 0

We talk about creation of complex registers in IDesignSpec, generation of their suitable RTL and UVM models.

The Software addressable registers in your design do not always just have simple read-write access. Sometimes they need to be designed with advanced behavior, due to the demands of application or because of implementation constraints. Modeling the behavior of these registers in an existing design (RTL) and test bench (UVM) is a challenge and very time consuming.  The time spent in the verification of these blocks is required since the UVM built-in library tests do not address these additional design features of the register blocks.  By combining the automation of the specification through verification cycle of complex registers, users can benefit from 100 percent coverage and significant time savings since tests are automated.  

Please check out a recent product release that automates register verification using either simulation or formal verification methods.  

Also please read the case study of Allegro Microsystems LLC and their use of ARV-Sim™.

With IDesignSpec you could model the behavior of almost all types of complex registers. All you have to do is attach properties on the registers/fields in IDesignSpec register map specification.  This post provide examples of how it is done with the five register types listed below.  

Complex registers that can be generated from IDesignSpec are:

  • Shadow registers
  • Alias registers
  • Indirect registers
  • Lock register
  • RO-WO pair registers at same address
  • And many more

We will cover some of these types in this article and follow up to discuss the rest.

shadow registersShadow Registers:

Designers may sometimes require that the data written to a register through the register bus (SW access) shall be copied or shadowed to another register in the address map automatically. This is often done to make the debugging of designs easier. A common use case is, checking what was written on write-only registers after reading their corresponding read-write shadow registers. Or writing to a memory which is shadowed with readable registers.

From the figure to the right, we could see that whatever is written to the “OriginalReg” is copied to its shadow register “ShadowedReg”.

So in the design whenever “OriginalReg” is decoded for write, the write valid of the shadow also gets asserted and data is written to the shadow as well.

Shadow register representation in IDS Word

shadow registers in IDesignSpec Word

In UVM we have implemented this kind of behavior by using callbacks.

class Shadow_cb extends uvm_reg_cbs;
    local uvm_reg_field  m_toF;
    
    function new(string name, uvm_reg_field toF);
        super.new(name);
        m_toF = toF;
    endfunction
    
    virtual function void post_predict(input uvm_reg_field  fld,
        input uvm_reg_data_t previous,
        inout uvm_reg_data_t value,
        input uvm_predict_e kind,
        input uvm_path_e path,
        input uvm_reg_map map);
        if (kind == UVM_PREDICT_WRITE && path == UVM_FRONTDOOR) begin
            void'(m_toF.predict(value, -1, UVM_PREDICT_DIRECT, path, map));
        end
    endfunction
endclass

 

Alias RegistersAlias registers

Sometimes a register can have two or more, different views for the software, i.e. it can be accessible from multiple addresses in the same address map. And physically it’s just a single register. Thus a register can have multiple aliases or simply alternate addresses in an address map.

Each of these aliases can have a different access type. For example, fields in a register may be readable when accessed using one address, but write-1-to-clear when accessed from another address. Application logic may use this register to store interrupts. These interrupts can be read by the host bus through the readable address and cleared through the second address.

Another popular approach is to alias only some fields so that they are set/cleared when a particular address is written.

Alias representation in IDS Word

Alias registers in IDesignSpec word

 

In the UVM model, callback class for alias register is created, just like the shadow registers.

The callback is added to the alias registers as shown below.

begin
     Alias_cb Alias_Complex_register_block_regA_Fld1;
     Alias_cb Alias_Complex_register_block_regB_Fld1;
      Alias_Complex_register_block_regA_Fld = new("Alias_Complex_register_block_regA_Fld1", regA.Fld1);
     uvm_reg_field_cb::add(regB.Fld1, Alias_Complex_register_block_regA_Fld1);
                
      Alias_Complex_register_block_regB_Fld1 = new("Alias_Complex_register_block_regB_Fld1", regB.Fld1);
      uvm_reg_field_cb::add(regA.Fld1, Alias_Complex_register_block_regB_Fld1);
 end

 

lock registersLock Registers

Registers in some design needs to be protected from inadvertent writes. To do that, modal registers may be used. A simple example of a modal register is a “lock” register. Once the register access is locked, the software writes to the protected register is disabled and it behaves as a read-only register, until unlocked. The locking and unlocking of the register access is done by writing a value to another register field or to an input signal of the design.

A lock register is often used for controlling user/supervisory modes in a design. A variant of a lock register is a security register which can be accessed when a complex sequence of writes happen to its address.

Lock representation in IDS Word

lock registers in IDesignSpec

lock-registers-IDesignSpec-2

 In the design the “write_valid” signal of “lockreg” is dependent on the value of the field “fldA” of the register “regA”.

The UVM callback class for lock is:

class Lock_field_cb extends uvm_reg_cbs;
        local uvm_reg_field  lock_field;

        function new(uvm_reg_field lock);
            lock_field = lock;
        endfunction

         virtual function void post_predict(input uvm_reg_field  fld,
              input uvm_reg_data_t previous,
              inout uvm_reg_data_t value,
              input uvm_predict_e kind,
              input uvm_path_e path,
              input uvm_reg_map map);
              if (kind == UVM_PREDICT_WRITE) begin
                   if(lock_field.get())
                        begin
                            value = previous;
                         end
                   end
            endfunction
 endclass

The callback class is then added to the register that is to be protected.

RO-WO Pair RegistersRO-WO pair registers at same address

It is common for registers to have shared address within the address map. It’s there in applications like UART, where a register containing write-only-fields (WO) share the same address with another register containing read-only-fields (RO, RC, RS).  Reading from the shared address gives the content of the Read-Only register and writing to the shared address updates the writeable register

 RO_WO pair in IDS Word

ro-wo-pair-in-IDS

Both registers in the RO-WO pair will be at the same offset and will be decoded at the same time in the design.

In the UVM register model also both registers will be added at the same address in the UVM address map as shown below.

class Complex_register_block_block extends uvm_reg_block;
        `uvm_object_utils(Complex_register_block_block)
        rand Complex_register_block_RX_Register RX_Register;
        rand Complex_register_block_TX_Register TX_Register;
        . . . . 
        . . .
       // Function : build
       virtual function void build();
         . . . . 
              . . . 
            default_map.add_reg( RX_Register, 'h3, "RW");
            default_map.add_reg( TX_Register, 'h3, "RW");
            lock_model();
       endfunction
  endclass : Complex_register_block_block

indirect-registersIndirect Registers

Sometimes due to design constraints registers are not directly accessible via, a dedicated address. Such registers are accessed indirectly by first writing to an “index” register with a value that specifies the array’s offset, followed by a read or write of a “data” register to obtain or set the value for the register at that specified offset.

Indirectly addressed registers are used when the available address space is limited.

Representation in IDS Word

indirect-registers-in-IDS-Word

In UVM register model the indirect registers is modeled as shown below.

class SpecialReg_Data extends uvm_reg_indirect_data;  
             `uvm_object_utils(SpecialReg_Data)                        
             // Function : new                
              function new(string name = "SpecialReg_Data");            
              super.new(name, 32, build_coverage(UVM_NO_COVERAGE));     
              add_coverage(build_coverage(UVM_NO_COVERAGE));              
         endfunction           
 endclass    
…
…
virtual function void build();           
 //create            
Index   =   SpecialReg_Index::type_id::create("Index");           
 foreach (Data_TABLE[_i])          
     begin               
          Data_TABLE[_i] = SpecialReg_Data_TABLE::type_id::create($sformatf("Data_TABLE[%0x]", _i));     end            
  Data   =   SpecialReg_Data::type_id::create("Data");                        
//config          
  Index.configure(this, null, "Index");           
   foreach (Data_TABLE[_i])            
            begin                
                 Data_TABLE[_i].configure(this, null, $sformatf("Data_TABLE[%0x]", _i));           
           end 
‘ifdef INCA           

 

     begin               
             uvm_reg r[256];                
            foreach (Data_TABLE[i])                
               r[i] = Data_TABLE[i];               
              Data.configure(, r ,this, null );            
          end            
`else           
           Data.configure(, Data_TABLE ,this, null );            
`endif                        
//build           
 Index.build();           
 foreach (Data_TABLE[_i])           
        begin                
              Data_TABLE[_i].build();            
end            
Data.build();                        
//define default map and add reg/regfiles                                   
 default_map= create_map("default_map", 'h0, 4, UVM_BIG_ENDIAN, 0);   
default_map.add_reg( Index, 'h0, "RW");            
default_map.add_reg( Data, 'h1, "RW");                                                           
 lock_model();                   
 endfunction

Conclusion

This article is all about my experience of flexibility of IDesignSpec as a tool, which could capture different kinds of complex behaviors of registers in a very simple way. And generate their suitable RTL and UVM model.

 Semiconductor register verification automation