ZYNQ的ARM和FPGA数据交互——AXI交互最重要的细节

作者:范龙飞,来源:MYMINIEYE微信公众号

在Xinlinx的ZYNQ中,拥有ARM+FPGA这种架构,每款产品均带有双精度浮点的双核ARMCortex-A9MPCore处理系统,ARM(PS端)具有比较强的事务管理功能,可以用来跑界面以及应用程序等,其优势主要体现在控制方面,里面整合了很多现成的硬件资源供编程调用。FPGA(PL端)灵活性强,拥有更大的并行度和计算能力,内部逻辑可以根据需求而改变。二者相互结合,不仅可以节约开发时间,还能实现更复杂的系统。

Xinlinx的PL和PS之间数据传输通过AXI总线连接,因此实现PL-PS协同通信,需要了解AXI。

1.AXI简要介绍

AXI全称(Advanced eXtensible Interface),主要描述了主设备和从设备之间的数据传输方式。适合高带宽低延时设计,无需复杂的桥就能实现高频操作,能满足大部分器件的接口要求,提供互联架构的灵活性与独立性。

(1)AXI总线

总线是一组传输通道,是各种逻辑器件构成的传输数据的通道,一般由数据线、地址线、控制线等构成。在ZYNQ中支持三种AXI总线。

●AXI4: 主要面向高性能地址映射通信的需求,允许最大256轮的数据突发传输。

●AXI4-Lite: 是一个轻量级的,适用于吞吐量较小的地址映射通信总线,占用较少的逻辑资源。

●AXI4_Stream:面向高速流数据传输,去掉了地址项,允许无限制的数据突发传输规模。

三种总线的组成如下所示,其中AXI与AXI_Lite有相同的组成部分:

(2)AXI接口

接口是一种连接标准,又常常被称之为物理接口。这里有三种接口分别为AXI_GP(4个)、AXI_HP(4个)、AXI_ACP(1个),ZYNQ主要的连接如下:

①I/0 :PS端的外设,包括SPI,I2C,UART,USB,ENET等接口。
②Mem :flash存储接口,包括SRAM,NAND,SPI这三种。

③EMIO :由于MIO管脚有限,PS端可以通过EMIO访问PL端引脚。

④GP :通用AXI接口,用来实现一般主从互联、数据交互,不用于高性能。

⑤HP :是高性能/带宽的标准接口,主要用于PL访问PS上的存储器。

⑥ACP : PL端可以直接从PS的Cache中拿到CPU计算的结果,延时低

⑦DMA :DMA控制接口,用于控制高速数据传输的通道。

(3)AXI协议

AXI所采用的是一种READY,VALID握手通信机制,简单来说主从双方进行数据通信前,有一个握手的过程。传输源产生VLAID信号来指明何时数据或控制信息有效。而目地源产生READY信号来指明已经准备好接受数据或控制信息。传输发生在VALID和READY信号同时为高的时候。如下图所示:

AXI的读写状态跳转就是基于几个传输通路的VALID和READY信号握手跳转的过程。

其中写操作的信号依赖关系如下:

①在写状态,master将AWVALID拉高。

②slave收到AWVALID后,将AWREADY拉高,持续到写完,master收到AWREADY拉高的信号后,将AWVALID拉低。

③AWADDR在AWVALID为高时给定对应地址。

④slave收到WVALID信号为高时,把WREADY信号拉高,保持一个周期,写入数据。

⑤BRESP和BVALID都由slave控制,当收到写的数据后,BVALID拉高。

⑥当master收到BVALID拉高的信号时,BREADY拉高,写传输完成。

读操作的依赖关系如下:

①在读状态,master将ARVALID拉高。
②slave收到ARVALID信号后,将ARREADY拉高,持续到读完,master收到 ARREADY拉高的信号后,将ARVALID拉低。

③ARADDR在ARVALID为高时给定对应地址。

④RREADY信号收到RVALID信号为高时拉高,保持一个周期,读出数据。

2.系统结构

这里通过如下的系统框图来实现PL和PS之间的数据传输:

主要实现以下的功能:PS端把数据写入RAM中,然后PL端通过AXI总线(这里使用AXI4_Lite)把数据从RAM中把数据读出来,进行相应的处理;PL端通过AXI(这里使用AXI4_Lite)总线把数据写入RAM中,PS端从RAM中读取数据。

3.PL端

(1)首先创建一个Block Design,加入以下IP核:

IP核的设置为:

①processing_system7

PS-PLConfiguration中打开AXI_GP0接口。

MIOConfiguration中Bank1 I/O Voltage 选择1.8V。

ClockConfiguration中FCLK_CLK0设置为100MHz。

DDRConfiguration 中需要根据自己的芯片型号进行选择、设置,如果不 对应,则程序无法运行。

②axi_bram_ctrl

AXIProtocol选择AXI4LITE。

Numberof BRAM interface选择1。

③blk_mem_gen

Mode选择BRAM Controller。

MemoryType选择True Dual Port RAM。

④axi_gpio

GPIO选择 ALL Outputs;width选择2。

设置完成之后,我们为axi_bram_ctrl_1创建端口,右键S_AXI,选择Create interface port,name设置为s_axi_lite,mode选择SLAVE,点击OK;同时为axi_gpio_0创建输出端口,Port name 设置gpio,点击OK。然后点击页面上方的Run Connection Automation,最后的结果如下:

其中clk和rstn为PL端提供时钟和复位,端口s_axi_lite需要关联时钟fclk,关联设置如下:

设置完之后需要对不同的模块分配地址,右键选择Auto Assign Address:

然后点击下图中左侧第二个打✔的图标,出现以下提示表示设置的原理图没有问题。

然后右键system,创建顶层例化文件,把设置的原理图当做一个IP核例化使用。

(2)PL端我们还需要通过AXI总线往Block RAM中写入和读取数据,这就需要PL端写AXI的控制逻辑,根据以上分析,设计AXI读写状态时序如下:

状态设计

其中rd_en和wr_en是由PS端给出,控制PL端是写还是读,结束条件指的是写入或读出的个数,也就是每次写入或读出数据的个数控制,这里使用计数器控制,每次写入或读出的长度为32,写入的数据为0-31。


AXI读时序

以上从机的响应信号均为假设收到valid信号后拉高,根据以上时序编写Verilog代码,然后产生Bit文件,Launch SDK进入软件编程界面。

4.PS端

创建一个新的工程,首先给出写使能信号,让PL端往BRAM中写入数据,然后PS端读取数据。

上述GPIO控制,实际就是向PL端发送一个脉冲(GPIO[1]由0->1->0)使能信号,GPIO[0]为0是写状态,为1是读状态。在Vivado波形中,可以看到数据以递增的形式在写入。

在PS端读取BRAM中的数据, 可以看到数据是一致的。

然后PS端向BRAM中写入递减数据

从波形上可以看到PL端读取的数据也是正确的

推荐阅读