使用burst_read / write和寄存器模型

时间:2014-04-17 21:30:49

标签: system-verilog uvm

我有一个16个寄存器的寄存器空间。 这些可以通过串行总线访问(单个和突发)。 我为这些寄存器定义了UVM reg模型。 但是,reg模型方法都不支持总线上的突发事务。

作为解决方法

  1. 我可以为相同的空间声明内存模型,每当我需要突发访问时,我都会使用内存模型,但为同样的事情声明2个单独的类似乎是多余的,这种方法不会正确地镜像寄存器值。
  2. 创建一个循环迭代字节数和逐个访问寄存器的函数,但这种方法不会在总线上创建突发事务。
  3. 所以我想知道是否有一种方法可以将burst_read和burst_write方法与寄存器模型一起使用。如果burst_read和burst_write支持镜像(当前实现不支持这种情况)会很好,但如果不是,我可以使用.predict和.set,所以它不是一个大问题。

    或者我可以轻松实现寄存器模型的方法以支持突发操作。

2 个答案:

答案 0 :(得分:2)

我发现这有助于您入门:

http://forums.accellera.org/topic/716-uvm-register-model-burst-access/

该家伙提到使用可选的'扩展程序'读/写的参数。您可以将突发长度的长度存储在容器对象中(在Java中考虑intInteger),然后在第一个寄存器上调用write()时将其作为参数传递。 / p>

粗略草图(未经测试):

// inside your register sequence
uvm_queue #(int) container = new("container");
container.push_front(4);
start_reg.write(status, data, .extension(container));


// inside your adapter
function uvm_sequence_item reg2bus(const ref uvm_reg_bus_op rw);
  int burst_len = 1;

  uvm_reg_item reg_item = get_item();
  uvm_queue #(int) extension;
  if ($cast(extension, reg_item.extension))
    burst_len = extension.pop_front();

  // do the stuff here based on the burst length
  // ...
endfunction

我使用了uvm_queue,因为在UVM中没有任何琐碎的容器对象。

答案 1 :(得分:2)

在结合Tudor提供的意见和讨论中的链接之后,以下是为reg模型添加突发操作的方法。

这个实现没有显示所有代码,只是添加突发操作所需的部分,我已经测试了它用于串行协议(SPI / I2C)的写和读操作。寄存器模型值已正确更新,RTL寄存器也会更新。

创建一个保存数据和突发长度的类:

class burst_class extends uvm_object;
 `uvm_object_utils (....);

  int burst_length;
  byte data [$];

  function new (string name);
    super.new(name);
  endfunction

endclass

内部寄存器序列(用于读取不初始化数据)

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));

成功运行后,应在obj对象中写入或收集数据值 在适配器类中(reg2bus更新为写入,bus2reg更新为读取) 有关事务的所有信息都可以在reg2bus中获得,除非是读取数据。

适配器类       uvm_reg_item start_reg;       int burst_length;       burst_class adapter_obj;

reg2bus实施

  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

根据burst_length更新此处的事务大小并正确分配数据。 至于读取bus2reg需要更新

bus2reg实现(已经拥有所有控制信息,因为reg2bus总是在bus2reg之前执行,使用reg2bus中捕获的值)

根据burst_length,只将数据分配给通过扩展名传递的对象,在本例中为adapter_obj