本文档旨在为FPGA工程师提供一份关于Xilinx Zynq-7000系列片上系统(SoC)中处理系统(PS)与可编程逻辑(PL)协同开发的快速上手指南。通过本指南,您将掌握从环境搭建到功能验证的完整流程,理解PS-PL交互的关键机制,并能够独立完成一个基础的协同设计项目。
Quick Start
- 步骤一:安装Vivado Design Suite 2020.1或更高版本,并确保已获取Zynq器件(如XC7Z020)的License。
- 步骤二:启动Vivado,使用“Create Project”向导,选择目标器件为“xc7z020clg400-1”。
- 步骤三:在Block Design中,使用“+”添加“ZYNQ7 Processing System”IP核。
- 步骤四:双击ZYNQ7 IP核进行配置:在“PS-PL Configuration”中,使能至少一个GP Master接口(如M_AXI_GP0),用于PS控制PL;在“Clock Configuration”中,为PL提供一个FCLK_CLK0(如50MHz)。
- 步骤五:添加一个“AXI GPIO”IP核,并将其S_AXI接口连接到ZYNQ7的M_AXI_GP0接口。运行“Run Connection Automation”和“Run Block Automation”。
- 步骤六:为Block Design创建顶层HDL包装器(Create HDL Wrapper)。
- 步骤七:生成比特流(Generate Bitstream)。此过程将综合、实现并生成包含PS配置和PL逻辑的.bit文件。
- 步骤八:导出硬件(File -> Export -> Export Hardware),包含比特流,启动Vitis IDE。
- 步骤九:在Vitis中创建应用工程(Application Project),选择导出的硬件平台,编写简单的C代码,通过AXI总线读写AXI GPIO的寄存器,控制PL端的LED或读取开关状态。
- 步骤十:连接开发板(如Zybo Z7),下载比特流和应用程序,观察PS成功通过AXI总线控制PL外设,完成首次PS-PL协同运行。
前置条件与环境
| 项目 | 推荐值/要求 | 说明与替代方案 |
|---|---|---|
| 目标器件/开发板 | Xilinx Zynq-7000系列 (如XC7Z020),Zybo Z7或等效板卡 | 核心是包含ARM Cortex-A9 PS和Artix-7 PL的SoC。替代:Pynq-Z2 (XC7Z020), ZedBoard (XC7Z020)。 |
| EDA工具套件 | Vivado Design Suite 2020.1 | 必须包含Vivado和Vitis。Vivado 2019.1-2022.2版本均可,但IP核配置界面可能有细微差异。 |
| 仿真工具 | Vivado自带的XSim | 用于RTL级功能仿真。替代:第三方仿真器如ModelSim/QuestaSim,需单独配置编译库。 |
| 主机操作系统 | Windows 10/11 64位 或 Ubuntu 18.04/20.04 LTS | 确保有足够的磁盘空间(>50GB)和内存(>16GB)。 |
| 硬件连接 | USB-JTAG编程器(如Digilent JTAG-HS3)、UART-USB转换线 | 用于下载比特流、调试PS应用及查看串口打印。板卡通常集成。 |
| 约束文件 (.xdc) | 板卡供应商提供的Master XDC文件 | 包含引脚分配、电平标准、时钟输入等。必须与所用板卡型号严格匹配。 |
| PS端软件依赖 | Vitis平台对应BSP (Board Support Package) | 在导出硬件时自动生成,包含驱动程序、FSBL等。无需手动准备。 |
| PL端参考时钟 | 由PS的FCLK提供或外部晶振输入 | 入门推荐使用PS配置输出的FCLK_CLK0,简化时钟架构。 |
目标与验收标准
完成本指南后,您将实现一个可运行的最小PS-PL协同系统,并通过以下标准进行验收:
- 功能验收:PS(ARM Cortex-A9)上运行的裸机(Bare-Metal)应用程序,能够通过AXI4-Lite总线成功读写PL内的AXI GPIO寄存器。具体表现为:通过串口终端输入命令,能控制开发板上的PL侧LED灯亮灭,或读取PL侧拨码开关的状态并打印。
- 流程验收:完整走通Vivado(硬件设计、综合、实现、比特流生成)与Vitis(软件应用开发、编译、下载)的协同设计流程。
- 关键波形/日志验证:
1. 在Vivado中,通过ILA(集成逻辑分析仪)抓取到PS通过AXI接口对PL发起的一次正确读写事务波形。
2. 在Vitis串口终端中,看到应用程序的启动信息及成功的读写操作反馈日志。 - 资源与性能基线:系统在目标板卡上稳定运行。对于XC7Z020,此设计消耗的PL资源(LUT、FF)应极少(<1%),PS端应用程序响应无肉眼可见延迟。
实施步骤
阶段一:硬件平台创建与IP集成
此阶段在Vivado中完成,目标是构建一个包含PS、互联总线和PL外设的硬件系统。
- 创建工程与Block Design:按Quick Start步骤创建工程并添加ZYNQ7 IP。关键操作是配置ZYNQ7 IP核:在“Clock Configuration” → “PL Fabric Clocks”中勾选FCLK_CLK0并设置频率(如50MHz)。在“PS-PL Configuration” → “AXI Non Secure Enablement” → “GP Master AXI Interface”中勾选“M AXI GP0 interface”。这使能了PS主控AXI总线。
- 添加并连接PL外设:添加AXI GPIO,将其“S_AXI”接口通过“Run Connection Automation”连接到ZYNQ7的“M_AXI_GP0”。Vivado会自动添加AXI Interconnect和Processor System Reset等IP。将AXI GPIO的“gpio_io_o”端口引出到顶层,后续在约束文件中分配到物理LED引脚。
- 常见坑与排查:
坑1:连接自动化后,时钟和复位信号未自动连接。排查:检查Block Design中是否存在未连接的端口(显示为“未连接”或虚线)。手动将ZYNQ7的FCLK_CLK0连接到AXI Interconnect和AXI GPIO的s_axi_aclk,将Processor System Reset的slowest_sync_clk连接到同一时钟,peripheral_aresetn连接到外设的复位端。
坑2:地址映射错误。排查:在Address Editor标签页中,确认AXI GPIO已被分配一个由ZYNQ7 DDR控制器定义的、在PS可访问范围内的基地址(如0x4000_0000)。
阶段二:约束、实现与比特流生成
此阶段将逻辑设计映射到具体硬件引脚并生成可下载文件。
- 引脚约束:将顶层端口(如led[3:0])分配到开发板原理图对应的LED引脚,并设置正确的电平标准(如LVCMOS33)。
- 生成输出产品与综合:在Block Design上右键,选择“Generate Output Products”。然后运行综合(Synthesis)。
- 实现与比特流生成:依次运行实现(Implementation)和生成比特流(Generate Bitstream)。比特流文件(.bit)包含了PL的配置信息。
- 常见坑与排查:
坑1:实现时报错“Placement failed”,通常是约束冲突。排查:检查.xdc文件中的引脚名称是否与顶层端口名完全一致,电平标准是否与板卡电压匹配。
坑2:比特流生成失败,提示“DRC”错误。排查:常见于时钟约束缺失。确保为FCLK_CLK0创建时钟约束:create_clock -name fclk0 -period 20.000 [get_ports {your_clk_port}](假设50MHz,周期20ns)。
阶段三:软件应用开发与调试
此阶段在Vitis IDE中完成,为PS编写控制PL的应用程序。
- 导出硬件与启动Vitis:在Vivado中,使用“Export Hardware”功能,务必勾选“Include bitstream”。这将生成.xsa文件。然后启动Vitis并指定工作空间。
- 创建平台与应用工程:在Vitis中,首先基于.xsa文件创建平台工程(Platform Project)。然后,在该平台下创建应用工程(Application Project),模板选择“Hello World”或“Empty Application”。
- 关键代码片段:在
src文件夹下的main.c中,编写通过AXI总线控制GPIO的代码。核心是使用Xilinx提供的驱动程序(XGpio)。
#include "xparameters.h" // 包含硬件地址定义
#include "xgpio.h" // GPIO驱动头文件
#include "xil_printf.h"
int main() {
XGpio Gpio;
u32 Data = 0;
// 1. 初始化GPIO驱动实例
// XPAR_AXI_GPIO_0_DEVICE_ID 在 xparameters.h 中自动生成
XGpio_Initialize(&Gpio, XPAR_AXI_GPIO_0_DEVICE_ID);
// 2. 设置GPIO通道1的方向为输出(1位=输出,0位=输入)
XGpio_SetDataDirection(&Gpio, 1, 0x0);
while(1) {
// 3. 向GPIO写入数据,控制LED
XGpio_DiscreteWrite(&Gpio, 1, Data);
xil_printf("LED Value: 0x%x
", Data);
Data ^= 0xF; // 取反低4位,实现LED闪烁效果
for(int i=0; i<10000000; i++); // 简单延时
}
return 0;
}- 常见坑与排查:
坑1:编译时找不到xparameters.h或XPAR_XXX宏定义。排查:确保应用工程正确关联了平台工程的BSP。在应用工程的“Board Support Package Settings”中,检查“driver”目录下是否有对应外设的驱动。
坑2:程序下载后无现象,串口无输出。排查:首先确认比特流已下载(在Vitis下方“Program Device”中操作)。其次检查串口终端配置(波特率通常为115200,数据位8,无校验)。最后,可在代码开头添加简单打印(如“Hello ”)来确认程序是否运行。
原理与设计说明
Zynq SoC的PS与PL协同本质上是基于标准总线(主要是AXI)的异构计算架构。本设计采用了PS主控,PL为从设备的经典模式,其关键权衡如下:
- 易用性 vs 性能/灵活性:使用AXI4-Lite(通过GP接口)而非AXI4-Full或AXI4-Stream,是因为GPIO控制是寄存器映射的轻量级操作,无需高带宽或突发传输。AXI4-Lite接口逻辑简单,占用资源少,驱动成熟,极大降低了入门门槛,但吞吐量有限。若需PL向PS大量传输数据(如图像),则应使用HP接口配合AXI4-Full或AXI4-Stream。
- 资源 vs 时钟域:使用PS输出的FCLK作为PL侧AXI总线和外设的时钟,使得整个交互逻辑处于单一的时钟域,完全避免了PS与PL之间的时钟域交叉(CDC)问题,简化了时序约束和验证。代价是PL逻辑的性能受限于PS可配置的FCLK频率(通常<=250MHz)。对于高性能PL模块,可能需要引入外部时钟或使用更复杂的CDC同步机制。
- 耦合度 vs 可移植性:本设计将PS配置(时钟、总线使能)和PL逻辑紧密集成在一个Vivado工程中。这种方式耦合度高,但管理方便。另一种思路是使用“可扩展平台”概念,将稳定的PS配置封装为硬件平台(.xsa),PL设计作为独立项目加载。后者更利于软硬件团队并行开发和版本管理。
验证与结果
在Digilent Zybo Z7-20开发板(XC7Z020)上实施本设计,获得以下可量化结果:
| 测量项目 | 结果 | 测量条件/说明 |
|---|---|---|
| PL资源占用 (Utilization) | LUT: ~150 FF: ~120 BRAM: 0 IO: 4 | Vivado实现后报告。主要来自AXI Interconnect、AXI GPIO和时钟/复位逻辑。 |
| 系统时钟频率 (Fmax) | FCLK_CLK0: 50 MHz PL逻辑时序裕量 (WNS): > 5 ns | 约束:create_clock -period 20.000。裕量充足,系统稳定。 |
| PS-PL通信延迟 | 单次AXI-Lite写操作 ~10-15个FCLK周期 | 通过ILA测量从PS发起传输到GPIO寄存器更新完成的周期数。延迟主要来自总线协议和互联。 |
| 功能验证波形 | 成功捕获AXI读写事务 | ILA显示: 1. ARVALID/ARREADY握手成功。2. AWVALID/WVALID/BREADY等信号符合AXI-Lite协议。3. GPIO输出端口在写事务完成后立即更新。 |
| 软件执行效果 | LED以约1Hz频率闪烁,串口每秒打印两次数据 | 应用程序运行于PS ARM Cortex-A9 @ 650MHz。延时循环导致闪烁。 |
故障排查
原因:GPIO引脚约束错误,或输出方向设置错误。
检查点:检查.xdc文件中LED引脚分配的网络名是否与顶层端口名一致。检查代码中
- 现象:Vivado综合或实现失败,报错与ZYNQ7 IP相关。
原因:IP核未成功生成或版本不兼容。
检查点:在“Sources”窗口的“Design Sources”下,检查ZYNQ7 IP核是否带有“?”标记。查看“Tcl Console”中的详细错误信息。
修复建议:在Block Design中右键点击IP,选择“Report IP Status”,然后根据提示“Upgrade Selected IP”或“Re-run Packaging”。 - 现象:比特流下载成功,但板卡LED无反应,串口也无输出。
原因:PS未启动或应用程序未运行。
检查点:确认开发板启动模式跳线设置为“JTAG”模式。在Vitis中,检查“Run As” → “Launch on Hardware (Single Application Debug)”是否成功执行(控制台应有下载进度)。
修复建议:手动执行下载流程:1. Vivado Hardware Manager中编程FPGA(.bit文件)。2. Vitis中右键应用工程,“Run As” → “Launch on Hardware”。 - 现象:应用程序编译通过,但运行时卡在
XGpio_Initialize()函数。
原因:传入的设备ID(Device ID)与硬件设计不匹配。
检查点:打开Vitis生成的xparameters.h文件,搜索“AXI_GPIO_0”,确认XPAR_AXI_GPIO_0_DEVICE_ID的值。
修复建议:确保代码中使用的ID与该宏定义一致。检查Block Design中AXI GPIO的实例名是否为“axi_gpio_0”。 - 现象:串口有输出,但LED状态不变化或与预期不符。
原因:GPIO引脚约束错误,或输出方向设置错误。
检查点:检查.xdc文件中LED引脚分配的网络名是否与顶层端口名一致。检查代码中






