两种逐次逼近的开平方算法sqrt

此处两种算法优势:通过移位、或运算 完成平方值的比较,无需乘法器。

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

 

 

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Verilog中的平方根算法可以使用牛顿迭代法来实现。下面是一个使用牛顿迭代法计算平方根的Verilog代码示例: ```verilog module sqrt_calculator ( input wire [31:0] x, output reg [15:0] sqrt ); reg [15:0] next_sqrt; reg [47:0] diff; always @(x or sqrt) begin next_sqrt = sqrt; diff = (next_sqrt * next_sqrt) - x; if (diff > 0) begin next_sqrt = next_sqrt - 1; diff = (next_sqrt * next_sqrt) - x; end while (diff < 0) begin next_sqrt = next_sqrt + 1; diff = (next_sqrt * next_sqrt) - x; end sqrt = next_sqrt; end endmodule ``` 在这个示例中,我们使用了一个输入端口 `x`,用于指定要计算平方根的数值。输出端口 `sqrt` 将给出计算得到的平方根值。 在 `always` 块中,我们定义了一个迭代过程来逐步逼近平方根。首先,我们将当前的 `sqrt` 值赋给 `next_sqrt`。然后,我们计算 `next_sqrt` 的平方,并将其与输入值 `x` 进行比较,得到 `diff`。 如果 `diff` 大于零,则说明 `next_sqrt` 的平方超过了 `x`,需要将 `next_sqrt` 减一,以使其平方小于或等于 `x`。然后,我们再次计算新的 `diff` 值。 接下来,我们使用一个循环来逐步增加 `next_sqrt` 的值,直到 `diff` 大于或等于零为止。这样,我们就得到了最接近输入值 `x` 的平方根。 最后,我们将计算得到的平方根值赋给输出端口 `sqrt`。 请注意,这只是一个简单的示例,可能存在精度或性能方面的改进空间,具体实现取决于您的需求和资源限制。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值