FPGA 部署 YOLO 完整指南:从模型量化到 Zynq PS+PL 硬件加速

关键词: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=cpu

PyTorch 会自动完成所有计算。

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 端控制程序
      ↓
单层验证
      ↓
完整网络验证
      ↓
接入摄像头或视频
      ↓
优化性能和资源

其中最关键的四步是:

  1. 模型量化;
  2. 卷积加速器设计;
  3. AXI DMA 数据搬运;
  4. 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-tiny

2. 输入分辨率

建议从:

复制代码
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.onnx

ONNX 可以用于:

  • ONNX Runtime;
  • OpenCV DNN;
  • TensorRT;
  • 模型转换工具;
  • 后续量化和分析。

但是 ONNX 不能直接下载到 FPGA 运行。

它只是表示:

复制代码
模型结构 + 权重

还需要硬件加速器来执行这些运算。


八、第三步:INT8 量化

FPGA 不适合大量浮点运算,通常需要将模型从 FP32 转换为 INT8。

流程:

复制代码
FP32 模型
    ↓
INT8 量化
    ↓
量化权重
    ↓
量化输入
    ↓
量化输出

量化内容包括:

  • 输入图片;
  • 特征图;
  • 卷积权重;
  • 偏置;
  • 中间累加结果;
  • 激活函数输出。

常见量化方式:

  1. 训练后量化 PTQ;
  2. 量化感知训练 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 数量;
  • 卷积并行度;
  • 权重加载速度;
  • 特征图访问次数;
  • 量化误差;
  • 后处理速度。

常用优化方法:

  1. 使用 INT8;
  2. 降低输入分辨率;
  3. 减少网络通道数;
  4. 增加输入和权重复用;
  5. 使用 Ping-Pong 缓存;
  6. 使用流水线设计;
  7. 合并卷积、BN 和激活;
  8. 将特征图放在 DDR;
  9. 只把当前层权重送入 PL;
  10. 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 部署真正要做的事情。

相关推荐
dadaobusi6 小时前
学习:chiesel,scala
学习·fpga开发·scala
FPGA小徐6 小时前
Ubuntu 22.04 安装 Miniconda、PyTorch 与 YOLOv8 并完成 CPU 推理
pytorch·yolo·ubuntu
爱吃汽的小橘7 小时前
异步FIFO核心揭秘:格雷码与指针同步
fpga开发
YOLO数据集集合7 小时前
桥梁病害检测数据集 | 桥梁病害 结构健康监测 裂缝检测 钢筋外露9134期
yolo·目标检测·外墙裂缝·建筑病害·桥梁病害·桥梁缺陷
璞致电子7 小时前
基于 P201Pro | 接收端基础知识——Costas环锁定后为何仍会错?DQPSK与前导码相位校正(6)
经验分享·fpga开发·ad9361·软件无线电·sdr·qpsk·pzsdr
zy_destiny18 小时前
深度学习实战-基于YOLOv8的玉米雄穗目标检测:从数据集下载到训练部署全流程实录
yolo·目标检测·机器学习
YOLO数据集集合1 天前
外墙裂缝目标检测YOLO数据集:6,296张图像助力建筑病害智能识别| 外墙裂缝检测 YOLO数据集 建筑健康监测 无人机巡检 目标检测8030期
yolo·目标检测·无人机·建筑·外墙裂缝·建筑病害
璞致电子1 天前
基于 AD9361 (PZSDR‑P201Pro) 软件无线电实战综述:从板卡选型、硬件平台升级到 GNU Radio QPSK 完整收发链路
经验分享·嵌入式硬件·fpga开发·软件无线电·sdr·璞致电子
richard_yuu1 天前
Hopfield 网络:联想记忆的「鼻祖」,为什么它能「回忆」?
深度学习·神经网络·yolo·机器学习