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 位 f l o a t 型数 V = ( − 1 ) S ∗ M ∗ 2 E
Layer 1 22 0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 23 30 31 指数位E 符号位S 有效数字M(实际计算时会包含前边的“1”,存储时省略“1”) (-1)^S*M*2^E
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) beginexponentA = 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 的数值相同但符号不同,结果为 0end else begin// 1.指数对齐if (exponentB > exponentA) beginshiftAmount = 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;endsign = floatA[31];end else begin //different signsif (floatA[31] == 1'b1) begin{cout,fraction} = fractionB - fractionA;end else begin{cout,fraction} = fractionA - fractionB;endsign = cout;if (cout == 1'b1) beginfraction = -fraction;end else beginend// 3.规范化结果,找出有效数字M的第一个“1”if (fraction [23] == 0) beginif (fraction[22] == 1'b1) beginfraction = fraction << 1;exponent = exponent - 1;end else if (fraction[21] == 1'b1) beginfraction = fraction << 2;exponent = exponent - 2;end else if (fraction[20] == 1'b1) beginfraction = fraction << 3;exponent = exponent - 3;end else if (fraction[19] == 1'b1) beginfraction = fraction << 4;exponent = exponent - 4;end else if (fraction[18] == 1'b1) beginfraction = fraction << 5;exponent = exponent - 5;end else if (fraction[17] == 1'b1) beginfraction = fraction << 6;exponent = exponent - 6;end else if (fraction[16] == 1'b1) beginfraction = fraction << 7;exponent = exponent - 7;end else if (fraction[15] == 1'b1) beginfraction = fraction << 8;exponent = exponent - 8;end else if (fraction[14] == 1'b1) beginfraction = fraction << 9;exponent = exponent - 9;end else if (fraction[13] == 1'b1) beginfraction = fraction << 10;exponent = exponent - 10;end else if (fraction[12] == 1'b1) beginfraction = fraction << 11;exponent = exponent - 11;end else if (fraction[11] == 1'b1) beginfraction = fraction << 12;exponent = exponent - 12;end else if (fraction[10] == 1'b1) beginfraction = fraction << 13;exponent = exponent - 13;end else if (fraction[9] == 1'b1) beginfraction = fraction << 14;exponent = exponent - 14;end else if (fraction[8] == 1'b1) beginfraction = fraction << 15;exponent = exponent - 15;end else if (fraction[7] == 1'b1) beginfraction = fraction << 16;exponent = exponent - 16;end else if (fraction[6] == 1'b1) beginfraction = fraction << 17;exponent = exponent - 17;end else if (fraction[5] == 1'b1) beginfraction = fraction << 18;exponent = exponent - 18;end else if (fraction[4] == 1'b1) beginfraction = fraction << 19;exponent = exponent - 19;end else if (fraction[3] == 1'b1) beginfraction = fraction << 20;exponent = exponent - 20;end else if (fraction[2] == 1'b1) beginfraction = fraction << 21;exponent = exponent - 21;end else if (fraction[1] == 1'b1) beginfraction = fraction << 22;exponent = exponent - 22;end else if (fraction[0] == 1'b1) beginfraction = fraction << 23;exponent = exponent - 23;endendendmantissa = fraction[22:0]; // 提取尾数的低 23 位作为有效尾数sum = {sign, exponent, mantissa}; // 将符号、指数和尾数组合成最终结果 end
endendmodule