热门标签 | 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


推荐阅读
  • Python 工具推荐 | PyHubWeekly 第二十一期:提升命令行体验的五大工具
    本期 PyHubWeekly 为大家精选了 GitHub 上五个优秀的 Python 工具,涵盖金融数据可视化、终端美化、国际化支持、图像增强和远程 Shell 环境配置。欢迎关注并参与项目。 ... [详细]
  • Coursera ML 机器学习
    2019独角兽企业重金招聘Python工程师标准线性回归算法计算过程CostFunction梯度下降算法多变量回归![选择特征](https:static.oschina.n ... [详细]
  • 基于Node.js、Express、MongoDB和Socket.io的实时聊天应用开发
    本文详细介绍了使用Node.js、Express、MongoDB和Socket.io构建的实时聊天应用程序。涵盖项目结构、技术栈选择及关键依赖项的配置。 ... [详细]
  • 本文介绍 Java 中如何使用 Year 类的 atMonth 方法将年份和月份组合成 YearMonth 对象,并提供代码示例。 ... [详细]
  • yikesnews第11期:微软Office两个0day和一个提权0day
    点击阅读原文可点击链接根据法国大选被黑客干扰,发送了带漏洞的文档Trumps_Attack_on_Syria_English.docx而此漏洞与ESET&FireEy ... [详细]
  • 为了解决不同服务器间共享图片的需求,我们最初考虑建立一个FTP图片服务器。然而,考虑到项目是一个简单的CMS系统,为了简化流程,团队决定探索七牛云存储的解决方案。本文将详细介绍使用七牛云存储的过程和心得。 ... [详细]
  • Logback使用小结
    1一定要使用slf4j的jar包,不要使用apachecommons的jar。否则滚动生成文件不生效,不滚动的时候却生效~~importorg.slf ... [详细]
  • 本文档汇总了Python编程的基础与高级面试题目,涵盖语言特性、数据结构、算法以及Web开发等多个方面,旨在帮助开发者全面掌握Python核心知识。 ... [详细]
  • PC时代的传奇人物
    回顾过去几十年,个人电脑(PC)的发展历程犹如一部英雄史诗。每一位杰出人物都在这一领域留下了不可磨灭的印记,他们的贡献不仅推动了技术的进步,也深刻影响了现代社会的发展。 ... [详细]
  • 1、字符型常量字符型常量指单个字符,是用一对单引号及其所括起来的字符表示。例如:‘A’、‘a’、‘0’、’$‘等都是字符型常量。C语言的字符使用的就是 ... [详细]
  • 嵌入式开发环境搭建与文件传输指南
    本文详细介绍了如何为嵌入式应用开发搭建必要的软硬件环境,并提供了通过串口和网线两种方式将文件传输到开发板的具体步骤。适合Linux开发初学者参考。 ... [详细]
  • 深入理解Vue.js:从入门到精通
    本文详细介绍了Vue.js的基础知识、安装方法、核心概念及实战案例,帮助开发者全面掌握这一流行的前端框架。 ... [详细]
  • 本文详细介绍了C语言中的基本数据类型,包括整型、浮点型、字符型及其各自的子类型,并探讨了这些类型在不同编译环境下的表现。 ... [详细]
  • C语言中的carry变量解析与应用
    本文详细解释了C语言中carry变量的不同使用场景及其含义,包括作为条件判断、运算结果存储等,旨在帮助初学者更好地理解和运用这一概念。 ... [详细]
  • 本文详细探讨了Java命令行参数的概念、使用方法及在实际编程中的应用,包括如何通过命令行传递参数给Java程序,以及如何在Java程序中解析这些参数。 ... [详细]
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社区 版权所有