32 位 float 型的二进制存储
- 在fpga系列 HDL:全连接层的浮点数乘法器FM实现中已经提到过32 位 float 型的二进制存储结构。
32
位
f
l
o
a
t
型数
V
=
(
−
1
)
S
∗
M
∗
2
E
32 位 float 型数V=(-1)^S*M*2^E
32位float型数V=(−1)S∗M∗2E
FADD
- 代码实现了两个 32 位浮点数的相加操作,遵循 IEEE 754 单精度浮点数标准。
// https://github.com/omarelhedaby/CNN-FPGA/blob/master/CNN-FPGA-Vivado/CNN-FPGA-Vivado.srcs/sources_1/imports/Integration%20first%20part/floatAdd.v
module floatAdd (floatA,floatB,sum);
input [31:0] floatA, floatB; // 两个 32 位的输入浮点数
output reg [31:0] sum; // 输出 32 位的结果
reg sign; // 结果的符号位
reg [7:0] exponent; // 结果的指数位
reg [22:0] mantissa; // 结果的尾数位(有效位)
reg [7:0] exponentA, exponentB; // 分别存储两个浮点数的指数
reg [23:0] fractionA, fractionB, fraction; // 尾数(包括隐含的 1)
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; // 如果 A 和 B 的数值相同但符号不同,结果为 0
end else begin
// 1.指数对齐
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
// 2.尾数相加或相减(如果两个数的符号相同,则尾数相加。如果符号不同,则进行尾数相减。)
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
// 3.规范化结果,找出有效数字M的第一个“1”
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]; // 提取尾数的低 23 位作为有效尾数
sum = {sign, exponent, mantissa}; // 将符号、指数和尾数组合成最终结果
end
end
endmodule