热度 21
2012-8-22 09:19
3469 次阅读|
1 个评论
专题五:开方运算 开方运算虽然不像加法、乘法那么常用,但是也有其用武之地。在去年的一个项目中,笔者负责的模块中就使用了开方运算,开始时使用的是Altera的IP Core,验证模块使用没有问题;但是因为平台转换,需要转换到Xilinx的平台,许多IP Core也需要转移,最后干脆自己写一个得了,包括前几个专题中的乘法器、除法器。 开方运算模块也使用与除法器类似的NonRestoring算法,包含输入D、输出开方结果Q和余数R;在FPGA中实现,则采用迭代方式一步步逼近结果,其中每一级的迭代式为:T i+1 =T i (3 – T i 2 )/2,T i 是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, output reg Q, output reg R, input ivalid, output reg ovalid ); reg D_t ; reg Q_t ; reg signed R_t ; reg ivalid_t ; always@(posedge clk) begin if(rst) begin R_t ={r_width{1'b0}}; D_t ={d_width{1'b0}}; Q_t ={q_width{1'b0}}; ivalid_t =1'b0; end else begin if(ivalid) begin R_t ={R ,D } - {{q_width-1{1'b0}},2'b01}; D_t =D; Q_t ={q_width{1'b0}}; ivalid_t =1'b1; end else begin R_t ={r_width{1'b0}}; D_t ={d_width{1'b0}}; Q_t ={q_width{1'b0}}; ivalid_t =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 ={q_width{1'b0}}; R_t ={r_width{1'b0}}; D_t ={d_width{1'b0}}; ivalid_t =1'b0; end else begin if(ivalid_t ) begin if(R_t =0) begin Q_t ={Q_t ,1'b1}; R_t ={R_t ,D_t } - {1'b0,Q_t ,1'b1,2'b01}; D_t =D_t ; ivalid_t =1'b1; end else begin Q_t ={Q_t ,1'b0}; R_t ={R_t ,D_t } + {1'b0,Q_t ,1'b0,2'b11}; D_t =D_t ; ivalid_t =1'b1; end end else begin Q_t ={q_width{1'b0}}; R_t ={r_width{1'b0}}; D_t ={d_width{1'b0}}; ivalid_t =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 ) begin if(R_t =0) begin Q={Q_t ,1'b1}; R=R_t ; end else begin Q={Q_t ,1'b0}; R=R_t + {1'b0,Q_t ,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所示为仿真图: 图1