1

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

作为一种解决方法

  1. 我可以为同一空间声明内存模型,并且每当我需要突发访问时,我都会使用内存模型,但是为同一事物声明 2 个单独的类似乎是多余的,并且这种方法不会正确反映寄存器值。
  2. 创建一个函数,该函数循环迭代字节数并逐个访问寄存器,但是此方法不会在总线上创建突发事务。

所以我想知道是否有办法在寄存器模型中使用 burst_read 和 burst_write 方法。如果 burst_read 和 burst_write 支持镜像会很好(当前的实现不支持这个),但如果不支持,我可以使用 .predict 和 .set 所以它不是大问题。

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

4

2 回答 2

2

我发现这可以帮助您入门:

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

这家伙提到使用读/写的可选“扩展”参数。您可以将突发长度的长度存储在容器对象中(想想int与Java 相比),然后在调用第一个寄存器Integer时将其作为参数传递。write()

粗略的草图(未经测试):

// 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 中没有任何琐碎的容器对象。

于 2014-04-21T00:28:42.353 回答
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;整数突发长度;突发类适配器_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

于 2014-04-25T21:52:32.927 回答