Zynq-7000 完整硬件平台构建与验证权威指南
前言
- 本文目标: 本文依托 Alinx的AX7021B ZYNQ开发板,介绍如何使用Vivado搭建PS与PL的通信的通道,包含AXI DMA,BRAM,以及AXI GPIO,旨在为PS和PL通信提供一个完整的标准流程
项目概述
项目目标: 创建一个包含 BRAM 和 AXI 接口的基础 Zynq 硬件平台,并使用 Vitis 裸机程序验证其功能,最终实现基于 AXI CDMA 和中断的 PL-PS 数据回环,为后续 PetaLinux 开发奠定经过硬件验证的坚实基础。
开发环境:
- Vivado 2023.2
- Vitis 2023.2
- 目标器件:XC7Z020-2CLG484I
第一阶段:Vivado 基础硬件平台设计与BRAM单向通路
创建 Vivado 工程
操作步骤:
- 启动 Vivado 2023.2,点击
Quick Start -> Create Project
- Project Name: 命名为
ZYNQ_7000_AXI_BRAM
- Project Location: 指定一个不包含中文、空格或特殊字符的路径
- Project Type: 选择
RTL Project
并勾选Do not specify sources at this time
决策依据与原因:
- 命名规范: 硬件开发工具链对特殊字符路径的兼容性较差,从源头避免能省去未来很多麻烦
- 项目类型: 我们将采用自顶向下的设计方法,从一个空白的 Block Design 画布开始,通过集成 IP 核来构建系统
指定目标器件(关键步骤)
信息收集:
- 芯片丝印:
XC7Z020CLG484ABX1813
(提供了基础型号和封装) - 用户手册:
XC7Z020-2CLG484I
(提供了最关键的速度等级-2
和温度等级I
)
决策: 我们必须使用用户手册提供的更详细的型号,因为速度等级 (-2
) 对 Vivado 的时序分析至关重要。丝印信息仅用于交叉验证。
操作步骤:
- 在
Default Part
页面,确保处于Parts
标签页 - 使用
Filters
(筛选器) 精确定位:- Family:
Zynq-7000
- Package:
clg484
- Speed:
-2
- Family:
- 从筛选后的列表中选择
xc7z020clg484-2
,点击Next
并Finish
完成工程创建
决策依据与原因:
- 选择
Parts
而非Boards
提供了最大的灵活性,适用于任何没有预装 BSP 的开发板 - 准确的速度等级确保了 Vivado 时序分析的准确性,是硬件能否稳定运行的根本保证
构建 Block Design 与配置 ZYNQ7 PS
创建画布:
- 在
Flow Navigator -> IP INTEGRATOR
下,点击Create Block Design
- 使用默认名
design_1
创建 - 点击加号
+
图标,搜索并添加ZYNQ7 Processing System
IP 核
配置 ZYNQ7 PS: 双击 Zynq IP 核打开 Re-customize IP
窗口,依据手册信息逐项配置:
MIO Configuration (外设IO配置)
信息来源: 手册指出核心板 USB-UART 连接到 MIO 14/15 (UART 0
),底板串口连接到 MIO 12/13 (UART 1
);PS 端以太网连接到 MIO 16..27 和 MIO 52..53
配置操作:
- 启用
UART 0
(分配到MIO 14..15
) - 启用
UART 1
(分配到MIO 12..13
) - 启用
ENET 0
(分配到MIO 16..27
和MIO 52..53
),并配置电平标准HSTL1.8V
- 启用
GPIO
并分配到MIO
(以太网 PHY 复位信号连接到PS_MIO7
) - 将
Bank 0 IO Voltage
设为LVCMOS33
,Bank 1 IO Voltage
设为LVCMOS18
配置解释
HSTL1.8V vs LVCMOS18
特性 | HSTL1.8V | LVCMOS18 |
---|---|---|
全称 | High Speed Transceiver Logic | 标准低功耗I/O |
驱动能力 | 24-48mA | 2-12mA |
应用场景 | 高速接口(RGMII、DDR) | 一般I/O(GPIO、UART) |
阻抗匹配 | 50Ω,适合高频信号 | 阻抗要求宽松 |
信号完整性 | 优秀的噪声抑制 | 一般 |
为什么以太网需要HSTL1.8V:
- RGMII接口工作频率高(125MHz)
- 需要精确的时序和信号完整性
- PHY芯片通常要求HSTL标准的驱动强度
Peripheral IO Pins(配置PHY Reset)
配置操作:
勾选:
GPIO MIO
->Ethernet Phy Reset
,配置网口复位引脚管脚指定:设置为MIO 7(根据开发板手册)

配置解释
系统上电 → GPIO拉低PHY复位引脚 → 延时等待 → GPIO拉高释放复位 → PHY芯片内部初始化 → 寄存器配置完成 → MDIO通信建立 → 网卡可用
Clock Configuration (时钟配置)
信息来源: 手册指出一个 33.3333MHz
晶振提供给 PS 系统
配置操作:
- 将
Input Frequency (PS_CLK)
精确设置为33.333333
- 保持
CPU Clock Ratio
为6:2:1
,这将使 CPU 运行在约667MHz
DDR Configuration (DDR内存配置)
信息来源: 手册指出内存由两片美光 MT41K256M16TW-107
组成,总线宽度 32-bit,运行速度 533MHz (1066 MT/s)。开发板实际焊接的是兼容型号海力士 H5TQ4G63AFR-PBI
决策: 由于 Vivado 的 Memory Part
列表中没有海力士的型号,我们采纳手册的建议,使用兼容性最好的美光型号进行配置
配置操作:
- 在
Memory Part
下拉列表中,选择最接近的MT41K256M16 RE-125
Effective DRAM Bus Width
确认选择32 Bit
- 其他时序参数(CAS Latency等)由 Vivado 根据所选型号自动填充,无需修改
点击 OK
保存 PS 配置。运行Block Automation连接DDR和FIXED_IO。至此,一个最小化的、可引导的 Zynq 核心系统构建完成。
第二阶段:BRAM回环数据通路搭建
目标: 在已验证的基础硬件平台上,实现BRAM回环数据通路
硬件平台设计 (Vivado)
添加、配置并连接 PL 端 BRAM
操作步骤:
- 在画布上添加
AXI BRAM Controller
和Block Memory Generator
【技术原理补充】为什么需要这两个IP核?
Block Memory Generator (BMG):
本质: 纯粹的存储资源,是 FPGA 内部 Block RAM 的封装
接口: 提供原生的 BRAM 接口(地址、数据、使能、写使能等信号)
特点: 没有总线协议概念,不能直接连接到 AXI 总线
类比: 相当于一个”裸露”的存储芯片
AXI BRAM Controller (ABC):
- 本质: AXI 总线协议转换器
- 功能:
- 作为 AXI Slave,响应来自 PS 的总线访问
- 将 AXI 读写事务转换为 BRAM 的原生控制信号
- 处理 AXI 协议的握手、突发传输、错误响应等复杂逻辑
- 功能:
- 类比:相当于存储芯片的”控制器芯片
- 本质: AXI 总线协议转换器
完整的 PS 访问 BRAM 数据流程
第1步:PS 发起访问
PS CPU 执行: Xil_Out32(0x40000000, data)
↓
生成 AXI Write 事务 (地址 + 数据 + 控制信号)第2步:AXI 总线路由
AXI SmartConnect 根据地址译码
↓
将事务路由到 AXI BRAM Controller 的 S_AXI 接口第3步:协议转换
AXI BRAM Controller 接收 AXI 事务
↓
解析 AXI 协议:地址、数据、字节使能等
↓
转换为 BRAM 原生信号:bram_addr = AXI地址的低位部分
bram_din = AXI写数据
bram_we = 根据AXI写使能生成
bram_en = 1 (使能BRAM)
第4步:BRAM 存储操作
Block Memory Generator 接收控制信号
↓
将数据写入指定地址的存储单元第5步:响应返回
AXI BRAM Controller 向 PS 发送 AXI Write Response
↓
PS 收到写操作完成确认
- 配置
Block Memory Generator
:Mode:
设为BRAM Controller
(让其与控制器自动匹配接口)Memory Type:
设为True Dual Port RAM
(为未来扩展保留双端口)Port A Options -> Write Depth:
设为2048
(创建 8KB 容量)
- 配置
AXI BRAM Controller
:- 确认
Number of BRAM Interfaces
为1
,以确保只使用 BRAM 的一个端口,释放另一个端口
- 确认
- 自动化连接:
- 点击
Run Block Automation
连接 PS 的 DDR 和 FIXED_IO - 点击
Run Connection Automation
连接 PS、AXI 总线和 BRAM。Vivado 会自动添加AXI SmartConnect
和Processor System Reset
IP
- 点击
- 地址分配:
- 切换到
Address Editor
标签页,为/axi_bram_controller_0
分配一个地址(如0x40000000
),并确认其Range
为8K
- 切换到
决策依据与原因: 我们搭建了一条从 PS 到 PL 的完整数据通路。PS (Master) -> AXI总线 -> BRAM控制器 (Slave) -> BRAM。为 AXI BRAM Controller 分配地址,是让 PS 能够通过 AXI 总线访问 BRAM 的关键
添加 CDMA 与中断逻辑实现回环通路
操作步骤:
添加第二个 BRAM 控制器: 点击
+
添加AXI BRAM Controller
(axi_bram_ctrl_1
)。双击确认其Number of BRAM Interfaces
为1
PS → AXI BRAM Controller #0 → BRAM Port A (作为数据源)
PS → AXI BRAM Controller #1 → BRAM Port B (作为数据目标)
CDMA → 可同时访问两个控制器 → 实现高效数据搬运
添加 CDMA 引擎: 点击
+
添加AXI CDMA
(axi_cdma_0
)。双击并取消勾选Enable Scatter Gather
什么是 AXI CDMA? CDMA (Central Direct Memory Access):
- 本质: 专用的数据搬运引擎,独立于 CPU 运行
- 角色: 在 AXI 总线上既是 Master(发起数据访问)又有 Slave 接口(接收配置命令)
- 核心价值: 将 CPU 从繁重的数据拷贝任务中解放出来
数据流程
系统数据流设计:
PS 配置阶段:
PS (AXI Master) → CDMA S_AXI_LITE (配置接口)
配置:源地址、目标地址、传输长度
数据搬运阶段:
CDMA M_AXI (数据Master) → AXI总线 → BRAM Controller #0 (读取数据)
CDMA M_AXI (数据Master) → AXI总线 → BRAM Controller #1 (写入数据)
完成通知阶段: CDMA → 中断信号 → PS (任务完成通知)
为什么禁用 Scatter Gather?
Scatter Gather 模式:
- 功能: 支持复杂的、非连续的内存访问模式
- 适用场景: 需要在多个分散的内存块间进行复杂数据重组
- 成本: 需要额外的描述符内存、更复杂的控制逻辑
Simple Transfer 模式(我们的选择):
- 功能: 点对点的连续数据传输
- 适用场景: 简单的内存拷贝、缓冲区交换
添加中断合并器: 点击
+
添加Concat
(xlconcat_0
)。双击并设置Number of Ports
为1
【技术原理补充】中断合并器的系统作用
- Zynq 中断系统硬件基础
- PS 端有 IRQ_F2P[15:0] 共 16 条从 PL 到 PS 的中断线,每条中断线都是 1 位宽度,互相独立,每条线只能连接一个信号源
- Concat (xlconcat) 的作用是将多个 1 位输入信号按顺序拼接成一个多位输出信号, 输入和输出位宽相等,Concat 不压缩信息,只是重新组织信号
- 什么时候需要 Concat?
- 节省连接线: 在复杂设计中整理信号
- 信号重组: 将分散的中断信号组织成总线形式
- 接口匹配: 某些 IP 需要总线形式的中断输入
- 大量中断源的解决方案,当中断源大于十六时,使用AXI Interrupt Controller
- Zynq 中断系统硬件基础
为什么当前只配置 1 个端口?
当前系统分析:
- 只有 CDMA 一个中断源
- 理论上可以直接连接到 PS
决策依据与原因:
axi_bram_ctrl_1
: 用于连接True Dual Port RAM
的第二个端口 (PORTB
),创建独立的读出通道AXI CDMA
: 这是实现硬件数据搬运的核心,它能作为独立的 AXI Master,在不同地址间传输数据,从而将 CPU 从繁重的拷贝任务中解放出来。禁用Scatter Gather
是为了节省资源,因为我们只需要简单的点对点传输Concat
: 这是连接 PL 中断源到 PS 中断端口的标准工程实践。即使只有一个中断源,使用它也能保证设计的规范性和未来扩展性
使能并连接中断通路(关键步骤)
操作步骤:
- 使能 PS 中断端口: 双击 Zynq IP 核,进入
Interrupts -> Fabric Interrupts
,勾选IRQ_F2P[15:0]
,点击OK
。此时 Zynq IP 上会出现IRQ_F2P
端口 - 自动连接 AXI 总线: 点击
Run Connection Automation
,勾选所有新添加的 IP(axi_bram_ctrl_1
和axi_cdma_0
),让 Vivado 自动连接时钟、复位和数据总线 - 手动连接数据与中断:
- 将
blk_mem_gen_0
的BRAM_PORTB
连接到axi_bram_ctrl_1
的BRAM_PORTA
- 将
axi_cdma_0
的cdma_introut
连接到xlconcat_0
的In0
- 将
xlconcat_0
的dout
连接到 Zynq IP 的IRQ_F2P[0:0]
- 将
决策依据与原因:
- 我们必须先在 Zynq 内部”打开”接收中断的大门,对应的物理端口才会出现
- 我们构建了一条完整的中断信号物理链路:CDMA (事件发生) -> Concat (信号捆绑) -> Zynq PS (信号接收)。这是实现中断功能的硬件基础
分配多视角地址
操作步骤:
- 切换到
Address Editor
标签页 - 配置 PS 视角: 确保下拉菜单为
/processing_system7_0/Data
,右键点击空白处并选择Assign All
- 配置 CDMA 视角: 切换下拉菜单为
/axi_cdma_0/Data
,再次Assign All
决策依据与原因: 地址映射是基于”访问者”的视角。
- PS 视角: PS 作为主控制器,需要知道所有外设的地址,以便配置它们(配置 CDMA)和与它们交换数据(读写两个 BRAM)
- CDMA 视角: CDMA 作为数据搬运工,它只需要知道”从哪搬”(源 BRAM 地址)和”往哪搬”(目标 BRAM 地址)。它不需要知道自己的配置地址,因此其
S_AXI_LITE
接口在此视图中被正确地Excluded
生成最终硬件平台
操作步骤:
Validate Design
(F6): 确保所有连接和配置无误Create HDL Wrapper
: 更新顶层封装Generate Bitstream
: 生成最终的比特流Export Hardware
: 导出包含最新设计和比特流的.xsa
文件
决策依据与原因: 至此,我们得到了一份经过完整硬件设计、包含高级功能的硬件平台文件,它是我们进行最终软件验证的”黄金标准版”蓝图。
Vitis 完整功能验证(BRAM回环验证)
目标: 编写一个综合性的裸机程序,验证 CDMA 数据回环和中断通知机制的正确性。
更新 Vitis 工程硬件规格
操作步骤:
- 若无 Vitis 工程,则从 Vivado 启动
Vitis IDE
并创建一个 - 若已有工程,则在 Vitis 中双击 Platform 的
platform.spr
文件,更新硬件规格 (Hardware Specification) 为我们最新导出的.xsa
文件 - 右键 Platform 工程,选择
Build Project
,强制 Vitis 重新解析硬件并生成 BSP
决策依据与原因: 这是解决我们在调试中遇到的**”软硬件不匹配”**问题的根本方法。必须确保 Vitis 的 BSP 是基于最终的、正确的 .xsa
文件生成的。
编写完整验证代码
操作步骤:
- 在
app_component/src
目录下,用以下经过最终验证的main.c
代码替换原有内容 - 右键应用工程 ->
Build Project
关键代码修正与说明:
- 手动定义 BRAM 地址: 由于 Vitis BSP 不为 BRAM Controller 生成宏,我们根据 Device Tree 和 Address Editor 的信息,在代码中手动定义
BRAM_A_BASE_ADDR
和BRAM_B_BASE_ADDR
- 使用确切的宏:
DEVICE_ID
和中断相关的掩码宏,全部使用从官方xaxicdma_hw.h
头文件中确认的、确切的名称,如XAXICDMA_XR_IRQ_ALL_MASK
- 中断号: 中断ID
CDMA_INTR_ID
直接使用XPAR_FABRIC...
宏,这是最可靠的方式 - 中断处理: 采用最经典、最兼容的模式:自定义中断处理函数
CdmaIntrHandler
,并将其直接连接到 GIC。函数内部通过XAxiCdma_IntrGetStatus
和XAxiCdma_IntrAck
进行状态获取和清除
1 | /****************************************************************************** |
关键代码改进说明:
使用基地址而非设备ID
原因: 某些BSP生成过程中可能不会生成设备ID宏,使用基地址更可靠
改进:
XAxiCdma_LookupConfig(CDMA_BASE_ADDR)
而非依赖可能不存在的设备ID
直接寄存器访问处理中断
原因: 匹配Vitis 2023.2驱动的实际底层行为,更稳定可靠
改进: 使用
XAxiCdma_ReadReg/WriteReg
直接操作CDMA状态寄存器
固定中断号使用
原因: Zynq-7000 的 IRQ_F2P[0] 中断号在所有系统中都是固定的61
改进: 直接使用
#define CDMA_INTR_ID 61
避免依赖生成的宏
增强的缓存处理
原因: 确保DMA传输前后的数据一致性
改进: 在程序开始时重新初始化缓存系统
更细粒度的数据类型
原因: 使用字节级操作可以更精确地验证DMA传输
改进: 使用
u8
数组而非u32
,提高测试覆盖率
决策依据与原因: 这份代码解决了Vitis 2023.2工具链中的几个关键问题:
- BSP自动生成宏的不确定性
- 驱动API在不同版本间的兼容性差异
- 中断处理机制的底层实现细节
- 缓存一致性在DMA操作中的重要性
这是经过实际验证、针对您的硬件平台和开发环境优化的最终版本。
最终硬件验证
操作步骤:
- 连接开发板的 JTAG 和 UART 端口
- 在 Vitis 中,右键应用工程 ->
Launch -> Launch on Hardware
预期结果: 在 Vitis 的串口终端 (Serial Terminal) 中,将按顺序打印出以下信息:
1 | --- AXI CDMA Loopback Test --- |
最终结论: 项目成功! 打印出 Data verification PASSED!
意味着我们设计的整个系统——从 PS 的 DDR,到 AXI 总线,到 PL 端的 BRAM 和 CDMA,再到中断返回 PS——形成了一个完美闭环。这份 .xsa
硬件平台现在可以被认为是完全经过验证、100% 可靠的,可以充满信心地交付给 PetaLinux 进行后续的系统开发。
第三阶段: AXI_GPIO控制PL端KEY与LED
目标: 在已验证的 BRAM+CDMA 硬件平台基础上,进一步集成 AXI GPIO IP 核,实现由 PL 端物理按键触发中断,PS 端软件响应并控制 PL 端 LED 亮灭的完整 I/O 闭环。此阶段将深入验证 PL-PS 中断合并、软件中断处理及 GPIO 驱动的使用。
硬件平台扩展 (Vivado)
添加并配置 AXI_GPIO IP 核
操作步骤:
- 在已有的 Block Design 画布中,点击
+
添加AXI GPIO
IP 核 (axi_gpio_0
)。 - 双击该 IP 核,打开
Re-customize IP
窗口进行精确配置:- 勾选
Enable Dual Channel
,为输入和输出创建独立通道。 - 通道 1 (GPIO):
- 勾选
All Inputs
。 - 将
GPIO Width
设置为1
。(用于连接单个按键)
- 勾选
- 通道 2 (GPIO2):
- 勾选
All Outputs
。 - 将
GPIO Width
设置为1
。(用于控制单个 LED)
- 勾选
- 勾选
Enable Interrupt
,为 IP 核添加中断输出端口。
- 勾选
决策依据与原因:
- 双通道: 将输入(按键)和输出(LED)在逻辑上分离,使驱动代码更清晰,每个通道可以独立控制。
- 精确位宽: 将位宽设为
1
,与我们的物理目标(1个按key,1个LED)完全匹配,可以最大化地节省 PL 逻辑资源,并使设计意图明确化。 - 使能中断: 这是实现“按键按下,软件才响应”这一低功耗、高效率模式的硬件基础。
集成 GPIO 到系统并连接中断
操作步骤:
- 连接 AXI 总线: 点击
Run Connection Automation
,在弹出的窗口中仅勾选新添加的/axi_gpio_0
,让 Vivado 自动完成其S_AXI
从接口、时钟和复位信号的连接。 - 扩展并连接中断:
- 双击项目中已有的
xlconcat_0
IP 核,将其Number of Ports
从1
修改为2
。 - 确认 CDMA 的中断输出仍连接在
In0
端口。 - 将
axi_gpio_0
的ip2intc_irpt
输出端口,手动连接到xlconcat_0
的In1
输入端口。
- 双击项目中已有的
- 引出物理端口:
- 右键点击
axi_gpio_0
上的gpio_io_i
端口 ->Create Port...
-> 命名为key_pl
。 - 右键点击
axi_gpio_0
上的gpio2_io_o
端口 ->Create Port...
-> 命名为led_pl
。
- 右键点击
- 分配地址:
- 切换到
Address Editor
,在/processing_system7_0/Data
视图下,为新出现的/axi_gpio_0
分配地址(如0x41200000
)。
- 切换到
决策依据与原因:
- 中断合并: 扩展
xlconcat
而非新增,是处理多中断源的标准工程实践,保证了系统的可扩展性,并维持了原有 CDMA 中断通路的完整性。 - 引出端口:
Create Port
是将 Block Design 内部的逻辑信号“暴露”到顶层设计的唯一方法,是后续进行物理引脚约束的前提。 - 分配地址: 为 AXI GPIO 分配地址,是让 PS 能够通过总线找到并配置它的“门牌号”。
分配物理引脚约束 (XDC)
信息来源: 核心板原理图指出,目标按键连接到 FPGA 的 A17
引脚,目标 LED 连接到 A16
引脚,其 IO Bank 供电为 3.3V。
操作步骤:
- 在
Flow Navigator
中,点击Open Implemented Design
。 - 在 Vitis 顶部菜单栏选择
Window -> I/O Ports
打开引脚分配窗口。 - 找到
key_pl
端口:- Package Pin: 输入
A17
- I/O Std: 选择
LVCMOS33
- Package Pin: 输入
- 找到
led_pl
端口:- Package Pin: 输入
A16
- I/O Std: 选择
LVCMOS33
- Package Pin: 输入
- 按
Ctrl + S
保存,将约束写入项目的 XDC 文件中。
决策依据与原因: 这是连接逻辑设计与物理现实的关键一步。Package Pin
确保信号能驱动正确的外部硬件,I/O Std
确保电气电平兼容,防止器件损坏。
生成最终硬件平台
操作步骤:

Validate Design
(F6): 检查最终设计。Create HDL Wrapper
: 更新顶层封装。Generate Bitstream
: 生成包含所有硬件逻辑(CDMA + GPIO)的比特流。Export Hardware
: 导出包含最新设计和比特流的.xsa
文件,作为 Vitis 软件开发的输入。
软件验证与协同调试 (Vitis Unified IDE)
创建并配置调试会话
操作步骤:
- 更新 Vitis Platform 的硬件规格,指向最新导出的
.xsa
文件,并重建 BSP。 - 在左侧活动栏进入
Run and Debug
视图。 - 点击齿轮图标
⚙️
创建或修改launch.json
文件。 - 在图形化配置页面,确保以下关键项被正确设置:
- ✅
Program Device
必须勾选。 Bitstream File
指向包含 GPIO 设计的最新.bit
文件。APPLICATION
指向您编译的 GPIO 测试程序的.elf
文件。
- ✅
决策依据与原因: Program Device
是确保 PL 端硬件(包括 AXI GPIO 和 ILA)在软件运行前被正确配置的核心开关。Vitis 2023.2 会基于此设置,在后台自动查找并关联同名的 .ltx
探针文件。
GPIO 中断验证 C 代码
1 | /***************************** Include Files *********************************/ |
新版Vitis中断配置问题
Vitis 2023.2 API变化
重要变化:设备初始化方式改变
1 | // ❌ 旧版本方式(不再适用) |
中断ID映射关键点
1 | // 必须包含PS中断定义 |
硬件连接验证
- AXI GPIO
ip2intc_irpt
→ xlconcatIn1
→ PSIRQ_F2P[1]
- 对应中断ID:62 (
XPS_FPGA1_INT_ID
)
第四阶段: 构建并验证高性能AXI-Stream数据通路
目标: 在前序硬件平台基础上,集成 AXI DMA,构建一个连接 PS-DDR 与 PL 的高性能 AXI-Stream 数据通路。通过实现一个带缓冲的硬件回环,并编写一份功能完整、符合 Vitis 2023.2 SDT 规范的裸机程序,深度验证该数据通路的正确性、稳定性与中断机制。
核心理念: 本阶段从“功能实现”迈向“性能与鲁棒性设计”。每一个新增的IP和配置决策,都旨在解决一个潜在的系统瓶颈或时序风险,并确保软件验证的全面性。
硬件平台升级:从内存映射到数据流 (Vivado)
在此阶段,我们进行一次重大的架构升级,引入**数据流(Stream)**的概念,其核心是构建一条从内存出发,经过PL,再回到内存的高速公路。
关键IP的添加与配置
AXI Direct Memory Access (DMA) IP核
操作步骤:
- 在 Block Design 画布中,点击
+
添加AXI Direct Memory Access
IP核。 - 双击 IP 核进行配置 (
Re-customize IP
):- 取消勾选
Enable Scatter Gather Engine
: 我们采用简单的点对点连续数据传输(Simple Mode),禁用此高级功能可节省大量逻辑资源并简化软件。 Width of Buffer Length Register
修改为23
: 将单次最大传输长度从默认的16KB提升至8MB,为处理大数据块提供充足的裕量。- 保持
Enable Write Channel (S2MM)
和Enable Read Channel (MM2S)
勾选,因为我们需要完整的读写双向通路。
- 取消勾选
【技术原理补充】为什么是AXI DMA,而不是AXI CDMA?
- 角色不同:
AXI CDMA
是 内存到内存 的搬运工,工作在地址世界。而AXI DMA
是 内存与数据流 之间的桥梁,它能将内存中的数据打包成 AXI-Stream 数据流(MM2S),也能将数据流解包存回内存(S2MM)。它是连接两个世界的唯一通道。 - 我们的需求: 要搭建 AXI-Stream 通路,AXI DMA 是必选项。
AXI4-Stream Data FIFO IP核 (关键优化)
操作步骤:
- 点击
+
添加AXI4-Stream Data FIFO
IP核。 - 双击进行配置:
- 保持
FIFO Depth
为默认的512
或1024
。 - 其他参数如
TDATA Width
保持Auto
,它会自动匹配连接的 AXI-Stream 总线宽度。
- 保持
【决策依据与原因】为什么要在回环中插入一个FIFO?
这是一个从“能用”到“好用”的关键决策。直接将DMA的输出M_AXIS_MM2S
连接到输入S_AXIS_S2MM
在功能上可行,但存在风险:
- 时序风险:
TVALID
/TREADY
握手信号路径过长,可能导致时序违规。FIFO作为一个独立的、带寄存器的模块,能将这条关键路径切断,提供时序隔离,极大提升系统稳定性。 - 流控缓冲: AXI DMA的读写引擎是两个独立的模块。在某些极端情况下,读引擎(MM2S)可能瞬间高速发送数据,而写引擎(S2MM)恰好有微小延迟。FIFO提供了数据缓冲区,能平滑这种速率上的微小不匹配,防止数据丢失或总线死锁。
高性能系统架构连接
使能并连接高性能HP接口(关键优化)
操作步骤:
- 双击 ZYNQ7 Processing System IP核。
- 导航至
PS-PL Configuration -> HP Slave AXI Interface
。 - 勾选
S AXI HP0 interface
并点击OK
。Zynq IP上会出现一个新的64位从端口S_AXI_HP0
。 - 运行
Run Connection Automation
,在为axi_dma_0
的M_AXI_MM2S
和M_AXI_S2MM
接口选择主接口时,手动指定或确保 Vivado 自动选择了连接到新出现的S_AXI_HP0
端口的总线。
【决策依据与原因】为什么必须用HP口,而不能用GP口?
这是性能的根本保障。
- 控制路径 vs 数据路径: PS上有两种PS-PL接口:
M_AXI_GP (General Purpose)
: 32位,低带宽,用于控制流,如CPU写IP核的配置寄存器。S_AXI_HP (High Performance)
: 64位,高带宽,直连DDR控制器,专为数据流设计。
- 带宽匹配: DMA的高速数据搬运,必须依赖HP接口提供的高速公路。如果连接到GP口,相当于让跑车跑乡间小路,性能将严重受限。
提升PL时钟频率(关键优化)
操作步骤:
- 双击 ZYNQ7 Processing System IP核。
- 导航至
Clock Configuration -> PL Fabric Clocks
。 - 将
FCLK_CLK0
的Requested Frequency
修改为100 MHz
。
决策依据与原因: 100MHz是AXI接口事实上的标准工作频率。它不仅能提供比默认50MHz高一倍的数据吞吐量,而且对于现代IP核来说,在这个频率下更容易实现时序收敛。
完成数据流与中断连接
操作步骤:
- 【最终】数据流连接 (经过FIFO缓冲):
- 将
axi_dma_0
的M_AXIS_MM2S
输出端口连接到axis_data_fifo_0
的S_AXIS
输入端口。 - 将
axis_data_fifo_0
的M_AXIS
输出端口连接到axi_dma_0
的S_AXIS_S2MM
输入端口。
- 将
- 中断连接:
- 双击
xlconcat_0
,将Number of Ports
从2扩展到4。 axi_dma_0
的mm2s_introut
→xlconcat_0
的In2
axi_dma_0
的s2mm_introut
→xlconcat_0
的In3
- 双击

Vitis裸机验证:编写生产级的验证程序
在硬件平台升级后,我们必须编写一个与之匹配的裸机程序来验证其功能。这份最终的验证代码,不仅适配 Vitis 2023.2 的 SDT 流程,更在功能上进行了增强,包含了多次传输、超时等待、详尽的状态打印等专业特性。
最终验证C代码 (经过实际验证)
(注意:这份代码直接来自您提供的、已验证成功的版本,体现了更完整的测试逻辑)
1 | /****************************************************************************** |
验证流程与预期结果
- 更新平台与构建: 在Vitis中更新Platform的硬件规格为最新的
.xsa
文件,并重建项目。 - 配置运行环境: 在
Run/Debug Configurations
中,必须确保Program Device
被勾选,以保证最新的比特流被下载到PL端。 - 执行与观察: 程序运行后,串口终端应按顺序、逐一打印出每次传输的详细日志。
预期最终结果:
串口终端将清晰地展示5次完整的传输、握手、数据校验过程,最终打印出成功信息:
1 | ... |
最终结论: 所有 5 次传输测试成功!
的打印结果,标志着我们成功构建并验证了一个高性能、高鲁棒性的 AXI-Stream 数据通路。这份经过专业级裸机程序严格验证的 .xsa
硬件平台,现在可以作为一份100%可靠的、高质量的蓝图,交付给 PetaLinux 进行后续的驱动开发和应用层实现。
附录A:常见问题与解决方案
工具版本兼容性问题
问题: Vitis 2023.2 中某些传统的 BSP 函数被废弃 解决方案:
避免使用
platform.h
和init_platform()
, Vitis BSP (v9.0) 已废弃platform.h
及init_platform()
直接使用
xil_printf.h
中的函数参考官方驱动源码确认正确的API
Vitis 2023.2引入了SDT流程,API发生重大变化
中断ID不再从xparameters.h获取,需要从xparameters_ps.h获取
初始化方式改为基于BASEADDR,不再使用DEVICE_ID
BRAM 地址宏缺失问题
问题: Vitis BSP 不自动为 BRAM Controller 生成地址宏 解决方案:
- 根据 Address Editor 中的配置手动定义地址
- 交叉验证 Device Tree 中的地址信息
- 在代码中使用明确的数值地址
中断配置问题
问题: 中断无法正常触发或处理 解决方案:
- 确保在 Vivado 中正确使能了 IRQ_F2P 端口
- 检查中断连接链路的完整性
- 使用官方推荐的中断处理模式
- 正确配置 GIC 和异常处理
缓存一致性问题
问题: DMA 传输后数据不一致 解决方案:
- 在 DMA 传输前使用
Xil_DCacheFlushRange()
- 在读取 DMA 结果前使用
Xil_DCacheInvalidateRange()
- 确保地址对齐要求