FPGA除法——迭代除法

FPGA的除法运算有恢复余数法、不恢复余数法(加减交替法)、Goldschmidt方法、泰勒级数展开等,今天来介绍一种较为简单的迭代除法,以及仿真验证。

基本的算法如下

如图介绍了算法的基本流程,在实现的方面,需要注意以下几点:

1、首先需要先要进行归一化,在这里我们默认被除数是大于除数的,然后我们需要将除数归一化到小于被除数但大于等于1/2的被除数。

2、以移位的次数作为结束的标志,这里我们一共移位6次。

具体实现的代码如下

// 迭代除法
// Author:Infinite
// Date:2020-4-2
// url:https://infinite-zh.com/
module Divide(
	input clk,
	input rst,
	input [7:0] divisor,
	input [7:0] dividend,
	output [7:0] quotient,
	output [3:0] shift
);
 
reg [3:0] count;  //迭代计数器
reg [3:0] shiftcount; 
reg [7:0] divisorReg;
reg [7:0] quotientReg;
reg [7:0] remainderReg;
reg [7:0] remainderTemp;
reg [7:0] compare;
reg shiftflag;
 
//进行归一化、并且输出结果需要移位的位数
always @(posedge clk or posedge rst) begin
	if (rst) begin
		// reset
		compare <= dividend - divisor;
		shiftcount <= 0;
		shiftflag <= 0;
		divisorReg <= divisor;
	end
	else if (!compare[7]) begin //判断是否是负数
		shiftcount <= shiftcount + 1;
		divisorReg = divisorReg << 1;
		compare <= dividend - divisorReg;
	end	
	else begin
		shiftflag <= 1;
		divisorReg <= divisor << (shiftcount - 1);
	end
end
 
assign shift = shiftcount - 1; //移位的位数
 
 
always @(posedge clk or posedge rst) begin
	if (rst) begin
		// reset
		remainderTemp <= 0;
		count <= 0;
		remainderReg <= dividend;
		quotientReg <= 0;
	end
	else if (shiftflag && (count < 7)) begin
		remainderTemp = remainderReg - divisorReg;
		if(!remainderTemp[7]) //判断是否是正数
		begin
			quotientReg <= (quotientReg << 1) + 1;
			remainderReg = remainderTemp << 1;
		end
		else if(remainderTemp[7]) //判断是否是负数
		begin
			quotientReg <= quotientReg <<1;
			remainderReg = remainderReg << 1;
		end
		count <= count + 1;
	end
end
assign quotient = quotientReg; //输出的结果 最高位为符号位
endmodule

仿真结果如下所示

图中可以看到因为shift为1,最高位为符号位,因此实际上是11/3=11.01010,13/4=100.0101。

如果需要精度更高,可以增加迭代次数,得到更多的位数。

头像

SNinfinite

立志成为Double E的程序猿

You may also like...

发表评论

电子邮件地址不会被公开。 必填项已用*标注