跳转到内容

数字电路/CORDIC

来自维基教科书,开放的书籍,开放的世界

一个 CORDIC (代表 **CO**ordinate **R**otation **DI**gital **C**omputer) 电路用于计算一些常见的数学函数,例如三角函数、双曲函数、对数函数和指数函数。

CORDIC 只使用加法器和位移来计算结果,因此它可以使用相对基本的硬件实现。

像幂级数或查表法通常需要执行乘法。如果硬件乘法器不可用,CORDIC 通常更快,但如果可以使用乘法器,其他方法可能更快。

CORDIC 可以用多种方法实现,包括单级迭代方法,与乘法器电路相比,它需要很少的门。此外,CORDIC 可以使用完全相同的硬件计算许多函数,因此它们非常适合那些将降低成本(例如通过减少 FPGA 中的门数)优先于速度的应用。这种优先级的一个例子是袖珍计算器,其中 CORDIC 被广泛使用。

CORDIC 最初是由 J.E. Volder 于 1959 年在康维尔航空电子部门发明的,它被设计用于 B-58 轰炸机的导航计算机,以取代模拟分解器,一种计算三角函数的设备(圆 CORDIC)。

1971 年,惠普的 J.S. Walther 将该方法扩展到计算双曲函数、自然对数、自然指数、乘法、除法和平方根(线性 CORDIC 和双曲 CORDIC)。

2019 年,基于双曲 CORDIC,罗元勇等人进一步提出了一种广义双曲 CORDIC (GH CORDIC) 来直接计算具有任意固定基数的对数和指数。理论上,双曲 CORDIC 是 GH CORDIC 的特例。

通用概念

[编辑 | 编辑源代码]

考虑以下向量的旋转

  • 从 (1, 0) 开始
  • 旋转 θ
  • 我们得到 (cosθ, sinθ)
  • 从 (1, y) 开始
  • 旋转直到 y = 0
  • 旋转是 tan−1y

如果我们有一个计算效率高的向量旋转方法,我们可以直接计算正弦、余弦和反正切函数。但是,任意角度的旋转并不容易(你必须知道正弦和余弦,而这正是我们所没有的)。我们使用两种方法来简化它

  • 我们不执行旋转,而是执行“伪旋转”,它们更容易计算。
  • 用一组特殊角度 αi 的和来构造所需的角度 θ

下图显示了长度为 Ri 的向量绕原点旋转 ai 角的旋转和伪旋转

绕原点旋转产生以下坐标

回想一下身份 .

我们的策略是消除因子 ,并设法消除乘以 。伪旋转生成一个与旋转向量具有相同角度但长度不同的向量。事实上,伪旋转将长度更改为

因此,我们现在有以下伪旋转后的坐标

伪旋转成功地消除了我们的长度因子,而长度因子本来需要一个代价高昂的除法运算。然而,向量将在n个伪旋转序列中增长K

然后,经过n个伪旋转后的坐标为

前三次伪旋转。注意我们如何收敛到正确的角度,θ

如果角度总是相同的集合,那么 K 是固定的,可以在以后考虑。我们根据两个标准选择这些角度

  • 我们还必须选择角度,以便任何角度都可以通过所有角度的总和来构建,并带有适当的符号。
  • 我们将所有 设置为 2 的幂,以便乘法可以通过二进制数的简单逻辑移位来执行。

正切函数在区间 [0, π/2] 上具有单调递增的梯度,因此给定角度的正切始终小于该角度的一半正切的两倍。这意味着如果我们使角度 ,我们可以满足这两个标准。请注意,正切函数是奇函数,这意味着要以另一种方式进行伪旋转,您只需减去而不是添加角度的正切。

i αi = tan−1 (2−i)
弧度
0 45.00 0.7854
1 26.57 0.4636
2 14.04 0.2450
3 7.13 0.1244
4 3.58 0.0624
5 1.79 0.0312
6 0.90 0.0160
7 0.45 0.0080
8 0.22 0.0040
9 0.11 0.0020

在过程的步骤 i 中,我们以 进行伪旋转,其中 是旋转的方向(或符号),这将在每一步都选择,以迫使角度收敛到所需的最终旋转。例如,考虑 28° 的旋转

我们采取的步骤越多,我们就可以通过连续旋转来进行更好的近似。因此,我们有以下迭代坐标计算

为了达到k位的精度,需要进行k次迭代,因为,随着i的增加而收敛。

使用CORDICs

[编辑 | 编辑源代码]

CORDICs可以用来计算许多函数。一个CORDIC有三个输入,x0, y0z0。根据CORDIC的输入,可以在输出xn, ynzn产生不同的结果。

在旋转模式下使用CORDIC

[编辑 | 编辑源代码]





为了使zn收敛到0,选择.

如果我们从x0 = 1/Ky0=0开始,在过程结束时,我们会发现xn=cos z0yn=sin z0

收敛域是,因为99.7°是列表中所有角度的总和。

在矢量模式下使用CORDIC

[编辑 | 编辑源代码]





为了使yn收敛到0,选择.

如果我们从x0 = 1和z0 = 0开始,我们会发现zn=tan−1y0

CORDICs的实现

[编辑 | 编辑源代码]

位并行,展开

[编辑 | 编辑源代码]

位并行,迭代

[编辑 | 编辑源代码]

如果不需要高速,可以使用一个加法器和一个移位器实现。

逐位串行

[编辑 | 编辑源代码]

通用 CORDIC

[编辑 | 编辑源代码]

通过引入因子μ,我们也可以满足线性函数和双曲函数的需求。

通用 CORDIC 实现的总结

[编辑 | 编辑源代码]
模式 旋转 矢量化
圆形

μ = 1
αi = tan−12−i

线性

μ = 0
αi = 2−i

双曲

μ = -1
αi = tanh−12−i

  • 在双曲模式下,需要重复第 4,13,40,121,...,j,3j+1,... 步。下面的常数K' 可以解释这一点。
  • K = 1.646760258121...
  • 1/K = 0.607252935009...
  • K' = 0.8281593609602...
  • 1/K' = 1.207497067763...

直接可计算函数

[编辑 | 编辑源代码]

间接可计算函数

[编辑 | 编辑源代码]

除了上述函数外,还可以通过组合先前计算结果来生成许多其他函数。

进一步阅读

[编辑 | 编辑源代码]
华夏公益教科书