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,这是后续软件读写寄存器的依据。

Zynq 软硬件协同工具链:Vivado → XSA → Vitis → 调试 Vivado 硬件平台构建 ZYNQ7 PS ARM Cortex-A9 DDR3 / UART / SD PL 逻辑 AXI GPIO / DMA HLS 加速 IP M_AXI_GP0 S_AXI_HP0 Address Editor 地址分配 AXI_GPIO → 0x41200000 | AXI_DMA → 0x40400000 FCLK_CLK0 = 100 MHz Validate Design → Generate Bitstream 检查时钟/复位/地址,综合实现后生成 .bit Export Hardware → 生成 XSA 包含硬件描述、比特流、地址映射 XSA Vitis 统一软件平台 Platform Project 导入 XSA → 生成 BSP(standalone / Linux) Application Project Hello World / AXI GPIO 读写 / DMA 传输 Build → Run Configuration 选择 UART 串口,下载 bit + elf 调试环境 Debug 视角:断点 / 变量 / 寄存器 Vivado ILA:PL 内部信号抓取 串口终端:printf 输出验证 关键闭环:硬件地址映射 → 软件寄存器读写 → 串口/ILA 观察结果 → 判断功能是否正确

三、平台导出: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是否真正发出了写事务。

调试判断顺序建议:先看串口是否有打印,确认程序是否运行;再看Vitis变量与寄存器,确认软件是否执行到目标语句;最后用ILA看PL信号,确认硬件是否收到并响应。三者结合,才能快速定位问题在PS、总线还是PL。

六、常见问题与检查要点

  • Validate Design报错:优先检查时钟和复位是否连接,M_AXI_GP0是否使能,地址是否分配。
  • Vitis找不到设备ID:确认XSA已更新,BSP已重新生成,xparameters.h中存在对应宏。
  • 程序下载后无反应:检查Run Configuration中是否勾选Program FPGA,比特流是否与硬件匹配。
  • ILA无触发:确认Debug net已标记并重新实现,触发条件与时钟域一致。
  • 地址冲突:在Address Editor中检查各从设备基地址范围是否重叠,必要时手动调整。

掌握这条工具链的关键,不在于记住每个按钮的位置,而在于理解XSA作为软硬件契约的作用,以及Vitis平台工程、BSP、应用工程之间的依赖关系。当硬件地址、软件寄存器操作和调试观察能够一一对应时,Zynq协同开发就从“能跑”进入了“可控、可查、可优化”的阶段。