简介:VD100 Vitis Platform是针对ALINX VD100开发板设计的Vitis软件平台实例,面向使用Versal ACAP进行AI边缘计算与嵌入式开发的工程师。它整合了硬件平台定义、设备树与启动镜像等关键组件,支持C/C++、Python高级语言编程,帮助开发者绕开底层硬件描述,专注AI引擎和高带宽内存应用开发。压缩包共48个文件,大小15.33MB,核心类型包括xsa硬件平台文件、dtsi/dts/dtb设备树文件、bif启动配置、elf固件、pdi镜像以及二十个h头文件,并附有少量txt/json说明,便于理解平台结构。目前已有166人学习下载,适合需要快速搭建VD100开发环境的开发者直接参考使用。资源提供了经过Vitis 2024.2验证的完整平台套件,包含QEMU与linux_psv_cortexa72等仿真运行支持,可显著降低从设计到部署的难度,为深度学习、机器学习等应用开发提供一站式基础。 不做平台的人,永远体会不到这种憋屈:Vitis 装好了,license 也通了,打开工具却发现可选平台里躺着的全是 Alveo 系列的模板,根本没有自己手上这块板子的影子。VD100 Vitis Platform 就是这个问题的答案——它不是赛灵思官方预置的现成平台,而是针对 VD100 这块自定义 PCIe 加速卡,在 Vitis 工具链里从零手搓出来的一套完整硬件软件平台。本文要把整个搭建过程掰开揉碎,讲清楚 XSA 要准备到什么粒度、Linux 内核和 rootfs 怎么配、平台文件如何打包验证,以及我在实际开发中踩过的几个容易让人一夜白头的坑。现在这个环境已经被我们用于好几个内部推理项目,稳定性实测下来是可以接受的。
1. 为什么自定义板卡的 Vitis 平台必须自己动手:先搞清平台文件在替谁说话
先交代一下 VD100 的背景。VD100 是一块面向数据中心推理场景的 PCIe 加速卡,主芯片用的是 UltraScale+ 架构的 VU9P,板载两条 DDR4 通道、一组 QSFP28 高速接口,通过 PCIe x16 金手指与主机通信。性能上它和 Alveo U250 有些相似,但 CLB 排列、时钟约束、PCIe 位置都不一样,直接套 U250 的平台文件,综合出来的 bitstream 放上去就是起不来——这件事我们团队在项目早期就验证过了,所以别抱侥幸心理。
1.1 Vitis 平台到底是什么
很多人把 Vitis 理解为"在 FPGA 上写 C 语言",这么说没错,但漏了最关键的一层:Vitis 并不是直接把你的 C 代码烧进 FPGA,它需要一个"中间人"来描述这块板子长什么样、有哪些资源、操作系统是什么、怎么启动。这个中间人就是平台文件。
一个 Vitis 平台文件(.xpfm)本质上就是一个结构化目录,内部包含:
- 硬件侧:由 Vivado 导出的 XSA 文件,里面封装了 FPGA 的静态逻辑、引脚约束、时钟频率、DDR 地址映射、PCIe 配置等信息。
- 软件侧:启动所需的 boot 组件、Linux 内核镜像、设备树(DTB)、根文件系统(rootfs)、以及对应的 sysroot 交叉编译环境。
- 平台描述元数据:告诉 Vitis 这个平台的名称、版本、支持的器件型号、有哪些 AXI 接口可以挂载用户 kernel。
你可以把平台理解成"板卡的护照+简历"。Vitis 在编译你的 kernel 之前,先读这份简历,搞清楚手上这块板子能提供多少个 SLR、哪些 AXI 接口能访问 DDR、时钟树长了什么样、跑的是什么系统。没有这份简历,编译器再聪明也无从下手。
1.2 为什么官方模板不能直接覆盖 VD100
赛灵思在 Vitis 安装目录下确实预置了一批平台模板,Alveo U200/U250/U280 都覆盖了。但这些模板是针对官方板卡调优过的,里面的时钟拓扑、复位逻辑、PCIe 桥接方式都和 VD100 的硬件设计有出入。比如 VD100 的 DDR4 走的是两个独立的内存控制器,而 U250 模板默认把内存当作一个统一地址空间来配置;再比如 VD100 的 PCIe 用了一颗 XDMA 的 IP,而 U250 用的是自己内部封装的 DMA 引擎。
这种差异导致最直接的后果是:kernel 在仿真里跑得好好的,上板之后一发起 DMA 读写就崩,或者频繁报 AXI 超时错误。你当然可以通过 patch 平台内部的 xsa 和 dtb 来打补丁,但那我建议你干脆自己从零搭一套,因为后续要维护、要升级内核、要加新功能,底子是自己的,改起来才顺手。
2. 硬件侧先行:Vivado 工程里 XSA 的准备粒度与关键参数
平台搭建的第一步永远在 Vivado 里做,这一步决定后面的软件工作能不能顺利进行。我的习惯是先建一个规范的 block design,把静态逻辑和可重配置区域分开规划,然后再导出 XSA。
2.1 Block Design 里必须包含的组件
VD100 的 block design 我最终定稿的版本包含这些核心组件:
- PCIe XDMA IP:作为主机和 FPGA 之间的数据通道,配置成 AXI Memory Mapped 模式,地址宽度 64 位,中断用 MSI-X。
- DDR4 MIG IP:两套,分别挂在不同的 AXI 端口上,对应板卡上两条物理内存通道。每套配了独立的时钟和复位。
- 时钟管理:一组 Clocking Wizard 为 kernel 区域提供 100MHz/200MHz 用户时钟,统一从 PCIe 参考时钟派生,保证上板后的时钟对齐。
- 外部中断控制器:把 XDMA 的中断和用户逻辑的中断汇总成一个 AXI INTC,再上报给主机。
这里有个容易被忽略的点:Block Design 里挂 user kernel 的 AXI 接口,Vivado 2019.2/Vitis 平台依赖的是 PFM 属性来识别。你需要用set_property把 AXI 主从端口的名称、类型、地址空间描述清楚。例如:
set_property PFM.AXI_PORT {S_AXI_CTRL} [get_bd_intf_pins /axi_intc/s_axi] set_property PFM.AXI_PORT {M_AXI_HPC0} [get_bd_intf_pins /xdma_0/M_AXI]M_AXI_HPC0这个名字不是随便起的,Vitis 会依据这个名字判断出这是一个高性能(High Performance)接口,并据此自动做地址对齐和 burst 长度匹配。
2.2 时钟和复位:最容易埋雷的区域
时钟在平台文件里是以 PFM.CLOCK_INFO 属性登记的,登记的内容包括时钟频率、时钟用途(clk_wiz输出的哪个端口、是不是全局时钟)等。我给 VD100 登记的 kernel 时钟方案如下:
| 时钟名 | 频率 | 用途 |
|---|---|---|
| kernel_clk0 | 200 MHz | kernel 主时钟 |
| kernel_clk1 | 100 MHz | AXI-Lite 控制通道时钟 |
| kernel_clk2 | 300 MHz | 高带宽数据通路时钟 |
Vitis 对 kernel 时钟的数量有限制(具体取决于器件型号的 clock region 数量),但更关键的是:你登记的时钟必须和实际的 Clocking Wizard 输出一一对应,而且频率值必须填写真实值。写错了不会在平台打包时报错,kernel 编译也通过,但上板后时序就是乱,跑起来数据全是花的。
复位也一样。Vitis 平台要求 reset 信号必须能够由主机端控制,也就是通过 AXI-Lite 寄存器去断言和释放。我的做法是在 block design 里加一个proc_sys_reset,把它的输出接到 kernel 区域的复位端口,并且确保这个 IP 的aux_reset_in连到了 PCIe 的 reset 域。这样主机侧xbutil reset才能真正把用户逻辑复位干净。
2.3 导出 XSA 时的要点
XSA 导出走的是 Vivado 的write_hw_platform命令,但导出的时机和选项很讲究:
write_hw_platform -include_bit -force ./vd100_platform.xsa注意必须带-include_bit,否则生成的 XSA 里没有 bitstream,Vitis 在硬件仿真和上板运行时都会报找不到 bit 文件的错误。导出之前还要跑一遍 implementation 并生成比特流,这个顺序不能乱。很多人习惯在综合完成后就导出,结果拿到 Vitis 里一跑就报错。
导出完成后,我建议先用platforminfo工具检查一下 XSA 的完整性:
platforminfo -xsa vd100_platform.xsa这个命令会列出 XSA 中包含的器件型号、PFM 接口、时钟、地址段等信息。对照自己的设计逐项检查,确认无误后再进入软件侧,能省掉后面一大半调试时间。
3. 软件侧合体:内核、u-boot 与 rootfs 的选择逻辑
硬件 XSA 就位后,Vitis 平台的另一半是软件组件。这里的核心难点不在"怎么编译",而在"怎么选版本"。
3.1 先想清楚 VD100 要不要跑 Linux
平台软件侧可以做成裸机(bare-metal)模式,也可以做成 Linux 模式。VD100 作为数据中心推理卡,我们的目标是让主机端通过 PCIe 驱动加载 kernel、用 XRT 管理运行时,那 Linux 就是刚需。如果只是做个简单加速实验,裸机平台也能用,但后期扩展性很差,所以我下面的内容都围绕 Linux 平台来讲。
Linux 平台需要准备的软件组件包括 boot 文件(u-boot 或 FSBL)、内核镜像、设备树、rootfs、以及 sysroot。对 VD100 这种基于 PCIe 的加速卡,启动方式和嵌入式 SoC 不太一样,VD100 上没有一个独立的 ARM 处理器来跑 Linux,它的"系统"其实跑在主机侧,而板卡侧只需要一个轻量级的微控制器或者直接由 FPGA 逻辑提供 PCIe 枚举能力。
这说着简单,但实际配置里差距很大。VD100 的板卡侧我做的是无处理器的 PCIe 从设备方案:主机通过 XDMA 的 AXI-Lite 接口访问 FPGA 内部的寄存器,通过 AXI-MM 接口做数据搬运。这样一来,Vitis 平台里 software 部分的"内核"就不再是板卡上跑的内核,而是主机侧加载的 XRT Linux 内核驱动模块。
这也是很多从 Zynq 转过来的人会纠结的地方:平台文件里到底放不放内核?我的答案是:放,但放的是 VD100 赖以工作的驱动框架所依赖的主机内核头文件和 PDI/bit 管理工具链,而不是一个嵌入式内核镜像。Vitis 在软件侧的组件划分里,对这类纯 PCIe 加速卡的处理方式和 MPSoC 平台完全不同,它会把重心放在 sysroot 和xrt运行时库上。
3.2 用 Xilinx 提供的配套版本,别自己另起炉灶
如果你用过petalinux-build,会知道赛灵思整个软件生态是"版本环环相扣"的。Vitis 2019.2 配套的内核版本、XRT 版本、GCC 版本都是锁定好的。我自己在别的项目中踩过一次:为了用新内核特性,把 host 内核升了一个小版本,结果 XRT 驱动编译不过,Vitis 运行时和内核模块的 ABI 对不上,最后整个平台都跑不了。
所以 VD100 平台我直接用了赛灵思发布包里的标准内核源码和 XRT 版本,不要自己从 kernel.org 拉一个最新内核来编。想升级内核?先查官方文档确认 XRT 支持矩阵,再动手。
# 以 Vitis 2019.2 为例,内核版本锁定在 4.19 分支 git clone -b xlnx-rebase-v4.19 git://github.com/Xilinx/linux-xlnx.git cp vd100_defconfig arch/arm64/configs/ make ARCH=arm64 xlnx_vd100_defconfig make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- -j$(nproc)3.3 设备树(DTB)里要写清楚哪些东西
设备树是 Vitis 平台软件侧最容易被忽视、但影响最直接的部分。它必须描述清楚 PCIe 枚举出来的黑马设备(XDMA 驱动节点)、中断、DMA 通道等信息。VD100 的设备树里我重点写了:
- XDMA 节点,指定了 AXI-Lite 控制寄存器基地址、中断号、MSI-X 能力。
- 板载温度、电源监控节点,这样主机的
xbutil examine才能正确读取传感器数据。 - 两个 DDR4 控制器的地址映射关系,确保用户 kernel 访问的地址和 MIG 配置一致。
适配 DTB 的通用做法是先把系统启动起来,然后通过/sys/firmware/devicetree/base/导出实际运行的树,和源文件对比,逐项修正。
4. 平台打包与 Vitis 侧验证:从 hello_world 到真实 kernel
软件组件备齐后,进入平台打包环节。在 Vitis 2019.2 里,有两种打包方式:命令行和 GUI。
4.1 命令行方式打包平台
我在脚本化流程里用的是platform命令(Vitis 2019.2 里是platform -create,再通过platform -finalize生成可发布平台)。命令行的好处是可以写进 CI,每次硬件改版后一键重新打包。
下面是一个从 XSA 创建平台的最小脚本:
platform -create -name vd100_platform -hw ./vd100_platform.xsa \ -proc psu_cortexa53 -os linux platform -write在实际项目里,还要指定 sysroot、boot 目录等参数。sysroot 交叉编译环境是整个平台最值钱的部分,Vitis 里的应用工程全靠它来链接 XRT 库和内核头文件。你在 Linux 平台上编译 App 时遇到的头文件找不到、库版本不匹配,十有八九是 sysroot 和内核版本没有严格配套。
GUI 方式则是打开 Vitis → 选择 XSA → 指定 Linux 系统组件 → 让工具自动生成平台。GUI 对新手友好,但版本升级后工程文件兼容性有时会出幺蛾子,所以团队统一约定用命令行构建平台工程,GUI 只用于快速预览。
4.2 hello_world 验证的真正意义
平台打包完,第一件要做的事不是急着跑自己写的算法 kernel,而是按下面的顺序逐级验证:
- 先跑 Vitis 自带的 hello_world 软件工程,确认平台能被正常枚举、system.bit 能下载、UART/串口能输出。
- 再跑一个空的
v++kernel 编译流程,确认 kernel 编译链、链接、打包都没有问题。 - 最后跑一个简单的 AXI 读写自测 kernel——比如往一个固定地址写值再读回来,验证 DDR 通路、XDMA 链路是否打通。
这一步别跳。我一共调过三块不同厂商的加速卡,每一次跳过中间层验证直接上算法,最后都沦为在仿真器和 JTAG 之间来回折腾的悲剧。hello_world 通过,只代表平台能启动,完全不代表 DDR 通路可靠;AXI 读写自测通过,才能说平台侧基本可信。
4.3 上板实测时的检查路径
VD100 上板后,建议的调试路径是:
- 主机上用
lspci -v确认 FPGA 设备被正常枚举,记录它的 BDF 号。 - 用
xbutil examine检查平台状态,观察温度、电压、DDR 校验结果。 - 用
xbutil validate跑一遍官方验证流程。 - 加载自测 kernel,观察 AXI 读写的返回值和预期是否一致。
在第 2 步如果发现 DDR 报错,优先检查 XSA 里的 MIG 配置是否和板卡实际颗粒匹配,尤其是地址位宽、bank group、刷新间隔等参数。曾经遇到过 MIG 配置死活没问题、结果发现是 DTB 里没有给 MIG 的 AXI 端口预留足够地址窗口,导致 DMA 访问越界的情况,这类问题在dmesg里往往只报一个通用 AXI 错误,排查起来非常费神。
5. 实测中吞过泪的三个"非典型"故障
平台本身的功能调试之外,还有几个环境类故障,单看报错信息根本想不到和平台构建有什么关系,但实际浪费的时间反而最多。我按踩坑顺序逐个说。
5.1 Windows 下 Vitis 启动时 Qt 平台插件加载失败
这个报错原文是qt.qpa.plugin: could not load the qt platform plugin "windows" in ...。大部分时候的原因不是 Vitis 本身坏了,而是系统里缺少对应的运行库,或者环境变量里QT_QPA_PLATFORM_PLUGIN_PATH被别的软件改掉了。我们这边就有同事装了另一套工业软件后 Vitis 就打不开。
处理方法:设置环境变量指向 Vitis 自带的 Qt 插件目录,同时确认 Visual C++ Redistributable 运行库已安装。我的常用检查命令是:
set QT_QPA_PLATFORM_PLUGIN_PATH=C:\Xilinx\Vitis\2019.2\data\vitis\plugins vitis5.2 Intel Platform License Manager 服务连接超时
Windows 机器上跑 Vitis 时,如果日志里出现等待 intel(r) platform license manager service 服务的连接超时(45000 毫秒),别觉得奇怪。这个服务是 Intel 的许可证管理器,和赛灵思的 license 没有关系,但它会拖慢 Vitis 启动时对 license 的枚举。我们的处理是在 Windows 服务管理器里把该服务设为手动启动,并且避免在系统启动阶段加载,这样 Vitis 起来时不会等它白白超时。
5.3 JUnit Platform Launcher 依赖解析失败
这个报错failed to resolve org.junit.platform:junit-platform-launcher:1.6.3一般出现在用 Gradle 构建主机端应用时。Vitis 自带的 Java 运行时可能是老版本,导致 JUnit 平台的分发解析失败。解决思路是在主机端应用里明确指定一个与当前 Java 版本兼容的 JUnit 版本,或者在 Gradle 配置里强制使用本地已下载的依赖仓库,不要让它走网络解析。
repositories { mavenCentral() } dependencies { testImplementation 'org.junit.platform:junit-platform-launcher:1.9.3' }这类问题和 FPGA 本身无关,但一旦卡住,很容易误导你在平台文件里找原因,浪费半天时间。
6. 一些想留给后来者的话
VD100 平台的这次搭建,前后我改了大概四版 XSA,第一版 PCIe 带宽跑不满,第二版 DDR 校验不稳定,第三版才把内核时钟和复位做干净,第四版主要是把设备树明细补完整。回头总结,最核心的经验就一句话:平台的每一层都要可验证,硬件侧有 AXI 自测,软件侧有 hello_world,别把"看起来能跑"当成真能跑。
如果你是第一次搭 Vitis 平台,我建议从官方提供的 xilinx_vcu1525 或类似开源平台工程入手,对比着看它的 block design 怎么建、PFM 属性怎么设、软件组件怎么组织,再落到自己的板卡上。直接打开一个空工程从头写,要摸索的东西太多了。
最后分享一个实用技巧:平台文件打包完成后,顺手把整个平台目录压缩归档,标好对应的 XSA 哈希和内核版本号。这个习惯在我们后续维护多版本、复现问题的时候帮了大忙——因为你会发现,三个月后再回来看,真的记不清当初这个平台配的是哪个版本的内核。
本文还有配套的精品资源,点击获取