从FPGA到AI:单通道卷积起步,打通CNN算法→PyTorch训练→硬件推理全链路教程

AI可以不停的输出,但是人的精力是有限的,人要做的是有条件的限制AI的输出,指示AI输出自己想要的内容。本文是多次修改条件,AI生成。AI就是一个只管输出不负责的莽撞汉子。最终还是要看人的调教,至少现在是这个阶段。
我已经完成第一篇,正在学习第二篇。

前言

本教程面向已掌握FPGA基础开发、熟悉AXI总线与DMA架构、希望入门FPGA AI加速的开发者。我们以已跑通的单通道3×3卷积 + 2×2最大池化工程为起点,不追求极致性能优化,先建立「CNN算法原理 ↔ PyTorch软件训练 ↔ FPGA硬件实现」的完整架构认知,逐步补全CNN标准组件,最终打通端到端全链路。

教程全程遵循「最小增量迭代」原则:每一步只修改少量代码,完成后立刻与软件结果对齐验证,确保每一步都可复现、可验证,避免陷入“一改全错”的调试困境。


目录

第一篇 基础认知篇:先建立CNN完整架构

第1章 CNN全景链路与核心概念
1.1 特征提取流水线:CNN的整体工作逻辑
1.2 核心名词速览:卷积、权重、偏置、激活、池化、特征图
1.3 三者对应关系:CNN算法 ↔ PyTorch接口 ↔ FPGA硬件实现

第二篇 基础实践篇:补齐CNN最核心标准单元

第2章 新增ReLU激活层——给网络加入非线性
第3章 Padding填充:控制特征图尺寸,保留边缘信息
第4章 Stride步长:控制计算密度,实现特征降采样

第三篇 核心进阶篇:从单通道到多通道,对应真实CNN结构

第5章 扩展多输出通道:理解多卷积核与多特征图
第6章 池化算子扩展:最大池化与平均池化
第7章 可配置算子设计:通过寄存器切换不同卷积核

第四篇 全链路闭环篇:从单个算子到完整网络

第8章 两级卷积级联:体验多层特征提取
第9章 端到端全流程:PyTorch训练 → 权重导出 → FPGA推理
第10章 全流程总结:从算法到硬件的完整落地路径


第一篇 基础认知篇:先建立CNN完整架构

第1章 CNN全景链路与核心概念

1.1 特征提取流水线:CNN的整体工作逻辑

卷积神经网络(CNN)本质是一套分层特征提取流水线:输入原始图像,经过多层算子堆叠,逐步提取从简单到复杂的特征(边缘→纹理→形状→物体),最终输出分类/检测结果。

一条标准CNN的完整数据流向:

原始输入图像 → 卷积层(Conv) → 批归一化层(BN) → 激活层(ReLU) → 池化层(Pooling)
                          ↓
                    (重复堆叠N次)
                          ↓
                全连接层(FC) → 最终输出结果

我们当前FPGA工程已实现的,是这条链路里的最小核心单元:单通道卷积 + 最大池化。所有大型CNN网络,本质都是这个单元的多次堆叠 + 通道数扩展。

1.2 核心名词速览
名词核心功能关键参数
特征图(Feature Map)每一层的输入/输出数据,格式为「通道数C × 高度H × 宽度W」C、H、W
卷积核(Kernel/Filter)也叫权重,在特征图上滑动计算,提取特定特征核大小(如3×3)、权重数值
偏置(Bias)每个输出通道对应一个偏移值,卷积计算完成后叠加单通道单数值
填充(Padding)特征图边缘补0,控制输出尺寸,避免边缘信息丢失补0圈数
步长(Stride)卷积核每次滑动的像素数,步长越大输出越小滑动步长
激活层(Activation)加入非线性变换,让网络可以拟合复杂函数ReLU、Sigmoid等
池化层(Pooling)降采样缩小特征图尺寸,减少计算量,保留核心特征最大池化、平均池化
全连接层(FC)二维特征展平为一维,映射到最终分类结果输入维度、输出类别数
1.3 三者对应关系:算法↔软件↔硬件

核心逻辑:PyTorch负责训练出权重参数,FPGA负责加载权重、用硬件电路完成推理计算

CNN算法概念PyTorch对应接口FPGA硬件实现
滑动卷积计算torch.nn.Conv2d()行缓存 + 3×3窗口生成 + 乘加树
卷积权重conv.weight权重寄存器组 + DSP乘法器
卷积偏置conv.bias偏置寄存器 + 加法器
ReLU激活torch.nn.ReLU()单路判断逻辑:负数置0,正数直通
最大池化torch.nn.MaxPool2d()窗口寄存器 + 数值比较器
特征图数据Tensor张量AXI-Stream高速数据流 + 片内缓存

补充说明:批归一化(BN)层在推理阶段一般会提前融合进卷积层的权重和偏置中,不需要单独做硬件电路,属于部署优化的常规操作。


第二篇 基础实践篇:补齐CNN最核心标准单元

第2章 新增ReLU激活层

算法原理

ReLU(Rectified Linear Unit)是CNN的标配激活函数,公式为:
y=max(0,x) y = max(0, x) y=max(0,x)

  • 正数原样输出,负数直接置0
  • 计算成本极低,硬件实现开销极小
  • 作用:给线性的卷积计算加入非线性,让多层网络才有意义
硬件实现(单通道版本增量修改)

在卷积输出、池化输入之间,增加一级ReLU处理逻辑,修改量仅几行代码:

// 卷积计算结果先经过ReLU,再进入后续池化
wire signed [15:0] conv_out;
reg signed [15:0] relu_out;

always @(posedge clk or negedge rst_n) begin
    if(!rst_n) begin
        relu_out <= 16'd0;
    end else begin
        // ReLU核心逻辑:小于0则输出0,否则直通
        relu_out <= (conv_out < $signed(16'd0)) ? $signed(16'd0) : conv_out;
    end
end
PyTorch验证对照
import torch
import torch.nn as nn

# 搭建和硬件完全对应的极简网络
model = nn.Sequential(
    nn.Conv2d(in_channels=1, out_channels=1, kernel_size=3, stride=1, padding=0),
    nn.ReLU(),
    nn.MaxPool2d(kernel_size=2, stride=2)
)

# 写入和FPGA完全相同的恒等算子权重
with torch.no_grad():
    model[0].weight.fill_(0)
    model[0].weight[0, 0, 1, 1] = 1.0  # 中心位置权重为1
    model[0].bias.fill_(0)

# 输入测试数据,得到软件基准结果
input_img = torch.zeros(1, 1, 128, 128)  # 全零输入
output_pytorch = model(input_img)
实践步骤
  1. 在现有卷积模块中增加ReLU逻辑,输出接入池化模块
  2. 重新打包IP、升级实例、清空综合缓存、生成比特流
  3. 运行测试程序,对比FPGA输出与PyTorch输出
验收标准
  • 全零输入下,输出全为0
  • 随机输入下,逐像素与PyTorch结果完全一致
  • 连续多帧传输无超时、无错位

第3章 Padding填充:控制特征图尺寸

算法原理
  • 问题:3×3卷积在特征图边缘滑动时,边缘像素计算次数少,输出尺寸会缩小(128×128输入→126×126输出)
  • 解决:在特征图四周补0(Padding),让边缘像素也能参与完整计算,控制输出尺寸
  • 常用padding=1搭配3×3卷积,可实现输出尺寸与输入完全一致

输出尺寸计算公式:
输出尺寸=输入尺寸−核大小+2×PaddingStride+1 输出尺寸 = \frac{输入尺寸 - 核大小 + 2×Padding}{Stride} + 1 输出尺寸=Stride输入尺寸核大小+2×Padding+1

硬件实现要点
  • 输入数据有效时,判断像素坐标,边缘位置补0
  • 行缓存读写逻辑配合调整,确保窗口生成正确
验收标准
  • 128×128输入 + padding=1 + 3×3卷积,输出尺寸为128×128
  • 结果与PyTorch padding=1 配置完全对齐

第4章 Stride步长:控制计算密度

算法原理
  • 步长(Stride):卷积核每次滑动的像素数
  • stride=1:逐像素滑动,计算最密集,输出尺寸变化小
  • stride=2:隔一个像素计算一次,输出尺寸减半,计算量减为1/4
  • 作用:降采样,减少后续计算量,扩大感受野
硬件实现要点
  • 输出有效信号间隔输出,每stride个输入周期产生一个有效输出
  • 行列计数器配合步长做跳变
验收标准
  • stride=2时,输出尺寸为输入的一半
  • 结果与PyTorch stride=2 配置完全对齐

第三篇 核心进阶篇:从单通道到多通道

第5章 扩展多输出通道

算法原理
  • 输出通道(Output Channel):一个卷积层包含多个卷积核,每个卷积核提取一种特征,输出一张特征图
  • 比如输出通道=2,就是同时用2个不同的卷积核计算,输出2张特征图
  • 这是真实CNN网络的基础结构:通道数逐层增加,尺寸逐层减小
硬件实现要点
  • 复制一套乘加计算单元,共用同一套行缓存和窗口生成逻辑
  • 两套计算单元分别加载不同的权重和偏置
  • 输出按通道顺序拼接,通过AXI-Stream串行输出
  • 调整TLAST计数,适配总数据长度(单帧字节数 × 通道数)
验收标准
  • 输出数据按通道0、通道1顺序排列
  • 两个通道的结果分别与PyTorch对应通道结果完全一致
  • 帧长度正确,DMA接收无溢出、无超时

第6章 池化算子扩展:最大池化与平均池化

算法原理
  • 最大池化:取窗口内最大值,保留最显著的特征,最常用
  • 平均池化:取窗口内平均值,特征更平滑
  • 两种池化硬件实现逻辑不同,对应不同的算法场景
硬件实现要点
  • 增加1位控制寄存器,通过软件配置选择池化模式
  • 平均池化需要增加加法器和移位器(除以4等价于右移2位)
验收标准
  • 两种模式下,结果分别与PyTorch的MaxPool2d、AvgPool2d对齐

第7章 可配置算子设计

算法原理
  • 卷积的功能完全由权重决定,权重不同,提取的特征就不同
  • 常见3×3算子:恒等、Sobel边缘检测、高斯模糊、浮雕、锐化
  • 可配置设计:权重通过寄存器写入,不需要修改硬件代码
实践内容
  1. 依次配置不同的卷积核权重
  2. 输入测试图像,观察输出效果
  3. 与OpenCV/PyTorch对应算子的结果做对比
验收标准
  • 切换不同权重后,输出效果符合算子预期
  • 数值结果与软件计算一致

第四篇 全链路闭环篇:从单个算子到完整网络

第8章 两级卷积级联:体验多层特征提取

算法原理
  • CNN的核心思想就是多层堆叠:浅层提取低级特征(边缘),深层提取高级特征(形状、物体)
  • 两级卷积+激活+池化级联,就是一个最简的浅层CNN网络
硬件实现要点
  • 两套「卷积+ReLU+池化」IP通过AXI-Stream无缝级联
  • 前一级的m_axis输出直接连接后一级的s_axis输入
  • 两级分别配置各自的权重和偏置
  • 流控反压正常:后一级暂停时,前一级自动暂停,数据不丢失
验收标准
  • 端到端输出与PyTorch两层网络结果完全一致
  • 连续传输无丢数、无错位

第9章 端到端全流程:PyTorch训练 → 权重导出 → FPGA推理

全流程步骤
  1. 训练阶段:用PyTorch搭建一个小型CNN网络(比如2层卷积+2层池化),在MNIST数据集上训练手写数字分类
  2. 参数导出:训练完成后,导出每一层的权重、偏置参数,做定点量化(8bit)
  3. 参数部署:把量化后的权重、偏置,通过AXI-Lite依次写入FPGA对应层的寄存器
  4. 硬件推理:输入手写数字图片,FPGA完成端到端计算,输出分类结果
  5. 结果校验:对比FPGA推理结果与PyTorch推理结果的准确率差异
验收标准
  • 完整走通「训练→导出→部署→推理」全流程
  • 同一输入图片,FPGA推理结果与PyTorch推理结果类别一致
  • 理解定点量化对精度的影响

第10章 全流程总结

完成以上所有章节后,你将掌握完整的FPGA AI加速知识架构:

  1. 算法层:理解CNN各核心算子的作用、参数、相互关系
  2. 软件层:掌握PyTorch搭建网络、训练、导出参数的基本流程
  3. 硬件层:掌握各算子的RTL实现、接口设计、模块级联方法
  4. 系统层:打通「参数配置→DMA数据搬运→硬件计算→结果回传」的软硬件协同全链路

后续可以根据需求,再深入性能优化(更高并行度、脉动阵列、量化优化、带宽优化),此时已有完整架构认知,优化方向会非常清晰。


后记

本教程遵循「先建立整体框架,再逐步填充细节」的学习思路,避免一开始就陷入底层优化的细节中。每一章都有明确的算法原理、硬件修改、验证方法和验收标准,可独立完成,也可按顺序逐步推进。

建议每完成一章,都做一次记录和总结,梳理清楚「这一步解决了什么问题、对应CNN里的什么概念、软硬件是怎么对应的」,逐步构建起完整的知识体系。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值