FPGA除法——迭代除法
FPGA除法——迭代除法

FPGA除法——迭代除法

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

基本的算法如下

image-20220823112749614

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

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

仿真结果如下所示

img

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

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

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

基本的算法如下

image-20220823112749614

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

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

仿真结果如下所示

img

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

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

发表回复

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