系列文章目录
基于FPGA的神经网络加速设计(一)
一、FP16(半精度浮点数)介绍
半精度浮点数 FP16 = {sign,exponent,mantissa} sign = 1bit exponent = 5bit mantissa = 10bit
x=±1.a×2^b 指数位是上述公式中的b加上偏置值,一般为2^(k−1)−1,其中k表示指数位的位数,尾数位是上述公式中的a
指数部分,5个比特位, 全0和全1有特殊用途,所以是00001~11110, 也就是1到30, 减去偏置15,指数部分最终范围为-14 ~15
二、FP16乘法器
1.设计代码及思路
代码如下(示例):
`timescale 100 ns / 10 ps
module floatMult (floatA,floatB,product);
input [15:0] floatA, floatB;
output reg [15:0] product;
reg sign;//符号位
reg signed [5:0] exponent; //指数位 多一位符号位
reg [9:0] mantissa;//尾数位
reg [10:0] fractionA, fractionB; //fraction = {1,mantissa} 表示负数
reg [21:0] fraction;
always @ (floatA or floatB) begin
if (floatA == 0 || floatB == 0) begin
product = 0;
end else begin
sign = floatA[15] ^ floatB[15];//最高位异或,符号位相同返回0,即结果是正数;符号位不同返回1,即结果是负数
exponent = floatA[14:10] + floatB[14:10] - 5'd15 + 5'd2;//加2是为了让其变量都变成小数类似于 0.1*10^10
fractionA = {1'b1,floatA[9:0]};
fractionB = {1'b1,floatB[9:0]} ;
fraction = fractionA * fractionB;
//判断第一个‘1’出现的位置,根据不同的位置,移动小数点位置
if (fraction[21] == 1'b1) begin
fraction = fraction << 1;
exponent = exponent - 1;
end else if (fraction[20] == 1'b1) begin
fraction = fraction << 2;
exponent = exponent - 2;
end else if (fraction[19] == 1'b1) begin
fraction = fraction << 3;
exponent = exponent - 3;
end else if (fraction[18] == 1'b1) begin
fraction = fraction << 4;
exponent = exponent - 4;
end else if (fraction[17] == 1'b1) begin
fraction = fraction << 5;
exponent = exponent - 5;
end else if (fraction[16] == 1'b1) begin
fraction = fraction << 6;
exponent = exponent - 6;
end else if (fraction[15] == 1'b1) begin
fraction = fraction << 7;
exponent = exponent - 7;
end else if (fraction[14] == 1'b1) begin
fraction = fraction << 8;
exponent = exponent - 8;
end else if (fraction[13] == 1'b1) begin
fraction = fraction << 9;
exponent = exponent - 9;
end else if (fraction[12] == 1'b1) begin
fraction = fraction << 10;
exponent = exponent - 10;
end else if (fraction[11] == 1'b1)begin
fraction = fraction << 11;
exponent = exponent - 11;
end else begin
fraction = fraction << 12;
exponent = exponent - 12;
end
mantissa = fraction[21:12];
if(exponent[5]==1'b1) begin //exponent is negative
product=16'b0000000000000000;
end
else begin
product = {sign,exponent[4:0],mantissa};
end
end
end
endmodule
2.仿真代码
`timescale 100 ns / 10 ps
module floatMult_TB ();
reg [15:0] floatA;
reg [15:0] floatB;
wire [15:0] product;
initial begin
// 4 * 5
#0
floatA = 16'b0100010000000000;
floatB = 16'b0100010100000000;
// 0.0004125 * 0
#10
floatA = 16'b0111010011100010;
floatB = 16'b0000000000000010;
#10
$stop;
end
floatMult FM
(
.floatA(floatA),
.floatB(floatB),
.product(product)
);
endmodule