热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

matlab编写识别手写数字_使用PYNQ搭建手写数字识别工程小白级说明(完整版)

距离上次pynq的基础设置一文已经过去蛮久了,难得还有人催我更新233那么今天就再来把玩一番。今天要做的事情是用pynq来搭一个数字识别的工程。在正式开始介绍工程之前

7802c66d-4713-eb11-8da9-e4434bdf6706.png

距离上次pynq的基础设置一文已经过去蛮久了,难得还有人催我更新233那么今天就再来把玩一番。今天要做的事情是用pynq来搭一个数字识别的工程。

在正式开始介绍工程之前,让我花一点篇幅简单说下pynq的内容结构以及数字识别的原理。

1.pynq结构简介。

7e02c66d-4713-eb11-8da9-e4434bdf6706.png

pynq这个板子的结构大概是介个样子的,我们知道普通的zynq是只有PS(即ARM)和PL(即FPGA)的,PYNQ就比较厉害了,在PS和PL的基础上自带一个linux,linux里面装好了python3.6、jupyter以及Overlay,jupyter就是一个python的编写软件,Overlay就理解成一个自动化的软件好了,他的作用就是根据tcl文件是指示来把FPGA内部的电路连成我们要的样子,就是个自动烧录代码和连电路的工具。

我光这么说可能大家不好理解,下面我以一个简单的加法器来演示一下在pynq上是怎么建工程并且运行的。先让大家有个直观的感受。

8902c66d-4713-eb11-8da9-e4434bdf6706.png

以上是我在学校做演示时用的PPT,首先我们在HLS软件里面将一个c语言的加法器代码adder.cpp打包成ip核,然后在vivado中新建一个工程,加入zynq和我们的ip核,接着就是仿真->综合->实现->生成bitstream文件。这样的流程完成之后,我们所得到的vivado工程的文件夹会变得比较大,因为里面包含了很多中间文件,我们只要记住一件事,就是一个工程跑完generate bitstream之后,pynq需要的只有两个东西,一个是tcl文件,一个是bit文件。我们只要把他们从vivado工程里面取出来,然后把他们命名成同样的名字,然后丢到pynq里面随便什么位置就可以了,如下图所示。

8c02c66d-4713-eb11-8da9-e4434bdf6706.png

然后,我们可以在网页打开pynq的jupyter(具体过程上次的文章讲得很详细了,不记得就回去看看),在jupyter中输入

from pynq import Overlay

这话的意思相当于是把Overlay加载起来了,这就跟我们在电脑上点开一个软件一样的意思。

overlay=Overlay("我们在pynq中存放.bit文件的位置")

这话的意思就是让overlay这个软件按照.bit文件所描述的电路把FPGA连好,pynq在看到这话之后会自动在同一个路径下搜索tcl文件,tcl文件也找到了才能正确连电路,这也就是为什么我们需要把tcl和bit文件改成一样的名字的原因了。

9402c66d-4713-eb11-8da9-e4434bdf6706.png

2.图像识别简介。

9d02c66d-4713-eb11-8da9-e4434bdf6706.png

本文意不在介绍图像识别,这里只非常简单地过一下。

卷积神经网络做图像识别主要分成四步,就是上图最上方写的那四步(1.生成卷积核 2.卷积 3.池化 4.全连接),上图中下方的那四点是这四步实际上分别对应的数学运算本质,本质来讲并不是特别复杂的运算,就是运算量大而已。

需要指出的是:

第一步,第四步运算是需要一些事先确定的参数的,确定这些参数的方法是机器学习,笼统而言是用TensorFlow之类的软件写好python程序,再丢给程序一堆图片,然后找一部显卡性能比较好的电脑上或者服务器上跑这个程序,跑个几天几夜就可以得到我们第一步和第四步所需要的参数。

第二步,第三步运算是根据已经得到的参数来进行两种运算,这两步是需要我们在pynq上通过连PFGA电路的方式来实现的,最终要得到的效果是我们在电脑上弄一张图片,在上头写一个数字,用python脚本来指挥FPGA跑一遍运算电路,就可以得到对这个数字识别的结果。

下面是一个讲解卷积神经网络的视频,有兴趣就看看,可以说是讲得很清晰明了了。

https://www.youtube.com/watch?v=FmpDIaiMIeA​www.youtube.com

3.搭建工程的过程。

(一)

首先要指出一点,我这个练习是买了moore8上蔡宇杰大佬的教学视频和代码来弄的,代码并不是我原创的,我只是在这里点一下用pynq开发工程的流程,一者是为了自己记录一下学习过程,二来也算是自发给蔡大佬打个广告吧233,为了保护他人的劳动成果,具体代码我是不会展示出来的。

1首先是开一个空文件夹,把h,cpp,testbench文件放进去,然后在HLS中新建一个工程,在向导中往工程加入cpp文件和testbench文件,不要忘了在向导中将cpp文件设置成TOP文件。只要h文件也在这个文件夹里,h文件会自动添加进来。

a602c66d-4713-eb11-8da9-e4434bdf6706.png

af02c66d-4713-eb11-8da9-e4434bdf6706.png

另外要说一下,我HLS综合卷积和池化函数用的都是20ns的周期,在向导中用系统默认的10ns池化函数是会出现时序违例的。

c102c66d-4713-eb11-8da9-e4434bdf6706.png

d002c66d-4713-eb11-8da9-e4434bdf6706.png

d502c66d-4713-eb11-8da9-e4434bdf6706.png

d902c66d-4713-eb11-8da9-e4434bdf6706.png

2对于我们要用电路实现的函数,我们希望可以把他的输入输出参数挂载到axi总线上,axi总线首先是一个总线,就像uart,i2c,spi那样。不了解硬件的孩子就把这玩意当做软件的fifo好了。

挂载的方法是点击函数代码右方的directive,这上头就会显示出函数的各个参数,右击这些参数,在上面可以选择insert directive,然后在弹出的界面先选类型是interface,接着就可以指定我们要把一个参数指定成axi的master端还是slave端,master端就是说这个参数是往外传的,slave端就是说这个参数是从外面传进这个函数的。

e002c66d-4713-eb11-8da9-e4434bdf6706.png

e802c66d-4713-eb11-8da9-e4434bdf6706.png

f002c66d-4713-eb11-8da9-e4434bdf6706.png

f502c66d-4713-eb11-8da9-e4434bdf6706.png

3接着在HLS中点击solution的export rtl就可以导出ip核了。

0403c66d-4713-eb11-8da9-e4434bdf6706.png

导出了之后,将来在vivado中只要在添加ip核的地方把我们这个hls工程所在的文件夹添加进来,vivado就会自动识别这个我们的ip核了。如果是用zedboard板子来搭项目,那么懂得刚才那些步骤就可以了。但是对于pynq的开发我们还需要知道一点,就是将来为了写python脚本,我们需要知道HLS将c++函数转成verilog的电路描述后,各个函数的参数被分配的axi上的地址是多少,这个内容是在工程中的这个位置。

0e03c66d-4713-eb11-8da9-e4434bdf6706.png

现在只是提一下,将来用到会再详细说。

(二)搭建vivado工程

1.新建vivado工程。

1303c66d-4713-eb11-8da9-e4434bdf6706.png

在工程向导里面什么文件都不用加,直接一路ok到向导的最后一步,上一个文章我讲过怎么添加pynq的信息包到vivado里了,添加过后这里的最后一步就可以直接选择pynq板子。

1503c66d-4713-eb11-8da9-e4434bdf6706.png

1703c66d-4713-eb11-8da9-e4434bdf6706.png

1a03c66d-4713-eb11-8da9-e4434bdf6706.png

2.添加block design需要的组件

点击左边的create block design选项。

1e03c66d-4713-eb11-8da9-e4434bdf6706.png

可以看到右边一片空白的窗口,在窗口中点击+号,弹出的搜索框搜zynq processing system,这就是一个ARM核,添加进来就可以了。

2303c66d-4713-eb11-8da9-e4434bdf6706.png

2703c66d-4713-eb11-8da9-e4434bdf6706.png

添加了之后点击窗口的auto connection。由于之前在向导那里vivado已经知道pynq板子的信息了,所以这时候它就会自动把DDR3,IO口都连好,连好后窗口中是下面这个样子的。

2c03c66d-4713-eb11-8da9-e4434bdf6706.png

3003c66d-4713-eb11-8da9-e4434bdf6706.png

接下来把我们生产的ip核添加到工程里来

3803c66d-4713-eb11-8da9-e4434bdf6706.png

3c03c66d-4713-eb11-8da9-e4434bdf6706.png

3.设置PS端

由于我们在3.4中加入的arm核默认情况下是没有打开axi总线的master口的,所以我们需要手动打开master口。双击arm核,在如下界面这么选,就阔以了。

4103c66d-4713-eb11-8da9-e4434bdf6706.png

4703c66d-4713-eb11-8da9-e4434bdf6706.png

在这个界面下还要修改的是下面这个紫色框的位置,vivado跟hls一样,软件默认的时钟周期都是10ns,而在咱们这个例子中10ns是会时序违例的,所以要在这个地方将时序改成20ns,也就是紫框中的数字从原来是100改成50,意思是50Mhz,也就是20ns。当然这步在第一次做的时候肯定是不知道要改的,正常情况是做到后面综合或实现那一步,发现时序违例了才会回来这里改的。

4c03c66d-4713-eb11-8da9-e4434bdf6706.png

4.连接block design的组件

接下来是再次点击窗口冒出来的自动连线。

5303c66d-4713-eb11-8da9-e4434bdf6706.png

5803c66d-4713-eb11-8da9-e4434bdf6706.png

5.create HDL wrapper

刚才相当于是在草稿纸上把一个房子的草稿纸画好了,vivado表示这个草稿纸要进行再稍微未加工一下它才能看懂并往下进行施工,这一步就是create HDL wrapper,所幸这个步骤是可以自动化的,主要点击一个按钮就可以了,如下图所示。

6003c66d-4713-eb11-8da9-e4434bdf6706.png

6.生成bit和tcl文件

如果对代码和电路都比较有信心,那么在create HDL wrapper后就可以直接点击软件左下角的generate bitstream来生成最后的结果了。vivado就会从综合->实现->生成这样一路跑下来。

6903c66d-4713-eb11-8da9-e4434bdf6706.png

跑完我们就得到了bit文件,它在vivado工程中的位置如下所示。

6f03c66d-4713-eb11-8da9-e4434bdf6706.png

但别忘了,之前说过,pynq需要两个文件,bit和tcl文件,bit有了,tcl哪来呢?看下图。

7103c66d-4713-eb11-8da9-e4434bdf6706.png

tcl文件在vivado文件夹中的位置:

7803c66d-4713-eb11-8da9-e4434bdf6706.png

得到tcl和bit文件,咱们把这俩拷贝一下,名字改成一样的,先找个地方把它们放起来,以后会用到。比如像下面这样,以后写好python脚本之后把脚本,这俩文件一块丢到pynq的一个文件夹下就可以运行了。

7f03c66d-4713-eb11-8da9-e4434bdf6706.png

这个工程中硬件部分到上面就算是完成了,接下来还有写python脚本,以及在pynq的terminal中运行脚本的操作。

(三)python脚本的编写和运行

由于这个代码是蔡大大写的,我想了想,觉得讲别人的东西不好,简单提下原理吧,以后有空自己再搞个工程写了python脚本再来细说吧。

之前在HLS那一步不是说了我们需要用到hwh文件吗,它就是下图中的最左边的代码,它里面记录了中间那个HLS自动生成的硬件层面的c代码用到的各个参数所存放的地址,我们需要做的就是根据左边的地址文件,中间的c代码文件来写出右边的python脚本,具体内容就是在指定我们例化的函数的参数要从哪个地址上读或者存数据。

8703c66d-4713-eb11-8da9-e4434bdf6706.png

当然脚本里不止是翻译一下c代码这么简单,还有设置参数(),读取图像(用pynq自带的python cv库函数),烧录程序(这个部分怎么写我在前面自己加法器的例子里面讲了)

8c03c66d-4713-eb11-8da9-e4434bdf6706.png

9603c66d-4713-eb11-8da9-e4434bdf6706.png

最后运行的效果

9c03c66d-4713-eb11-8da9-e4434bdf6706.png


推荐阅读
  • 向QTextEdit拖放文件的方法及实现步骤
    本文介绍了在使用QTextEdit时如何实现拖放文件的功能,包括相关的方法和实现步骤。通过重写dragEnterEvent和dropEvent函数,并结合QMimeData和QUrl等类,可以轻松实现向QTextEdit拖放文件的功能。详细的代码实现和说明可以参考本文提供的示例代码。 ... [详细]
  • 在Oracle11g以前版本中的的DataGuard物理备用数据库,可以以只读的方式打开数据库,但此时MediaRecovery利用日志进行数据同步的过 ... [详细]
  • 微软头条实习生分享深度学习自学指南
    本文介绍了一位微软头条实习生自学深度学习的经验分享,包括学习资源推荐、重要基础知识的学习要点等。作者强调了学好Python和数学基础的重要性,并提供了一些建议。 ... [详细]
  • 本文介绍了在开发Android新闻App时,搭建本地服务器的步骤。通过使用XAMPP软件,可以一键式搭建起开发环境,包括Apache、MySQL、PHP、PERL。在本地服务器上新建数据库和表,并设置相应的属性。最后,给出了创建new表的SQL语句。这个教程适合初学者参考。 ... [详细]
  • 本文介绍了数据库的存储结构及其重要性,强调了关系数据库范例中将逻辑存储与物理存储分开的必要性。通过逻辑结构和物理结构的分离,可以实现对物理存储的重新组织和数据库的迁移,而应用程序不会察觉到任何更改。文章还展示了Oracle数据库的逻辑结构和物理结构,并介绍了表空间的概念和作用。 ... [详细]
  • Java序列化对象传给PHP的方法及原理解析
    本文介绍了Java序列化对象传给PHP的方法及原理,包括Java对象传递的方式、序列化的方式、PHP中的序列化用法介绍、Java是否能反序列化PHP的数据、Java序列化的原理以及解决Java序列化中的问题。同时还解释了序列化的概念和作用,以及代码执行序列化所需要的权限。最后指出,序列化会将对象实例的所有字段都进行序列化,使得数据能够被表示为实例的序列化数据,但只有能够解释该格式的代码才能够确定数据的内容。 ... [详细]
  • 关于我们EMQ是一家全球领先的开源物联网基础设施软件供应商,服务新产业周期的IoT&5G、边缘计算与云计算市场,交付全球领先的开源物联网消息服务器和流处理数据 ... [详细]
  • 怎么在PHP项目中实现一个HTTP断点续传功能发布时间:2021-01-1916:26:06来源:亿速云阅读:96作者:Le ... [详细]
  • 解决nginx启动报错epoll_wait() reported that client prematurely closed connection的方法
    本文介绍了解决nginx启动报错epoll_wait() reported that client prematurely closed connection的方法,包括检查location配置是否正确、pass_proxy是否需要加“/”等。同时,还介绍了修改nginx的error.log日志级别为debug,以便查看详细日志信息。 ... [详细]
  • mac php错误日志配置方法及错误级别修改
    本文介绍了在mac环境下配置php错误日志的方法,包括修改php.ini文件和httpd.conf文件的操作步骤。同时还介绍了如何修改错误级别,以及相应的错误级别参考链接。 ... [详细]
  • 本文介绍了Swing组件的用法,重点讲解了图标接口的定义和创建方法。图标接口用来将图标与各种组件相关联,可以是简单的绘画或使用磁盘上的GIF格式图像。文章详细介绍了图标接口的属性和绘制方法,并给出了一个菱形图标的实现示例。该示例可以配置图标的尺寸、颜色和填充状态。 ... [详细]
  • 基于Socket的多个客户端之间的聊天功能实现方法
    本文介绍了基于Socket的多个客户端之间实现聊天功能的方法,包括服务器端的实现和客户端的实现。服务器端通过每个用户的输出流向特定用户发送消息,而客户端通过输入流接收消息。同时,还介绍了相关的实体类和Socket的基本概念。 ... [详细]
  • 本文介绍了Android中的assets目录和raw目录的共同点和区别,包括获取资源的方法、目录结构的限制以及列出资源的能力。同时,还解释了raw目录中资源文件生成的ID,并说明了这些目录的使用方法。 ... [详细]
  • 本文介绍了在Python张量流中使用make_merged_spec()方法合并设备规格对象的方法和语法,以及参数和返回值的说明,并提供了一个示例代码。 ... [详细]
  • 本文介绍了在Cpp中将字符串形式的数值转换为int或float等数值类型的方法,主要使用了strtol、strtod和strtoul函数。这些函数可以将以null结尾的字符串转换为long int、double或unsigned long类型的数值,且支持任意进制的字符串转换。相比之下,atoi函数只能转换十进制数值且没有错误返回。 ... [详细]
author-avatar
a怪周璇_981
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有