一起学习用Verilog在FPGA上实现CNN----SoftMax层设计
Posted 鲁棒最小二乘支持向量机
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了一起学习用Verilog在FPGA上实现CNN----SoftMax层设计相关的知识,希望对你有一定的参考价值。
1 SoftMax层设计
1.1 softmax
SoftMax函数的作用是输入归一化,计算各种类的概率,即计算0-9数字的概率,SoftMax层的原理图如图所示,输入和输出均为32位宽的10个分类,即32x10=320
本项目softmax实现逻辑为:
- 指数计算(通过exponent实现)
- 计算指数和(通过floatAdd实现)
- 求指数和倒数(通过floatReciprocal实现)
- 计算每个元素的softmax值(通过floatMult实现)
1.2 exponent
每个输入分别输入到各自的exponent模块,计算指数,该模块的输入和输出位宽均为32位,输入1个数,计算输出1个指数
exponent模块展开原理图,如图所示,包含2个乘法器和1个加法器
1.3 floatAdd
加法器计算所有指数的和
1.4 floatReciprocal
floatReciprocal模块计算指数和的倒数
floatReciprocal模块展开原理图,如图所示
1.5 floatMult
乘法器计算各输入的softmax值,然后输出
2 代码实现
2.1 floatAdd
2.1.1 设计输入
创建floatAdd文件,操作如图:
输入文件名:
双击打开,输入代码:
module floatAdd (floatA,floatB,sum);
input [31:0] floatA, floatB;
output reg [31:0] sum;
reg sign;
reg [7:0] exponent;
reg [22:0] mantissa;
reg [7:0] exponentA, exponentB;
reg [23:0] fractionA, fractionB, fraction; //fraction = 1,mantissa
reg [7:0] shiftAmount;
reg cout;
always @ (floatA or floatB) begin
exponentA = floatA[30:23];
exponentB = floatB[30:23];
fractionA = 1'b1,floatA[22:0];
fractionB = 1'b1,floatB[22:0];
exponent = exponentA;
if (floatA == 0) begin //special case (floatA = 0)
sum = floatB;
end else if (floatB == 0) begin //special case (floatB = 0)
sum = floatA;
end else if (floatA[30:0] == floatB[30:0] && floatA[31]^floatB[31]==1'b1) begin
sum=0;
end else begin
if (exponentB > exponentA) begin
shiftAmount = exponentB - exponentA;
fractionA = fractionA >> (shiftAmount);
exponent = exponentB;
end else if (exponentA > exponentB) begin
shiftAmount = exponentA - exponentB;
fractionB = fractionB >> (shiftAmount);
exponent = exponentA;
end
if (floatA[31] == floatB[31]) begin //same sign
cout,fraction = fractionA + fractionB;
if (cout == 1'b1) begin
cout,fraction = cout,fraction >> 1;
exponent = exponent + 1;
end
sign = floatA[31];
end else begin //different signs
if (floatA[31] == 1'b1) begin
cout,fraction = fractionB - fractionA;
end else begin
cout,fraction = fractionA - fractionB;
end
sign = cout;
if (cout == 1'b1) begin
fraction = -fraction;
end else begin
end
if (fraction [23] == 0) begin
if (fraction[22] == 1'b1) begin
fraction = fraction << 1;
exponent = exponent - 1;
end else if (fraction[21] == 1'b1) begin
fraction = fraction << 2;
exponent = exponent - 2;
end else if (fraction[20] == 1'b1) begin
fraction = fraction << 3;
exponent = exponent - 3;
end else if (fraction[19] == 1'b1) begin
fraction = fraction << 4;
exponent = exponent - 4;
end else if (fraction[18] == 1'b1) begin
fraction = fraction << 5;
exponent = exponent - 5;
end else if (fraction[17] == 1'b1) begin
fraction = fraction << 6;
exponent = exponent - 6;
end else if (fraction[16] == 1'b1) begin
fraction = fraction << 7;
exponent = exponent - 7;
end else if (fraction[15] == 1'b1) begin
fraction = fraction << 8;
exponent = exponent - 8;
end else if (fraction[14] == 1'b1) begin
fraction = fraction << 9;
exponent = exponent - 9;
end else if (fraction[13] == 1'b1) begin
fraction = fraction << 10;
exponent = exponent - 10;
end else if (fraction[12] == 1'b1) begin
fraction = fraction << 11;
exponent = exponent - 11;
end else if (fraction[11] == 1'b1) begin
fraction = fraction << 12;
exponent = exponent - 12;
end else if (fraction[10] == 1'b1) begin
fraction = fraction << 13;
exponent = exponent - 13;
end else if (fraction[9] == 1'b1) begin
fraction = fraction << 14;
exponent = exponent - 14;
end else if (fraction[8] == 1'b1) begin
fraction = fraction << 15;
exponent = exponent - 15;
end else if (fraction[7] == 1'b1) begin
fraction = fraction << 16;
exponent = exponent - 16;
end else if (fraction[6] == 1'b1) begin
fraction = fraction << 17;
exponent = exponent - 17;
end else if (fraction[5] == 1'b1) begin
fraction = fraction << 18;
exponent = exponent - 18;
end else if (fraction[4] == 1'b1) begin
fraction = fraction << 19;
exponent = exponent - 19;
end else if (fraction[3] == 1'b1) begin
fraction = fraction << 20;
exponent = exponent - 20;
end else if (fraction[2] == 1'b1) begin
fraction = fraction << 21;
exponent = exponent - 21;
end else if (fraction[1] == 1'b1) begin
fraction = fraction << 22;
exponent = exponent - 22;
end else if (fraction[0] == 1'b1) begin
fraction = fraction << 23;
exponent = exponent - 23;
end
end
end
mantissa = fraction[22:0];
sum = sign,exponent,mantissa;
end
end
endmodule
如图所示:
2.1.2 分析与综合
将floatAdd设置为顶层:
对设计进行分析,操作如图:
分析后的设计,Vivado自动生成原理图,如图:
对设计进行综合,操作如图:
综合完成,关闭即可:
2.1.3 功能仿真
创建仿真激励文件,操作如图:
输入激励文件名:
确认创建:
双击打开,输入激励代码:
`timescale 1ns / 1ps
module tb_floatAdd();
reg [31:0] floatA;
reg [31:0] floatB;
wire [31:0] sum;
initial begin
// 0.0004125 + 0.000000525
#0
floatA = 32'hbab1cf4b;
floatB = 32'h3aaaad74;
// 0.0004125 + 0
#10
floatA = 32'b00111001110110000100010011010000;
floatB = 32'b00000000000000000000000000000000;
#10
$stop;
end
floatAdd FADD
(
.floatA(floatA),
.floatB(floatB),
.sum(sum)
);
endmodule
如图所示:
将tb_floatAdd设置为顶层:
开始进行仿真,操作如下:
仿真波形,如图:
仿真结束,关闭仿真:
2.2 floatMult
2.2.1 设计输入
创建floatMult文件,操作如图:
双击打开,输入代码:
module floatMult (floatA,floatB,product);
input [31:0] floatA, floatB;
output reg [31:0] product;
reg sign;
reg [7:0] exponent;
reg [22:0] mantissa;
reg [23:0] fractionA, fractionB; //fraction = 1,mantissa
reg [47:0] fraction;
always @ (floatA or floatB) begin
if (floatA == 0 || floatB == 0) begin
product = 0;
end else begin
sign = floatA[31] ^ floatB[31];
exponent = floatA[30:23] + floatB[30:23] - 8'd127 + 8'd2;
fractionA = 1'b1,floatA[22:0];
fractionB = 1'b1,floatB[22:0];
fraction = fractionA * fractionB;
if (fraction[47] == 1'b1) begin
fraction = fraction << 1;
exponent = exponent - 1;
end else if (fraction[46] == 1'b1) begin
fraction = fraction << 2;
exponent = exponent - 2;
end else if (fraction[45] == 1'b1) begin
fraction = fraction << 3;
exponent = exponent - 3;
end else if (fraction[44] == 1'b1) begin
fraction = fraction << 4;
exponent = exponent - 4;
end else if (fraction[43] == 1'b1) begin
fraction = fraction << 5;
exponent = exponent - 5;
end else if (fraction[42] == 1'b1) begin
fraction = fraction << 6;
exponent = exponent - 6;
end else if (fraction[41] == 1'b1) begin
fraction = fraction << 7;
exponent = exponent - 7;
end else if (fraction[40] == 1'b1) begin
fraction = fraction << 8;
exponent = exponent - 8;
end else if (fraction[39] == 1'b1) begin
fraction = fraction << 9;
exponent = exponent - 9;
end else if (fraction[38] == 1'b0) begin
fraction = fraction << 10;
exponent = exponent - 10;
end else if (fraction[37] == 1'b1) begin
fraction = fraction << 11;
exponent = exponent - 11;
end else if (fraction[36] == 1'b1) begin
fraction = fraction << 12;
exponent = exponent - 12;
end else if (fraction[35] == 1'b1) begin
fraction = fraction << 13;
exponent = exponent - 13;
end else if (fraction[34] == 1'b1) begin
fraction = fraction << 14;
exponent = exponent - 14;
end else if (fraction[33] == 1'b1) begin
fraction = fraction << 15;
exponent = exponent - 15;
end else if (fraction[32] == 1'b1) begin
fraction = fraction << 16;
exponent = exponent - 16;
end else if (fraction[31] == 1'b1) begin
fraction = fraction << 17;
exponent = exponent - 17;
end else if (fraction[30] == 1'b1) begin
fraction = fraction << 18;
exponent = exponent - 18;
end else if (fraction[29] == 1'b0) begin
fraction = fraction << 19;
exponent = exponent - 19;
end else if (fraction[28] == 1'b1) begin
fraction = fraction << 20;
exponent = exponent - 20;
end else if (fraction[27] == 1'b1) begin
fraction = fraction << 21;
exponent = exponent - 21;
end else if (fraction[26] == 1'b1) begin
fraction = fraction << 22;
exponent = exponent - 22;
end else if (fraction[27] == 1'b1) begin
fraction = fraction << 23;
exponent = exponent - 23;
end
mantissa = fraction[47:25];
product = sign,exponent,mantissa;
end
end
endmodule
如图所示:
2.2.2 分析与综合
将floatMult设置为顶层:
关闭上次的分析文件:
对设计进行分析,操作如图:
分析后的设计,Vivado自动生成原理图,如图:
对设计进行综合,综合完成,关闭即可:
2.2.3 功能仿真
创建激励文件tb_floatMult:
双击打开,输入激励:
`timescale 1ns / 1ps
module tb_floatMult();
reg [31:0] floatA;
reg [31:0] floatB;
wire [31:0] product;
initial begin
// 0.0004125 * 0.000000525
#0
floatA = 32'b00111001110110000100010011010000;
floatB = 32'b00110101000011001110110110111010;
// 0.0004125 * 0
#10
floatA = 32'b00111001110110000100010011010000;
floatB = 32'b00000000000000000000000000000000;
#10
$stop;
end
floatMult FM
(
.floatA(floatA),
.floatB(floatB),
.product(product)
);
endmodule
如图所示:
将tb_floatMult设置为顶层:
开始进行仿真:
仿真波形如图:
仿真结束,关闭仿真:
2.3 exponent
2.3.1 设计输入
创建exponent文件,如图:
一起学习用Verilog在FPGA上实现CNN----integrationFC设计
一起学习用Verilog在FPGA上实现CNN----池化层设计
一起学习用Verilog在FPGA上实现CNN----integrationConv设计
一起学习用Verilog在FPGA上实现CNN----SoftMax层设计