ZCU106开发板PYNQ实战:手把手教你配置DMA回环测速(附完整代码)

张开发
2026/4/17 17:55:32 15 分钟阅读

分享文章

ZCU106开发板PYNQ实战:手把手教你配置DMA回环测速(附完整代码)
ZCU106开发板PYNQ实战从零构建DMA回环测速系统第一次拿到ZCU106开发板时看着这块集成了Zynq UltraScale MPSoC的硬件平台既兴奋又忐忑。作为嵌入式开发者我们常需要处理PS处理器系统与PL可编程逻辑之间的数据交互而DMA直接内存访问正是实现高效数据传输的利器。本文将带你完整实现一个DMA回环测速系统从Vivado配置到PYNQ实测手把手解决每个环节可能遇到的问题。1. 硬件环境准备与Vivado工程搭建在开始之前确保你已经完成以下准备工作安装Vivado 2018.3或更高版本本文以2018.3为例ZCU106开发板及配套电源、线缆已生成PYNQ镜像并成功启动参考前序教程创建Vivado工程的关键步骤新建RTL工程选择ZCU106开发板型号添加ZYNQ UltraScale MPSoC IP核到Block Design配置ZYNQ核时务必在PS-PL Configuration中启用一个HPHigh Performance端口注意DMA传输需要通过HP端口访问DDR内存这是后续数据传输的物理通道2. DMA IP核配置与硬件设计DMA IP核是构建PS与PL数据通道的核心组件。在Vivado的Block Design中添加AXI DMA IP后需要进行以下关键设置配置项推荐值说明Enable Scatter Gather关闭简单回环测试无需SG模式Width of Buffer Length Register23决定最大传输长度Memory Map Data Width64匹配HP端口位宽Stream Data Width32常见数据位宽连接示意图S_AXIS_S2MM → M_AXIS_MM2S (输入) (输出)这种回环连接方式可以直接测试DMA本身的传输性能无需额外逻辑。完成连接后记得验证地址映射是否正确生成HDL Wrapper执行综合与实现3. 生成PYNQ可用的Overlay文件硬件设计完成后需要准备三个关键文件供PYNQ使用.bit文件包含FPGA配置比特流路径工程目录/项目名.runs/impl_1/*.bit.hwh文件硬件描述文件路径工程目录/项目名.srcs/sources_1/bd/bd_name/hw_handoff/*.hwh.tcl文件Block Design重建脚本通过菜单File → Export → Export Block Design生成将这三个文件复制到PYNQ板的/home/xilinx目录下备用。这里有个常见坑点文件权限问题。建议使用chmod 644命令确保Jupyter有访问权限。4. Jupyter Notebook中的DMA测速实现打开PYNQ的Jupyter环境新建Notebook我们分步骤实现测速功能4.1 初始化Overlay与DMAfrom pynq import Xlnk, Overlay import numpy as np import time # 加载Overlay ol Overlay(/home/xilinx/zcu106_dma/dma.bit) dma ol.axi_dma_0 # 获取DMA实例4.2 内存分配与数据准备PYNQ通过Xlnk管理CMA连续内存分配器内存xlnk Xlnk() # 分配25MB的输入输出缓冲区 input_buffer xlnk.cma_array(shape(6553600,), dtypenp.uint32) output_buffer xlnk.cma_array(shape(6553600,), dtypenp.uint32) # 填充测试数据可选 for i in range(len(input_buffer)): input_buffer[i] i % 2564.3 DMA传输与性能测试核心测速代码实现def measure_dma_speed(data_size): # 重置缓冲区 output_buffer[:] 0 # 执行传输并计时 start time.time() dma.sendchannel.transfer(input_buffer[:data_size]) dma.recvchannel.transfer(output_buffer[:data_size]) dma.sendchannel.wait() dma.recvchannel.wait() end time.time() # 计算速度 time_cost end - start speed (data_size * 4) / (time_cost * 1024 * 1024) # MB/s return time_cost, speed4.4 多规模测试与结果分析建议测试不同数据量下的表现test_sizes [64*1024, 1*1024*1024, 10*1024*1024, 25*1024*1024] # 64KB到25MB results [] for size in test_sizes: time_cost, speed measure_dma_speed(size//4) # 除以4因为uint32占4字节 results.append((size, time_cost, speed)) print(fSize: {size/1024/1024:.1f}MB | Time: {time_cost:.3f}s | Speed: {speed:.2f}MB/s)典型结果可能如下数据量耗时(秒)传输速率(MB/s)64KB0.001252.081MB0.018554.0510MB0.18254.9525MB0.45554.955. 常见问题排查与优化建议在实际操作中你可能会遇到以下情况问题1DMA传输速度远低于预期如100MB/s检查HP端口是否已启用确认Vivado中DMA配置的位宽设置尝试增加传输数据量小数据量测试开销占比高问题2Jupyter报错Unable to allocate memory检查PYNQ镜像版本建议v2.6尝试减小测试数据量重启kernel释放内存问题3传输数据校验失败使用np.array_equal(input_buffer, output_buffer)验证检查DMA是否配置为回环模式确认buffer数据类型一致性能优化技巧增大DMA缓冲区长度寄存器位宽尝试使用多个HP端口并行传输考虑使用HLS优化数据流6. 扩展应用实际场景中的DMA使用掌握了基础DMA操作后可以尝试以下进阶应用图像处理加速将摄像头数据通过DMA传输到PL进行实时处理网络数据加速实现TCP/IP协议栈与自定义硬件的快速数据交换多DMA通道管理同时控制多个数据传输流一个实用的技巧是封装DMA操作为Python类class DMAController: def __init__(self, bitfile_path): self.ol Overlay(bitfile_path) self.dma self.ol.axi_dma_0 self.xlnk Xlnk() def transfer(self, data): in_buf self.xlnk.cma_array(shapedata.shape, dtypedata.dtype) out_buf self.xlnk.cma_array(shapedata.shape, dtypedata.dtype) np.copyto(in_buf, data) start time.time() self.dma.sendchannel.transfer(in_buf) self.dma.recvchannel.transfer(out_buf) self.dma.sendchannel.wait() self.dma.recvchannel.wait() return out_buf, time.time() - start在实际项目中我发现DMA性能与内存访问模式密切相关。连续的大块传输通常能获得最佳性能而随机小数据包会导致吞吐量显著下降。建议根据应用特点设计合适的数据缓冲策略。

更多文章