A step-by-step guide on how to create a base platform in Vivado for Xilinx Versal devices.
使用 AIE 进行开发之前需要有一个基础硬件平台 (Base Platform) 给 Vitis 使用, 它从里面读取硬件信息 (包括 AIE 配置, 系统连接配置等), 然后才能链接成一整个平台. Vitis 提供了官方评估板的预构建基础平台, 例如 VCK190, VEK280 等. 但如果要使用第三方开发板, 就需要自己创建基础平台. 本文将介绍如何使用 Vivado 创建一个基础平台的硬件部分, 然后导出给 Vitis 使用.
本文使用到的平台是 Vitis/Vivado 2025.2 版本, 在 Ubuntu 24.04 LTS 上进行演示. 开发板是 ALINX 的 VD100, 基于 XCVE2302 (AIE-ML) 核心, 参考文档.
需要安装好的软件有
本文编写的时间点 2025.2 刚发布没几天, 这是一个相对较新的版本, 但在 2023.2, 2024.2 这些版本上的操作几乎一模一样.
在使用 Xilinx 的各种工具链的时候 (例如 Vitis/Petalinux Tools/Common Image SDK), 如果同时设置它们各自所需的环境变量, 可能遇到环境变量互相打架的问题. 如果发现莫名其妙的错误先检查环境变量是否如你所预期的那样. 例如 Vitis 2024.2 的环境变量设置脚本就会把它自带的那个远古 3.3 版本 CMake 放到最优先的查找路径上, 导致非常莫名的构建错误.
关于怎么创建 Vivado 工程这里不再赘述, 直接创建一个空工程, 选择对应的器件型号 (例如 XCVE2302) 即可. 然后创建一个 Block Design. 整个系统顶层设计的连线如下图所示
Loading Document...
这是 Versal 架构的示意, 对于 Zynq 系列会简单一些, 因为 Zynq 没有 AIE, 也没有 NoC. 这个基础平台主要包括几个部分: PS 端 (CIPS, NoC), AIE 端, PL 端 (包括几个频率不同的时钟域和相关联的复位信号, AXI 中断控制器).
构建这个设计的基本步骤如下:
首先添加一个 CIPS IP 核, 启动模式根据开发板的手册选择, 大部分用 SD/eMMC 启动, 根据引脚配置选择引脚位置和工作模式即可. PS 端的硬核外设选择性的开一下, 一般 USB, UART 是必须开的, 以太网, SPI 这些看着办, 引脚根据手册选择. Versal 的 CIPS 上已经集成了很多的外设硬核 IP, 不像以前的系列还要在 PL 端进行实现, 这点方便多了. IO 选项卡可以统一地配置引脚, 方便看有没有引脚冲突

PS2PL 时钟开一个 100MHz 的时钟输出给 PL 端使用就行, 直接传给 Clock Wizard IP 进行分频和相位调整.

PL PS 接口选择上, 至少开一个 PL 复位信号端口和一条 M_AXI_FPD 总线用来做复位逻辑和 PL 端控制信号传递.

NoC PS 接口选择上, PS Master 端口全开, Slave 端口可选.

PL PS 中断端口至少开一个给 PL 端使用. 无论是 DMA 也好, 其它中断也好, 几乎不可能用不到中断的. 下面的 IPI 端口建议全部打开.

和 ZynqMP 不同的是, Versal 里面新加入了 NoC 作为 PS/PL/AIE 之间的互联总线. 它单独作为一个 IP 核存在, 并且集成了 DDRMC 的功能. NoC IP 对外可以通过 AXI 总线访问, 或者通过 DDRMC 访问内存, 而 NoC IP 之间通过内部的端口进行连接. 在上面的 Block Design 里面可以看到添加了两个 NoC IP, 其中一个作为总线互联, 另一个单纯作为 DDR 控制器使用, 尽管看起来这是两块 IP, 但实际上和连在一起, 也就是同一个 IP 里面既启用互联又启用 DDRMC 功能是一模一样的效果.
第一块 NoC IP 的配置看图可以很清楚, 开 8 个 AXI Slave 端口, 对应于 PS 上和 NoC 互联的 8 个 Master 端口, 以及数个 NoC 内部互联 Master 端口连接到 DDRMC 所在的 NoC IP. 另外开一个 AXI Master 端口, 给 AIE 使用. 这个端口不用来和 AIE 之间传输数据, 只传递控制信号. 关于 AIE 的计算数据传输, Vivado 里面做不了任何定制, 只能连这一条控制信号, 其它的需要交给 Vitis 做.
在 Inputs 选项卡里面需要配置端口的连接类型, 连接到 Coherent/Non-Coherent 总线, LPD/PMC 等等. Outputs 也是同理, 将唯一的 AXI Master 端口配置为连接到 AIE 即可. NoC IP 之间的互联端口不需要配置, 自动处理.

Connectivity 选项卡可以看到所有端口在内部那两两之间是互通的, 按照下面的图连就行. 需要注意的是 LPD 端口, 也就是连接到 CIPS 上的 RPU 的总线, 因为 RPU 本身只能访问低 32 位地址空间, 所以无法直接访问 AIE, 需要地址重映射, 但我们这里它没有连接的必要.

另一个 NoC IP 用来做 DDRMC. 关于 DDR 的配置那就五花八门了, 工作频率, ECC, 时序参数什么的. 这里只提供连接方法, 具体参数参考手册. 首先开启 DDRMC 的功能, 然后关闭所有和外部的 AXI 端口连接, 只保留几个内部互联的 Slave 端口, 连到第一个 NoC IP 上对应的 Master 端口即可.

Connectivity 和第一个 NoC IP 类似, 配置要互通的端口即可. DDR 的时钟, 时序就不赘述了, 参考手册配置.
到目前为止我们就完成了 CIPS 和 NoC 的配置, 并且添加了内存控制器. 关于连线直接参考上面的 Block Design 图即可.
配置 AIE 再简单不过了, 因为 Vivado 这边几乎什么都配置不了. 添加一个 AIE IP 核, 然后连到 NoC IP 上刚刚给它分配的 AXI Master 端口即可.
PL 端的基本组件包括几个时钟域和对应的复位信号, 以及一个 AXI 中断控制器. 大概的思路如下, 按照思路用 Block Automation 连接很快, 选好时钟域一下子就搞定了.
ACTIVE LOW, 因为 PS 端引出的 PL 复位信号是低电平有效的.ext_reset_in 全部连到 PS 端引出的 PL 复位信号上.s_axi 控制端口连到 PS 端的哪个 Master AXI 总线上 (也就是在 CIPS 上开启过的那个 M_AXI_FPD 总线). 另外这条总线需要一个驱动时钟 m_axi_fpd_aclk, 这个时钟也接在默认时钟域上.Block Automation 界面如下图所示. Slave Clock 是 IP 本身的时钟输入, Master Clock 是它要连接的 AXI 总线的时钟输入, Bridge IP 是用来将 s_axi 端口连接到 PS 端的 M_AXI_FPD 总线的桥接 IP, 这个桥接 IP 会自动生成并添加到设计里面去的, 但需要指定时钟. 这三者连到同一个时钟域就是最简单的做法.

一个需要注意的点是型号的速度等级, 有些型号的 M_AXI_FPD 总线就跑不了那么高的频率, 比如 ALINX VD100 这块的速度等级最高好像只能跑到 250MHz 时钟 (至少 300MHz 下实现跑不过), 所以需要对应地降低一点频率, 至于多少是上限找手册或者看时序报告.
如果对 Block Automation 不太熟悉, 也可以照着上面给出的 Block Design 图手动连线, 就是麻烦一些.
连线完成后需要配置一些平台设置, 也就是 "Platform Setup" 部分. 在这里面勾选的端口会被暴露给 Vitis 使用, 否则 Vitis 无法访问这些硬件端口. 首先配置 AXI Port, Vivado 会强制你至少勾选一个 Master AXI 端口和一个 Slave AXI 端口. 我们把 DDRMC 所在的 NoC IP 上的所有 Slave AXI 端口都勾选上, Tag 设成 DDR , 这样 Vitis 就能利用这些端口访问 DDR 内存了. 另外配置中断控制器的时候应该生成了一个 AXI SmartConnect IP, 把它的 M_AXI 端口多勾几个(十几个都行, 反正不嫌多), Memport 就用默认的 M_AXI_GP 就行.

接着是时钟域配置, 我们把刚刚创建的几个时钟源全部添加进去, 这样在 Vitis 里面生成的 HLS 设计才能在链接阶段使用这些时钟源. 必须选择其中一个作为默认的时钟源.

最后是中断配置, 我们将刚刚创建的 AXI 中断控制器暴露给 Vitis 使用, Vitis 中后续用到的所有 PL 端中断都会通过这个中断控制器来管理.

配置完成后就可以生成 HDL Wrapper 了, 这和常规的 Block Design 一样, 右键菜单里面找 "Create HDL Wrapper" 即可.
在导出平台之前还要做一些最后的处理. 首先要导入板子的管脚约束文件 (XDC), 例如 DDR 控制器的时序约束, 管脚绑定等等, 一般第三方板子都会配套给一个完整的 XDC 文件. 另一点是修改 CIPS 和 NoC IP 的仿真模式, 从 rtl 改为 tlm , 因为后续如果用 QEMU 模拟硬件的话是基于 TLM 级别的模型做的模拟, 如果不修改, Vivado 也会有警告. 在 Block Design 里面点击对应的 IP, 然后在左下角的 Block Properties 里面切换到 Properties 选项卡, 找到 SELECT_SIM_MODE 选项, 修改为 tlm 即可.

最后 Generate Block Design, 然后 Export Platform 导出 .xsa 文件即可. 导出 .xsa 文件的时候有几个选项. 首先是平台类型, 直接选同时用于硬件和硬件模拟 (Hardware and hardware emulation) 比较省事. 第二个是平台状态, 选择 “Pre-Synthesis” 即可, 因为我们现在只是导出一个基础平台, 各种加速核还要由 Vitis 来链接, 现在导出一个 Post-Implementation 的平台没有意义.

到此为止, 基础平台的硬件部分就完成了, 生成 Block Design 的时候唯一应该产生的 Critical Warning 是提示有 AXI 中断控制器的输入端口没有任何链接, 这是合理的, 因为这个端口本身就是用来给后续 Vitis 加速核使用的, 现在是不会连接上的. 除此之外的 Warning 都需要检查一下.

打开 Vitis, 创建一个新的 Platform Project, 选择刚刚导出的 .xsa 文件作为硬件描述文件导入即可, 如果单独创建了硬件平台模拟用的 .xsa 文件可以单独设置, 否则就用同一个文件即可.

选择操作系统和处理器的界面, 随便选择, 后续还要添加其它的处理器支持.

创建好平台项目后, 在平台项目的设置界面左上角找到 + 号, 添加其它操作系统的支持. 一共需要三种操作系统, standalone , linux , aie_runtime . 所有添加过程都使用默认配置即可.

三种操作系统添加完成后重点关注 linux 运行时的设置. Bif File 直接点击右侧的按钮让 Vitis 自动生成一个, Pre-Built Image Directory 选择之前下载并且解压好的 Versal Common Image 的路径. 最后一个是设备树. 设备树没有办法直接用 Vitis 生成, 需要用 Petalinux Tools 来生成. 具体生成方法见下文 "生成设备树和启动引导文件" 一节. 生成好设备树后将 system.dtb 文件复制到某个路径下, 然后在这里指定这个路径即可.

到此平台组件创建基本完成, 可以点左下角的 Build 构建一下平台组件.
生成设备树需要用到 Petalinux Tools, 因为 Vitis 自动生成的设备树不会添加 zocl 驱动节点, 没法直接使用 XRT. 另外如果有自定义 bl31.elf , u-boot.elf 的需求也需要用 Petalinux Tools 来生成启动引导文件.
假设已经安装好了 Petalinux Tools. 如果你不想污染你的环境, 可以参考附录的方法构建一个 Docker 镜像来使用 Petalinux Tools, 但这仍然要求先在宿主机上安装好 Vitis 和 Petalinux Tools 的文件夹, 然后挂载到 Docker 里面去使用.
首先设置一下环境变量
source /opt/petalinux/2025.2/settings.sh然后创建一个新的 Petalinux 项目
petalinux-create project --template versal -n my_versal_platform
cd my_versal_platform接着导入之前在 Vivado 里面创建的硬件描述文件 .xsa
petalinux-config --get-hw-description /path/to/hw.xsa稍等片刻会跳出 KConfig 用来配置 Linux 内核. Petalinux Tools 在 2021.2 之后会自动为生成的设备树中注入 zocl 驱动相关的节点, 只要你在 Vivado 中勾选了 Project As Extensible Platform (这一步之前已经勾选了). 所以无需手动配置 zocl 驱动相关的选项. 主要需要修改的地方是内核的启动参数, 例如我的开发板通过 eMMC 启动, 也就是 RootFS 放在 /dev/mmcblk1p2 上 (通常 eMMC 是 mmcblk1 , SD 卡是 mmcblk0 ). 那么我要
/dev/mmcblk1p2. 如果你使用的是 SD 卡启动, 那么默认就是 /dev/mmcblk0p2, 无需修改.
有一点需要说明, 按理说修改这个配置后, 内核启动参数 bootargs 会有一段类似于 root=/dev/mmcblk1p2 rw 的内容被添加进去, 你可以在 "DT Settings" -> "Kernel Bootargs" 里面看到. 但是它的显示不会实时更新, 你需要修改完保存退出后重新进去才能看到更新后的内容. 这点比较迷惑.
其它的配置自行修改, 因为我们只是要一个设备树, 其它配置几乎都不影响设备树生成的结果. 配置完成后保存退出.
如果需要自定义设备树节点属性, 例如附录中的限制 TF 卡频率的例子, 可以修改 system-user.dtsi 文件, 添加需要的节点属性.
vim project-spec/meta-user/recipes-bsp/device-tree/files/system-user.dtsi然后执行构建
petalinux-build -c kernel
# if you need bl31.elf, u-boot.elf, then run the full build
# petalinux-build编译的时间比较长, 因为它没有一个单独编译设备树的选项. 而 Vitis 又不能自动添加 zocl 驱动节点 😅 .
编译完之后设备树文件位于项目目录的 images/linux/system.dtb. 将它复制到某个路径下, 然后在 Vitis 平台组件的设置界面指定这个路径, 最后重新构建一次平台组件.
如果需要启动引导文件 (bl31.elf, u-boot.elf), 执行完整构建后也可以在 images/linux 目录下找到对应的文件, 然后用生成的这几个文件替换掉 Xilinx 预构建 Versal Common Image 里面的对应文件即可.
到此为止, 基础平台的创建就全部完成了, 可以用它来创建 Vitis 应用项目或者 AIE 项目了. 可以在 Vitis 中找到平台组件的导出位置, 主要是 .xpfm 文件的路径. 通常的使用方法 (例如链接 AIE 设计和 PL 端设计) 类似于:
v++ -l -t $(TARGET) \
--platform /path/to/export/platform.xpfm \
--save-temps \
--temp_dir ./tmp \
-o system.xsa \
$(LIBADF) $(HLS_KERNELS) | tee link.log说实话 Petalinux 工具链本身并不好用, 理论上而言最好在 Docker 里面用, 防止污染宿主机环境, 但是偏偏工具在 Docker 里面配置又很麻烦, 所以这里直接给一个现成的 Dockerfile, 方便使用.
FROM ubuntu:24.04
ENV DEBIAN_FRONTEND=noninteractive
WORKDIR /work
COPY installLibs.sh /work/installLibs.sh
RUN chmod +x /work/installLibs.sh
RUN bash /work/installLibs.sh
# install petalinux deps
RUN apt-get update && apt-get install -y \
build-essential \
autoconf \
libtool \
rsync \
bc \
texinfo \
lsb-release \
dnsutils \
xterm \
sudo \
locales \
wget \
vim \
&& rm -rf /var/lib/apt/lists/* && \
rm -rf installLibs.sh*
# install libncurses5
RUN wget http://security.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu0.1_amd64.deb \
http://security.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2ubuntu0.1_amd64.deb && \
apt install -y ./libtinfo5_6.3-2ubuntu0.1_amd64.deb ./libncurses5_6.3-2ubuntu0.1_amd64.deb && \
rm -f libtinfo5_6.3-2ubuntu0.1_amd64.deb libncurses5_6.3-2ubuntu0.1_amd64.deb
# set locale for petalinux tools
RUN echo "export LANG=en_US.UTF-8" >> /etc/locale.gen && \
locale-gen en_US.UTF-8 && \
update-locale LANG=en_US.UTF-8
ENV LANG=en_US.UTF-8
# create new user for petalinux
RUN useradd -m dev && echo "dev ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers && \
chown -R dev:dev /work
USER dev
CMD [ "/bin/bash" ]要使用这个 Dockerfile, 要求将 Vitis 安装目录的 /path/to/vitis/scripts/installLibs.sh 复制到和 Dockerfile 同一目录下, 然后执行以下命令构建镜像:
docker build -t petalinux-tools .构建完成后直接将 Vitis 和 Petalinux Tools 的安装目录挂载进去.
docker run -it --name petalinux-tools \
-v /opt/petalinux/2025.2:/opt/petalinux/2025.2 \
-v /opt/Xilinx/2025.2:/opt/Xilinx/2025.2 \
petalinux-tools /bin/bash进去设置一下环境变量就可以使用
source /opt/petalinux/2025.2/settings.sh
source /opt/Xilinx/2025.2/Vitis/settings64.sh # Optional某些开发板的 TF 卡插槽可能不支持高速模式, 或者板子设计有问题, 导致频率一高(比如 SDR104 要 208MHz 的频率)就不能正常工作, 可能表现为 Linux 内核加载时卡在读取根文件系统阶段.
[ 2.632483] mmc1: Tuning failed, falling back to fixed sampling clock
[ 2.638943] mmc1: new ultra high speed SDR104 SDHC card at address 0001
[ 2.645976] mmcblk1: mmc1:0001 MSSD0 29.2 GiB
[ 2.699708] mmc1: Tuning failed, falling back to fixed sampling clock
[ 2.828642] mmc1: Tuning failed, falling back to fixed sampling clock
[ 2.883455] mmc1: Tuning failed, falling back to fixed sampling clock
[ 2.889911] I/O error, dev mmcblk1, sector 0 op 0x0:(READ) flags 0x0 phys_seg 1 prio class 0
[ 2.899929] Buffer I/O error on dev mmcblk1, logical block 0, async page read
[ 2.955549] mmc1: Tuning failed, falling back to fixed sampling clock
[ 3.010411] mmc1: Tuning failed, falling back to fixed sampling clock
[ 3.065242] mmc1: Tuning failed, falling back to fixed sampling clock
[ 3.120020] mmc1: Tuning failed, falling back to fixed sampling clock
[ 3.126475] I/O error, dev mmcblk1, sector 0 op 0x0:(READ) flags 0x0 phys_seg 1 prio class 0
[ 3.136510] Buffer I/O error on dev mmcblk1, logical block 0, async page read
[ 3.143667] mmcblk1: unable to read partition table
[ 3.157939] /dev/root: Can't open blockdev
[ 3.162055] VFS: Cannot open root device "/dev/mmcblk1p2" or unknown-block(179,2): error -6
[ 3.170409] Please append a correct "root=" boot option; here are the available partitions:这个时候可以修改设备树来限制 TF 卡的工作频率, 在你的 Petalinux 的项目目录下找到
project-spec/meta-user/recipes-bsp/device-tree/files/system-user.dtsi进去在最后添加一段
&sdhci1 {
max-frequency = <50000000>;
};限制最高频率为 50MHz, 或者
&sdhci1 {
no-1-8-v;
disable-wp;
};保存后重新编译 Petalinux 项目并烧录到板子上即可解决问题. 如果你在用 Xilinx 预构建的 Versal Common Image, 可以在你的平台设置中单独指定设备树文件, 系统镜像仍然用这个预构建镜像的, 只是覆盖掉设备树部分.
petalinux-build -c kernel
cp /path/to/project/images/linux/system.dtb /some/path/system.dtb然后在 Vitis 平台组件中指定这个路径的 system.dtb 即可.