当前位置:首页 > 新闻资讯 > FPGA之家动态 >

CAFIR-10的CNN识别网络在FPGA上的实现——PYNQ-z2试用报告

时间:2024-07-29      来源:网络搜集 关于我们 0

摩尔吧宇杰老师开设的AI初阶&高阶课的上线,受到了网友的大力好评,再加上XILINX的大力支持,为我们提供的PYNQ板卡,协助于课程进行免费试用,给广大网友提供了学习的便利!

免费申请很难吗?

公众号回复:“PYNQ申请流程”!

仔细阅读!

里面有如何增加获得板卡的机会!

感谢XILINX的大力支持

PYNQ唯一社区官方微信,有最新消息的发布和项目分享交流,微信扫一扫即可关注,还可获取PYNQ入门资料集锦。

以下是来自摩尔吧用户——周志刚的试用报告,供广大网友参考学习!点击最下方阅读原文报名学习课程,即可赠送课程源码以及本项目PYNQ的试用源码

PYNQ-z2板卡基于Xilinx Zynq Soc,支持PYNQ框架。PYNQ不是Xilinx FPGA芯片的名字,而是一个开源框架的名字。这个框架的目标是使用Python语言方便地开发嵌入式应用,本次试用主要是卷积神经网络在FPGA上的实现过程。

一、开发板简单概述

PYNQ-Z2板卡板载了下载器,可以不用额外的下载器下载程序。包括的主要资源如下表所示:

关于PYNQ框架的详细资料(开始文档等)可以在以下链接中找到:

http://www.pynq.io/home.html

关于PYNQ-z2板卡的资料(电路原理图和使用手册等)可以在以下链接中找到:

http://www.tul.com.tw/ProductsPYNQ-Z2.html

二、项目简介和准备工作

1、项目内容

根据卷积神经网络的计算原理用C语言实现一个简单的卷积神经网络API框架,然后用API搭建模型,再此尝试了两种识别模型,手写数字识别(基于MNIST数据集)和自然物体识别(基于CIFAR-10数据集)。

这两个模型的实现过程相似,以MNIST为例,首先在PC机上训练MNIST网络,将训练好的权值保存到一个bin文件,将此bin文件放到SD上备用;用Vivado HLS高级综合工具设计卷积计算结构和池化计算结构,搭建FPGA硬件平台;在实际应用过程中,板卡初始化将训练好的权值从SD卡中读出,PC机将需要识别的图片通过串口发送给ARM,ARM调用卷积核池化计算结构完成计算将结算结果返回PC机。

2. 工具

一张SD卡,一条USB下载线。设置电源供应为USB供电,跳帽在拨码开关旁边;设置启动为JTAG启动,跳帽在HDMI OUT接口旁边。首次使用的时候,可能需要安装驱动,我是直接联机搜索安装的驱动,安装好后可以在设备管理器中看到端口号。

开发工具为VS2015、PyCharm Community Edition 2018.3、Vivado 2018.3、Vivado HLS 2018.3和Xilinx SDK 2018.3。

注意:如果是第一次安装vivado,建议安装18.3版本,我用Vivado HLS 18.2新建的工程的时候,一个窗口的next按钮不起作用,无法新建工程(不知是不是共性问题)

三、分解动作

1.点亮LED

点灯是学习使用一块板卡的敲门砖,其地位就像学习一门编程语言都要hello world一样,从51到ARM都是一路点灯过来的。LED的管脚绑定如下:

(1)新建工程

1

2

3

4

5

6

7

(2)添加设计文件

1

2

3

4

5

6

7

(3)编辑文件

(4)进行综合

(5)综合完成后,打开原理图,在原理图上打开端口,进行引脚绑定

(6)实现

(7)生成bit文件

(8)打开硬件管理器,自动连接到板卡

(9)下载bit文件,查看效果

下载完成后,可以看到LD0-3根据程序设定点亮,以上就是新建工程的一个简单过程。

2.建立PS最小系统

PS即为Processor System,为Zynq 7000中内嵌的ARM-A9硬核,为了测试系统是否运行,我们加入串口打印hello world。首先还是新建一个工程,然后添加文件,设计,综合,实现,生成。

(1)工程新建后,新建块设计 – Create Block Design

(2)添加PS

(3)对PS进行设置

勾选UART0,根据使用手册中UART0使用的管教说明,选择对应的管脚,管脚定义如下图所示:

设置时钟,这里是一个非常关键的注意点,板卡上的晶振是50MHz。

建立的是最小系统暂且不用DDR

点击Run Block Automation

连接时钟线

(4)验证建立的系统是否正确

(5)封装

(6)生成输出

(7)生成bit文件

(8)导出硬件平台设计

(9)打开SDK,进行软件设计

(10)在SDK中新建工程 File -> New -> Application Project,创建一个hello world样例工程

等待工程初始化完成后在操作

(11)可以打开helloworld.c文件进行简单修改,每隔1秒输出一个“hello world”,保存后自动编译,等待编译后,下载bit文件,将刚才在vivado中建立的硬件平台的bit文件下载到板卡上形成硬件平台共软件运行。

(12)运行软件,在hello工程上右键 -> Run as -> launch on Hardware(System Debugger),将软件的可执行文件下载到板卡上运行。软件下载完成后,可以在串口助手上看到输出。串口助手设置为波特率为115200,停止位1位,8位数据,无校验。

到此,就是一个PS系统的主要建立过程,与自己写verilog代码的过程其实相似,只不过一个是自己写功能,一个是通过工具直接设计一个功能,然后包上一个壳。大致的过程如下:

新建Vivado工程

新建Block Design

添加PS(ARM-A9核)

进行相应的设置,这一块具体问题具体分析,用到什么设置什么

生成warp

生成hardware products

生成bit文件

导出硬件平台设计

打开SDK,下载bit文件

根据自己需求改动代码,下载软件,运行。如果Block Design改动了就重新5-10

3.PS使用DDR

使用手册中关于DDR的说明→

**注意**:DDR这里一定要设置正确,不然在SDK中下载软件时会出现下面错误!

DDR设置→

4.使用SD卡

(1)关于SD接口的设置

(2)SDK中FATFS文件系统的加入

加入FATFS后重新编译(软件自动完成),可以在左侧的项目框架中看到加入的库和使用的头文件

加入FATFS后,不用在disk.c文件对SD卡驱动与FATFS连接,可以直接使用f_mount()函数挂载SD卡

FATFS详细的使用可以参考链接:

http://elm-chan.org/fsw/ff/00index_e.html

5.Vivado HLS 生成IP并在Vivado中添加IP

卷积神经网络的搭建需要卷积计算单元Conv_Core和池化计算单元Spooling_Core。这里以矩阵乘法为例使用HLS高级综合一个矩阵乘法IP,然后在Vivado中使用,过程是参考“双杰”的课程。

在SDK中新建工程,测试计算单元是否工作正常?有两个需要注意的点:

由于我使用了math函数,编译链接的时候需要指定math库,如果没有设置可能会出现虽然#include “math.h”,但是还是编译出错(undefined)

最初初始化的时候,禁止Caches,如果没有禁止Caches可能会出现硬件计算单元计算的结果都是0的情况。

设置math库:

禁止Caches:

现在总结一下使用HLS高级综合出的IP与PS搭建硬件系统和软件的过程如下:

(1)  新建Vivado工程

(2)  新建Block Design

(3)  添加PS(ARM-A9核)

(4)  进行相应的设置,这一块具体问题具体分析,用到什么设置什么

注意:

①  设的引脚要对应,电平标准要对应(PYNQ-z2的SD外设对应的电平标准为1.8V)

②  DDR配置要准确

③  时钟设置要准确(50MHz)

(5)  添加IP,连接

(6)  生成warp

(7)  生成hardware products

(8)  生成bit文件

(9)  导出硬件平台设计

(10)打开SDK进行软件设计

注意:

①  关闭cache,不然会出现IP_core计算出的结果都是0

②  如用到math函数,在工程属性中添加-lm,不然编译出错

(11)软件设计完成后,先下载bit文件,然后再run as。

如果硬件平台有改动(Block Design有更改),关闭SDK,重新(6)-(11)

7.利用PYNQ-z2的源码生成想要的系统

既然PYNQ-z2可以从SD卡启动,运行Linux系统,驱动板卡上的各种外设,那么我们完全可以直接利用PYNQ-z2的源码产生我们想要的系统。在PYNQ-z2的源码中有生成vivado项目的脚本,可以直接运行脚本就可以生成vivado工程,在此工程上裁剪,更改就可以将卷积核池化的IP过上去,生成最后的系统。需要注意的是运行这个脚本需要vivado 2018.2。

(1)  项目源码下载链接:

https://github.com/xilinx/pynq

(2)  综合HLS的IP

source PYNQ-master\PYNQ-master\boards\Pynq-Z2\base\build_base_ip.tcl

(3)  生成vivido工程

在执行脚本之前注释掉脚本第4617行,不生成bit文件(否则编译时间很长)

# launch_runs impl_1 -to_step write_bitstream -jobs 4

source PYNQ-master\PYNQ-master\boards\Pynq-Z2\base\base.tcl

(4)  用vivado 2018.3打开上面生成的工程,更新项目版本

(5)  打开工程后,设置IP路径为PYNQ-master\PYNQ-master\boards\ip

(6)  更新IP status

(7)  对Block Design根据自己需要进行修改,剩下的步骤就和以前一样了。

8.程序固化

PYNQ-z2的启动方式有 JTAG,QSPI,SD,前面一直都是使用JTAG方式。最开始的我试用了一下PYNQ-z2的python环境(https://pynq.readthedocs.io/en/latest/getting_started.html),那个就是从SD卡启动,所以我想试用一下让自己的项目在SD卡和QSPI启动来固化程序。

PYNQ-z2板卡上的启动方式本质上是zynq soc的启动方式,zynq从SD/QSPI启动需要BOOT.bin文件,这个文件包括了启动初始化文件fsbl.elf,应用工程的PL的FPGA编程文件.bit,应用工程的运行文件.elf。

生成BOOT.bin的过程如下:

(1)生成fsbl.elf

其实就是利用SDK自动的Zynq FSBL工程来生成fsbl.elf文件。

(2)生成BOOT.bin

可以在SDK Log窗口看到BOOT.bin已经生成了。

(3)放置BOOT.bin文件

① QSPI方式启动,将BOOT文件烧写进FLASH

首先确认当前启动方式为JTAG启动

烧写FLASH

关闭电源,设置QSPI启动

打开电源,可以看到DONE绿色LED灯亮起,表示启动完成,打开串口可以看到hello word打印,说明启动成功了。

②  SD启动

SD卡启动直接将BOOT.bin文件复制到SD上即可,设置SD卡启动方式

插入SD卡,打开电源,DONE绿色LED灯亮起,启动完成。

四、项目结果

1.在PC机上训练好模型

Mnist的loss曲线如下左图,最终准确率为98%

CIFAR-10的loss曲线如下右所示,最终准确率为60%

PC机上训练模型使用的是C语言,工具为VS2015。将训练好的模型的权值参数复制到SD卡备用。

2.在PYNQ-z2板卡上实现CNN

一开始没有对CNN计算过程中的循环进行展开,所以并没有起到什么加速作用,后来考虑到我的mnist模型和cifar-10模型每层的卷积核的尺寸都是5×5,卷积核尺寸固定,所以只展开了卷积核结算乘累加和的循环,相对比没有展开的情况要快。板卡上我试用拨码开关选择是识别SD中的测试文件,还是作为下位机来协同PC机上位机识别。

3.上位机

上位机用python + pyserial + opencv 完成,启动程序后,自动扫描串口,开始给板卡发送图片,接收识别结果,将是被结果显示在图片上。

以上就是我所有的试用过程,非常高兴能够试用Xilinx的PYNQ-z2这块板卡。

- END -

▼热门活动

ps:参加活动加小编QQ:3236328377咨询哦

欢迎加入微信群

加入与非社群,找到同道,一起切磋技艺、化解难题。

当然还有不定期的红包雨等着你哦!

与非网大大(小编)微信

注意: 

添加小编微信后,回复对应关键词+公司+岗位,方可被拉入社群,否则一律禁止入群,每人只可申请一个技术群

关键词:嵌入式、模拟、人工智能、RF、传感器、汽车电子、物联网、IC设计、EDA、PCB、开源硬件、树莓派。

点“阅读原文”立即报名获取全套源码!


注明:本内容来源网络,不用于商业使用,禁止转载,如有侵权,请来信到邮箱:429562386ⓐqq.com 或联系本站客服处理,感谢配合!

用户登陆

    未注册用户登录后会自动为您创建账号

提交留言