本文转载自:FPGA探索者微信公众号
在 Vivado 中自定义 AXI4-Lite 接口的 IP,实现一个简单的 LED 控制功能,并将其挂载到 AXI Interconnect 总线互联结构上,通过 ZYNQ 主机控制,后面对 Xilinx 提供的整个 AXI4-Lite 源码进行分析。
整体系统如下所示:
![](http://xilinx.eetrend.com/files/2021-04/%E5%8D%9A%E5%AE%A2/100069833-142243-1.png)
一、封装 AXI-Lite 协议的 IP
1. 新建一个工程
2. 打包 IP 工程
Tools 下选择创建并打包一个新的 IP。
![](http://xilinx.eetrend.com/files/2021-04/%E5%8D%9A%E5%AE%A2/100069833-142244-2.png)
选择创建一个新的带AXI4总线的 IP。
![](http://xilinx.eetrend.com/files/2021-04/%E5%8D%9A%E5%AE%A2/100069833-142246-3.png)
IP命名。
![](http://xilinx.eetrend.com/files/2021-04/%E5%8D%9A%E5%AE%A2/100069833-142247-4.png)
IP 的 AXI4-Lite 总线的配置:
(1)选择 Lite 总线;
(2)选择 Slave 设备从机模式,这里考虑到我们的实际应用,以 ZYNQ 的 PS 做主机 Master,来读写自定义的从机LED IP;
(3)数据位宽 32-bit;
(4)内部寄存器最少为4个,这里选择4,实际上本例中只使用了 1 个,这里的 4 就代表内部由 4 个 32 位的寄存器,依次命名为 slv_reg0 ~ slv_reg3。
按照微机寻址的思想,当找到设备的基地址后,加上偏移地址能够找到设备的内部寄存器。这里,当偏移地址为 0 时,表示 slv_reg0,偏移地址为 4 时(4 个字节,32-bit),表示 slv_reg1,8 代表 slv_reg3,12 代表 slv_reg4。
例子中只使用 slv_reg0,偏移地址为0,这个在 ZYNQ 的 PS 端编程时使用。
![](http://xilinx.eetrend.com/files/2021-04/%E5%8D%9A%E5%AE%A2/100069833-142248-5.png)
上述配置完成后,编辑IP,会自动打开一个新的工程,在 AXI-Lite 接口协议基础上,添加自定义的端口和用户逻辑。
![](http://xilinx.eetrend.com/files/2021-04/%E5%8D%9A%E5%AE%A2/100069833-142249-6.png)
3. 修改 IP
打开底层的代码,在第18行添加自己需要的输出端口。
ZC706的 PL 侧有 4 个 LED 可供操作,这里定义输出 4 位去控制 LED。
![](http://xilinx.eetrend.com/files/2021-04/%E5%8D%9A%E5%AE%A2/100069833-142250-7.png)
中间的实现逻辑先不看,是 AXI-Lite 协议中的 Valid、Ready 握手信号的产生以及读、写、响应等操作,后面再进行具体的分析。
找到尾部第401行,添加用户逻辑,上面我们已经说了PS 侧向 slv_reg0 写入 LED 的控制信息,这里从 slv_reg 读出控制信息,低 4 位为需要的有效控制信息。
![](http://xilinx.eetrend.com/files/2021-04/%E5%8D%9A%E5%AE%A2/100069833-142251-8.png)
完成底层的端口和用户逻辑后,在顶层中第 18 行也加入输出端口,并在例化底层时第 51 行将新加入的端口进行连接。
![](http://xilinx.eetrend.com/files/2021-04/%E5%8D%9A%E5%AE%A2/100069833-142253-9.png)
![](http://xilinx.eetrend.com/files/2021-04/%E5%8D%9A%E5%AE%A2/100069833-142254-10.png)
修改后,打包 IP 时可能出现如 1处所示的编辑图样,在 2 处点击蓝色字体会自动更新,点击 3 处打包。
![](http://xilinx.eetrend.com/files/2021-04/%E5%8D%9A%E5%AE%A2/100069833-142255-11.png)
二、使用自定义的 AXI-Lite的IP
找到开始时的新建工程,新建一个 Block Design 原理图设计文件,添加 IP 时就可以搜索到自定义的 LED_MyIP_Lite。
![](http://xilinx.eetrend.com/files/2021-04/%E5%8D%9A%E5%AE%A2/100069833-142256-12.png)
添加 ZYNQ,使用自动连接会自动添加复位逻辑和 AXI总线互联结构,添加一个 ILA 集成逻辑分析仪,并设置成 AXI4 LITE 接口,引出 LED 输出,原理图文件右键生成顶层 wrapper。
![](http://xilinx.eetrend.com/files/2021-04/%E5%8D%9A%E5%AE%A2/100069833-142257-13.png)
对 ILA 的配置。
![](http://xilinx.eetrend.com/files/2021-04/%E5%8D%9A%E5%AE%A2/100069833-142258-14.png)
新建约束文件,增加 4 个 LED的物理约束,由于使用的是 Xilinx 的 FPGA评估版,其他引脚的约束已经由系统自动完成。
![](http://xilinx.eetrend.com/files/2021-04/%E5%8D%9A%E5%AE%A2/100069833-142259-15.png)
可以打开阅读一下 Xilinx 给的一些约束,如下图所示,首先对时钟频率和抖动进行时序约束,然后对输入输出引脚进行物理约束,最重要的是“电平标准”和“引脚位置”。
![](http://xilinx.eetrend.com/files/2021-04/%E5%8D%9A%E5%AE%A2/100069833-142261-16.png)
综合、布局布线、生成 bitstream 后,导出硬件到 SDK。
新建 SDK 工程,加入代码如下,设置基地址和偏移地址。
![](http://xilinx.eetrend.com/files/2021-04/%E5%8D%9A%E5%AE%A2/100069833-142262-17.png)
三、运行结果
Run As 下载观察流水灯效果。
Debug As 下载,Vivado 中连接硬件,打开 ILA。
对于写事务,设置 WVALID和 WREADY 两个均为 1 时触发;
对于读事务,设置检测 RVALID 和 RREADY 都为 1,两个断点处单步运行。
(1)初始化
![](http://xilinx.eetrend.com/files/2021-04/%E5%8D%9A%E5%AE%A2/100069833-142263-18.png)
(2)写事务
写事务涉及到写地址通道、写数据通道和写响应通道。测试时,ZYNQ 的 PS 主机向 slv_reg0 写 1。
![](http://xilinx.eetrend.com/files/2021-04/%E5%8D%9A%E5%AE%A2/100069833-142264-19.png)
(3)读事务
读事务涉及到读地址通道和读数据通道。测试时,ZYNQ 的 PS 主机向 slv_reg0 写 1,然后读取该寄存器。
![](http://xilinx.eetrend.com/files/2021-04/%E5%8D%9A%E5%AE%A2/100069833-142265-20.png)
四、AXI4-Lite源码分析
运行 PS 端的程序,PL 端的 4 个 LED 按照流水灯方式循环点亮。
改成 Debug 下载,并打开 ILA 集成逻辑分析仪,单步调试,设置触发条件。
对于写事务,设置检测 WVALID 和 WREADY 均有效;
对于读事务,设置检测 RVALID 和 RREADY 都有效。
(1)写事务
写事务涉及到写地址通道、写数据通道和写响应通道。
![](http://xilinx.eetrend.com/files/2021-04/%E5%8D%9A%E5%AE%A2/100069833-142266-21.png)
(a)AWADDR[3:0] 写地址
AWADDR[3:0] = 0,表示写 slv_reg0。
主机(ZYNQ的PS)给出从机的基地址 0x43C00000 和 偏移地址 0x0,其中基地址主要用于对整个从机的寻址,偏移地址用于对从机内部寄存器的寻址。
偏移地址为0,对应 AXI_AWADDR[3:0] = 0,在 32 位 WDATA 写数据配置下,AXI_AWADDR[3:2] 表示选择写哪个寄存器,
=0 时写 slv_reg0;
=1 时写 slv_reg1;
=2 时写 slv_reg2;
=3 时写 slv_reg3;
对应到 AXI_AWADDR[3:0] 就是 0 / 4 / 8 / 12。
![](http://xilinx.eetrend.com/files/2021-04/%E5%8D%9A%E5%AE%A2/100069833-142268-22.png)
(b)AWPORT[2:0] 写保护
AWPORT[2:0] = 1,即 3'b001,表示特权且安全的写入数据信息。
AWPORT[2:0] 提供三种级别的写入保护,提供用于禁止非法传输事务的访问权限:
![](http://xilinx.eetrend.com/files/2021-04/%E5%8D%9A%E5%AE%A2/100069833-142269-23.png)
(c)AWREADY 和 WREADY 准备好
根据 Xilinx 的 AXI-Lite 源码,对于从机部分,当检测到主机发出的 AWVALID 写地址有效 和 WVALID 写数据有效同时有效的下一个时钟的上升沿,将从机部分的 AWREADY 和 WREADY 拉起接收写地址和写数据。
对 AWREADY 写地址准备好:
![](http://xilinx.eetrend.com/files/2021-04/%E5%8D%9A%E5%AE%A2/100069833-142270-24.png)
对 WREADY 写数据准备好:
![](http://xilinx.eetrend.com/files/2021-04/%E5%8D%9A%E5%AE%A2/100069833-142271-25.png)
(d)WDATA[31:0] 写数据
当 WVALID 和 WREADY 都为高电平的时候,WDATA 有效,此处表示有效的写数据是 0x0000_0001。
按照设计,将该数据写入到 slv_reg0,并取低 4 位赋值给 LED。
这样,LED[3:0] = 4'b0001,点亮其中一个 LED。
![](http://xilinx.eetrend.com/files/2021-04/%E5%8D%9A%E5%AE%A2/100069833-142273-26.png)
(e)WSTRB[3:0] 写阀门
WSTRB[3:0] = 4'hf,即 4'b1111,表示 32 位的 WDATA 都有效,4 位分别表示 4 个字节。
WSTRB[3:0]:对应哪个写字节有效,WSTRB[n] 对应 WDATA[8n+7 : 8n],WSTRB[3:0] 对应 32 位的写数据 WDATA。
WVALID 为低电平时,WSTRB 可以为任意值;
WVALID 为高电平有效时,WSTRB 为高的字节线必须指示有效的数据。
窄传输:
当主机产生比数据总线宽度更窄的数据传输时,比如 32 位数据总线上只传输 8 bit 信息,且利用最低的 8 位传输,则 WSTRB[3:0] = 4'b0001。
![](http://xilinx.eetrend.com/files/2021-04/%E5%8D%9A%E5%AE%A2/100069833-142274-27.png)
(f)BRESP[1:0] 和 BVALID
BRESP[1:0] 写响应信息;
= 0 表示正常写入成功(OKAY);
= 1 表示独占式写入(EXOKAY,AXI4-Lite 不支持独占式读写,AXI4 中表示独占式写入成功);
= 2 表示设备错误(SLVERR);
= 3 表示译码错误(DECERR)。
根据 Xilinx 的 AXI-Lite 源码,对于从机部分,当检测到主、从机的写数据/写地址通道上的 VALID 和 READY 都有效时,在下一个时钟的上升沿给出写响应有效信号 BVALID。
![](http://xilinx.eetrend.com/files/2021-04/%E5%8D%9A%E5%AE%A2/100069833-142277-28.png)
![](http://xilinx.eetrend.com/files/2021-04/%E5%8D%9A%E5%AE%A2/100069833-142278-29.png)
(2)读事务
读事务涉及到读地址通道和读数据通道。
测试时,ZYNQ 的 PS 主机向 slv_reg0 写 1,然后读取该寄存器。
![](http://xilinx.eetrend.com/files/2021-04/%E5%8D%9A%E5%AE%A2/100069833-142280-30.png)
(a)ARREADY 读准备好
当检测到主机发来的有效的读地址(S_AXI_ARVALID),并且自身的 ARREADY 还没拉高,那么下一个时钟的上升沿拉高。
![](http://xilinx.eetrend.com/files/2021-04/%E5%8D%9A%E5%AE%A2/100069833-142281-31.png)
(b)RVALID 读数据有效和 RRESP 读响应信息
当 ARREADY 拉高后,如果此时主机的 ARVALID 还是有效,且此时从机还没有给出都数据有效信号 RVALID,则在下一个时钟的上升沿给出 RVALID 有效信号,且同时给出读响应信息。
读响应信息 RRESP[1:0] 的含义和前文的写响应 BRESP[1:0] 一样:
= 0 表示正常读取成功;
= 1 表示独占式读取(AXI4-Lite 不支持独占式读写,AXI4 支持);
= 2 表示设备错误;
= 3 表示译码错误。
![](http://xilinx.eetrend.com/files/2021-04/%E5%8D%9A%E5%AE%A2/100069833-142282-32.png)
(c)RDATA[31:0] 读数据
与写事务的分析一样,根据读地址中的控制信息 axi_araddr[3:2] 表明 从 slv_reg0 中读出数据,并写入到读数据通道的 RDATA 上。
![](http://xilinx.eetrend.com/files/2021-04/%E5%8D%9A%E5%AE%A2/100069833-142283-33.png)
参考资料:
[1] Xilinx. ds768_axi_interconnect;
[2] AXI总线中文详解;
[3] 米联客_S02_基于ZYNQ的SOC入门基础;