AXI VIP 中产生传输事务的基本方法

描述

 

本系列我想深入探寻 AXI4 总线。不过事情总是这样,不能我说想深入就深入。当前我对 AXI总线的理解尚谈不上深入。但我希望通过一系列文章,让读者能和我一起深入探寻 AXI4。

欢迎来到深入 AXI4 总线的实战篇,系列第二篇文章中,我们将首先了解调用 AXI VIP 产生激励与响应的方法,并完成一个小目标:实现三种情况下的握手信号。

关于平台移植

本文的实战在第一篇的示例工程上,新建 tb 来实现我们的功能。新建 tb 中的逻辑由 demo tb 的内容搬运简化而来。

本来计划新建一个工程,但是阅读 PG267 (IP 核的产品文档)发现,当前 Vivado 对于该 IP 的支持还比较弱,需要将 IP 的实例名以及层次路径硬编码至 tb 中,如果新建工程还比较麻烦。所以本文暂时还是在 example 的基础上展开 。

想要重新搭建工程的读者请注意阅读 demo tb 开头的说明,或者 PG267 第六章中的内容。

本文的场景为主机与从机之间通过 Pass-through (以后叫 ta 中间机?)进行通信。从机选用 mem 模式,有自己的存储模型,即使用 mem_stimulus.sv 作为激励。关于存储模型,我们将在后续的文章中讨论。

我们的改动在于主机的激励部分,以原先的 mst_stimulus.sv 为基础,构建我们自己的主机激励,改动后的 testbench 结构如下图所示。

编码

是的,新的激励加上了 headbig 字段,这来自于 深入 AXI4 总线 系列文章的英文名:Headbig AXI4。

VIP API 基本调用方式

PG 文档中,Xilinx 表示 VIP 基于 SystemVerilog 语言开发,同时在 API 的设计上,命名与数据结构的设计均参考了 UVM 框架,便于 VIP 在验证系统中的集成。由于本文的重点不在于 UVM 或者 API 的设计,因此仅跟着 demo 以及 PG 中的 API 调用流程过一遍。

主机 master

首先来看主机,定义于 axi_vip_master_mst_stimulus.sv 中

为主机 master ip 创建一个 agent 对象,传入 master ip 的层级路径,后续通过该 agent 控制主机 ip

agent = new("master vip agent",DUT.ex_design.axi_vip_mst.inst.IF);

通过 agent 启动主机

agent.start_master();

在 fork ...join 并发块中同时发出主机的读写传输事务。

 

fork
 begin
  //调用写传输事务 API
 end
 
 begin
  //调用读传输事务 API
 end
join

 

产生两者的 API 结构相似,我们以写传输事务为例。例程中依次使用了 3 种 API ,分别产生

完全随机化的写传输事务

multiple_write_transaction_full_rand ("single write",1);

定制化的写传输事务

 

single_write_transaction_api("single write with api",
                                     .id(mtestWID),
                                     .addr(mtestWADDR),
                                     .len(mtestWBurstLength), 
                                     .size(mtestWDataSize),
                                     .burst(mtestWBurstType),
                                     .wuser(mtestWUSER),
                                     .awuser(mtestAWUSER), 
                                     .data(mtestWData)
                                     );

 

部分随机化的写传输事务

multiple_write_transaction_partial_rand(相关参数);

我们常说,不想知道 API 函数之下发生了什么的程序员不是好程序员,IC 工程师同样如是。以较简单的定制化写传输事务函数为例,所谓函数实质上是一个 sv task,以下是 task 中的主要内容:

 

    axi_transaction                               wr_trans;
    wr_trans = agent.wr_driver.create_transaction(name);
    wr_trans.set_write_cmd(addr,burst,id,len,size);
    wr_trans.set_prot(prot);
    //...
    wr_trans.set_data_block(data);
    agent.wr_driver.send(wr_trans);  

 

首先声明一个 axi 传输事务对象,然后在主机 ip 的 agent 下建立传输事务。

通过 API 函数设定写命令信息,设定传输属性以及待传输的数据块。数据块的数据类型为

bit [4 * 1024 * 8 - 1:0]

从机 slave

接下来,我们看一下从机的相关流程,定义于 axi_vip_master_mem_stimulus.sv 中。

同样为从机创建并启动相应 agent,此处与主机相似不表。

在 demo 中构造了一个虚拟数据作为后续对主机读数据的回应,因为本文的主要工作是得到握手信息的波形,因此并不会实际存储主机写入的数据,而是在主机读取任意地址时,返回这个虚拟数据。

最后,从机调用 API 产生 wready 信号应答

 

  task user_gen_wready();
    axi_ready_gen                           wready_gen;
    wready_gen = agent.wr_driver.create_ready("wready");
    wready_gen.set_ready_policy(XIL_AXI_READY_GEN_OSC);
    wready_gen.set_low_time(1);
    wready_gen.set_high_time(2);
    agent.wr_driver.send_wready(wready_gen);
  endtask

 

此处表示 wready 信号在从机空闲时周期性生成,有效时间为 2/3,我们可以在后续的波形中看到。

握手波形

我们对主机的激励代码进行修改,仅保留单次定制化的读写传输事务,地址为 0x0,突发长度为 0。在波形中我们得到了三种情况下的握手信号。

(1)VALID 信号等待 READY 信号

编码

在 tb 中主机并行地启动读写传输事务,AR/W VALID 同时置高,在等待从机给出 READY 信号后完成地址与控制信号的传输,此时地址为 0x0.

(2)READY 信号等待 VALID 信号

编码

主机在发出读传输事务后,置高 RREADY 信号等待接收从机返回的读数据。在从机置高 RVALID 后,读传输事务完成。

(3)READY 与 VALID 信号同时置起

在设置从机的 READY 信号类型时,我们设置为周期性置高 READY,从下图中可以看到,READY 信号在送出 2 个周期高电平后置低 1 个周期。

编码

在这个场景中,写数据通道中的 WREADY 信号正好与 WVALID 信号同时置起,解锁了最后三种握手姿势中的最后一种,OK 本文实战篇收工了。

结语

本文首先介绍了 AXI VIP 中产生传输事务的基本方法。基于 demo 修改了一个简单纯粹的例子,并基于这个例子观察到了握手信号。 

      审核编辑:彭静
打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分