对已有YOLO加速模块进行Layer0仿真
对已有YOLO加速模块进行Layer0仿真
# Layer0仿真模块
## 输入数据
- 从文本文件中读取
- 每个通道144个8位数据
- 文件名如下:
- layer0_txt/r_data.txt
- layer0_txt/g_data.txt
- layer0_txt/b_data.txt
- layer0_txt/layer0_leakyrelu.txt
- layer0_txt/layer0_ch0.txt
- layer0_txt/layer0_ch1.txt
- layer0_txt/layer0_ch2.txt
- layer0_txt/layer0_ch3.txt
- layer0_txt/layer0_ch4.txt
- layer0_txt/layer0_ch5.txt
- layer0_txt/layer0_ch6.txt
- layer0_txt/layer0_ch7.txt
## 输出数据
- 通过AXI4-Stream接口发送
- 64位数据流,每次发送两个通道的数据
- 每个通道32位,高16位为偏置或激活函数,低16位为权重或特征
- 有有效位和结束位,表示数据流的状态
## 内部逻辑
- 由状态机控制,有七个状态:
- S_IDLE:空闲状态,等待开始信号
- S_BIAS_TX:发送偏置数据状态,从RAM中读取偏置数据并发送给YOLO加速模块
- S_LEAKYRELU_TX:发送激活函数数据状态,从RAM中读取激活函数数据并发送给YOLO加速模块
- S_WEIGHT_TX:发送权重数据状态,从RAM中读取权重数据并发送给YOLO加速模块
- S_FEATURE_TX:发送特征数据状态,从RAM中读取特征数据并发送给YOLO加速模块
- S_CONV_CAL:卷积计算状态,从YOLO加速模块接收读取地址,并从RAM中读取相应的数据进行卷积计算
- S_FINISH:完成状态,从YOLO加速模块接收任务完成信号,并结束仿真
## 内部存储
- 由四个RAM实现,每个RAM存储两个通道的数据
- 每次读取或写入64位,高32位为一个通道,低32位为另一个通道
- RAM的写入地址由一个计数器生成,计数器在每次发送数据时加一
- RAM的读取地址由YOLO加速模块提供,用于从不同位置读取数据进行卷积计算
-
首先,定义一个顶层模块
layer0_sim
,该模块包含了以下端口和信号:- 系统信号:时钟
sclk
和复位s_rst_n
- AXI4-Stream接口:用于与YOLO加速模块通信的数据通道
m_axis_mm2s_tdata
,有效位m_axis_mm2s_tvalid
,就绪位m_axis_mm2s_tready
,结束位m_axis_mm2s_tlast
和保持位m_axis_mm2s_tkeep
- AXI4-Lite接口:用于与YOLO加速模块交换控制信息的寄存器
slave_lite_reg0
到slave_lite_reg3
- 任务完成信号:用于指示YOLO加速模块是否完成当前任务的信号
task_finish
- 系统信号:时钟
-
然后,定义一个有限状态机(FSM),该FSM包含了以下状态:
S_IDLE
:空闲状态,等待开始仿真S_BIAS_TX
:发送偏置数据状态,从RAM中读取偏置数据并发送给YOLO加速模块S_LEAKYRELU_TX
:发送激活函数数据状态,从RAM中读取激活函数数据并发送给YOLO加速模块S_WEIGHT_TX
:发送权重数据状态,从RAM中读取权重数据并发送给YOLO加速模块S_FEATURE_TX
:发送特征数据状态,从RAM中读取特征数据并发送给YOLO加速模块S_CONV_CAL
:卷积计算状态,从YOLO加速模块接收读取地址,并从RAM中读取相应的数据进行卷积计算S_FINISH
:完成状态,从YOLO加速模块接收任务完成信号,并结束仿真
-
接着,定义四个子模块,分别负责偏置、激活函数、权重和特征的传输:
layer0_bias_tx
:该模块将偏置数据存储在一个数组中,并根据时钟和就绪信号逐个发送给YOLO加速模块layer0_leakyrelu_tx
:该模块将激活函数参数存储在一个数组中,并根据时钟和就绪信号逐个发送给YOLO加速模块layer0_weight_tx
:该模块将权重数据存储在八个数组中,并根据时钟和就绪信号逐个发送给YOLO加速模块layer0_feature_tx
:该模块将特征数据存储在三个数组中,并根据时钟和就绪信号逐个发送给YOLO加速模块
-
最后,定义一个测试平台(testbench)模块,用于生成时钟、复位和控制信号,并实例化顶层模块和YOLO加速模块:
-
tb_top
:该模块生成一个周期为10ns的时钟信号sclk
,以及一个复位信号s_rst_n
-
layer0_sim_inst
:该实例是顶层模块的实例,与测试平台和YOLO加速模块相连 -
yolo_accel_top_inst
:该实例是YOLO加速模块的实例,与顶层模块相连
-
Layer0仿真模块的仿真步骤如下:
-
初始状态为S_IDLE,输出Lite-Reg信号为32'h21,表示准备传输偏置数据。
-
首先,将偏置数据从文本文件中读取到bias_arr数组中,并通过layer0_bias_tx子模块发送给YOLO加速模块,直到发送完毕或收到任务完成信号。
当任务完成信号为1时,状态转变为S_BIAS_TX,输出Lite-Reg信号为32'h20,表示开始传输偏置数据。layer0_bias_tx模块从文本文件中读取16个偏置数据(每个32位),并将其打包成8个64位数据(每个包含两个偏置),通过AXI4-Stream接口发送给YOLO加速模块。每发送一个数据,输出Lite-Reg信号的最低位加1,表示传输进度。最后一个数据发送时,输出tlast信号为1,表示传输结束。
-
然后,将激活函数数据从文本文件中读取到data_arr数组中,并通过layer0_leakyrelu_tx子模块发送给YOLO加速模块,直到发送完毕或收到任务完成信号。
当任务完成信号为1时,状态转变为S_LEAKYRELU_TX,输出Lite-Reg信号为32'h31,表示准备传输激活函数参数。layer0_leakyrelu_tx模块从文本文件中读取32个LeakyReLU参数(每个8位),并将其打包成8个64位数据(每个包含8个参数),通过AXI4-Stream接口发送给YOLO加速模块。每发送一个数据,输出Lite-Reg信号的最低位加1,表示传输进度。最后一个数据发送时,输出tlast信号为1,表示传输结束。
-
接着,将权重数据从文本文件中读取到ch0_data_arr、ch1_data_arr等八个数组中,并通过layer0_weight_tx子模块发送给YOLO加速模块,直到发送完毕或收到任务完成信号。
当任务完成信号为1时,状态转变为S_WEIGHT_TX,输出Lite-Reg信号为32'h11,表示准备传输权重数据。layer0_weight_tx模块从文本文件中读取144个权重数据(每个8位),并将其打包成18个64位数据(每个包含8个权重),通过AXI4-Stream接口发送给YOLO加速模块。每发送一个数据,输出Lite-Reg信号的最低位加1,表示传输进度。最后一个数据发送时,输出tlast信号为1,表示传输结束。
-
最后,将特征数据从文本文件中读取到ch0_data_arr、ch1_data_arr和ch2_data_arr三个数组中,并通过layer0_feature_tx子模块发送给YOLO加速模块,直到发送完毕或收到任务完成信号。
当任务完成信号为1时,状态转变为S_FEATURE_TX,输出Lite-Reg信号为32'h10_1181,表示准备传输特征数据。layer0_feature_tx模块从文本文件中读取173056个特征数据(每个8位),并将其打包成21632个64位数据(每个包含3个特征),通过AXI4-Stream接口发送给YOLO加速模块。每发送一个数据,输出Lite-Reg信号的最低位加1,表示传输进度。最后一个数据发送时,输出tlast信号为1,表示传输结束。
- 当任务完成信号为1时,状态转变为S_CONV_CAL,输出Lite-Reg信号为32'h10_1184,表示开始进行卷积计算。
-
当任务完成信号为1时,状态转变为S_FINISH,保持不变。
-
Layer0仿真模块的仿真思路如下:
- 使用状态机控制Layer0模块的各个子模块的复位、使能和数据传输,并根据任务完成信号切换状态。
- 使用$readmemh函数从文本文件中读取偏置、激活函数、权重和特征数据,并将其打包成64位数据通过AXI4-Stream接口发送。
- 使用计数器和状态机来控制数据的发送顺序和时序。
- 使用AXI4-Stream接口来与YOLO加速模块进行通信,并根据tvalid、tready和tlast信号来判断数据的有效性和结束性。
- 使用Lite-Reg接口来与YOLO加速模块进行配置,并根据不同的状态输出不同的寄存器值。
- 使用task_finish信号来接收YOLO加速模块的任务完成信号,并根据该信号来切换状态或结束仿真。