差别
这里会显示出您选择的修订版和当前版本之间的差别。
后一修订版 | 前一修订版 | ||
students:xuhao [2019/08/17 18:52] xuhao 创建 |
students:xuhao [2019/08/26 19:07] (当前版本) xuhao |
||
---|---|---|---|
行 1: | 行 1: | ||
+ | # 培训总结 | ||
+ | |||
+ | [培训内容](students:peixun) | ||
+ | |||
# KiCad pcb和原理图设计 | # KiCad pcb和原理图设计 | ||
* KiCad,是一款免费开源的PCB设计工具,提供了一个用于原理图输入和PCB布局布线的集成化开发环境,在这个工具中还有用于产生BOM、Gerber文件、对PCB及其上元器件进行3D查看的功能,支持Python脚本定制。 | * KiCad,是一款免费开源的PCB设计工具,提供了一个用于原理图输入和PCB布局布线的集成化开发环境,在这个工具中还有用于产生BOM、Gerber文件、对PCB及其上元器件进行3D查看的功能,支持Python脚本定制。 | ||
行 5: | 行 9: | ||
* [官方库](https://kicad.github.io/) | * [官方库](https://kicad.github.io/) | ||
* [Ultra Librarian](https://www.ultralibrarian.com/) | * [Ultra Librarian](https://www.ultralibrarian.com/) | ||
- | * [SamacSys](www.samacsys.com) | + | * [SamacSys](https://www.samacsys.com) |
* 几点心得 | * 几点心得 | ||
* 少用标签 | * 少用标签 | ||
行 20: | 行 24: | ||
* 充分仿真:功能仿真、时序仿真、TestBench | * 充分仿真:功能仿真、时序仿真、TestBench | ||
* FPGA设计流程 | * FPGA设计流程 | ||
- | |||
- | |||
* 设计准备:方案论证、系统级设计 | * 设计准备:方案论证、系统级设计 | ||
* 设计输入:将所涉及的系统或电路以开发软件要求的某种形式表示出来,并送入计算机的过程。包括原理图输入、硬件描述语言输入、波形输入、IP核、状态机和网表等。 | * 设计输入:将所涉及的系统或电路以开发软件要求的某种形式表示出来,并送入计算机的过程。包括原理图输入、硬件描述语言输入、波形输入、IP核、状态机和网表等。 | ||
行 36: | 行 38: | ||
* 传统调试:示波器、逻辑分析仪等 | * 传统调试:示波器、逻辑分析仪等 | ||
* 软件逻辑分析仪:FPGA 片内集成化信号分析工具,利用 FPGA 中未使用的逻辑资源和块存储器,根据用户设定的触发条件,将信号实时的保存到块存储器中,再通过 JTAG 接口传送到计算机,通过计算机的用户界面显示出所采集的时序波形。 | * 软件逻辑分析仪:FPGA 片内集成化信号分析工具,利用 FPGA 中未使用的逻辑资源和块存储器,根据用户设定的触发条件,将信号实时的保存到块存储器中,再通过 JTAG 接口传送到计算机,通过计算机的用户界面显示出所采集的时序波形。 | ||
+ | |||
+ | {{ :students:fpga设计流程.png?200 |}} | ||
## Verilog | ## Verilog | ||
行 132: | 行 136: | ||
- MISO:数据通道,从设备=>主设备 | - MISO:数据通道,从设备=>主设备 | ||
- SS:设备选通信号 | - SS:设备选通信号 | ||
+ | {{ :students:SPI主从连接图.png?200 |}} | ||
+ | |||
+ | |||
* 通信时序 | * 通信时序 | ||
+ | {{ :students:spi通信时序.png?200 |}} | ||
+ | |||
+ | |||
* I2C(Inter-Integrated Ciruits) **同步串行**总线,集成电路之间的连接 | * I2C(Inter-Integrated Ciruits) **同步串行**总线,集成电路之间的连接 | ||
* 两根信号线(SCL、SDA)必须要有上拉电阻 | * 两根信号线(SCL、SDA)必须要有上拉电阻 | ||
- | * 通信时序按字节交换信息,每个字节后跟一个ACK或NACK | + | {{ :students:I2C连接图.png?200 |}} |
+ | |||
+ | |||
+ | * 通信时序:按字节交换信息,每个字节后跟一个ACK或NACK | ||
+ | {{ :students:I2C通信时序.png?200 |}} | ||
+ | |||
* UART(Universal Asynchronous Receiver/Transmitter) **异步串行**总线 | * UART(Universal Asynchronous Receiver/Transmitter) **异步串行**总线 | ||
+ | {{ :students:UART原理图.png?200 |}} | ||
+ | |||
+ | |||
* 通信时序:起始位、数据位、校验位、停止位、空闲位 | * 通信时序:起始位、数据位、校验位、停止位、空闲位 | ||
+ | {{ :students:UART通信时序.png?200 |}} | ||
+ | |||
+ | |||
* 几点心得:在verilog设计实现UART功能时,检验起始位下降沿后开启Boud时钟,在Boud时钟中间读取Rx数据,能够保证数据的稳定性;除了UART的基本的并行数据和串行数据相互转化外,可以添加FIFO缓存单元,避免数据丢失;在利用UART通信的时候,可以采用数据帧的格式发送数据,以帧头、数据个数、数据、帧校验和帧尾的格式来传输数据。 | * 几点心得:在verilog设计实现UART功能时,检验起始位下降沿后开启Boud时钟,在Boud时钟中间读取Rx数据,能够保证数据的稳定性;除了UART的基本的并行数据和串行数据相互转化外,可以添加FIFO缓存单元,避免数据丢失;在利用UART通信的时候,可以采用数据帧的格式发送数据,以帧头、数据个数、数据、帧校验和帧尾的格式来传输数据。 | ||
* IP核例化:IP核(Intellectual Property core知识产权核)是一段具有特定电路功能的硬件描述语言程序,该程序与集成电路工艺无关,可以移植到不同的半导体工艺中去生产集成电路芯片。在FPGA的设计中调用IP核可以简化设计流程。 | * IP核例化:IP核(Intellectual Property core知识产权核)是一段具有特定电路功能的硬件描述语言程序,该程序与集成电路工艺无关,可以移植到不同的半导体工艺中去生产集成电路芯片。在FPGA的设计中调用IP核可以简化设计流程。 | ||
行 163: | 行 185: | ||
# PYNQ和Vivado | # PYNQ和Vivado | ||
+ | [一些学习笔记](https://blog.csdn.net/xh116996/article/details/89218766) | ||
# MNIST数据集训练与加速 | # MNIST数据集训练与加速 | ||
## 方案思路 | ## 方案思路 | ||
- | * 利用tensorflow训练神经网络识别mnist数据集,保存训练参数;利用vivado hls定制卷积和池化ip核;在pynq上复现训练好的神经网络,导入网络参数,利用硬件加速手写数字识别。 | + | * 搭建并训练神经网络 |
- | * mnist神经网络的搭建和训练([深入MNIST](http://www.tensorfly.cn/tfdoc/tutorials/mnist_pros.html)) | + | * 利用tensorflow训练神经网络识别mnist数据集,保存训练参数;利用vivado hls定制卷积和池化ip核;在pynq上复现训练好的神经网络,导入网络参数,利用硬件加速手写数字识别。 |
- | * 开发工具 PyCharm, python 3.7, tensorflow 1.14.0 | + | * mnist神经网络的搭建和训练([深入MNIST](http://www.tensorfly.cn/tfdoc/tutorials/mnist_pros.html)) |
- | * 搭建四层的神经网络: | + | * 开发工具 PyCharm, python 3.7, tensorflow 1.14.0 |
- | * (1, 5, 5, 32)卷积,relu激活,2X2池化; | + | * 搭建四层的神经网络: |
- | * (32, 5, 5, 64)卷积,relu激活,2X2池化; | + | * (1, 5, 5, 32)卷积,relu激活,2X2池化; |
- | * (7X7X64, 1024)全连接层,relu激活,dropout; | + | * (32, 5, 5, 64)卷积,relu激活,2X2池化; |
- | * (1024, 10)全连接输出层,softmax分类; | + | * (7X7X64, 1024)全连接层,relu激活,dropout; |
- | * 如何保存训练数据?训练好的网络参数是以浮点数(float)类型存储,而在硬件电路中,浮点数计算较慢,所以把网络参数转化为定点数类型导入网络。设计的硬件ip中,乘法运算采用int16型乘法,所以网络权重参数采用int16存储,但可以配置小数点位数(fraction_cnt)来存储小数(= int16 / pow(2, fraction_cnt))。将数据以字节的形式存放在bin中。 | + | * (1024, 10)全连接输出层,softmax分类; |
+ | * 保存神经网络数据 | ||
+ | * 如何保存训练数据?训练好的网络参数是以浮点数(float)类型存储,而在硬件电路中,浮点数计算较慢,所以把网络参数转化为定点数类型导入网络。设计的硬件ip中,乘法运算采用int16型乘法,所以网络权重参数采用int16存储,但可以配置小数点位数(fraction_cnt)来存储小数(= int16 / pow(2, fraction_cnt))。将数据以字节的形式存放在bin中。 | ||
+ | * 在pynq的pl中搭建神经网络 | ||
+ | * fpga的配置采用ip设计,主要包括卷积运算ip和池化运算ip。 | ||
+ | * 利用对卷积计算ip和池化运算ip的复用来实现多层卷积神经网络。 | ||
+ | {{ :students:硬件卷积神经网络.jpg?200 |}} | ||
+ | * 在pynq的ps中控制神经网络,能够实现对数字的识别 | ||
+ | * 在jupyter notebook的环境中开发。 | ||
+ | * 主要包括导入比特流文件配置pl部分,读取图片和利用网络识别数字。 | ||
- | ## vivado综合硬件模块:卷积和池化 | + | ## 搭建并训练神经网络,保存网络数据 |
+ | * 参考[深入MNIST](http://www.tensorfly.cn/tfdoc/tutorials/mnist_pros.html)搭建网络,网络数据按照想要的格式保存下来。 | ||
+ | |||
+ | ## vivado综合硬件ip:卷积和池化 | ||
### 开发工具 | ### 开发工具 | ||
行 189: | 行 224: | ||
* pool1D:按行进行池化 | * pool1D:按行进行池化 | ||
* pool2D:按列进行池化 | * pool2D:按列进行池化 | ||
+ | |||
+ | {{ :students:池化运算原理图.png?200 |}} | ||
+ | |||
+ | |||
+ | |||
```c | ```c | ||
行 207: | 行 247: | ||
**out** 特征数据流按照[ch_div_K][height_in][width_out]顺序输出; | **out** 特征数据流按照[ch_div_K][height_in][width_out]顺序输出; | ||
**Kx** 特征数据流按行进行Kx池化。 | **Kx** 特征数据流按行进行Kx池化。 | ||
+ | |||
+ | {{ :students:pool1d原理图.png?200 |}} | ||
+ | |||
```c | ```c | ||
行 215: | 行 258: | ||
**out** 特征数据流按照[ch_div_K][height_out][width_out]顺序输出; | **out** 特征数据流按照[ch_div_K][height_out][width_out]顺序输出; | ||
**Ky** 特征数据流按列进行Ky池化。 | **Ky** 特征数据流按列进行Ky池化。 | ||
+ | |||
+ | {{ :students:pool2d原理图.png?200 |}} | ||
+ | |||
* 优化选项与接口协议设置 | * 优化选项与接口协议设置 | ||
行 256: | 行 302: | ||
* C综合是根据上述设定的优化选项和接口协议等将C++程序综合成RTL级HDL语言,并生成综合报告,描述综合后的硬件的时序、消耗的逻辑资源和对外接口类型。 | * C综合是根据上述设定的优化选项和接口协议等将C++程序综合成RTL级HDL语言,并生成综合报告,描述综合后的硬件的时序、消耗的逻辑资源和对外接口类型。 | ||
* C&RTL联合仿真是对综合出来的硬件进行仿真,分析仿真波形来修改C++程序或优化选项等。 | * C&RTL联合仿真是对综合出来的硬件进行仿真,分析仿真波形来修改C++程序或优化选项等。 | ||
+ | |||
+ | {{ :students:池化ip的时序和逻辑消耗.png?200 |}} | ||
+ | {{ :students:池化ip外部接口类型.png?200 |}} | ||
+ | |||
* 生成IP核 | * 生成IP核 | ||
- | * 选择 Export RTL生成ip核,包括硬件描述、HDL程序和C驱动程序等。在Vivado中调用生成的ip核时,需要将生成的文件夹添加到Vivado的ip搜索目录下;配置ip时参考driver目录下的xxx_hw.h文件。 | + | * 选择 Export RTL生成ip核,包括硬件描述、HDL程序和C驱动程序等。在Vivado中调用生成的ip核时,需要将生成的文件夹添加到Vivado的ip搜索目录下;在jupyter notebook中配置ip时参考driver目录下的xxx_hw.h文件。 |
+ | |||
+ | {{ :students:ip核驱动程序.png?200 |}} | ||
行 263: | 行 315: | ||
* 卷积算法 | * 卷积算法 | ||
- | ## jupyter硬件加速识别数字 | + | ## jupyter配置硬件,加速识别数字 |
* Vivado构建pynq的overlay——利用ip配置pynq中的PL部分 | * Vivado构建pynq的overlay——利用ip配置pynq中的PL部分 | ||
- | * | + | * 搭建如图所示的结构,综合、实现、生成比特流。将生成的.srcs\sources_1\bd\design_1\hw_handoff\design_1.hwh文件和.runs\impl_1\design_1_wrapper.bit文件找出来并修改为同样的名字。 |
+ | |||
+ | {{ :students:捕获.jpg?200 |}} | ||
+ | |||
+ | * 连上pynq开发板,将hwh文件和bit文件通过本地资源管理器连接pynq上传到板子的文件系统内,并在该目录下新建一个ipynb文件,在该文件中实现相应功能程序。 | ||
+ | * 导入比特流文件,配置pynq上的pl部分。 | ||
+ | |||
+ | ```python | ||
+ | from pynq import Overlay | ||
+ | from pynq import Xlnk | ||
+ | ol = Overlay("conv.bit") | ||
+ | ol.download() | ||
+ | print(ol.ip_dict.keys()) | ||
+ | dma = ol.axi_dma_0 | ||
+ | pool = ol.pool_stream_0 | ||
+ | conv = ol.Conv_0 | ||
+ | xlnk = Xlnk() | ||
+ | ``` | ||
+ | * 导入网络参数 | ||
+ | |||
+ | ```python | ||
+ | import driver | ||
+ | from MNIST_LARGE_cfg import * | ||
+ | driver.Load_Weight_From_File(W_conv1, "./record/W_conv1.bin") | ||
+ | driver.Load_Weight_From_File(W_fc1, "./record/W_fc1.bin") | ||
+ | driver.Load_Weight_From_File(W_fc2, "./record/W_fc2.bin") | ||
+ | ``` | ||
+ | * 导入数字图片,并使用搭建好的网络识别数字,同时利用内置计时器观察硬件执行时间 | ||
+ | |||
+ | ```python | ||
+ | start=time.time() | ||
+ | driver.Run_Conv(conv, 1,32, 3,3, 1,1, 1,0, src_buffer,PTR_IMG,W_conv1,PTR_W_CONV1,h_conv1,PTR_H_CONV1) | ||
+ | driver.Run_Pool(pool,dma, 32, 4,4, h_conv1,h_pool1) | ||
+ | driver.Run_Conv(conv, 32,256, 7,7, 1,1, 0,0, h_pool1,PTR_H_POOL1,W_fc1,PTR_W_FC1,h_fc1,PTR_H_FC1) | ||
+ | driver.Run_Conv(conv, 256,10, 1,1, 1,1, 0,0, h_fc1,PTR_H_FC1,W_fc2,PTR_W_FC2,h_fc2,PTR_H_FC2) | ||
+ | end=time.time() | ||
+ | print("Hardware run time=%s s"%(end-start)) | ||
+ | ``` | ||
+ | * 观察最后识别出的数字 | ||
+ | |||
+ | ```python | ||
+ | max=-32768 | ||
+ | num=0 | ||
+ | for i in range(10): | ||
+ | if(h_fc2[i//K][0][0][i%K]>max): | ||
+ | max=h_fc2[i//K][0][0][i%K] | ||
+ | num=i; | ||
+ | print("predict num is %d"%num); | ||
+ | ``` | ||