此处两种算法优势:通过移位、或运算 完成平方值的比较,无需乘法器。
1、方法一
根据被开方数位宽,从结果的最到位[ (asize/2)-1]到最低位[0]逐次逼近。核心代码理解:
tt = (v << (i + 1)) | (1 << (i + i))=2*v*2^i + 2^(2*i) = (v+2^i)^2 - v^2;// | 相当于加法。
v+2^i表示结果v的第[i]bit 新变为1,则tt代表v[i]=1后,v^2的增量。
每次变位完,需要从被开方总数r-增量tt,剩余值继续用于判断后续bit变位。
parameter asize = 52;//输入数据位宽
input [asize-1:0] a;
output reg [(asize/2)-1:0] z;
reg [asize-1:0] v, r, tt;
always @(a) begin //此段代码只适用于仿真,无法综合
integer i;
// r is remainder,
// tt 增加1个bit后平方值的增量
// v is current sqrt value
v = 0;
r = a;
for(i = asize/2 - 1; i >= 0; i = i - 1) begin//i循环0~25
tt = (v << (i + 1)) | (1 << (i + i));
if(tt <= r) begin
v = v | (1 << i);//v的对应位置1
r = r - tt;
end
end
z = v;
end
2、方法二
被开方数ai为32位,结果位宽[15:0],ai[15]=1时平方值=32'h4000_0000=2^30=(2^15)*(2^15),右移15位又得到ai[15]=1。
按照每位的平方值m逐次逼近,每次m>>2,直到m>0
parameter m_s = 32'h4000_0000;
parameter a_s = 32'd1000;
reg [31:0] y = 0;
reg [31:0] b,result;//开方结果
reg [31:0] t;
reg [31:0] m = m_s;
reg [31:0] ai= a_s;//ai为输入的32bits 数据
always @(posedge clk) begin
if (m>0) m <= m>>2;
else
result <= ( (y !=65535 ) && (a_s > (y*y+y)) ) ? y+1 :y;//做舍入判断 +1
end
always @( * ) begin //此段代码只适用于仿真,无法综合
if(m>0) begin
b = y | m;//最新平方和 的累加
y = y>>1; //平方和通过每次移位,缩小为开方值
t = (ai>b) ? 32'hffff_ffff : 32'h0000_0000 ;//ai>b 表示当前bit有效为1
ai = ai - (b & t);//平方和 的剩余未分解值
y = y | (m & t);//相当于有效平方和 的累加
end
end