搭建YOLO加速模块上板验证工程
搭建YOLO加速模块上板验证工程
目的
- 搭建YOLO加速模块上板验证工程的目的是为了测试和验证YOLO加速模块的功能和性能,确保它能够正确地完成YOLO算法的计算,并且与ZYNQ芯片之间能够正常地通信和协作。
- 搭建YOLO加速模块上板验证工程的方法是先不加摄像头和显示器驱动模块,只在PL端实例化YOLO加速模块,然后在PS端使能SD卡外设,并将YOLO算法需要用到的参数文件和图像输入文件存储在SD卡中,然后通过PS端将这些文件读取到DDR3中,并按照命令控制流程去控制YOLO加速模块进行相关操作,最后将YOLO加速模块的输出结果返回给PS端,并与Python代码中的计算结果进行比较,从而验证YOLO加速模块的正确性和有效性。
思路
- 本工程的思路是先在PS端使能SD卡外设,并将YOLO网络需要用到的参数文件、量化文件和输入图像文件存储在SD卡中,然后通过PS端读取这些文件到DDR3中。
- 然后在PL端实例化YOLO加速模块,并通过AXI接口与PS端进行通信,包括命令控制、数据传输和中断信号。
- 最后通过PS端按照正常的流程控制YOLO加速模块进行前向计算,并将结果返回给PS端,与Python代码中的计算结果进行比较,验证正确性和精度。
- 本工程的思路是先在Python环境中生成YOLO网络需要用到的参数文件、量化文件和输入图像文件,并保存为.bin格式,然后将这些文件存储在SD卡中。
- 然后在Vivado中搭建一个包含ZYNQ、YOLO加速模块、DMA和AXI Lite等IP核的工程,并配置相应的时钟、电压、中断、接口等参数,生成比特流文件并烧录到开发板中。
- 最后在PS端通过SD卡读取参数文件和输入图像文件,并按照命令控制流程通过AXI Lite接口向YOLO加速模块发送控制信号和数据,然后通过AXI Stream接口接收YOLO加速模块返回的结果,并与Python环境中的计算结果进行比较,验证工程的正确性。
步骤
1. 生成参数文件、量化文件和输入图像文件
- 在Python环境中,根据YOLO网络的结构和量化方法,生成相应的参数文件、量化文件和输入图像文件,并保存为.bin格式。
- 参数文件包括卷积核参数、激活函数查找表、偏置参数等,每个参数占用一个字节(8位)。
- 量化文件包括每层网络的输入输出尺度因子等,每个因子占用四个字节(32位)。
- 输入图像文件是将一张输入图像转换为灰度图,并按照网络输入尺寸进行裁剪或填充,然后将每个像素值保存为一个字节(8位)。
- 将这些文件按照一定的顺序存储在SD卡中,例如:
- 参数文件:conv1_w.bin, conv1_b.bin, conv1_lut.bin, …, conv13_w.bin, conv13_b.bin, conv13_lut.bin
- 量化文件:scale_in.bin, scale_out.bin
- 输入图像文件:image_in.bin
2. 搭建Vivado工程
-
在Vivado中创建一个新工程,并添加相应的IP核,包括ZYNQ、YOLO加速模块、DMA和AXI Lite等。
-
配置ZYNQ的PS端,使能SD卡外设,并设置相应的IO口、电压、时钟等参数。
PS端使能SD卡外设
- SD卡是一种存储设备,可以存储YOLO网络中需要用到的卷积参数、激活查找表、偏置参数、量化参数等文件,以及图像的输入数据文件。这些文件都是由Python代码生成的,并保存为.bin格式。
- PS端需要使能SD卡外设,以便从SD卡中读取这些文件,并将它们存储到DDR3内存中。
- 为了使能SD卡外设,需要在Vivado中对ZYNQ IP进行配置,勾选SD0外设,并设置对应的MIO引脚和电压。具体如下:
外设 MIO引脚 电压 SD0 40-45 1.8V SD CD 10 3.3V PS端与加速模块之间的连接
-
PS端与加速模块之间需要通过一些接口进行连接,以实现数据和命令的传输和控制。这些接口包括:
Axi Lite接口
- Axi Lite接口需要连接到ZYNQ IP的GP Master接口上,并设置对应的地址映射。
Axi Stream接口
- Axi Stream接口需要连接到ZYNQ IP的HP Slave接口上,并通过DMA(直接内存访问)控制器进行数据的读写操作。
- DMA控制器需要配置相应的参数,如数据宽度、地址宽度、突发长度、FIFO深度等。
-
配置ZYNQ的PL端,将YOLO加速模块与PS端通过AXI Lite接口和AXI Stream接口连接起来,并设置相应的时钟、复位等信号。
时钟和复位信号
- 时钟和复位信号是用来同步和初始化PS端和加速模块之间的通信和计算的。
- 时钟信号可以由ZYNQ IP提供,也可以通过时钟向导IP生成,本项目中使用了200MHz的时钟信号。
- 复位信号可以由ZYNQ IP提供,也可以通过处理器系统复位IP生成,本项目中使用了ZYNQ IP提供的复位信号。
中断信号
-
中断信号是用来通知PS端加速模块的工作状态,如是否完成计算任务等。
-
中断信号需要连接到ZYNQ IP的中断控制器上,并设置对应的中断ID。
外设 MIO引脚 中断 IRQ_F2P[0]
-
配置DMA模块,将其与YOLO加速模块和ZYNQ的HP接口连接起来,并设置相应的数据宽度、地址宽度、突发长度等参数。
DMA IP
-
实现AXI stream接口和AXI memory接口之间的数据传输,支持突发模式
-
读写数据宽度:64位
地址宽度:32位
FIFO深度:4096
突发长度:14位
-
-
验证工程的连接和参数是否正确,生成输出产品,包括比特流文件和硬件描述文件。
3. 烧录比特流文件并运行PS端程序
- 将比特流文件烧录到开发板中,并将SD卡插入到开发板的SD卡槽中。
- 在PS端运行一个控制程序,该程序可以通过串口或其他方式与用户交互,接收用户的命令,并执行相应的操作。
- 操作包括从SD卡中读取参数文件和输入图像文件,并将其存储在DDR3中;通过AXI Lite接口向YOLO加速模块发送控制信号和数据地址;通过AXI Stream接口从YOLO加速模块接收结果数据;通过中断信号判断YOLO加速模块是否完成计算;将结果数据与Python环境中的计算结果进行比较,并输出比较结果。
按照命令控制流程执行YOLO计算
- 命令控制流程是指PS端通过Axi Lite接口向加速模块发送一系列的命令,控制加速模块进行YOLO网络的前向计算,并通过Axi Stream接口和DMA控制器进行数据的读写操作,最后通过中断信号接收加速模块的计算结果,并与Python代码中的计算结果进行比较,验证加速模块的正确性和有效性。
- 命令控制流程具体如下:
步骤 | 命令 | 说明 |
---|---|---|
1 | 写入卷积参数地址 | PS端向加速模块写入卷积参数在DDR3内存中的起始地址 |
2 | 写入激活查找表地址 | PS端向加速模块写入激活查找表在DDR3内存中的起始地址 |
3 | 写入偏置参数地址 | PS端向加速模块写入偏置参数在DDR3内存中的起始地址 |
4 | 写入量化参数地址 | PS端向加速模块写入量化参数在DDR3内存中的起始地址 |
5 | 写入图像输入地址 | PS端向加速模块写入图像输入在DDR3内存中的起始地址 |
6 | 写入计算结果地址 | PS端向加速模块写入计算结果在DDR3内存中的起始地址 |
7 | 写入启动命令 | PS端向加速模块写入启动命令,使能加速模块开始计算 |
8 | 等待中断信号 | PS端等待加速模块发送中断信号,表示计算完成 |
9 | 读取计算结果 | PS端通过DMA控制器从DDR3内存中读取计算结果,并存储到本地文件中 |
10 | 比较计算结果 | PS端使用Python代码读取本地文件中的计算结果,并与Python代码中的计算结果进行比较,验证加速模块的正确性和有效性 |
举例
- 假设用户输入了一个命令,要求PS端运行YOLO网络的第一层卷积,并将结果与Python环境中的结果进行比较,那么PS端程序可能会执行以下操作:
- 从SD卡中读取conv1_w.bin, conv1_b.bin, conv1_lut.bin, scale_in.bin, scale_out.bin, image_in.bin这六个文件,并将其存储在DDR3的不同地址中,例如:
- conv1_w.bin -> 0x10000000
- conv1_b.bin -> 0x10010000
- conv1_lut.bin -> 0x10020000
- scale_in.bin -> 0x10030000
- scale_out.bin -> 0x10030004
- image_in.bin -> 0x20000000
- 通过AXI Lite接口向YOLO加速模块发送控制信号和数据地址,例如:
- 写入0x00000001到0x43C00000,表示启动YOLO加速模块
- 写入0x00000001到0x43C00004,表示选择第一层卷积
- 写入0x10000000到0x43C00008,表示卷积核参数的地址
- 写入0x10010000到0x43C0000C,表示偏置参数的地址
- 写入0x10020000到0x43C00010,表示激活函数查找表的地址
- 写入0x10030000到0x43C00014,表示输入尺度因子的地址
- 写入0x10030004到0x43C00018,表示输出尺度因子的地址
- 写入0x20000000到0x43C0001C,表示输入图像数据的地址
- 通过AXI Stream接口从YOLO加速模块接收结果数据,并将其存储在DDR3的另一个地址中,例如:
- 读取数据流从0x43C00100,并将其存储在0x30000000
- 通过中断信号判断YOLO加速模块是否完成计算,例如:
- 等待中断信号从0x43C00104为1,表示计算完成
- 将结果数据与Python环境中的计算结果进行比较,并输出比较结果,例如:
- 读取Python环境中的计算结果文件conv1_out.bin,并与DDR3中的结果数据进行逐字节比较
- 如果比较结果相同,则输出“第一层卷积计算正确”
- 如果比较结果不同,则输出“第一层卷积计算错误”,并给出不同的字节位置和值
- 从SD卡中读取conv1_w.bin, conv1_b.bin, conv1_lut.bin, scale_in.bin, scale_out.bin, image_in.bin这六个文件,并将其存储在DDR3的不同地址中,例如:
graph TD
A[启动Vivado并创建工程]
B[添加ZYNQ IP核并配置PS端]
C[添加YOLO加速模块IP核并配置PL端]
D[添加DMA和FIFO IP核并连接数据通路]
E[生成比特流文件并导出硬件]
F[启动SDK并创建应用程序工程]
G[编写控制代码并生成可执行文件]
H[使用Python生成参数文件和图像输入文件]
I[将参数文件和图像输入文件存储到SD卡中]
J[将SD卡插入开发板并下载可执行文件]
K[运行可执行文件并观察输出结果]
L[与Python代码中的结果进行比较并分析性能]
A --> B
B --> C
C --> D
D --> E
E --> F
F --> G
G --> H
H --> I
I --> J
J --> K
K --> L