版本:Vivado2020.2(Vitis)
任务:PL 端自定义一个 AXI4 接口的 IP 核,通过 AXI_HP 接口对 PS 端 DDR3 进行读写 测试,读写的内存大小是 4K 字节,
目录
一、介绍
(1)AXI
(2)AXI SmartConnect 与 AXI Interconnect IP核
(3)ZYNQ AXI GP/HP 接口
二、硬件设计
三、软件设计
四、效果
一、介绍
(1)AXI
AXI:高级可扩展接口(Advanced eXtensible Interface)是 ARM 公司提出的 高性能、高带宽、低延迟 的片上总线协议,属于 AMBA:高级微控制器总线架构(Advanced Microcontroller Bus Architecture)协议家族的一部分,广泛应用于 FPGA 和 SoC 设计中。
AXI 协议目前主要有 3 种版本:
-
AXI4(AXI4-Full):支持高带宽数据传输,适用于内存映射(Memory-Mapped)设备。
-
AXI4-Lite:简化版,适用于低复杂度外设(如寄存器配置)。
-
AXI4-Stream:无地址协议,用于高速流数据传输(如视频、网络数据)。
AXI4 (Full) | AXI4-Lite | AXI4-Stream | |
---|---|---|---|
地址支持 | ✔️ | ✔️ | ❌ (无地址) |
突发传输 | ✔️ | ❌ | ❌ (但本身流数据连续,且不限制长度) |
乱序支持 | ✔️ | ❌ | ❌ |
适用场景 | DDR访问、DMA | 寄存器配置 | 流数据传输:视频流、网络数据 |
(2)AXI SmartConnect 与 AXI Interconnect IP核
两者都是 Xilinx 提供的基础互联 IP,用于管理多个AXI主设备(Master)和从设备(Slave)之间的通信,支持地址路由、仲裁和基础QoS(服务质量)。AXI SmartConnect 为更高性能互联IP,在AXI Interconnect 基础上优化了 延迟、吞吐量和资源利用率,支持更复杂的系统拓扑。
AXI Interconnect | AXI SmartConnect | |
---|---|---|
协议支持 | AXI4, AXI4-Lite | AXI4, AXI4-Lite, AXI4-Stream |
QoS 能力 | 基础轮询仲裁 | 权重仲裁、优先级抢占 |
数据宽度转换 | 需手动配置 | 自动适配 |
延迟优化 | 中等 | 更低延迟 |
适用场景 | 简单到中等复杂度系统 | 高性能复杂系统(如Versal) |
资源占用 | 较少 | 较多(但更高效) |
(3)ZYNQ AXI GP/HP 接口
Zynq 的 PS 与 PL 端之间通过多种AXI接口连接,其中 GP(通用)接口和 HP(高性能)接口是最常用的两类,主要区别在于带宽、用途和连接对象。以下是核心对比与使用指南:
特性 | GP(General Purpose)接口 | HP(High Performance)接口 |
---|---|---|
AXI版本 | AXI4(32位数据位宽) | AXI3/AXI4(32/64位数据位宽) |
数据带宽 | 较低 | 高 |
主要用途 | 控制寄存器访问、低速数据传输 | 高速数据流(如DMA、视频处理) |
连接对象 | PS 作为主设备访问 PL 外设、 进行一般性的数据传输交互 | PL 作为主设备访问 PS 端 DDR 或 OCM |
典型应用 | 配置IP核寄存器、传感器数据读取 | 视频帧缓冲、高速ADC/DAC数据交互 |
二、硬件设计
整体系统框图如图所示,ZYNQ 配置用到了UART、AXI HP接口(PL端访问 PS端 DDR)、DDR、以及提供给PL端的时钟、复位信号:
(1)自定义 IP 核创建流程之前有介绍,参考:ZYNQ笔记(六):自定义IP核-LED呼吸灯。此外本次 IP 要实现 PL 端读写 PS 端 DDR,因此接口类型需要选FULL(AXI4-FULL)接口模式为Master。如图所示:
(2)所创建的自定义 IP 核 Vivado 提供了实现 AXI-Full 接口的读写功能的模板(顶层模块下的.v文件):不用对代码作任 何修改,即可实现本次例程对 DDR 的读写测试功能
模板代码设计了一个状态机实现读写功能(模板代码分析可参考正点原子视频教程):
状态机流程 |
---|
1. 系统复位后,状态机处于IDLE 初始状态,等待外部输入的启动传输脉冲 init_txn_pulse。 |
2. IDLE 状态下检测到 init_txn_pulse 为高电平,状态机跳转到 INIT_WRITE 状态。 |
3. INIT_WRITE 状态下,状态机拉高 start_single_burst_write 信号,来不断地启动 AXI4 Master 接口对 Slave 端大小为 4KB 的存储空间进行突发写操作。写操作完成后,write_done 信号会拉高,状态机进入 INIT_READ 状态。 |
4. INIT_READ 状态下,状态机拉高 start_single_burst_read 信号,不断地启动 AXI4 Master 接口对 Slave 端同一存储空间进行突发读操作,同时将读出的数据与写入的数据进行对比。读操作完成后,read_done 信号拉高,状态机进入 INIT_COMPARE 状态。 |
5. INIT_COMPARE 状态下,判断 AXI4 接口在读写过程中的是否发生错误,并将错误状态赋值给 ERROR 信号,然后将 compare_done 信号拉高,表示一次读写测试完成。最后跳转到 IDLE 状态,等待下一次读写操作的启动信号。 |
(3)直接封装打包IP核,不用对内部代码进行修改,直接使用生成的模板实现读写操作。再将自定义IP核添加到BD设计中,双击进行配置,将变量C M AXI TARGET SLAVE BASE ADDR 的值修改为0x1000_0000,它位于DDR3存储器的地址空间,是axi4_rw_test IP核进行读写操作的起始地址,约为中间位置(不同板卡的ddr大小可能不一样)。将该地址之前约DDR一半的存储空间预留下来,用于运行PS中的软件程序:
写满这些配置参数用于 AXI4 总线 的 用户侧扩展信号,允许在 AXI4 事务中添加额外的用户自定义信息,没有使用全部设置0。
(4)PL通过按键输入一个启动信号,因此需要添加一个按键消抖模块key_filter,实现按键按下输出一个时钟周期的高电平脉冲,模块时钟周期为50MHz,正好是zynq配置提供给PL的时钟频率。新建key_filter.v源文件并完成verilog设计后,在 BD 界面空白处右键选择“Add Module”,添加源文件,将按键消抖模块 key_filter.v 添加进来,如图所示:
(5)最后整体 bd 设计部分如图所示:设计检查、Generate Output Products、 Create HDL Wrapper、管脚约束、Gnerate Bitstream、Export Hardware(包含比特流文件)、启动Vitis
三、软件设计
#include "stdio.h"
#include "xil_printf.h"
#include "xil_cache.h"
#include "xil_io.h" //用于访问内存映射的寄存器或外设:包含读写内存数据函数#define DDR3_DATA_BASEADDR 0x10000000 //宏定义DDR3数据存储的起始地址(对应硬件设计中的配置)int main()
{int i;int data;int c;//关闭数据缓存Data Cache以免从缓存中读取数据。因为对同一地址进行读操作时,读出的有可能是 Data Cache中缓存数据,而非 DDR中真正数据Xil_DCacheDisable();while(1){xil_printf("Enter 1 to start read data in DDR \r\n");scanf("%d",&c);if(c==1){//for循环从地址 0x1000_0000读取 DDR3存储器中的数据,读取的存储空间大小为 4KB。for(i=0; i<4096; i+=4)//i每次累加 4,因为调用Xil_In32()读取内存数据,每次读取 32bit。而内存地址以字节为单位,一次读操作后地址应加 4。{//通过地址读取32位数据data = Xil_In32(DDR3_DATA_BASEADDR + i);//打印地址和数据xil_printf("Address:%d Data:%d \r\n",(DDR3_DATA_BASEADDR+i), data);}}}return 0;
}
四、效果
1.不按按键(没有向DDR写数据)直接读取DDR,可以看到打印的数据为随机数。
2.按下按键后,仅指示读写操作结束的LED灯亮起(DDR数据读写成功),这时PS再读取DDR,可以看到打印的数据为1到1024(一个数据32位,一共刚好 4Byte×1K=4KB数据),正是自定义IP写入DDR的数据。