在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端读取的数据也是正确的