fpga系列 HDL:全连接层的浮点数乘法器FM实现

  • 此代码实现了一个简单的浮点数乘法器,处理两个32位的单精度浮点数。它通过将两个浮点数的有效数字部分进行乘法操作,并对结果进行规范化以生成最终的浮点乘积。

主要逻辑与电路

  • 去掉指数对齐部分后的主要逻辑电路图示:

代码

// https://github.com/omarelhedaby/CNN-FPGA/blob/master/CNN-FPGA-Vivado/CNN-FPGA-Vivado.srcs/sources_1/imports/Integration%20first%20part/floatMult.v
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; // 计算结果的指数部分。首先加上两个输入的指数部分,然后减去偏移量127,并加2(因为在乘法中指数的偏移量增加了)。

	
		fractionA = {1'b1,floatA[22:0]};
		fractionB = {1'b1,floatB[22:0]};
		fraction = fractionA * fractionB;
		
		// 规范化结果,调整指数exponent和有效数字fraction以保持数值的正确性
		if (fraction[47] == 1'b1) begin // 找出第一个一开头的"1"
			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

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
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

语句fraction = fractionA * fractionB;

verilog 复制代码
        fractionA = {1'b1, floatA[22:0]};
        fractionB = {1'b1, floatB[22:0]};
        fraction = fractionA * fractionB;
  • fractionAfractionB 将浮点数的有效数字部分扩展到24位(包括隐含的1位)。
  • fractionfractionAfractionB 的乘积结果,占48位。
  • 示例计算过程,实际计算没有点号:
verilog 复制代码
        fractionA = {1'b1, floatA[2:0]};
        fractionB = {1'b1, floatB[2:0]};
        fraction = fractionA * fractionB;

Layer 1 1 1 0 1 1 0 1 1 1 1 0 1 1 1 0 1 0 0 0 0 1 1 0 1 1 0 0 0 1 1 1 1

语句exponent = floatA[30:23] + floatB[30:23] - 8'd127 + 8'd2;

其中- 8'd127的作用

  • floatA[30:23] 和 floatB[30:23] 表示从30位到23位的位值,即分别取浮点数floatA和floatB的指数部分。在IEEE 754单精度浮点格式中,这8位代表了带有偏移量的指数值(即真实指数加上127得到的值)。- 8'd127 这里的8'd127表示一个8位的二进制数,值为127,这是用来去除指数的偏移量。在浮点数中,为了能表示负的指数值,实际的指数是存储的指数值减去一个固定的偏移量,在单精度模式下该偏移量为127。

其中+ 8'd2的作用

  • 8'd2 在计算完两个数的指数之和后,再加上2。这一步骤可能是为了补偿乘法过程中指数的变化。方便后续代码的统一编写。如1.101*1.011=10.001111
    变为浮点数表示的有效数字,除去第一位的1( fraction = fraction << 1; ),变为0001111(表示.0001111,实际上为0.001111),所以表示成实际上的值还需要*2^(1)
    写成代码就是

    exponent = floatA[30:23] + floatB[30:23] - 8'd127;

    if (fraction[47] == 1'b1) begin
    fraction = fraction << 1;
    exponent = exponent + 1;

这里+2后,在处理规格化问题时就能统一成如下代码:

exponent = floatA[30:23] + floatB[30:23] - 8'd127 + 8'd2; 

if (fraction[47] == 1'b1) begin 
	fraction = fraction << 1;
	exponent = exponent - 1; 

生成输出

verilog 复制代码
        mantissa = fraction[47:25];
        product = {sign, exponent, mantissa};
  • mantissafraction 的高24位作为有效数字部分。
  • 最终输出 productsign(符号位)、exponent(指数部分)和 mantissa(有效数字部分)组成。
相关推荐
邹莉斯21 小时前
FPGA基本结构和简单原理
fpga开发·硬件工程
悲喜自渡72121 小时前
易灵思FPGA开发(一)——软件安装
fpga开发
ZxsLoves21 小时前
【【通信协议ARP的verilog实现】】
fpga开发
爱奔跑的虎子1 天前
FPGA与Matlab图像处理之伽马校正
图像处理·matlab·fpga开发·fpga·vivado·xilinx
机器未来2 天前
基于FPGA的SD卡的数据读写实现(SD NAND FLASH)
arm开发·嵌入式硬件·fpga开发
贾saisai2 天前
Xilinx系FPGA学习笔记(八)FPGA与红外遥控
笔记·学习·fpga开发
吉孟雷3 天前
ZYNQ FPGA自学笔记
fpga开发·verilog·led·仿真·vivado·zynq
行者..................3 天前
1. ZYNQ 2. MPSOC 3. FPGA 4. IO分配 5. 硬件设计
fpga开发
tsumikistep3 天前
【无标题】Efinity 0基础进行流水灯项目撰写(FPGA)
fpga开发
行者..................3 天前
FPGA学习 VIVADO Verilog 编程
学习·fpga开发