2. Vivado与Vitis工具链实战
在Zynq软硬件协同开发中,Vivado与Vitis并不是两个彼此独立的软件,而是一条前后衔接的工具链:Vivado负责把PS(Processing System)与PL(Programmable Logic)组织成一个可实现的硬件系统,并导出描述该系统的XSA(Xilinx Support Archive);Vitis则基于XSA建立软件平台,编译运行在ARM核上的应用,并通过调试器观察软硬件交互。本节围绕这条链路,讲清工程创建、Block Design、IP Integrator、平台导出、Vitis统一软件平台与调试环境的关键操作与判断依据。
一、工程创建:先确定器件与设计意图
启动Vivado后选择Create Project,工程类型选RTL Project,并勾选“Do not specify sources at this time”,因为Zynq系统通常先搭硬件平台再补逻辑源码。器件选择必须与开发板一致,例如Zynq-7000系列常见器件为xc7z020clg400-1,Zynq UltraScale+则为xczu3eg-sbva484-1-e。器件选错会导致后续IP核不可用或引脚约束无法匹配。工程创建完成后,建议立即在Settings中确认目标语言、仿真器与默认库,避免中途切换造成综合结果不一致。
二、Block Design与IP Integrator:把PS和PL连成系统
在Flow Navigator中点击Create Block Design,命名如system。IP Integrator的核心操作是“加IP—连接口—跑验证”。首先添加ZYNQ7 Processing System,双击进入配置:在PS-PL Configuration中使能M_AXI_GP0用于PS控制PL,使能S_AXI_HP0用于PL高速访问DDR;在Clock Configuration中确认FCLK_CLK0为100MHz;在DDR Configuration中按开发板选择DDR3型号与位宽。配置完成后,IP Integrator会自动推导出DDR、FIXED_IO等外部接口。
接着添加自定义或官方IP,例如AXI GPIO、AXI DMA或HLS生成的加速IP。以AXI GPIO控制LED为例,将其S_AXI接口连接到PS的M_AXI_GP0,GPIO接口通过Make External引出到顶层,再在Constraints中绑定到具体引脚。连接完成后点击Validate Design,若出现“critical warning”需逐条处理,常见问题是时钟未连接、复位未连接或地址未分配。验证通过后,在Address Editor中确认每个从设备都有唯一基地址,例如AXI GPIO分配为0x41200000,这是后续软件读写寄存器的依据。
三、平台导出:XSA是软硬件之间的契约
硬件设计通过综合、实现并生成比特流后,执行File → Export → Export Hardware,勾选Include bitstream,输出格式选XSA。XSA中封装了PS配置、PL比特流、IP地址映射和时钟信息,是Vitis识别硬件的唯一依据。若后续修改了Block Design,必须重新导出XSA并在Vitis中更新平台,否则软件看到的地址与外设可能与实际硬件不一致。导出前建议执行一次Report → Address Report,确认没有地址重叠或未分配的外设。
四、Vitis统一软件平台:从平台工程到应用工程
打开Vitis后先创建Platform Project,选择从XSA创建,工具会自动解析硬件并生成BSP。BSP中包含了standalone或Linux下的驱动、库和链接脚本。随后创建Application Project,选择刚建立的平台,模板可选Hello World或Empty Application。对于裸机程序,链接脚本通常为lscript.ld,需确认DDR起始地址与大小,例如0x00100000起始、512MB空间,避免程序段越界。
以AXI GPIO控制LED为例,软件侧关键代码如下:
#include "xgpio.h"
#include "xparameters.h"
XGpio gpio;
int main(void) {
XGpio_Initialize(&gpio, XPAR_AXI_GPIO_0_DEVICE_ID);
XGpio_SetDataDirection(&gpio, 1, 0x0); // 通道1设为输出
while (1) {
XGpio_DiscreteWrite(&gpio, 1, 0x1); // LED亮
for (volatile int i = 0; i < 10000000; i++);
XGpio_DiscreteWrite(&gpio, 1, 0x0); // LED灭
for (volatile int i = 0; i < 10000000; i++);
}
return 0;
}
其中XPAR_AXI_GPIO_0_DEVICE_ID由BSP根据XSA自动生成,基地址对应Address Editor中的0x41200000。编译后生成.elf,与.bit一起通过Run Configuration下载。若使用JTAG,Vitis会自动完成FPGA配置和ARM程序加载;若使用SD卡启动,则需将BOOT.BIN与应用程序按启动流程打包。
五、调试环境:软硬件两侧同时观察
Vitis的Debug视角支持源码级断点、变量监视和寄存器查看。对于裸机程序,可以在XGpio_DiscreteWrite处打断点,单步执行后观察GPIO寄存器值是否变化。若软件逻辑正确但硬件无响应,问题往往在PL侧,此时应回到Vivado使用ILA(Integrated Logic Analyzer)抓取AXI总线或GPIO内部信号。ILA的添加方式是在Block Design中标记需要观察的net为Debug,重新生成比特流后,在Hardware Manager中设置触发条件,例如AXI写地址等于0x41200000时触发,从而确认PS是否真正发出了写事务。
六、常见问题与检查要点
- Validate Design报错:优先检查时钟和复位是否连接,M_AXI_GP0是否使能,地址是否分配。
- Vitis找不到设备ID:确认XSA已更新,BSP已重新生成,xparameters.h中存在对应宏。
- 程序下载后无反应:检查Run Configuration中是否勾选Program FPGA,比特流是否与硬件匹配。
- ILA无触发:确认Debug net已标记并重新实现,触发条件与时钟域一致。
- 地址冲突:在Address Editor中检查各从设备基地址范围是否重叠,必要时手动调整。
掌握这条工具链的关键,不在于记住每个按钮的位置,而在于理解XSA作为软硬件契约的作用,以及Vitis平台工程、BSP、应用工程之间的依赖关系。当硬件地址、软件寄存器操作和调试观察能够一一对应时,Zynq协同开发就从“能跑”进入了“可控、可查、可优化”的阶段。