当前位置:首页 > 工业控制 > 电路设计项目集锦
[导读]在我的上一篇项目文章中,我介绍了使用 AMD 新的 Yocto 工作流结合 EDF(嵌入式开发框架)为 Kria SoM 构建嵌入式 Linux 镜像的基本步骤。该项目详细说明了克隆 AMD Yocto 项目的流程,包括专用于 AMD FPGA 的 Xilinx 层,并利用 meta-kria 层中的默认设置和 Kria 的比特流文件,将其构建为目标平台——Kria KV260 Vision AI 开发套件。

在我的上一篇项目文章中,我介绍了使用 AMD 新的 Yocto 工作流结合 EDF(嵌入式开发框架)为 Kria SoM 构建嵌入式 Linux 镜像的基本步骤。该项目详细说明了克隆 AMD Yocto 项目的流程,包括专用于 AMD FPGA 的 Xilinx 层,并利用 meta-kria 层中的默认设置和 Kria 的比特流文件,将其构建为目标平台——Kria KV260 Vision AI 开发套件。

尽管在 Zynq UltraScale+ 等核心可编程逻辑芯片上已预装默认比特流,仍有许多开发工作可以进行,但为了充分发挥 Kria SoM 和 KV260 载板上所有功能与外设的潜力,最终仍需实现一个自定义的 HDL 设计。本项目将介绍如何在 Vivado 中创建针对 Kria KV260 的自定义 HDL 设计,然后将其集成到使用 Yocto 构建的、专为 Kria 设计的嵌入式 Linux 镜像中,并使其成为 Zynq US+ 在启动时加载到可编程逻辑中的默认位流。

注意:本项目使用的是 Vivado 2025.2 版本和 Xilinx Yocto 项目,以及 EDF 25.11 版本。主机开发环境为 Ubuntu 24.04 LTS。

Vivado 中的 HDL 设计

我认为 Vivado 中最实用的功能之一是,可以为不同厂商的开发板创建预设文件,并在项目中直接使用这些文件,以预先配置特定于该开发板的项目设置。

启动 Vivado 并选择创建新项目。通过项目设置向导窗口逐步操作,选择项目的名称和目录位置。

在项目类型中选择 RTL 项目,并暂时取消勾选“不指定源文件”选项。本文示例项目不会采用可扩展的 Vitis 平台,因此我保持此选项未选中:

在“默认部件”页面,切换到“Board”标签页,搜索 KV260:

在“显示名称”部分,点击“添加伴侣卡连接”的超链接,然后选择“Vision AI 开发套件载板”。

这将确保 ZynqMP 处理系统中为 KV260 载板启用正确的默认外设配置。

在选择 Kria KV260 并确认已正确选择伴侣卡连接后,继续浏览项目设置向导的其余页面,以生成新项目。

创建项目后,从流程导航器窗口中选择“创建模块设计”选项。

Vivado 中的模块设计是用于将 AMD 及第三方 IP 的 HDL 作为“模块”放置,并通过 AXI 等接口进行连接的图形化画布。

使用模块设计的方法在 Vivado 中也被称为 IP 集成器工作流。该工作流还具备自动连接 AXI 接口和设计规则检查器等优点。

点击模块设计窗口顶部的“+”按钮,搜索“zynq”,选择 ZynqMP 处理系统 IP。

在模块设计窗口顶部出现的绿色横幅中,选择“运行模块自动化”选项。这将为KV260载板的外设配置应用上述预设。

ZynqMP处理系统IP提供了配置Zynq UltraScale+ MPSoC芯片可编程逻辑中内置物理ARM核心处理器设置的接口。即使您不打算使用ARM处理器,该IP也必须在每个设计中实例化,因为可编程逻辑的主要时钟信号来自ARM处理器(系统时钟振荡器芯片直接连接到它)。

一旦将ZynqMP处理系统IP添加到设计中,即可添加所需的自定义外设和逻辑。

KV260载板上的某些外设仅可通过可编程逻辑(PL)在Zynq MPSoC中访问ARM核心处理器,这意味着必须在设计中显式实例化某种用户逻辑才能使用这些外设(与直接连接到ARM处理器的其他外设不同,例如RJ45接口上的千兆以太网)。PMOD GPIO连接器是仅可通过PL访问的外设之一。我选择使用一个简单的AXI GPIO IP,以便通过Linux的Sysfs GPIO接口进行访问。此外,我目前决定将8个GPIO全部设置为输出模式:

在添加AXI GPIO IP并将其配置为PMOD GPIO后,块设计窗口顶部将出现一个绿色横幅,提供“运行连接自动化”选项,可自动将AXI GPIO连接到ZynqMP处理系统IP:

KV260上仅通过PL连接但对任何设计都至关重要的其他GPIO包括第45号银行的12V风扇引脚和复位芯片I/O。这些信号的控制可通过“Board”标签页轻松添加。

右键单击第45号银行的GPIO,然后选择“ConnectBoard Component...”。

对于嵌入式Linux镜像而言,这些信号只需使用AXI GPIO IP即可满足需求。

再次选择图表窗口顶部绿色横幅中显示的“运行连接自动化”选项。

完成设计后(目前我仅添加了两个AXI GPIO IP),请使用设计规则检查器验证设计无误,方法是点击块设计窗口顶部的复选框图标。所有错误和关键警告必须在继续之前得到解决。

保存块设计,然后切换到“Sources”标签页,右键单击块设计文件,选择“创建HDL封装...”选项。这将把模块设计实例化为项目中的源文件。

Vivado 会询问你是否希望它为你管理这个封装的 HDL 文件(如果模块设计的顶层端口发生更改,它会自动更新该文件),或者你是否只想手动编辑。我个人发现,如果想对设计进行修改,总是让 Vivado 自动管理这个自动生成的 HDL 文件,比自己手动创建更方便。这样我只需将自动管理的文件中的修改内容复制粘贴到自己的自定义 HDL 文件中即可。

一旦顶级 HDL 文件创建完成,设计就已准备好进行综合。在流程导航器窗口中选择“运行综合”。

完成后,在弹出的窗口中选择打开综合后的设计。由于通过可编程逻辑器件(PL)传输的信号已被添加到设计中,因此需要在约束文件中配置 FPGA 芯片上的具体引脚。虽然可以通过文本编辑器手动编写约束文件,但 Vivado 中的“综合设计”也提供了图形用户界面(GUI)供你进行配置。当需要指定少量引脚时,例如我的 8 个 PMOD 引脚,这种方式更为简便。对于第45号银行上的12V风扇引脚和复位芯片GPIO,这些约束条件已通过板定义文件自动包含在项目中(当在项目设置向导中指定Kria KV260为目标板时选择的)。因此,我只需手动添加PMOD GPIO的约束即可。

在合成设计中,使用右上角的下拉菜单切换到IO规划视图,然后选择底部的I/O端口选项卡。为8个PMOD GPIO选择封装引脚B11、D11、E12、B10、C11、D10、E10和H12:

由于Zynq MPSoC的第45号银行由3.3V电源轨供电,因此I/O标准为LVCMOS33。

由于AMD仅发布载板的原理图,我在追踪这些封装引脚时花费了一些时间,因此必须根据PMOD信号参考标识符,在KV260原理图中的240针SoM连接器处进行查找,然后使用K26的主约束文件:

保存对合成设计所做的更改。这将弹出提示,询问是否创建新的约束文件以将指定的约束保存到现有文件中。

一旦生成了约束文件,便可对其进行编辑,且用户所做的任何修改都将保留。保存合成设计后,重新运行合成,完成后选择“运行实现”选项,以将设计放置并布线至 Kria K26 SoM 上的特定 Zynq MPSoC FPGA。

导出包含 Bin 的 XSA 文件

当实现运行完成后,选择“打开已实现设计”选项。打开已实现设计后,在流程导航器窗口中选择“设置”。

在“项目设置” → “比特流” → “写比特流”中,勾选 -bin_file* 选项。这将告诉 Vivado 生成设计的 .bit 比特流文件以及 .bin 比特流文件。对于 Kria 板而言这一点非常重要,因为自定义设计将以叠加方式加载到 Linux 系统中,Linux FPGA 管理器在编程可编程逻辑(PL)时需要 .bin 格式的比特流文件。

点击“应用”,然后点击“确定”以关闭设置窗口并运行“生成比特流”。

成功生成比特流后,硬件设计需导出为 XSA 文件,以便用于 Yocto 项目和设备树编译器。

选择“文件” → “导出” → “导出硬件”。在“输出”页面中,选择“包含比特流/二进制文件”,并勾选“包含比特流”和“包含二进制文件”两个选项。然后指定 XSA 文件的名称及输出位置:

注意:如果在设置中忘记勾选“在写比特流设置中包含 bin 文件”的选项,导出 XSA 时将会报错,提示找不到 bin 文件。

创建新的 Yocto 项目

硬件设计完成后,切换到终端并使用所需的Xilinx版本创建一个新的Yocto项目(截至2025年撰写时为最新版本2025.2)。克隆Yocto项目后,需先加载其环境工具:

此外,建议同时将Vitis工具也加载到环境中(但必须在加载Yocto项目工具之后进行,否则会发生冲突):

此步骤仅适用于Ubuntu 24.04及更高版本的主机。由于我尚未完全理解该安全设置的含义,因此无法将其设为常驻/持久状态,故每次重启后都必须重新执行:

为HDL设计启用相应的内核驱动

如前所述,我计划通过Sysfs GPIO接口在Linux系统中访问自定义HDL设计中的GPIO。因此,内核还需要加载相关的Sysfs模块以及AXI GPIO IP的驱动模块:

要启用这些内核模块,可通过menuconfig linux-xlnx bitbake菜单配置界面完成。当前使用的设备是kria-zynqmp-generic,因为Kria SoM是目标设备:按下 / 键弹出搜索菜单的功能与 PetaLinux 工具中的功能相同,因为这一直是 Yocto 的核心特性。

在启用所有需要的内核模块后,退出配置菜单,并在提示时保存。

构建 Kria QSPI 启动二进制文件

由于内核已更新,Kria 的启动二进制文件需要重新编译,因为内核是其中包含的组件之一:

Kria 的启动二进制文件存储在 SoM 的 QSPI 快闪存储器中。所有 Kria SoM 都有配置模式引脚被初始化为仅支持从 QSPI 启动,因此无法从其他位置(如 SD 卡)读取 boot.bin 文件。

如果您不熟悉在 AMD 载体板(如 KV260 或 KR260)上更新 Kria SoM QSPI 中启动二进制文件的过程,我已在之前的项目中详细说明过。

构建 Kria 命令行镜像

接下来重新构建 Kria 的根文件系统。kria-zynqmp-generic 是所有 AMD Kria 开发套件(KV260、KR260、KD240)共用的镜像名称。您仍然可以安全地忽略关于该镜像仅用于其他机器的警告。

用于 kria-zynqmp-generic 机器的 bitbake 还会将根文件系统的 WIC 镜像进行通用化处理,以便使用 Balena Etcher 等工具轻松地将其刷入 SD 卡。

为自定义 XSA 设计创建设备树二进制(XSCT)

最后一个需要的组件是 Kria 可编程逻辑中各逻辑节点的设备树二进制(DTBO)。

当我撰写本项目初稿时,尚未能成功让新的系统设备树(SDT)工作流程生效。因此我最初使用了已过时的 Xilinx 命令行工具(XSCT)来生成自定义 HDL 设计的设备树覆盖层。不久之后,我找到了正确使用 SDTGen 进行 Kria 设计的方法。除了我已经写好了这一部分且没有心情删除之外,如果能同时对比两种流程,我会觉得非常有帮助,因此在此说明中保留了 XSCT 工作流。但需要明确的是,你无需为你的设计生成两个 DTBO。请使用本节中的 XSCT 工作流,或下一节中的 SDTGen 工作流即可。

要为自定义的Kria HDL设计生成设备树覆盖层,请先创建一个输出目录,并将Vitis或Vivado工具源码添加到环境变量中,然后启动XSCT:

使用硬件软件接口(HSI)打开XSA文件:

运行createdts命令以生成设备树源文件。Kria覆盖层设计需要使用-zocl标志,该标志会添加来自Xilinx运行时驱动程序的钩子。

一旦成功创建了设备树源文件,退出XSCT以返回正常的终端:

接着使用设备树编译器(DTC)命令,将XSCT生成的设备树源文件编译成设备树二进制块(DTBO),该DTBO将在Linux系统中作为设备树覆盖层加载,当自定义HDL比特流被编程到可编程逻辑(PL)时使用:

为自定义XSA设计创建设备树二进制块(SDTGen)

System Device Tree Generator用于为设计生成DTBO的主要工作流程是:SDTGen → Lopper → 设备树编译器(DTC)。

从SDTGen开始,其工作方式与XSCT类似,即在底层仍调用硬件软件接口(HSI),而Kria覆盖层设计仍然需要使用-zocl标志,该标志会添加来自Xilinx运行时驱动程序的钩子。该过程将生成一个pl.dtsi文件,与XSCT工作流中的操作类似,但对比两者会发现它们并不相同,DTC仍可对其进行编译。这时就派上了Lopper的作用。Lopper是一个基于Python的框架,它从SDTGen生成的系统设备树system-top.dts中提取系统元数据,生成可供DTC工具编译成设备树二进制块(blob)的设备树源文件。

Lopper的副本已包含在AMD Tools安装包内,因此无需单独从源码安装(除非你愿意,我可不是你的妈妈)。只需在环境中设置Vitis工具即可使用Lopper工具。然后需要创建一个专门用于存放Lopper命令输出的目录,这是我学习硬件时经历的一课,花了三天时间才弄明白:

接下来,设置Lopper的DTC标志:

调用Lopper,并将输出目录设为刚刚创建的一个目录,输入设备树文件则为SDTGen生成的system-top.dts。Lopper还会生成一个system-top设备树,其中排除了PL部分的所有节点(即system-top-no-pl.dts)。对于Kria,我们需要一个完整的系统DT覆盖层,通过设置xlnx_overlay_pl_dt标志并传递完整参数来实现。然后指向由SDTGen生成的pl.dtsi文件。最后,需要使用firmware-name标志传递Vivado中生成比特流时输出的.bin文件名,因为Kria在运行时会将输出的设备树作为覆盖层加载。

我发现Xilinx Lopper目录下的assists目录中的readme文档对正确使用Lopper命令最为有帮助。

最后,使用设备树编译器(DTC)命令,将Lopper生成的设备树源文件编译为设备树块(dtblob),该块将在Linux中作为设备树覆盖层加载,当自定义HDL比特流被编程到PL时:

从硬件方式的经验中总结几点小提示:确保Lopper输出目录与SDTGen输出目录不同。Lopper工具无法覆盖SDTGen生成的pl.dtsi文件,因为它正用该文件作为自身生成pl.dtsi的源文件(即你用于DTC创建dtbo并传输到Kria的那一个)。

因此,我建议在使用所有 lopper 命令时都加上 -v / --verbose 选项,以便更好地理解这些命令的工作原理。这是我唯一弄清楚某些问题的方法,比如为什么 lopper 的输出目录不能与 sdtgen 的输出目录相同,因为标准输出几乎可以忽略不计。

例如,以下是不使用详细输出标志的修剪器输出:

而使用详细输出标志时:

为自定义XSA设计准备源文件

在主机上生成所有所需文件后,我通常会将它们集中存放在一个位置,以便传输到目标Kria板:

创建JSON文件,用于定义FPGA管理器DFX-MGR将从/lib/firmware/xilinx加载的shell设计:

对于此设计(以及大多数Kria HDL设计),shell的定义如下:

复制在Vivado中生成比特流时产生的.bin文件,以及使用DTC编译的DTBO文件:

将两个文件重命名为相同的名称,这将成为在Kria上通过xmutil加载的应用程序名称:

将自定义XSA设计文件传输至Kria

使用前一步生成的新启动二进制文件和SD卡镜像启动Kria,并将其连接到本地网络,然后使用类似scp的命令从主机传输.bin文件、设备树blob和json文件:

创建固件目录

在Kria上,在/lib/firmware/xilinx中创建一个子目录,其名称与bin和dtbo文件所选的名称一致:

将.bin文件、设备树blob和json文件复制到该固件目录中:

测试自定义XSA固件

使用 xmutil 命令卸载默认的固件设计,并加载新添加的固件:

为了验证我的自定义固件设计是否已正确加载,我首先查询了 sysfs GPIO 总线,确认我添加用于驱动 PMOD 的 AXI GPIO 是否存在:

然后,我使用自己最喜欢的猫形 RGB LED 来验证 PMOD 的 GPIO 端口是否确实按预期切换:

设置自定义 XSA 在启动时加载

当我将设计成功加载到 KV260 并验证其正常工作后,我希望它能成为系统启动时默认加载的固件,而不再每次都需要手动使用 xmutil 命令来加载。

FPGA 管理器目录 DFX-MGRD 中,使用 Kria 镜像上的 vim 编辑器创建一个名为 default_firmware 的文件:

然后在 /lib/firmware/xilinx 目录中指定要启动时加载的固件名称:

使用 :wq 保存更改并退出 vim。

接着重启 Kria 板进行测试:

就这样!现在你可能已经注意到,这个项目帖子的标题是“第一部分”,因为下一步将自动让Yocto项目把自定义固件文件集成到kria-zynqmp-generic镜像中,而无需手动将这些文件传输到每个需要部署的Kria板上。敬请期待!

本文编译自hackster.io

本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除( 邮箱:macysun@21ic.com )。
换一批
延伸阅读

体积更小、支持多摄像头接入,为NVIDIA边缘AI系统提供可扩展的以太网架构,同时降低功耗、成本与集成复杂度

关键字: 边缘AI 传感器 FPGA

预算有限的情况下,我成功在经济实惠的Raspberry Pi Pico 2W上开发出实时C++嵌入式软件。它可连接路由器,与我的HomeServer通信,并完美控制LED指示灯以实现浇水决策。

关键字: 嵌入式 路由器 LED Wi-Fi

2026年8月11日 – 提供超丰富半导体和电子元器件™的业界知名新品引入 (NPI) 代理商贸泽 (Mouser) 宣布与Arduino合作推出一本全新电子书From Blink to Think:How Arduin...

关键字: AI 嵌入式 开发板

PSOC™ Edge E84 AI 开发套件是一款用于嵌入式和边缘人工智能应用的开发板。本指南将说明如何配置 Arduino IDE 以支持 PSOC™ Edge E84 AI 开发套件,并提供在该开发板上编译、上传和运...

关键字: 嵌入式 边缘人工智能 Arduino

Agentic AI 正在生成比以往更多的模型、代码、需求以及测试工件,但更多的产出并不意味着更快的系统级开发进展。这种脱节源于系统连续性的中断:每次工具之间的交接都会丢失可执行的系统状态,迫使工程师在继续工作之前,从静...

关键字: 电动汽车 Agentic AI 嵌入式

本项目将一块STM32板改造为一个简单的音频设备,通过三个按钮进行控制。按下其中一个按钮可播放音调,另外两个按钮则用于通过扬声器调节频率的上下变化。该项目探索了嵌入式编程的基础知识,包括GPIO配置、方波生成以及实时响应...

关键字: 扬声器 嵌入式 方波 STM32

树莓派Pico 2是树莓派推出的最新微控制器开发板,搭载强大的RP2350微控制器。它提供更快的性能、更大的内存、增强的安全性,并支持Arm Cortex-M33和Hazard3 RISC-V两种架构。

关键字: 嵌入式 MicroPython 树莓派 RP2350

语音控制在消费电子产品中已十分常见,但将其集成到嵌入式项目中却仍然令人意外地困难。大多数解决方案依赖云服务、需要大量编程,或仅限于固定的一组预设命令。对于创客、学生和业余爱好者而言,将离线语音识别功能融入ESP32项目可...

关键字: 消费电子 嵌入式 ESP32-S3

在Linux系统中,我们在终端输入一条命令按下回车,几毫秒后程序就开始运行。很多开发者每天都在执行各类可执行文件,却很少深究背后的细节:磁盘上一个静态的ELF二进制文件,是如何一步步变成内存中活跃的进程?为什么物理内存明...

关键字: Linux 虚拟内存
关闭