关键词:FPGA、YOLO、Zynq、Vivado HLS、INT8 量化、AXI DMA、卷积加速器、PS+PL 协同设计
在 PC 或服务器上运行 YOLO,通常只需要 Python、PyTorch 和 Ultralytics:
输入图片 ↓ PyTorch 模型推理 ↓ 输出检测框但在 FPGA 上部署 YOLO,流程完全不同。FPGA 不能直接运行 PyTorch,也不能直接把 ONNX 文件下载进去执行。
FPGA 部署 YOLO 的本质是:
把 YOLO 的卷积、池化、上采样等运算 转换为 FPGA 中的硬件电路本文介绍 FPGA 部署 YOLO 的完整流程、硬件架构、开发工具、量化方法和常见注意事项。
一、为什么 FPGA 部署 YOLO 和 PC 不一样
1. PC 上的 YOLO
PC 上运行 YOLO 依赖软件框架:
Python ↓ PyTorch ↓ YOLO 模型 ↓ CPU 或 GPU你只需要执行:
yolo predict model=yolov8n.pt source=test.jpg device=cpuPyTorch 会自动完成所有计算。
2. FPGA 上的 YOLO
FPGA 没有 PyTorch,也不会自动解释神经网络。
FPGA 需要:
- 卷积硬件模块;
- 池化硬件模块;
- 上采样硬件模块;
- 激活函数模块;
- 数据缓存;
- AXI 总线;
- DMA;
- ARM 控制程序。
整体关系是:
ARM PS ↓ 控制层调度 ↓ AXI DMA ↓ FPGA PL ↓ 卷积/池化/上采样硬件 ↓ 检测结果因此,ONNX 只是中间格式:
ONNX ≠ 可以直接在 FPGA 上运行ONNX 需要进一步转换为 HLS、RTL 或专用加速器支持的数据和指令格式。
二、FPGA 部署 YOLO 的总体流程
完整流程通常如下:
训练 YOLO 模型 ↓ PC 端验证模型 ↓ 导出 ONNX ↓ INT8 量化 ↓ 设计卷积和池化加速器 ↓ 搭建 Vivado Block Design ↓ 编写 PS 端控制程序 ↓ 单层验证 ↓ 完整网络验证 ↓ 接入摄像头或视频 ↓ 优化性能和资源其中最关键的四步是:
- 模型量化;
- 卷积加速器设计;
- AXI DMA 数据搬运;
- PS 与 PL 协同工作。
三、目标器件资源评估
如果使用 Zynq-7015,例如:
xc7z015clg485-2它的 PL 资源比较有限:
| 资源 | 大致规模 |
|---|---|
| Logic Cells | 约 74K |
| DSP | 约 160 |
| BRAM | 约 3.3 Mb |
因此需要明确:
- 完整 YOLOv8n 640×640 基本不可行;
- YOLOv8n 320×320 也很困难;
- YOLOv3-tiny、YOLOv4-tiny 更适合;
- 必须进行 INT8 量化;
- 输入分辨率需要降低;
- 卷积并行度不能太高;
- 特征图和权重必须放在 DDR 中,不能全部放在 BRAM。
比较现实的目标是:
YOLOv3-tiny 或 YOLOv4-tiny + INT8 量化 + 160×160 或 192×192 输入 + 低并行度卷积加速器 + PS 负责预处理和后处理不要一开始就尝试:
YOLOv8n 640×640这个规模对小型 Zynq 器件来说太大。
四、推荐模型和输入分辨率
1. 模型选择
| 模型 | FPGA 部署难度 | 说明 |
|---|---|---|
| YOLOv3-tiny | 较低 | 网络较小,资料较多 |
| YOLOv4-tiny | 较低 | 比 YOLOv3-tiny 精度稍好 |
| YOLOv5n | 中等 | 需要较多优化 |
| YOLOv8n | 较高 | 网络结构较复杂 |
| YOLOv8s 及以上 | 很高 | 不建议小型 FPGA 使用 |
对于 Zynq-7015,优先选择:
YOLOv3-tiny YOLOv4-tiny2. 输入分辨率
建议从:
160×160 192×192开始,成功后可以尝试:
224×224 256×256分辨率越高,特征图越大,对 BRAM 和 DDR 带宽要求越高。
五、PS 与 PL 如何分工
Zynq 是 ARM PS + FPGA PL 的异构结构,适合软硬件协同设计。
推荐分工如下:
| 模块 | 负责内容 |
|---|---|
| PS / ARM | 图像预处理、权重加载、层调度、后处理 |
| PL / FPGA | 卷积、池化、上采样、激活函数 |
| DDR | 输入图片、特征图、权重、输出结果 |
| AXI DMA | PS 与 PL 之间搬运数据 |
| BRAM | 缓存当前卷积窗口、局部权重和行缓存 |
整体架构:
摄像头或图片 | v ARM PS 图像缩放、颜色转换、归一化、量化 | v DDR | v AXI DMA | v FPGA PL 卷积、池化、上采样、激活 | v DDR | v ARM PS YOLO 解码、置信度过滤、NMS、画框 | v HDMI 或显示设备六、第一步:在 PC 上完成模型
先在 PC 上完成训练、验证和推理。
使用 Ultralytics:
yolo train model=yolov8n.pt data=data.yaml epochs=50 imgsz=640 device=cpu yolo val model=runs/detect/train/weights/best.pt data=data.yaml device=cpu yolo predict model=runs/detect/train/weights/best.pt source=test.jpg device=cpu建议先确认:
- 模型能正常加载;
- 图片能正常检测;
- 检测框位置正确;
- 类别和置信度正确;
- 输出数据格式明确。
只有 PC 端模型正确,后续 FPGA 部署才有意义。
七、第二步:导出 ONNX
导出模型:
yolo export model=yolov8n.pt format=onnx opset=12生成:
yolov8n.onnxONNX 可以用于:
- ONNX Runtime;
- OpenCV DNN;
- TensorRT;
- 模型转换工具;
- 后续量化和分析。
但是 ONNX 不能直接下载到 FPGA 运行。
它只是表示:
模型结构 + 权重还需要硬件加速器来执行这些运算。
八、第三步:INT8 量化
FPGA 不适合大量浮点运算,通常需要将模型从 FP32 转换为 INT8。
流程:
FP32 模型 ↓ INT8 量化 ↓ 量化权重 ↓ 量化输入 ↓ 量化输出量化内容包括:
- 输入图片;
- 特征图;
- 卷积权重;
- 偏置;
- 中间累加结果;
- 激活函数输出。
常见量化方式:
- 训练后量化 PTQ;
- 量化感知训练 QAT。
YOLO 的检测头对量化比较敏感,建议分别比较:
- 量化前 mAP;
- 量化后 mAP;
- 置信度变化;
- 小目标检测效果;
- 检测框位置误差。
如果精度下降过多,可以使用:
- 分通道量化;
- 混合精度;
- QAT;
- 只量化卷积层;
- 保留部分层为 FP16。
九、第四步:设计卷积加速器
卷积是 YOLO 中最主要的计算部分。
1. HLS 方案
使用 Vivado HLS 编写:
- 3×3 卷积;
- 1×1 卷积;
- 行缓存;
- 权重缓存;
- 乘加阵列;
- ReLU / Leaky ReLU;
- 输出流合并。
核心优化包括:
数组分割 流水线 数据复用 双缓冲 并行乘加2. Verilog RTL 方案
直接设计:
- MAC 阵列;
- 行缓存;
- 权重缓存;
- 特征图缓存;
- AXI4-Stream 接口;
- 状态机控制。
RTL 控制更精细,但开发周期更长。
3. 常见加速器结构
输入特征图 ↓ 行缓存 Line Buffer ↓ 3×3 卷积窗口 ↓ 乘加阵列 MAC Array ↓ 累加器 ↓ 激活函数 ↓ 输出特征图为了减少 DDR 访问,需要:
- 权重复用;
- 输入特征复;
- 输出 Ping-Pong 缓存;
- 分块计算 Tiling;
- 多通道并行。
十、第五步:实现池化和上采样
最大池化
2×2 窗口 ↓ 取最大值 ↓ 输出特征图上采样
输入特征图 ↓ 2 倍放大 ↓ 输出特征图这些模块比卷积简单,但仍然需要:
- 行缓存;
- 地址控制;
- AXI Stream 握手;
- 输出缓存。
十一、第六步:搭建 Vivado Block Design
典型结构:
Processing System 7 | +-- AXI Interconnect | +-- AXI DMA | +-- AXI Stream Switch | +-- Convolution IP +-- Max Pool IP +-- Upsample IP +-- Activation IP | +-- DDR 控制器需要重点设置:
- PS7 的 DDR 参数;
- HP 端口;
- AXI DMA 读写通道;
- AXI Stream 数据位宽;
- 时钟和复位;
- 中断;
- 地址映射;
- 位流生成。
十二、第七步:编写 PS 端控制程序
PS 端负责控制所有硬件模块:
初始化系统 ↓ 加载权重 ↓ 加载输入图片 ↓ 启动 DMA ↓ 启动卷积 IP ↓ 等待完成 ↓ 启动池化 IP ↓ 等待完成 ↓ 执行所有网络层 ↓ 读取输出 ↓ 执行 YOLO 解码 ↓ 执行 NMS ↓ 输出检测框开发方式:
- 裸机 Bare-metal;
- Xilinx SDK;
- Vitis;
- PetaLinux;
- PYNQ。
对于 Zynq-7015,建议先从裸机开始,便于调试。
十三、第八步:验证与调试
建议按照以下顺序验证:
第一层:单层卷积 第二层:卷积 + 激活 第三层:卷积 + 池化 第四层:完整 YOLO 网络 第五层:单张图片 第六层:视频 第七层:摄像头实时检测每完成一层,都需要与 PC 端结果比较:
- 输入数据是否一致;
- 输出特征图是否一致;
- 量化误差是否可接受;
- 地址是否正确;
- DMA 是否完成;
- 中断是否触发。
十四、工具选择建议
| 工具 | 适用场景 |
|---|---|
| Vivado HLS | 自定义卷积加速器 |
| Verilog RTL | 精细控制资源和时序 |
| Vitis AI DPU | 更适合 Zynq UltraScale+ |
| FINN | 适合小型量化神经网络 |
| hls4ml | 适合小型网络 |
| PYNQ | 适合 Zynq-7000 快速验证 |
| ONNX Runtime | 用于 PC 端参考推理 |
对于 Zynq-7015,推荐路线是:
Vivado HLS + 自定义卷积加速器 + AXI DMA + PS 端控制程序Vitis AI DPU 通常更适合 Zynq UltraScale+,不建议直接用于 XC7Z015 这类小型 Zynq-7000 器件。
十五、优化方向
FPGA 部署 YOLO 时,性能通常受以下因素限制:
- DDR 带宽;
- BRAM 容量;
- DSP 数量;
- 卷积并行度;
- 权重加载速度;
- 特征图访问次数;
- 量化误差;
- 后处理速度。
常用优化方法:
- 使用 INT8;
- 降低输入分辨率;
- 减少网络通道数;
- 增加输入和权重复用;
- 使用 Ping-Pong 缓存;
- 使用流水线设计;
- 合并卷积、BN 和激活;
- 将特征图放在 DDR;
- 只把当前层权重送入 PL;
- PS 端使用高效 NMS。
十六、常见误区
误区一:ONNX 可以直接下载到 FPGA
错误。
ONNX 只是模型文件,FPGA 需要硬件加速器来执行计算。
误区二:FPGA 上可以直接运行 YOLOv8n 640×640
对于小型 Zynq 器件,通常不可行。
应优先选择:
YOLOv3-tiny YOLOv4-tiny 160×160 或 192×192 INT8误区三:所有计算都放在 FPGA 里
不建议。
推荐:
PS:预处理、调度、后处理 PL:卷积、池化、上采样 DDR:特征图和权重误区四:只关注卷积计算
数据搬运往往比计算更关键。
需要重点设计:
- AXI DMA;
- DDR 带宽;
- 行缓存;
- 权重复用;
- 双缓冲。
十七、最小可行开发路线
不要一开始就做完整 YOLO。
建议按以下顺序进行:
第一步:单层卷积
输入 160×160 ↓ 一层 3×3 卷积 ↓ INT8 输出第二步:卷积加激活
加入 ReLU 或 Leaky ReLU。
第三步:卷积加池化
验证行缓存和池化逻辑。
第四步:多层小网络
先实现一个简化 CNN。
第五步:完整 Tiny YOLO
实现 YOLOv3-tiny 或 YOLOv4-tiny。
第六步:接入图片
先测试单张图片。
第七步:接入摄像头或视频
最后再考虑实时视频检测。
十八、总结
FPGA 部署 YOLO 的核心流程是:
训练 YOLO ↓ 导出模型 ↓ INT8 量化 ↓ 设计卷积和池化加速器 ↓ AXI DMA 连接 PS 和 PL ↓ PS 负责调度和后处理 ↓ 得到检测结果对于 Zynq-7015:
- 不要直接部署 640×640 YOLOv8n;
- 优先选择 YOLOv3-tiny 或 YOLOv4-tiny;
- 输入分辨率建议 160×160 到 224×224;
- 使用 INT8 量化;
- PS 负责预处理和 NMS;
- PL 实现卷积、池化、上采样;
- 先完成单层卷积,再扩展到完整网络;
- 优先解决数据搬运和 DDR 带宽问题。
一句话总结:
PC 上运行 YOLO,是软件推理。 FPGA 上部署 YOLO,是把神经网络的每一层拆开,做成硬件电路。这就是 FPGA YOLO 部署真正要做的事情。