如何获取FPGA 板的 XADC 获取模拟数据,并在 LabVIEW 中显示
本项目展示了如何从 Digilent Arty Z7 FPGA 板的 XADC 获取模拟数据,并在运行于 Windows 电脑上的 LabVIEW 中显示。FPGA 与 LabVIEW 之间的通信通过自定义硬件接口实现,可实时可视化模拟输入信号。
与传统的 FPGA 开发需要嵌入式软件或 Jupyter 笔记本不同,本项目专注于 LabVIEW 与 FPGA 直接通信,适用于实验室仪器和教学环境。
基于 FPGA 的数据采集面临的主要挑战之一是为用户提供直观的硬件交互方式。尽管 Python 已成为控制 FPGA、自动化任务以及访问硬件资源时最受欢迎的语言之一,但构建完善的图形用户界面通常需要额外的框架和开发工作。
另一方面,LabVIEW 是专门针对测量、仪器开发和虚拟仪器设计而设计的。其图形化编程环境便于创建交互式用户界面、显示实时测量结果,并为在实验室环境中工作的工程师和研究人员提供熟悉的操作体验。
通过结合两个平台的优势,可以构建出更完整的解决方案。Python 提供了灵活且强大的 FPGA 接口,而 LabVIEW 则提供了直观的前端界面,用于可视化、配置和仪器控制。这种组合方式使得开发出易于使用的虚拟仪器成为可能,同时不牺牲基于 FPGA 的硬件灵活性与性能。
本工作是围绕费米实验室 DUNE(深地下中微子实验)项目所推动的更广泛技术发展展开的。作为这些努力的一部分,我们一直在研究 Xilinx Zynq-7000 系列 FPGA 芯片,并开发软件工具,以简化其在科学仪器和数据采集系统中的应用。目标不仅在于理解硬件架构,更在于开发实用的接口,以降低FPGA开发的复杂性,使这些平台更易于学生、研究人员和工程师使用。
DUNE是一项国际实验项目,旨在建造全球最先进的中微子探测器之一,用于研究粒子物理学中的基本问题,包括中微子振荡、物质与反物质不对称性以及质子衰变。在DUNE的数据采集系统中,基于AMD/Xilinx Kria FPGA技术的DAPHNE读出平台,在探测器信号的数字化和处理方面发挥着核心作用。尽管该项目采用Digilent Arty Z7作为开发平台,但其中探讨的许多概念——如FPGA通信、模拟数据采集以及用户友好的仪器接口——均可直接应用于现代科学数据采集系统的工具开发。
尽管本项目通过读取单个XADC通道来演示该概念,但相同的架构可扩展至更高级的应用,例如多通道数据采集、基于DMA的高速传输、数字信号处理、定制FPGA外设以及适用于实验室和研究环境的完整虚拟仪器系统。
项目文件
所有用于重现本项目的文件,包括Vivado设计、Python脚本和LabVIEW文件,均可在项目的GitHub仓库中获取。
在VIVADO中实现XADC
使用Vivado中的XADC Wizard IP来实现和配置XADC。本项目仅使用一个模拟输入通道,使硬件架构保持简单,同时提供一个完整的基于FPGA的模拟数据采集示例。
XADC被配置为采集选定的模拟通道,其内部寄存器通过AXI4-Lite接口进行访问。这使得处理器或外部控制系统能够通过一个明确的内存映射接口读取数字化的XADC值。
采用AXI4-Lite提供了简单且灵活的方式访问XADC数据,无需依赖高速串流架构。这对于当前应用尤为实用,其目标是读取模拟值并将其传输至LabVIEW以实现可视化和仪器控制。
创建Vivado模块设计
打开Vivado,并为Arty Z7板创建一个新项目。创建项目后,打开模块设计环境并创建一个新的模块设计。
在模块设计窗口中,选择“添加IP”,搜索XADC Wizard,双击该IP将其添加到设计中。
对于本项目,XADC向导已配置如下设置。
基本配置:在基本配置中,选择AXI4-Lite作为接口,并将XADC设置为连续模式。DCLK频率设定为104 MHz。
ADC设置:在ADC设置中,关闭通道平均功能。未对采集的样本进行额外的平均或滤波处理。其余ADC设置选项保持默认关闭状态。此配置使XADC能够持续采集样本,而无需使用硬件平均,从而确保采集的数据可供主机应用程序处理。
本项目未启用任何XADC报警功能,因为其目标仅为采集和可视化模拟输入信号,无需报警功能。
单通道配置:该设计使用一个辅助模拟输入通道。Vaux1(A0通道)被选为该通道的正负输入端。通道配置为单极性输入,因此禁用双极性工作模式。
连接XADC与Zynq处理系统
完成XADC配置后,需将模拟输入引脚在模块设计中暴露为外部端口。在 xadc_wiz_0 模块中,右键单击 VauxP1 和 VauxN1 输入连接,然后选择“创建外部端口”。Vivado 将为所选的 XADC 输入创建外部端口。建议保留 Vivado 生成的端口名称。通过保持默认的 XADC 端口名称,物理引脚分配可由板子现有的约束条件处理,因此无需为这些 XADC 连接单独创建约束文件。
接下来,从 IP 目录中添加 ZYNQ7 处理系统 IP。该模块提供了集成在 Zynq-7000 设备中的处理系统,允许通过 AXI4-Lite 接口访问 XADC 外设。
添加 Zynq 处理系统后,运行“模块自动化”以配置处理器,并应用针对所选板子的推荐连接。然后运行“连接自动化”,自动将 Zynq 处理系统与 XADC IP 之间的 AXI 接口及其他必要信号进行连接。
在确认模块设计无误后,生成 HDL 包装代码并运行“生成比特流”。最终生成的位文件包含FPGA硬件配置,将在后续阶段用于建立Arty Z7与LabVIEW应用程序之间的通信。
内存映射寄存器
在进行软件实现之前,首先需要确定与FPGA外设关联的内存地址。这些地址将用于主机应用程序访问XADC寄存器。
本项目中,我们仅需访问与xadc_wiz_0外设相关的寄存器。地址信息可在Vivado的地址编辑器中“地址映射”部分找到。
对于当前设计,XADC外设被映射到以下地址范围:
基地址0x43C00000是分配给XADC的内存映射区域的起始点。各个XADC寄存器位于该64 KB地址空间内的特定偏移位置。
这些地址在项目下一阶段尤为重要,因为它们为FPGA硬件与运行在PC上的软件之间提供了连接桥梁。
使用XADC编程FPGA
完成Vivado设计并生成比特流后,下一步是准备用于编程Arty Z7的FPGA配置文件。随后可根据所采用的编程方法,通过Linux环境或直接使用Windows命令提示符(CMD)对FPGA进行编程。
创建.bin文件
虽然Vivado可以直接生成.bin文件,但在FPGA系统上安装不同版本的Vivado与不同版本的Linux或PetaLinux时,可能会出现兼容性问题。因此,建议使用Windows命令提示符(CMD)手动创建.bin文件,这样更安全可靠。
在生成Vivado比特流文件(.bit)的目录中打开CMD。在同一目录下,创建一个名为download.bif的文本文件,使用文本编辑器打开该文件,并添加以下内容:
your_bitstream.bit 是由Vivado生成的文件。
检查Bootgen是否可用
在生成.bin文件之前,必须确认Windows环境中已安装Bootgen工具。
打开命令提示符(CMD),执行以下命令之一:
或者:
如果Windows返回类似以下信息:
这并不一定意味着 Bootgen 没有安装。大多数情况下,只是当前命令提示符会话中未加载 AMD/Xilinx 开发环境。要解决此问题,请打开与您的 Vivado/Vitis 安装关联的 AMD/Xilinx 命令提示符,或手动通过执行 settings64.bat 文件来加载 AMD/Xilinx 环境。例如:
安装路径可能因 Vivado/Vitis 版本和安装目录的不同而有所差异。加载环境后,请再次检查 Bootgen:
如果环境已正确加载,Windows 应该现在能够识别 bootgen 命令。
运行 Bootgen
在包含之前创建的 .bit 文件和 download.bif 文件的文件夹中打开一个 CMD 窗口,然后执行以下命令:
此时,文件夹中将生成一个名为 filename.bit.bin 的新文件。
重命名文件
传输并编程 FPGA
从 Windows CMD 中,使用 scp 将 .bin 文件复制到 Arty Z7:
连接至 Arty Z7
在 Windows CMD 中,建立 SSH 连接以访问 FPGA:
当提示输入密码时,输入:
成功连接到 Arty Z7 后,将二进制文件复制到 FPGA 固件目录中:
现在可以使用 Linux FPGA 管理器界面对 FPGA 进行编程:
要检查 FPGA 是否成功编程,首先查看最新的内核消息:
然后检查当前 FPGA 管理器的状态:
如果编程成功,预期结果如下:
这表明 FPGA 已成功配置为生成的比特流。
LabVIEW 和 Python
LabVIEW 可以执行 Python 脚本,但并非所有版本的 LabVIEW 都与所有版本的 Python 兼容。Python 版本必须与所使用的特定 LabVIEW 版本兼容。下表总结了不同 LabVIEW 版本支持的 Python 版本:
除了 Python 版本外,系统架构也必须匹配。LabVIEW 和 Python 必须使用相同的架构:32 位或 64 位。
Python
在安装所需软件包之前,建议先检查系统上已安装的 Python 版本。打开 Windows 命令提示符(CMD),并运行以下命令:
该命令将显示计算机上已安装的 Python 版本。
如有需要,请从官方 Python 网站下载与您的 LabVIEW 安装兼容的 Python 版本,并根据所使用的 LabVIEW 版本选择相应的架构(32 位或 64 位)。
安装所需的 Python 软件包
本项目使用 Paramiko 来在 Python 和 Arty Z7 之间建立 SSH 连接。在安装 Paramiko 之前,建议先为将要使用的特定 Python 版本更新 pip。本项目中选择的 Python 安装版本为 Python 3.9,32 位。
由于同一台计算机上可能同时存在多个 Python 版本,因此在安装软件包时必须明确指定 Python 版本,以防止软件包被安装到其他 Python 环境中。
安装加密库
根据所使用的 Python 版本,安装 Paramiko 可能会与依赖项产生兼容性问题。特别是,Paramiko 需要 cryptography 包。对于较旧的 Python 版本,可能需要安装兼容版本的 cryptography。
本项目使用 Python 3.9 32 位系统:
安装 Paramiko
在安装了兼容版本的 cryptography 后,安装 Paramiko:
上述显示的具体版本对应本项目中使用的 Python 3.9 32 位环境。如果选择不同的 Python 版本,则相应的 Paramiko 和 cryptography 版本可能不同。
Python 脚本
Python 脚本将作为 LabVIEW 与 Arty Z7 之间的通信层。LabVIEW 将调用该脚本中的特定函数来建立 SSH 连接并操作 FPGA。
Shebang(shebang)
Shebang 用于指定执行脚本时应使用的解释器。在此情况下,它指定了 Python 3 解释器:
这使得脚本可以直接在 Linux 系统上通过以下命令执行:
导入 Paramiko
Paramiko 是本项目中用于实现与 Arty Z7 进行 SSH 通信的 Python 库。
定义登录凭据。访问 Arty Z7 的默认登录凭据被定义为全局变量:
USUARIO 变量包含用户名,PASSWORD 变量包含对应的密码。
创建 SSH 对象
变量 ssh 将包含表示与 FPGA 建立 SSH 连接的对象。程序开始时没有活动连接,因此将其初始化为 None:
Connect(host) 函数
LabVIEW 通过函数来访问 Python 脚本。因此,脚本被组织为一组函数,每个函数执行特定任务,并可选择返回一个值。第一个函数是 connect(host),它接收一个参数 host,即包含 Arty Z7 IP 地址的字符串。
全局的 ssh 语句表示该函数将使用之前定义的全局变量 ssh。该变量保存了 SSH 连接对象,其中包含与当前 FPGA 连接相关的各项信息。
这会创建一个由 Paramiko 提供的 SSHClient 类的对象。此时,对象已创建,但与FPGA的连接尚未建立。
SSH使用加密主机密钥来识别远程计算机。首次连接服务器时,标准SSH客户端可能会显示类似以下信息:
通常情况下,用户必须回答“是”以接受主机密钥。当主机密钥尚未被识别时,paramiko.AutoAddPolicy() 会自动执行相同操作。对于本项目而言,这非常方便,因为连接是通过Python从LabVIEW程序化地建立的。
SSH连接
此指令用于建立与FPGA的SSH连接。其原理相当于在终端中手动执行以下命令:
host参数包含Arty Z7的IP地址。随后,函数将使用先前定义的用户名和密码对连接进行身份验证。timeout=10参数指定了连接尝试的最大等待时间为10秒。如果连接成功建立,函数将返回字符串:
断开连接函数
disconnect() 函数会关闭与 Arty Z7 的 SSH 连接,并返回一条消息,表示 FPGA 已断开连接。
execute(command) 函数
execute(command) 函数允许 LabVIEW 通过 SSH 连接在 Arty Z7 上执行 Linux 命令。
该函数接收一个参数 command,其中包含要在 FPGA 上执行的 Linux 命令。首先,它会验证是否存在有效的 SSH 连接:
如果当前没有活动的连接,函数将立即返回错误消息。随后,命令将通过 Paramiko 远程执行:
函数返回的三个对象分别对应远程 Linux 进程的标准输入、标准输出和标准错误流。标准输出随后被读取,并从字节转换为 Python 字符串:
同样地,Linux 命令产生的任何错误也会从标准错误流中读取:
如果出现错误消息,该函数将返回该消息;否则,返回命令输出:
此函数对LabVIEW界面特别有用,因为它允许LabVIEW在FPGA上执行Linux命令,而无需用户手动打开SSH终端。
_execute_python(code) 函数
该函数使LabVIEW能够以管理员(root)权限直接在FPGA的Linux系统上执行Python代码。这非常有用,因为Python代码可以访问诸如/dev/mem之类的资源,从而直接与FPGA设计中实现的硬件外设进行通信。
code参数包含要发送并执行到Arty Z7上的Python代码。
检查SSH连接
以下代码用于验证与FPGA之间是否存在有效的SSH连接。如果没有连接,函数将停止并抛出异常。
以管理员权限执行Python
该操作向运行在Arty Z7上的Linux系统发送以下命令:
使用sudo命令以管理员权限执行Python解释器。-S 选项告诉 sudo 从标准输入(stdin)读取密码,而不是从键盘输入。这一点很重要,因为整个过程由 LabVIEW 通过 Python 进行程序化控制。
最终的 - 表示 Python 应该从标准输入读取程序,而不是从 .py 文件中读取。因此,Python 程序可以直接通过 SSH 连接发送。
发送密码
发送 Python 代码
代码参数的内容随后被发送到运行在 FPGA 上的 Python 解释器。这意味着 LabVIEW 可以动态构建一个 Python 程序,并直接发送到 Arty Z7 执行。此外,也可以创建一个完整的 Python 脚本,将其保存在 FPGA 上,并通过相同的 SSH 机制在 LabVIEW 中执行。
读取输出和错误
定义 readRegister(base, offset) 函数
该函数将生成一个 Python 程序字符串,并通过前面描述的 _execute_python() 函数发送到 FPGA。
创建将发送至 ARTY 的 Python 代码
在 FPGA 上运行的最终 Python 代码负责访问与 FPGA 外设相关的物理内存。
导入所需库
使用了三个Python库:
os 提供对操作系统资源的访问,包括 /dev/mem。
mmap 允许将物理内存区域映射到Python进程。
struct 将从内存中读取的原始字节转换为32位整数。
定义内存参数
这些变量用于定义要访问的内存区域。BASE 是分配给FPGA外设的基地址,OFFSET 则标识该外设中的特定寄存器。因此,寄存器的物理地址为:
地址 = BASE + OFFSET
SIZE = 0x10000 定义了一个64 KB的内存映射窗口,对应本项目中XADC外设所分配的地址空间。
打开 /dev/mem
/dev/mem 提供对Zynq系统物理内存地址空间的访问。使用 os.open() 函数打开此设备并获取读写权限。返回的fd是一个文件描述符,将用于访问物理内存。os.O_SYNC 标志要求对设备进行同步访问。
由于 /dev/mem 直接提供对物理内存的访问,Python代码必须以管理员权限运行。这就是为什么之前的 _execute_python() 函数使用了 sudo。
映射物理内存
这会创建一个与外设物理地址空间相对应的内存映射窗口。mem 变量表示该映射的内存区域。
映射从 BASE 开始,覆盖 SIZE 个字节。一旦完成映射,FPGA 寄存器就可以作为 mem 对象中的位置来访问。
选择寄存器
这会将内存指针移动到映射区域内的指定寄存器。由于映射从 BASE 开始,所访问的寄存器对应于:BASE + OFFSET。
读取寄存器
使用 mem.read(4) 指令读取 4 个字节,对应一个 32 位 AXI 寄存器。struct.unpack("
•< — little-endian 字节序。
•I — unsigned 32-bit 整数。
struct.unpack() 返回一个元组,因此使用 [0] 获取第一个元素:得到的结果值随后被打印出来:
这个打印出的值将成为通过 SSH 连接返回的输出。
定义 writeRegister(base, offset, value) 函数
writeRegister(base, offset, value) 函数的工作方式与前面描述的 readRegister() 函数类似。主要区别在于,它不是读取寄存器,而是将一个 32 位值写入指定的内存地址。
执行写入操作的主要指令是:
struct.pack("
定义 takeData(samples) 函数
takeData(samples) 函数与之前的寄存器访问函数类似,但其功能不是读取单个值,而是采集多个ADC采样,并将这些数据以列表形式返回给LabVIEW。
在该函数中,XADC外设的基地址为:0x43C00000,用于获取ADC测量值的寄存器偏移量为:0x0244。因此,实际访问的物理地址为:0x43C00000 + 0x0244 = 0x43C00244
LabVIEW
LabVIEW程序相对简单,只需调用前文所述的Python脚本,并根据每项任务调用相应的函数即可。在LabVIEW的方框图中,右键点击打开“函数面板”,然后选择“连接性”→“Python”。在此处可找到“打开Python会话”、“Python节点”和“关闭Python会话”三个选项,分别用于初始化Python、调用Python脚本中的函数以及关闭Python会话。
初始化Python
“打开Python会话”模块用于从LabVIEW初始化Python解释器。本项目中使用的Python版本为:3.9.12。该模块配置了将要使用的Python安装路径。如果计算机上仅安装了一个Python版本,则可能无需指定路径。
连接FPGA
Python节点用于调用Python脚本中的函数,并传递所需的参数。必须为Python节点配置.py文件的路径以及要调用的函数名称。在此情况下,函数为:
标有abc的灰色输入用于指定函数返回值所期望的数据类型。由于conectar()函数返回字符串,因此该输入应设置为字符串类型。下一个输入对应函数参数。对于conectar()函数,所需参数是host,即Arty Z7的IP地址:
函数通过返回值输出返回结果。如果连接成功,Python函数将返回:
读取数据
Python节点还可用于调用tomarDatos()函数。需传入采样数量作为参数。该函数返回一个包含ADC测量值的整数数组(向量或列表)。该数组随后直接连接到LabVIEW图形界面,可实时显示从Arty Z7获取的XADC数据。
方框图
LabVIEW的方框图包含初始化Python、建立与FPGA的SSH连接、请求ADC采样以及显示采集数据所需的所有组件。
本文编译自hackster.io





