赞
踩
目录
逐次逼近算法流程如图 1所示,首先数据输入data[7:0],接着设置实验值D_z[3:0]和确定值D_q[3:0],然后按照从高往低的顺序,依次将每一位置1(如D_z[3]置1),再将实验值平方后与输入数据比较,若实验值的平方大于输入值(D_z^2 > data),则此位为0(D_q[3]为0),反之((D_z^2 ≤ data)),此位为1(D_q[3]为1);以此迭代到最后一位。
可见,如果是n bit的数据,那么需要n/2次迭代,每次计算如果一个周期,则需要n/2个周期。
图 1逐次逼近算法框图
// // // 逐次逼近算法 // module sqrt_1 #( parameter d_width = 8, parameter q_width = d_width/2 - 1, parameter r_width = q_width + 1 ) ( input wire clk, input wire rst, input wire i_vaild, input wire [d_width:0] data_i, //输入 output reg o_vaild, output reg [q_width:0] data_o, //输出 output reg [r_width:0] data_r //余数 ); //-------------------------------------------------------------------------------- reg [d_width:0] D [r_width:1]; //被开方数 reg [q_width:0] Q_z [r_width:1]; //临时 reg [q_width:0] Q_q [r_width:1]; //确认 reg ivalid_t [r_width:1]; //-------------------------------------------------------------------------------- always@(posedge clk or posedge rst) begin if(rst) begin D[r_width] <= 0; Q_z[r_width] <= 0; Q_q[r_width] <= 0; ivalid_t[r_width] <= 0; end else if(i_vaild) begin D[r_width] <= data_i; //被开方数据 Q_z[r_width] <= {1'b1,{q_width{1'b0}}}; //实验值设置 Q_q[r_width] <= 0; //实际计算结果 ivalid_t[r_width] <= 1; end else begin D[r_width] <= 0; Q_z[r_width] <= 0; Q_q[r_width] <= 0; ivalid_t[r_width] <= 0; end end //------------------------------------------------------------------------------- // 迭代计算过程 //------------------------------------------------------------------------------- generate genvar i; for(i=r_width-1;i>=1;i=i-1) begin:U always@(posedge clk or posedge rst) begin if(rst) begin D[i] <= 0; Q_z[i] <= 0; Q_q[i] <= 0; ivalid_t[i] <= 0; end else if(ivalid_t[i+1]) begin if(Q_z[i+1]*Q_z[i+1] > D[i+1]) begin Q_z[i] <= {Q_q[i+1][q_width:i],1'b1,{{i-1}{1'b0}}}; Q_q[i] <= Q_q[i+1]; end else begin Q_z[i] <= {Q_z[i+1][q_width:i],1'b1,{{i-1}{1'b0}}}; Q_q[i] <= Q_z[i+1]; end D[i] <= D[i+1]; ivalid_t[i] <= 1; end else begin ivalid_t[i] <= 0; D[i] <= 0; Q_q[i] <= 0; Q_z[i] <= 0; end end end endgenerate //-------------------------------------------------------------------------------- // 计算余数与最终平方根 //-------------------------------------------------------------------------------- always@(posedge clk or posedge rst) begin if(rst) begin data_o <= 0; data_r <= 0; o_vaild <= 0; end else if(ivalid_t[1]) begin if(Q_z[1]*Q_z[1] > D[1]) begin data_o <= Q_q[1]; data_r <= D[1] - Q_q[1]*Q_q[1]; o_vaild <= 1; end else begin data_o <= {Q_q[1][q_width:1],Q_z[1][0]}; data_r <= D[1] - {Q_q[1][q_width:1],Q_z[1][0]}*{Q_q[1][q_width:1],Q_z[1][0]}; o_vaild <= 1; end end else begin data_o <= 0; data_r <= 0; o_vaild <= 0; end end //--------------------------------------------------------------------------------
//--------------------------------------------------------------------------------
`define d_w 8
`define q_w `d_w / 2
`define r_w `q_w + 1
//--------------------------------------------------------------------------------
module tb_sqrt;
//--------------------------------------------------------------------------------
// Inputs
reg clk;
reg rst;
reg i_vaild;
reg [`d_w-1:0] data_i;
// Outputs
wire o_vaild;
wire [`q_w-1:0] data_o;
wire [`r_w-1:0] data_r;
//--------------------------------------------------------------------------------
// Instantiate the Unit Under Test (UUT)
sqrt_1
#(
.d_width ( `d_w-1 ),
.q_width ( `q_w-1 ),
.r_width ( `r_w-1 )
)
uut
(
.clk ( clk ),
.rst ( rst ),
.i_vaild ( i_vaild ),
.data_i ( data_i ),
.o_vaild ( o_vaild ),
.data_o ( data_o ),
.data_r ( data_r )
);
//--------------------------------------------------------------------------------
initial begin
// Initialize Inputs
clk = 0;
rst = 1;
// Wait 100 ns for global reset to finish
#100;
rst = 0;
// Add stimulus here
end
always #5 clk = ~ clk ;
reg [`d_w:0] cnt ;
reg [31:0] a ;
//--------------------------------------------------------------------------------
always@(posedge clk or posedge rst)
begin
if(rst)
begin
i_vaild <= 0;
data_i <= 0;
cnt <= 0;
end
else if(cnt < 10)
begin
i_vaild <= 1;
data_i <= {$random} % 255;
cnt <= cnt + 1;
end
else
begin
i_vaild <= 0;
data_i <= 0;
cnt <= cnt;
end
end
//--------------------------------------------------------------------------------
endmodule
用语句 data_i <= {$random} % 255; 产生一个0~255的随机数进行测试。
仿真结果如图 2所示,计算周期为4个时钟周期,输入数据data_i,开方结果data_o,余数data_r。
图 2 仿真结果
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。