当前位置:   article > 正文

基于cordic算法的小数开方及其FPGA实现_cordic开根号

cordic开根号

基于cordic算法的小数开方及其FPGA实现

目录

前言

一、坐标旋转公式推导

二、cordic算法简介

三、cordic IP核配置 

四、仿真

1.顶层代码

2.仿真代码

五、仿真结果分析

总结

参考文献


前言

        现实中很多算法本身就包含开方运算,硬件实现中很多时候也会涉及到开方运算,本次较为详细的介绍用cordic算法实现开方运算的基本原理以及如何使用xilinx公司提供的cordic IP核来完成无符号小数开方运算。


提示:以下是本篇文章正文内容,写文章实属不易,希望能帮助到各位,转载请附上链接。

一、坐标旋转公式推导

        欲明白cordic算法中如何实现开方运算,首先需要知道坐标旋转公式。

        如图1所示,在二维坐标系中,有一点A(x,y),其与原点之间连线的长度为r,连线和x轴正向夹角为\alpha,将其绕原点逆时针旋转\Theta可得到点A^{'}(x^{'},y^{'})

图1 坐标旋转图

 由图知:

x’=rcos(α+θ)=rcosαcosθ−rsinαsinθ    (1.1)

y’=rsin(α+θ)=rsinαcosθ+rcosαsinθ     (1.2)

x=rcosα                                            (1.3)

y=rsinα                                             (1.4)

将(1.3)和(1.4)代入(1.1)和(1.2)可知:

x’=xcosθ−ysinθ                                 (1.5)

y’=xsinθ+ycosθ                                 (1.6)

(1.5)和(1.6)组成的即为坐标旋转公式,写成矩阵形式即为:

 

 注:在word公式编辑器中编辑后复制过来居然有乱码,不兼容,所以以图片形式给出了。

那么如果是顺时针旋转我们由式(1.7)可知只需要将θ用-θ代替即可得到:

 

二、cordic算法简介

         CORDIC 算法最早是由 Volder 提出的,其有两种计算模式:旋转 (Rotation)模式和求模 (Vectoring)模式。它是一种迭代算法,只通过移位操作和加减操作就可以实现任意角度的坐标变换。假设坐标(x,y)旋转角度Ф后得到坐标(x',y'),则:
         如果限定旋转角度Ф ,使 tanФ= ±2^{-i} ,那么由tanФ引入的乘法运算就简化为移位操作。任意角度的旋转可通过一系列\phi =tan^{-1}(2^{-i}) 的角度旋转迭代完成,那么第 i+1 次角度旋转可表示为:
         其中,k_{i}=cos(tan^{-1}(2^{-i}))=\frac{1}{\sqrt{1+2^{-2i}}}di = ±1。如果去掉常数项Ki ,迭代方程(2)就只有移位和加减操作。而常数项可以在系统的其它地方进行补偿,或者直接当作系统的增益。当迭代次数趋于无穷时,常数项趋于0.6073,其倒数趋于1.6467。

        i+1 迭代旋转的角度为:

        d{_{i}}决定每次迭代旋转的方向(逆时针或顺时针),若 z{_{i}} < 0,d{_{i}} = -1;否则 d{_{i}} =1。当 z{_{i+1}} =0 时迭代结束,此时迭代的最终值为:

 

        CORDIC算法也可用于投影计算,即将向量 (x,y)投影到x轴或y轴,当投影到x轴时,迭代方
程为:

        
        若 y_{i}< 0 ,d{_{i}}=1;否则,d{_{i}}= -1,当 y_{i+1}= 0时,迭代结束,迭代的最终值为:  
 
        扩展迭代方程式(2)和式(5),CORDIC 算法可用于计算线形方程和双曲线方程,扩展后方程为:

         e_{i}是每次迭代中的旋转角度。当 m=1 时,e_{i}=tan^{-1}(2^{-i}),此时为正弦方程;当 m=0 时,e_{i}=2^{-i},此时为线性方程;当 m=-1 时, e_{i}=tanh^{-1}(2^{-i}),此时为双曲线方程。

        对于平方根运算采用的是双曲线方程,而且迭代模式为投影模式,迭代的最终值为:
        迭代中的方向 d{_{i}}的选取为,若 y_{i}< 0,d{_{i}}=1;否则, d{_{i}}= -1。
        如果要求值a 的平方根,只需将x_{0} 、y_{0} 分别赋值为:x_{0}=a+1/4,y_{0}=a-1/4,代入式(8),可得x_{n}=\sqrt{\alpha }
 

三、cordic IP核配置

四、仿真

1.顶层代码

  1. `timescale 1ns / 1ps
  2. //
  3. // Company: cq university
  4. // Engineer: clg
  5. // Create Date: 2022/09/01 20:52:25
  6. // Design Name:
  7. // Module Name: square_root
  8. // Project Name:
  9. // Target Devices:
  10. // Tool Versions: 2017.4
  11. // Description:
  12. // Dependencies:
  13. // Revision:1.0
  14. // Revision 0.01 - File Created
  15. // Additional Comments:
  16. //
  17. module square_root(
  18. input clk,
  19. input rst_n,
  20. input data_in_valid,
  21. input [31:0] data_in,
  22. output data_out_valid,
  23. output [31:0] data_out
  24. );
  25. cordic_square u1_cordic_square( //ip核例化
  26. .aclk(clk),
  27. .aresetn(rst_n),
  28. .s_axis_cartesian_tvalid(data_in_valid),
  29. .s_axis_cartesian_tdata(data_in),
  30. .m_axis_dout_tvalid(data_out_valid),
  31. .m_axis_dout_tdata(data_out)
  32. );
  33. endmodule

2.仿真代码

  1. `timescale 1ns / 1ps
  2. //
  3. // Company: cq university
  4. // Engineer: clg
  5. // Create Date: 2022/09/01 21:07:29
  6. // Design Name:
  7. // Module Name: square_root_tb
  8. // Project Name:
  9. // Target Devices: 2017.4
  10. // Tool Versions:
  11. // Description:
  12. // Dependencies:
  13. // Revision:1.0
  14. // Revision 0.01 - File Created
  15. // Additional Comments:
  16. //
  17. module square_root_tb();
  18. reg clk;
  19. reg rst_n;
  20. reg data_in_valid;
  21. reg [31:0] data_in;
  22. wire data_out_valid;
  23. wire [31:0] data_out;
  24. square_root u1_square_root(
  25. .clk(clk),
  26. .rst_n(rst_n),
  27. .data_in_valid(data_in_valid),
  28. .data_in(data_in),
  29. .data_out_valid(data_out_valid),
  30. .data_out(data_out)
  31. );
  32. initial begin
  33. clk=1'b1;rst_n=1'b1;data_in_valid=1'b0;data_in=32'b0;
  34. #10 rst_n=1'b0;
  35. #10 rst_n=1'b1;
  36. #10 data_in_valid=1'b1;data_in=32'b0_001_0000_0000_0000_0000_0000_0000_0000;
  37. #10 data_in_valid=1'b1;data_in=32'b0_111_0000_0000_0000_0000_0000_0000_0000;
  38. end
  39. always #5 clk=!clk;
  40. endmodule

五、仿真结果分析

         如上图所示,从数据输入到数据输出会有32个时钟周期延时(与数据位数长短有关),注意实际的data_in和data_out是图中显示的2倍,因为我是把二进制的结果用定点数显示了,它显示的其实是真实值的一半,(这个运算是正确的,这里的误差完全是为了显示方便带来的一个倍数误差)因为实际上这个IP核开方运算时数据并不是真真正正的定点数,它的第一位算作的是小数点前面的0,其格式如下图所示:

         所以图中仿真的输入为0.4375*2=0.875,输出为0.467707173200324*2=0.93541434346400648,我用计算器对0.875开方得到的结果是0.93541434346693485346,对比可知32位的精度挺高了,到小数点后第11位了,实际使用时完全可以自己根据需要的精度设置运算数据的位数。

总结

        以上就是此次介绍的cordic算法开方。

参考文献

利用 CORDIC 算法计算平方根及其 FPGA 实现

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/不正经/article/detail/471040
推荐阅读
相关标签
  

闽ICP备14008679号