(转载)FPGA实现开发运算verilog

http://bbs.ednchina.com/BLOG_ARTICLE_3003247.HTM

 

专题五:开方运算

开方运算虽然不像加法、乘法那么常用,但是也有其用武之地。在去年的一个项目中,笔者负责的模块中就使用了开方运算,开始时使用的是Altera的IP Core,验证模块使用没有问题;但是因为平台转换,需要转换到Xilinx的平台,许多IP Core也需要转移,最后干脆自己写一个得了,包括前几个专题中的乘法器、除法器。

开方运算模块也使用与除法器类似的NonRestoring算法,包含输入D、输出开方结果Q和余数R;在FPGA中实现,则采用迭代方式一步步逼近结果,其中每一级的迭代式为:Ti+1=Ti(3 – Ti2)/2,Ti是1/Q的近似值。

Verilog HDL代码如下:

module sqrt

#( parameter d_width=32,

             q_width=d_width/2,

             r_width=q_width + 1)

(

    input clk,

    input rst,

    input [d_width-1:0] D,

    output reg [q_width-1:0] Q,

    output reg [r_width-1:0] R,

    input ivalid,

    output reg ovalid

 );

 

reg [d_width-1:0] D_t[q_width:1];

reg [q_width-1:0] Q_t[q_width:1];

reg signed [r_width-1:0] R_t[q_width:1];

reg ivalid_t[q_width:1];

 

always@(posedge clk)

begin

         if(rst)

         begin

                   R_t[q_width]<={r_width{1'b0}};

    D_t[q_width]<={d_width{1'b0}};

    Q_t[q_width]<={q_width{1'b0}};

    ivalid_t[q_width]<=1'b0;

         end

         else

         begin

    if(ivalid)

    begin

      R_t[q_width]<={R[r_width-3:0],D[d_width-1:d_width-2]} - {{q_width-1{1'b0}},2'b01};

      D_t[q_width]<=D;

      Q_t[q_width]<={q_width{1'b0}};

      ivalid_t[q_width]<=1'b1;

    end

    else

    begin

      R_t[q_width]<={r_width{1'b0}};

      D_t[q_width]<={d_width{1'b0}};

      Q_t[q_width]<={q_width{1'b0}};

      ivalid_t[q_width]<=1'b0;

    end

         end

end

        

generate

genvar i;

for(i=q_width-1;i>=1;i=i-1)

begin:U

         always@(posedge clk)

         begin

                   if(rst)

                   begin

                            Q_t[i]<={q_width{1'b0}};

                            R_t[i]<={r_width{1'b0}};

             D_t[i]<={d_width{1'b0}};

             ivalid_t[i]<=1'b0;

                   end

                   else

                   begin

                            if(ivalid_t[i+1])

                            begin

                                     if(R_t[i+1]>=0)

                                     begin

                                               Q_t[i]<={Q_t[i+1][q_width-2:0],1'b1};

                                               R_t[i]<={R_t[i+1][r_width-3:0],D_t[i+1][2*i-1:2*i-2]} - {1'b0,Q_t[i+1][q_width-4:0],1'b1,2'b01};

                                D_t[i]<=D_t[i+1];

                                ivalid_t[i]<=1'b1;

                              end

                              else

                              begin

                                   Q_t[i]<={Q_t[i+1][q_width-2:0],1'b0};

                                               R_t[i]<={R_t[i+1][r_width-3:0],D_t[i+1][2*i-1:2*i-2]} + {1'b0,Q_t[i+1][q_width-4:0],1'b0,2'b11};

                                D_t[i]<=D_t[i+1];

                                ivalid_t[i]<=1'b1;

                              end

                     end

                     else

                     begin

                          Q_t[i]<={q_width{1'b0}};

                                     R_t[i]<={r_width{1'b0}};

                       D_t[i]<={d_width{1'b0}};

                       ivalid_t[i]<=1'b0;

                     end

                   end

         end

end

endgenerate

 

always@(posedge clk)

begin

         if(rst)

         begin

                   Q<={q_width{1'b0}};

                   R<={r_width{1'b0}};

                   ovalid<=1'b0;

         end

         else

         begin

                   if(ivalid_t[1])

                   begin

                            if(R_t[1]>=0)   

                            begin

                                     Q<={Q_t[1][q_width-2:0],1'b1};

                                     R<=R_t[1];

                            end

                            else

                            begin

                                     Q<={Q_t[1][q_width-2:0],1'b0};

                                     R<=R_t[1] + {1'b0,Q_t[1][q_width-3:0],1'b0,1'b1};

                            end

                            ovalid<=1'b1;

                   end

                   else

                   begin

                            Q<={q_width{1'b0}};

                            R<={r_width{1'b0}};

                            ovalid<=1'b0;

                   end

         end

end

 

endmodule

         综合结果如下:

Number of Slice Registers:             677

Number of Slice LUTs:                 1105

Minimum period: 3.726ns (Maximum Frequency: 268.384MHz)

         如图1所示为仿真图:

snap1.jpg

图1

posted @ 2016-04-14 15:04  努力的人会幸运  阅读(712)  评论(0编辑  收藏  举报