FPGA除法之迭代除法器

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

  基本的算法如下:

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

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

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

具体实现的代码如下:

 1 // *********************************************************************************
 2 // Project Name : 
 3 // Email        : 
 4 // Create Time  : 2022/02/18 19:08
 5 // Module Name  : Divide
 6 // editor        : Qing
 7 // Version        : Rev1.0.0
 8 // *********************************************************************************
 9 
10 module Divide(
11     input                                clk            ,
12     input                                rst_n        ,
13     
14     input        [27:0]                    divisor        ,
15     input        [27:0]                    dividend    ,
16     
17     output        [27:0]                    quotient    ,
18     output        [13:0]                    shift
19 );
20 
21 //========================================================================\
22 // =========== Define Parameter and Internal signals =========== 
23 //========================================================================/
24 
25 reg                [13:0]                    count        ;
26 reg                [13:0]                    shift_count    ;
27 reg                [27:0]                    divisor_reg    ;
28 reg                [27:0]                    quotient_reg;
29 
30 reg                [27:0]                    remainder_reg;
31 reg                [27:0]                    remainder_temp;
32 
33 reg                [27:0]                    compare        ;
34 
35 reg                                        shift_flag    ;
36 
37 //=============================================================================
38 //****************************     Main Code    *******************************
39 //=============================================================================
40 
41 always @(posedge clk or posedge rst_n) begin
42     if(rst_n) begin
43         compare    <= dividend    - divisor;
44         shift_count <= 28'd0;
45         shift_flag <= 1'b0;
46         divisor_reg <= divisor;
47     end
48     else if(compare[27] == 1'b0) begin
49         shift_count <= shift_count + 1'b1;
50         divisor_reg = divisor_reg << 1;
51         compare <= dividend - divisor_reg;
52     end
53     else begin
54         shift_flag <= 1'b1;
55         divisor_reg <= divisor << (shift_count - 1'b1);
56     end
57 end
58 
59 assign shift = shift_count - 1;
60 
61 always @(posedge clk or posedge rst_n) begin
62     if(rst_n) begin
63         remainder_temp <= 28'd0;
64         count <= 14'd0;
65         remainder_reg <= dividend;
66         quotient_reg <= 28'd0;
67     end
68     else if(shift_flag && (count < 27)) begin
69         remainder_temp = remainder_reg - divisor_reg;
70         if(!remainder_temp[27]) begin
71             quotient_reg <= (quotient_reg << 1) + 1;
72             remainder_reg <= remainder_temp << 1;
73         end
74         else if(remainder_temp[27])begin
75             quotient_reg <= quotient_reg << 1;
76             remainder_reg = remainder_reg << 1;
77         end
78         count <= count + 1'b1;
79     end
80 end
81 
82 assign    quotient = quotient_reg;
83 
84 endmodule
View Code

仿真代码:

 1 `timescale 1ns/1ps
 2 
 3 module    Divide_tb;
 4     reg                                    clk            ;
 5     reg                                    rst_n        ;
 6     
 7     reg            [27:0]                    divisor        ;
 8     reg            [27:0]                    dividend    ;
 9     
10     wire        [27:0]                    quotient    ;
11     wire        [13:0]                    shift        ;
12     
13 Divide Divide_inst(
14     .clk        ( clk            ),
15     .rst_n        ( rst_n            ),
16     .divisor    ( divisor        ),
17     .dividend    ( dividend        ),
18     .quotient    ( quotient        ),
19     .shift        ( shift            )
20 );
21 
22 initial
23     begin
24         $fsdbDumpfile("wave.fsdb");
25         $fsdbDumpvars(0,Divide_tb);
26     end
27 
28 initial
29     clk = 1'b0;
30     always #10 clk = ~clk;
31     
32 initial
33     begin
34         #1;
35         rst_n = 1'b1;
36         divisor = 28'd3;
37         dividend = 28'd200;
38         #201;
39         rst_n = 1'b0;
40         #1000;
41 
42         rst_n = 1'b1;
43         divisor = 28'd7;
44         dividend = 28'd300;
45         #201;
46         rst_n = 1'b0;
47         #1000;
48 
49         rst_n = 1'b1;
50         divisor = 28'd7;
51         dividend = 28'd800;
52         #201;
53         rst_n = 1'b0;
54 
55     
56 
57 
58         #10000000;
59         
60 
61         
62         $finish;
63     end
64     
65 endmodule
View Code

仿真截图如下:

 

上述内容摘录于:https://infinite-zh.com/archives/174

posted @ 2022-02-22 19:39  青河  阅读(519)  评论(0编辑  收藏  举报