基于FPGA的数字信号处理3.7开平方运算分析

开平方运算(Non-Restoring)

在书《基于FPGA的数字信号处理》中的开平方运算一节中,作者给出了一种基于Non-Restoring的算法,但是没有给出具体推导过程,本文试图给出算法的简单证明。熟悉十位数的开方运算的读者可以跳转到第二部分

十位数的开平方运算

对于十位数的开方运算,我们有许多算法,比如泰勒展开、牛顿迭代法、利用常数0x5f375a86加速收敛的牛顿迭代法等。在书中使用的是Non-Restoring算法,本文就专门讨论这个算法。
对于一个6位的十位数D,它的每一位用dn表示,即
D = d 5 d 4 d 3 d 2 d 1 d 0 D=d_5d_4d_3d_2d_1d_0 D=d5d4d3d2d1d0
它的n次根号的位数为 6 / n位,不严谨的简单证明如下:
一个数字a的整数部分长度为n,小数部分长度为无限长,它的平方的取值范围即为 [ 1 0 n , 1 0 n + 2 ] [10^n,10^{n+2}] [10n,10n+2]

类比除法的运算规则,我们可以利用迭代的减法操作,从高位到低位逐级算出解。
回顾除法运算,例如除法算式 1354 / 3 1354/3 1354/3,我们有如下操作
151 3  ⁣ ⁣ ⁣ ⁣ ⁣ ⁣ ) 1354 ‾ 12      ‾ 15    15    ‾ 4 3 ‾ 1 \begin{array}{lr} & 151 \\ 3 \!\!\!\!\!\! & \overline{)1354} \\ & \underline{12\ \ \ \ } \\ & 15\ \ \\ & \underline{15\ \ } \\ & 4 \\ & \underline{3}\\ & 1 & \end{array} 3151)135412    15  15  431
为了取得每一位的解,在每一位上,我们都需要找出数字n,n满足两个条件:

  1. n是正整数且只有一位,对于十进制取值范围为{0,1,2,3,4,5,6,7,8,9}。
  2. {上一次运算的余项,本次运算的被除数对应位} - n * 除数 的值 为最小值。

我们来看看根号的手解法。
D = d 5 d 4 d 3 d 2 d 1 d 0 D=d_5d_4d_3d_2d_1d_0 D=d5d4d3d2d1d0
Q = D = q 2 q 1 q 0 = q 2 ∗ 1 0 2 + q 1 ∗ 10 + q 0 Q=\sqrt{D}=q_2q_1q_0=q_2*10^2+q_1*10+q_0 Q=D =q2q1q0=q2102+q110+q0
当我们要计算Q时, q 2 q_2 q2的值可以由 d 5 d 4 d_5d_4 d5d4直接平方后试减得到,如 598213 \sqrt{598213} 598213 的百位为7。
可以把算出来的数字设置为a(上句话运算结果为a=700),下一位待计算的值为b。我们可以利用 ( a + b ) 2 − a 2 = 2 a b + b 2 (a+b)^2-a^2=2ab+b^2 (a+b)2a2=2ab+b2试出数字b,b满足两个条件:

  1. b是正整数,对于十进制,最高位取值范围为{0,1,2,3,4,5,6,7,8,9},其余位为0。
  2. 2 a b + b 2 2ab+b^2 2ab+b2 - {上一次运算的余项,本次运算的被除数对应位} 的值 为最小值。

如果a、b的值不包含未计算部分,则上述条件将会有些许变化:

  1. b是正整数且只有一位,对于十进制,取值范围为{0,1,2,3,4,5,6,7,8,9}
  2. {上一次运算的余项,本次运算的被除数对应位} 20 a b + b 2 20ab+b^2 20ab+b2 的值 为最小值。

一个例子是
7     7     3    ⁣ ⁣ ⁣ ⁣ ⁣ ⁣ 59   82   13 49            ‾ 10   82       10   29       ‾ 53   13 46   29 ‾ 6   84 \begin{array}{lr} & 7\ \ \ 7\ \ \ 3\ \\ \!\!\!\!\!\! & \sqrt{59\ 82\ 13}\\ & \underline{49\ \ \ \ \ \ \ \ \ \ } \\ & 10\ 82\ \ \ \ \ \\ & \underline{10\ 29\ \ \ \ \ } \\ & 53\ 13\\ & \underline{46\ 29}\\ & 6\ 84 & \end{array} 7   7   3 59 82 13 49          10 82     10 29     53 1346 296 84
795213 = 77 3 2 + 684 \sqrt{795213} = 773^2+684 795213 =7732+684

a前次余项+本次运算块 20 a b + b 2 20ab+b^2 20ab+b2b
059497
7108210297
77531346293
773684--

对于n次根号,我们需要将被n次开方处理的数字每n位分割。将上述迭代减法的计算式换成 ( a + b ) n − a n (a+b)^n-a^n (a+b)nan即可。

fpga上的开平方运算

针对上述算法我们可以进行电路实现。首先面临的就是进制转换问题。二进制数字的平方与十进制数有很多相似之处,比如:

  1. 一个定点数二进制数字a的整数部分(无符号位)长度为n,小数部分长度为无限长,它的平方的取值范围即为 [ 2 n , 2 n + 2 ] [2^n,2^{n+2}] [2n,2n+2]
  2. 它的n次根号的位数为 6 / n位
  3. 迭代计算中用到的式子同样是 ( a + b ) 2 − a 2 (a+b)^2-a^2 (a+b)2a2(a、b包括未计算部分),第二种形式为 4 a b + b 2 4ab+b^2 4ab+b2(a、b不包括未计算部分)

不过,二进制数有一些有利的性质,我们可以利用他们来简化大量计算,如迭代用的式子 4 a b + b 2 4ab+b^2 4ab+b2,用二进制表示可以优化为 ( 100 ) b a b + ( b ) 2 = ( a b   0 b ) b (100)_bab+(b)^2=(ab\ 0b)_b (100)bab+(b)2=(ab 0b)b 其中a为一串二进制数,b为一位二进制数。

当迭代的减法式子写作 ( a b   0 b ) b (ab\ 0b)_b (ab 0b)b时:
1     1     0     1  ⁣ ⁣ ⁣ ⁣ ⁣ ⁣ 10   10   10   01 01                 ‾ 01   10            1   01            ‾ 01   10       00   00       ‾ 1   10   01 1   10   01 ‾ 0 \begin{array}{lr} & 1\ \ \ 1\ \ \ 0\ \ \ 1\\ \!\!\!\!\!\! & \sqrt{10\ 10\ 10\ 01}\\ & \underline{01\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ } \\ & 01 \ 10\ \ \ \ \ \ \ \ \ \ \\ & \underline{1\ 01\ \ \ \ \ \ \ \ \ \ } \\ & 01\ 10\ \ \ \ \ \\ & \underline{00\ 00\ \ \ \ \ }\\ & 1\ 10\ 01\\ & \underline{1\ 10\ 01 }\\ &0 & \end{array} 1   1   0   110 10 10 01 01               01 10          1 01          01 10     00 00     1 10 011 10 010
( 10101001 ) b = ( 1101 ) b 2 \sqrt{(10101001)_b} = (1101)_b^2 (10101001)b =(1101)b2

a前次余项+本次运算块 ( a b   0 b ) b (ab\ 0b)_b (ab 0b)bb
00100011
101101011
11011000000
11011001110011
11010--

此计算过程可以用恢复余数算法表示。
在这里插入图片描述
当相减后b<0时,需要恢复相减之前的值。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

Restoring 算法很直观,但存在的问题是:若当前部分余数为负时,需要额外的加法操作使其恢复到前一次迭代时产生的部分余数。这不仅需要额外的资源,还增加了Latency。是否可以不恢复余数呢?这需要对算法进行一定的修改。
由式(3.62)可知,式(3.63)可重写为 r 0 = r 1 D ( 1 ) D ( 0 ) + q 2 0100 − q 1 01 r_0=r_1D(1)D(0)+q_20100-q_101 r0=r1D(1)D(0)+q20100q101
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

书中的开平方运算

在《基于FPGA的数字信号处理》一书中,用到的算法(Non Restoring)如下:
在这里插入图片描述

简单分析可知,书中算法比我们的算法大致相同,不过为了保持运算的一致性,将减法操作统一为加法。图片中有一个错误,即 0 S 3 S 2 11 0S_3S_211 0S3S211应该为 0 S 3 S 2 S 1 11 0S_3S_2S_111 0S3S2S111
看懂这个算法需要两个小知识点:

  1. A - B = A + ( -B) ,等于A的补码加(-B)的补码
  2. if (A >= B) A+补(B)将会产生进位
    else if(A < B) A+补(B)将不会产生进位

我们可以根据 补 ( 余数 : 当前项 ) + 迭代式 补({余数:当前项})+迭代式 (余数:当前项)+迭代式 是否产生进位来决定下一步迭代的迭代式选取。Q(k+1)代表前一次运算的进位情况,补码情况下
由前文可知,
r k = { r k + 1 D ( 2 k + 1 ) D ( 2 k ) − q k + 1 01 if Q(k+1)==1  r k + 1 D ( 2 k + 1 ) D ( 2 k ) + q k + 1 11 ( if Q(k+1)==0 r_k=\begin{cases} r_{k+1}D(2k+1)D(2k) -q_{k+1}01 &\text{if Q(k+1)==1 }\\ r_{k+1}D(2k+1)D(2k) +q_{k+1}11 ( &\text{if Q(k+1)==0} \end{cases} rk={rk+1D(2k+1)D(2k)qk+101rk+1D(2k+1)D(2k)+qk+111(if Q(k+1)==1 if Q(k+1)==0
如果使用补码运算,式子将会修改如下+
r k = { r k + 1 D ( 2 k + 1 ) D ( 2 k ) + 0 q k + 1 11 if Q(k+1)==0 r k + 1 D ( 2 k + 1 ) D ( 2 k ) + 1 q ~ k + 1 11 ( if Q(k+1)==1 r_k=\begin{cases} r_{k+1}D(2k+1)D(2k) +0q_{k+1}11 &\text{if Q(k+1)==0}\\ r_{k+1}D(2k+1)D(2k) +1\widetilde{q}_{k+1}11 ( &\text{if Q(k+1)==1} \end{cases} rk={rk+1D(2k+1)D(2k)+0qk+111rk+1D(2k+1)D(2k)+1q k+111(if Q(k+1)==0if Q(k+1)==1

q k q_k qk r k + 1 D ( 2 k + 1 ) D ( 2 k ) r_{k+1}D(2k+1)D(2k) rk+1D(2k+1)D(2k) Q ( k + 1 )   ?   0 q k + 1 11   :   0 q k + 1 11 Q(k+1)\ ?\ 0q_{k+1}11\ :\ 0q_{k+1}11 Q(k+1) ? 0qk+111 : 0qk+111进位情况
-0101111
10110 1 S ~ 3 11 = 1011 1\widetilde{S}_311=1011 1S 311=10111
1100110 1 S ~ 3 S ~ 2 11 = 10011 1\widetilde{S}_3\widetilde{S}_211=10011 1S 3S 211=100110
110100101 0 S 3 S 2 S 1 11 = 011011 0S_3S_2S_111=011011 0S3S2S111=0110111
11010--
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值