Search code examples
system-veriloguvm

Using burst_read/write with register model


I've a register space of 16 registers. These are accessible through serial bus (single as well as burst). I've UVM reg model defined for these registers. However none of the reg model method supports burst transaction on bus.

As a workaround

  1. I can declare memory model for same space and whenever I need burst access I use memory model but it seems redundant to declare 2 separate classes for same thing and this approach won't mirror register values correctly.
  2. create a function which loops for number of bytes iterations and access registers one by one however this method doesn't create burst transaction on bus.

So I would like to know if there is a way to use burst_read and burst_write methods with register model. It would be nice if burst_read and burst_write support mirroring (current implementation doesn't support this) but if not I can use .predict and .set so its not big concern.

Or can I implement a method for register model easily to support burst operation.


Solution

  • After combining opinions provided by Tudor and links in the discussion, here is what works for adding burst operation to reg model.

    This implementation doesn't show all the code but only required part for adding burst operation, I've tested it for write and read operation with serial protocols (SPI / I2C). Register model values are updated correctly as well as RTL registers are updated.

    Create a class to hold data and burst length:

    class burst_class extends uvm_object;
     `uvm_object_utils (....);
    
      int burst_length;
      byte data [$];
    
      function new (string name);
        super.new(name);
      endfunction
    
    endclass
    

    Inside register sequence (for read don't initialize data)

    burst_class obj;
    obj = new ("burstInfo");
    
    obj.burst_length = 4; // replace with actual length
    obj.data.push_back (data1);
    obj.data.push_back (data2);
    obj.data.push_back (data3);
    obj.data.push_back (data4);
    
    start_reg.read (status,...., .extension(obj));
    start_reg.write (status, ...., .extension (obj));
    

    After successful operation data values should be written or collected in obj object In adapter class (reg2bus is updated for write and bus2reg is updated for read) All the information about transaction is available in reg2bus except data in case of read.

    adapter class uvm_reg_item start_reg; int burst_length; burst_class adapter_obj;

    reg2bus implementation

      start_reg = this.get_item;
      adapter_obj = new ("adapter_obj");
    
      if($cast (adapter_obj, start_reg.extension)) begin
         if (adapter_obj != null) begin
            burst_length     = adapter_obj.burst_length;
         end
         else
            burst_length              = 1; /// so that current implementation of adapter still works
      end
    

    Update the size of transaction over here according to burst_length and assign data correctly. As for read bus2reg needs to be updated

    bus2reg implementation (Already has all control information since reg2bus is always executed before bus2reg, use the values captured in reg2bus)

    According to burst_length only assign data to object passed though extension in this case adapter_obj