2. Vivado与Vitis开发环境搭建
Zynq 实时控制系统的开发不是“写一份代码”那么简单,它横跨 PL(可编程逻辑)与 PS(处理系统)两个世界:PL 侧需要 Vivado 完成 RTL/BD 设计、综合实现并导出硬件平台;PS 侧需要 Vitis 基于导出的 XSA 建立应用工程、配置 BSP、编译调试。本节把这条链路拆成可执行的四段:Vivado 工程创建 → IP 集成与 Block Design → 硬件导出(XSA)→ Vitis 软件工程与调试环境,并给出可直接照做的示例参数与判断依据。
一、Vivado 工程创建:器件、板卡与目录约定
启动 Vivado 后选择 Create Project,关键决策有三项:工程名与路径、工程类型(RTL 或 Post-synthesis)、目标器件或开发板。以常见的 Zynq-7000 教学平台为例,若使用官方开发板,优先在 Boards 页选择板卡(如 Zybo Z7-20、PYNQ-Z2 等),这样后续 BD 会自动带入板级约束与 DDR/MIO 预设;若使用自制板,则切到 Parts 页,按封装与速度等级精确选择,例如 xc7z020clg400-1。器件选错会导致后续引脚约束、时钟资源与 IP 可用性全部错位,这是新手最常见的返工点。
工程目录建议固定为:prj/ 存放 .xpr,src/rtl 存放自定义 RTL,src/bd 存放 Block Design,constr/ 存放 XDC,export/ 存放导出的 XSA。这样做的目的是让 Vitis 工作区与 Vivado 工程解耦,避免路径含中文或空格导致导出失败。
二、IP 集成:Block Design 中的最小可用系统
Zynq 系统的核心是 Block Design。新建 BD 后添加 ZYNQ7 Processing System,先运行 Run Block Automation 让工具根据板卡预设配置 DDR 与 MIO。随后按实际需求打开 Re-customize IP 逐项确认:
- PS-PL Configuration:使能
M_AXI_GP0用于 PS 访问 PL 寄存器;若需 PL 主动读写 DDR,再使能S_AXI_HP0。 - Clock Configuration:确认
FCLK_CLK0输出频率,例如实时控制常用 100 MHz,作为 PL 逻辑主时钟。 - Interrupts:使能
PL-PS Interrupt Ports中的IRQ_F2P,用于 PL 向 PS 上报控制完成或故障事件。 - MIO Configuration:按原理图勾选 UART1、SD0、Ethernet0 等外设,UART 是后续 Vitis 串口打印的物理通道。
若本节示例需要一个“PL 侧 AXI 寄存器 + 中断”的最小闭环,可再添加 AXI GPIO 或自定义 AXI-Lite IP,通过 Connection Automation 自动连接 M_AXI_GP0、FCLK_CLK0 与复位。完成后点击 Validate Design,无红色报错即可。此时 BD 已具备“PS 配置外设 + PL 提供寄存器/中断”的基本骨架。
三、硬件导出:XSA 里到底装了什么
综合与实现通过后,执行 File → Export → Export Hardware,勾选 Include bitstream,输出格式选择 .xsa。XSA 不是单纯的比特流,它同时携带:PS 配置参数、PL 的地址映射(Address Editor 中每个 AXI 从设备的基地址与范围)、时钟与中断连接信息、以及可选的 bitstream。Vitis 正是靠这些信息自动生成 BSP 中的 xparameters.h,例如 XPAR_AXI_GPIO_0_BASEADDR。因此,如果后续软件里读到的基地址与预期不符,应回到 Vivado 的 Address Editor 检查是否分配了地址,而不是在 C 代码里硬改。
四、Vitis 软件工程配置:平台、应用与 BSP
打开 Vitis,先 Create Platform Project,在 Hardware Specification 中选择刚导出的 XSA。平台创建完成后,右键 Build,工具会生成 FSBL、PMU 固件与 BSP。接着 Create Application Project,选择该平台,模板可先选 Hello World 验证链路,再替换为实际控制应用。
BSP 配置是容易被忽略的一环。在 platform → ps7_cortexa9_0 → standalone 下打开 Board Support Package Settings,按需使能:stdin/stdout 指向 ps7_uart_1,使能 xiltimer 与 xscugic(中断控制器)。若应用要用到 PL 中断,必须在 BSP 中确认 XPAR_FABRIC_*_INTERRUPT_INTR 已生成,否则 XScuGic_Connect 会因中断号缺失而失败。
一个典型的控制应用初始化顺序如下(示例,非实测结果):
#include "xparameters.h"
#include "xgpio.h"
#include "xscugic.h"
#include "xil_printf.h"
XGpio gpio;
XScuGic intc;
int main(void) {
XGpio_Initialize(&gpio, XPAR_AXI_GPIO_0_DEVICE_ID);
XGpio_SetDataDirection(&gpio, 1, 0x0); // 通道1设为输出
XGpio_DiscreteWrite(&gpio, 1, 0x1); // 置位,观察LED/示波器
XScuGic_Initialize(&intc, XPAR_SCUGIC_SINGLE_DEVICE_ID);
// 后续注册 PL 中断服务函数
xil_printf("PL control ready\r\n");
while (1);
}
编译后若报 undefined reference,优先检查 BSP 是否包含对应驱动库;若 XPAR_... 宏找不到,说明 XSA 未正确导入或平台未重新 Build。
五、调试环境准备与结果判读
硬件上连接 JTAG(如 Digilent HS2/HS3)与 USB-UART,确认设备管理器中出现对应串口。Vitis 中右键应用工程 Debug As → Launch Hardware,工具会自动完成:下载 bitstream → 初始化 PS → 下载 ELF → 停在 main。此时可设置断点、单步、查看 XGpio 寄存器值。
判断链路是否真正打通,看三个信号:串口终端是否打印 PL control ready;用示波器或板载 LED 观察 GPIO 输出是否翻转;在 Xilinx → Memory 视图中读取 AXI GPIO 基地址处的寄存器,确认写入值与读回值一致。三者同时成立,说明“Vivado 硬件平台 → XSA → Vitis 软件工程 → 调试”这条链路已闭环,可以进入后续的实时控制算法与 PL 加速开发。