记录LeNet的硬件加速器设计(二)

笔者的所有代码已经更新至Gitee,vivado工程需要自己创建。

LeNet code:LeNet4FPGA: 包含剪枝量化

Verilog code:FPGA4LeNet: Lenet的硬件实现。更新中......

上一篇博客已经分析了整体设计思路和参考的python代码,这篇博客会对网络的输入以及第一层进行分析。

卷积核模块

首先分析进行矩阵卷积的模块,本文由于是流水线设计,因此没有把整体的乘加计算拆分到PE单元进行设计。LeNet的卷积核大小都是5x5,因此我们直接设计一个模块完成25个数对应相乘再相加。对应代码里的conv5x5.v,这个模块较简单。

卷积窗移动模块

其次有了卷积模块,还需要一个使卷积模块源源不断工作的给他提供数据的模块,即卷积窗口移动模块。对应代码line_loader.v。

对应的权重数据直接跟随卷积窗口移动模块传入卷积核以供计算,设计思路为利用一个5行的缓冲器存储当前连续五行的像素信息(在后面的层中称特征信息),这五行以低位存储最左边的像素,高位存储右边的像素。每进入一次卷积核,行缓冲器整体右移一个像素位宽(挤出已用的像素)。

状态机

具体实现:使用状态机将模块分为以下状态:

在IDLE状态时,随时准备响应输入。由于进入第一行时,不足够进行计算,因此设计了LOAD_INIT_LINE状态来等待足够信息。等到足够进行计算时,进入BEGIN_CALC,此时卷积窗口移动模块会把数据送入卷积核进行计算,并得到输出,在经过添加BIAS和缩放移位后输出至下一层。BEGIN_CALC会持续若干次,直到一行即将算完,此时状态会转移至LOAD_NEW_LINE,以加载新的行进入。然后状态会再次转移至BEGIN_CALC,等所有计算都完成后,状态来到CALC_END,这里预留了这个状态,暂时没有做特殊设计。CALC_END会把当前的计算收尾后恢复至IDLE等待下一帧信息。

无缝计算

细心的朋友们应该发现了,计算至行尾会加载新行,这样是否会增加计算时间呢?即计算时间+加载时间=整体时间?在设计这里的时候,笔者选择了预加载一行,即用6个line_buffer来存储行,用另外5个line_buffer来送数和移位。当加载新行时,实际上是加载到了6个line_buffer中较老的那一行。通过不断滚动这个较老一行来实现不会错误更新。

在输入至卷积窗的5个line_buffer处也进行了类似的设计

这样即可无缝完成计算了。

仿真波形图如下

如波形图,计算从开始后没有空拍。

下一篇博客会分析平均池化层设计和ReLU设计。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值