# 基于ZYNQ的卷积神经网络硬件加速器 **Repository Path**: Bite__the__dust/Convolutional-Neural-Network-Hardware-Accelerator-Based-on-ZYNQ ## Basic Information - **Project Name**: 基于ZYNQ的卷积神经网络硬件加速器 - **Description**: 基于ZYNQ实现了软硬协同的硬件加速器系统,实现对于LeNet-5卷积神经网络识别MNIST手写集的加速。PL端实现卷积层、池化层、全连接层的并行加速,PS端实现验证测试流程的控制。两者通过AXI总线连接,实现控制信识别结果的传递。 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 19 - **Forks**: 5 - **Created**: 2022-06-02 - **Last Updated**: 2025-05-21 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 简介 基于ZYNQ实现了软硬协同的硬件加速器系统,实现对于LeNet-5卷积神经网络识别MNIST手写集的加速。 PL端实现硬件加速器(包括卷积层、池化层、全连接层的实现,缓存区,共享乘累加器)。PS端实现验证测试流程的控制(非常简单的逻辑,就是发送start信号,等待done拉高,读出识别结果,重复200次后计算准确率和耗时。真正软硬协同的PS端应该连上摄像头,然后把摄像头的数据发送过去识别。但因为是毕设,所以做的不够完善)。 最终在开发板上的效果是200张图片,准确率96.5%,耗时47ms。 # 文件构成 ## Lenet5 为卷积神经网络的训练测试和量化工程,包含三个子文件 * code 使用了jupyter notebook开发环境。train文件用于训练和测试卷积神经网络,quantize文件用于量化神经网络,测试量化后效果并导出参数。model文件定义了Lenet5神经网络类,module文件定义了各层的量化实现过程,function文件仅有一个伪量化函数。代码参考了知乎专栏https://zhuanlan.zhihu.com/p/149659607。old_version文件夹中存放了量化时仍使用zero point的老版本。 * data 存放了训练集和测试集。 * model 存放了训练完的模型数据,需要导入硬件加速器的参数coe文件,200张测试图片的标签和在电脑上的识别结果。 ## LeNet_RTL 为硬件加速器PL端的vivado工程。包括综合、仿真、实现、上机全过程。设计参考了童耀宗的论文,同时也是在他的工程基础上修改得来的。 ## custom_ip 为硬件加速器封装成带AXI总线的IP核工程。 ## LeNet5_PSPL 最终的硬件加速器系统工程,包括PS端和PL端。实现了block design和PS端的嵌入式代码编写和运行测试。 # 运行流程 1. 在Lenet5文件夹中训练并测试卷积神经网络。 2. 量化神经网络并测试效果,最后导出参数。 3. 在custom_ip工程待封装的硬件加速器各BROM IP核中加载刚生成的coe文件。 4. 综合custom_ip中的工程,并导出IP核。 5. 在LeNet5_PSPL工程中导入刚生成的IP核,综合、实现、导出bit流。 6. 运行Xilinx SDK,导入测试图片的标签数据,进行测试。 # 注意事项 vivado版本为2017,因为vivado各年份版本之间兼容性过差,所以不是2017版本的可能需要自己重新搭建工程。重新搭建工程其实最大的工作量也就是生成IP核。因此再提供一些便于生成各IP核的信息。如下图分别为权重存储器和缓存区存储器IP的位宽和深度。 | **层级** | **存储空间(位宽*深度)** | | :------------: | :-----------------------: | | **C1卷积层** | 48*25 | | **C3卷积层** | 768*25 | | **F5全连接层** | 960*400 | | **F6全连接层** | 672*120 | | **F7全连接层** | 80*84 | | **层级** | **存储空间(位宽***长***宽)** | | :------------: | :----------------------------: | | **C1卷积层** | 16\*32\*32 | | **S2池化层** | 96\*28\*28 | | **C3卷积层** | 96\*14\*14 | | **S4池化层** | 256\*10\*10 | | **F5全连接层** | 256\*5\*5 | 生成存储器IP的时候要注意,一定要去掉**Primitives Output Register**这个选项,因为所有的存储器都是在一个时钟周期读出来的。计算用的IP核也都是一样,不要增加内部流水线,所有计算都是在一个时钟周期内完成的。 LeNet_RTL工程中的上机测试有一点点问题,因为使用了按钮去生成start信号,而start信号保持的时间不应该长于整个识别周期。所以使用按钮和LED灯测试PL端的时候存在逻辑问题。使用寄存器去读取上升沿也还是不行,可能是因为抖动。此外,LeNet_RTL工程中的复位和start信号因为要和按钮绑定,所以和其他地方不一样,有取反的过程,从信号前缀的button中就可以看出。需要注意。LeNet_RTL工程的存在主要是方便看懂硬件加速器Verilog代码,完成仿真测试。