牛顿迭代法求输入数据的倒数(输入数据格式为FP32)

1.Verilog代码

module floatReciprocal(number,enable,clk,output_rec,ack);

parameter DATA_WIDTH=32;
input [DATA_WIDTH-1:0] number; //the number that we need to get the 1/number of
input clk,enable; 
output reg[DATA_WIDTH-1:0] output_rec; // = 1/number
output reg ack;

wire [DATA_WIDTH-1:0] Ddash; // D' = Mantissa of D and exponent of -1
wire [DATA_WIDTH-1:0] P2Ddash; // (-32/17) * D'
wire [DATA_WIDTH-1:0] Xi ; // X[i]= 43/17 - (32/17)D'
wire [DATA_WIDTH-1:0] Xip1; //X[i+1]
wire [DATA_WIDTH-1:0] out0; // X[i]*D'
wire [DATA_WIDTH-1:0] out1; // 1-X[i]*D'
wire [DATA_WIDTH-1:0] out2; // X[i]*(1-X[i]*D')
reg  [DATA_WIDTH-1:0] mux;

localparam P1=32'b01000000001101001011010010110101; // 43/17
localparam P2=32'b10111111111100001111000011110001; // -32/17

assign Ddash={{1'b0,8'b01111110},number[22:0]};

floatMult FM1 (P2,Ddash,P2Ddash); // -(32/17)* D'
floatAdd FADD1 (P2Ddash,P1,Xi); // 43/17 +(-32/17)D'
floatMult FM2 (mux,Ddash,out0); // X[i]*D'
floatAdd FSUB1 (32'b00111111100000000000000000000000,{1'b1,out0[DATA_WIDTH-2:0]},out1); // 1-X[i]*D
floatMult FM3 (mux,out1,out2); // X[i]*(1-X[i]*D')
floatAdd FADD2 (mux,out2,Xip1); //X[i]+X[i]*(1-X[i]*D')

/*always @(number) begin
	//when a new input is entered the ack signal is reset and the mux is Xi
	ack=1'b0; //reset finish bit
	reset=1'b1;
end*/


always @ (negedge clk) begin
	if (enable==1'b0) begin
		mux=Xi;
		ack=1'b0;
	end
	else begin 
		if(mux==Xip1) begin
			ack=1'b1; //set ack bit to show that the division is done
			if(Xip1[30])
			output_rec={{number[31],8'b11111110-number[30:23]},Xip1[22:0]};
			else
			output_rec={{number[31],8'b11111101-number[30:23]},Xip1[22:0]}; //sign of number, new exponent, mantissa of Xip1;127-(number[30:23]-126)
		end 
		else begin
			mux=Xip1; //continue until ack is 1
		end
	end
	
end

endmodule



        如上是一个开源项目的代码,但有些细节可能晦涩难懂,在这里我就谈谈我的理解,如有错误,欢迎指正!

2.牛顿迭代法求解倒数原理

什么是牛顿迭代法?

        百度上的大致意思是这种方法可以解方程,得到方程的近似解,就比如对于f(x)=0这个方程,我们就可以通过牛顿迭代法寻找它的近似根(几何意义很重要,方便理解)。大致操作如下:

对于一个函数f(x)进行泰勒展开有:

这里我们只取一阶,当f(x)=0时,有

转化成迭代的形式则为:

以上就是牛顿迭代法的大致理解,可以通过设置一个初值x0得到x1,再把x1代入迭代公式得到x2,以此往复,最后x的值会越来越趋近f(x)=0时的那个根。

牛顿迭代法求倒数

因为我们要求倒数,所以就有这样一个函数:y=1/x。这里我们设一个函数 f(y)=1/y - x,所以就是求解当f(y)=0时方程的根,带入如上的迭代公式,有

化简后,有

verilog代码中实现的就是这个迭代公式!代码注释中Xi就是初值y0,D‘就是x,为什么用D’不直接用D我之后会谈谈我的理解。

3.Verilog代码理解

对除数D进行缩放得到D'(0.5\leqD'<1):

assign Ddash={{1'b0,8'b01111110},number[22:0]};

由于最开始对D进行缩放得到D‘,故最后得到1/D’,还需要再缩放回去才能得到1/D:

output_rec={{number[31],8'b11111101-number[30:23]},Xip1[22:0]};

求exponent时,代码这里其实进行了化简,这里也能写成8‘d127 - (number[30:23] - 8'd126);

这一项:“(number[30:23] - 8'd126)” ,就是缩放回去;

这一项:“8’d127”,由于0.5\leq D' <1 , 故1<1/D' \leq2,要使1/D'在这个范围内,求出的1/D'的exponent就必须为8’d127;(当然也可以是8‘d128,因为上面是小于等于2,所以加了个if语句判断!!!这个点是我自行修改的,经验证目前无bug)

初值yn(即X[i])为什么要取 43/17 +(-32/17)D' ?

这个点我确实不太理解,可能是反复试验后发现这个初值迭代次数较少,算的比较快叭

4.波形验证

  • 5
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值