您现在的位置是:首页 > 正文

CORDIC算法的matlab和FPGA实现

2024-02-01 04:19:21阅读 2

目录

1.算法原理

2.matlab实现

2.1 在已知坐标,用cordic算法计算相角

2.2 在已知相角,用cordic算法计算正余弦

3.FPGA实现

3.1 简单的状态机结构 

3.1.1 verilog代码 

3.1.2 仿真结果

3.2 高速全流水线结构  

3.2.1 verilog代码 

 3.2.2 RTL视图

3.2.3 仿真结果

3.2.4 思考拓展 


1.算法原理

CORDIC算法原理参考《FPGA并行编程》中的第三章,此书中有c代码实现,链接如下:

https://xupsh.github.io/pp4fpgas-cn/

2.matlab实现

2.1 在已知坐标,用cordic算法计算相角

%% ***********************************************************************************
%   再已知坐标,用cordic算法计算相角。
%   此代码引用博主"数字IC",并加以修改 
%% ***********************************************************************************

%% 初始化
N = 18;  %迭代次数
tan_table = 2.^-(0 : N-1);
angle_LUT = atan(tan_table);

K = 1;
for k = 0 : N-1
    K = K*(1/sqrt(1 + 2^(-2*k)));
end

x = cos(pi);
y = sin(pi);
angle_accumulate = 0;

%% cordic算法计算-------------------------------
if (x==0 && y==0) 
    radian_out = 0;
    amplitude_out = 0;
else  % 先做象限判断,得到相位补偿值
    if (x > 0)
        phase_shift = 0;
    elseif (y < 0)
        phase_shift = -pi;
        x=-y;
        y=x;
    else
        phase_shift = pi;
        x=y;
        y=-x;
    end
  
    for k = 0 : N-1   % 迭代开始
        x_temp = x;
        if (y < 0)  % d(k)=1,逆时针旋转
            x = x_temp - y*2^(-k);
            y = y + x_temp*2^(-k);
            angle_accumulate = angle_accumulate - angle_LUT(k+1);
        else          % d(k)=-1,顺时针旋转
            x = x_temp + y*2^(-k);
            y = y - x_temp*2^(-k);
            angle_accumulate = angle_accumulate + angle_LUT(k+1);
        end     
        radian_out = angle_accumulate + phase_shift; %弧度输出 
    end
    
end   
angle_out = radian_out*180/pi;  %相角输出</span>

2.2 在已知相角,用cordic算法计算正余弦

%% ***********************************************************************************
%   再已知相角,用cordic算法计算正余弦。
%   此代码引用博主"数字IC"
%% ***********************************************************************************

% 初始化----------------------------------------
N = 16;  %迭代次数
tan_table = 2.^-(0 : N-1);
angle_LUT = atan(tan_table);

K = 1;
for k = 0 : N-1
    K = K*(1/sqrt(1 + 2^(-2*k)));
end

theta = -120;
x = 1;
y = 0;
phase_accumulate = theta/180*pi;  %转化为弧度

% cordic算法计算-------------------------------
if (phase_accumulate > pi/2)  % 先做象限判断,得到相位补偿值
    phase_accumulate = phase_accumulate - pi;
    sign_x = -1;
    sign_y = -1;
elseif (phase_accumulate < -pi/2)
    phase_accumulate = phase_accumulate + pi;
    sign_x = -1;
    sign_y = -1;
else
    sign_x = 1;
    sign_y = 1;
end
     
 for k = 0 : N-1   % 迭代开始
        x_temp = x;
        if (phase_accumulate > 0)  % d(k)=1,逆时针旋转
            x = x_temp - y*2^(-k);
            y = y + x_temp*2^(-k);
            phase_accumulate = phase_accumulate - angle_LUT(k+1);
        else                                     % d(k)=-1,顺时针旋转
            x = x_temp + y*2^(-k);
            y = y - x_temp*2^(-k);
            phase_accumulate = phase_accumulate + angle_LUT(k+1);
        end
end
    
cos_out = sign_x*x*K;  %余弦输出
sin_out = sign_y*y*K;   %正弦输出</span>

3.FPGA实现

cordic算法有两种 体系结构:为简单的状态机高速全流水线处理器,下面分别给出两种结构实现在已知正余弦情况求相角

3.1 简单的状态机结构 

3.1.1 verilog代码 

3.1.2 仿真结果

3.2 高速全流水线结构  

3.2.1 verilog代码 

//***********************************************************************************
// 已知坐标,用cordic算法计算相角和幅值。基本公式如下:
// x(k+1) = x(k) - d(k)*y(k)*2^(-k)
// y(k+1) = y(k) + d(k)*x(k)*2^(-k)
// z(k) = z(k) - d(k)*actan(2^(-k))
//***********************************************************************************

module cordic_parallel #(parameter W = 31)  // Bit width - 1
(input  clk,                 // System clock
 input  rst,               // Asynchronous rst
 input  signed [W:0] x_in,   // System real or x input
 input  signed [W:0] y_in,   // System imaginary or y input
 output reg signed [W:0] phi // Phase result
 );
  parameter angle_0 = 32'd2949120;		//45度*2^16
  parameter angle_1 = 32'd1740992;     //26.5651度*2^16
  parameter angle_2 = 32'd919872;      //14.0362度*2^16

  reg signed [W:0] x [0:3]; 
  reg signed [W:0] y [0:3]; 
  reg signed [W:0] z [0:3]; 

  always @(posedge rst or posedge clk) begin:P1
    integer k; // Loop variable
    if (rst) begin             // Asynchronous clear
      for (k=0; k<=3; k=k+1) begin
        x[k] <= 0; y[k] <= 0; z[k] <= 0; 
      end
      phi <= 0;
    end else begin
      if (x_in >= 0)            // Test for x_in < 0 rotate
        begin                   // 0, +90, or -90 degrees
          x[0] <= x_in<<<16; // Input in register 0
          y[0] <= y_in<<<16;
          z[0] <= 0;
        end
      else if (y_in >= 0) 
        begin
          x[0] <= y_in;
          y[0] <= - x_in;
          z[0] <= 90;
        end
      else
        begin
          x[0] <= - y_in;
          y[0] <= x_in;
          z[0] <= -90;
        end

      if (y[0] >= 0)                 // Rotate 45 degrees
        begin
          x[1] <= x[0] + y[0];
          y[1] <= y[0] - x[0];
          z[1] <= z[0] + angle_0;
        end
      else
        begin
          x[1] <= x[0] - y[0];
          y[1] <= y[0] + x[0];
          z[1] <= z[0] - angle_0;
        end

      if (y[1] >= 0)                 // Rotate 26 degrees
        begin
          x[2] <= x[1] + (y[1] >>> 1); // i.e. x[1]+y[1]/2
          y[2] <= y[1] - (x[1] >>> 1); // i.e. y[1]-x[1]/2
          z[2] <= z[1] + angle_1;
        end
      else
        begin
          x[2] <= x[1] - (y[1] >>> 1); // i.e. x[1]-y[1]/2
          y[2] <= y[1] + (x[1] >>> 1); // i.e. y[1]+x[1]/2
          z[2] <= z[1] - angle_1;
        end

      if (y[2] >= 0)                   // Rotate 14 degrees
        begin
          x[3] <= x[2] + (y[2] >>> 2); // i.e. x[2]+y[2]/4
          y[3] <= y[2] - (x[2] >>> 2); // i.e. y[2]-x[2]/4
          z[3] <= z[2] + angle_2;
        end
      else
        begin
          x[3] <= x[2] - (y[2] >>> 2); // i.e. x[2]-y[2]/4
          y[3] <= y[2] + (x[2] >>> 2); // i.e. y[2]+x[2]/4
          z[3] <= z[2] - angle_2;
        end

      phi <= z[3]>>>16;
    end
  end                

endmodule

 3.2.2 RTL视图

3.2.3 仿真结果

 正余弦的值都为100,迭代3次,输出相角应该为57,根据仿真结果可看出复位为0后的第五个时钟周期输出的结果为57,与代码相符,仿真结果如下: 

`timescale 1ns/1ps

module cordic_parallel_tb();

parameter PERIOD = 10;
reg clk;
reg rst;
reg signed [31:0] x;
reg signed [31:0] y;
wire signed [31:0] 	angle;
initial begin
	clk = 1;
	rst = 1;
	x = 9'd100;
	y = 9'd100;
	#100 rst = 0;	
	#100000 $stop;	
end

always #PERIOD clk = ~clk;

cordic_parallel inst1(
		.clk(clk),
		.rst(rst),
		.x_in(x),
		.y_in(y),
		
		.phi(angle)		
);
endmodule

3.2.4 思考拓展 

若将上述verilog代码中的非阻塞型赋值(<=)改为阻塞型赋值(=)结果会如?RTL视图会有怎样的变化?,同样的仿真代码,仿真结果如下:

 可见,复位为0后的第1个时钟周期输出的结果就为57,而<=的情况第5个时钟周期输出才为57,接下来看一下RTL视图有什么不一样?

网站文章

  • Python自动化框架搭建——日志收集

    学习日志收集的基本使用方法

    2024-02-01 04:19:13
  • 【MongoDB】深入了解MongoDB不可不知的十点

    一、对象ID的生成 每个mongoDB文档那个都要求有一个主键,它在每个集合中对所有的文档必须是唯一的,主键存放在文档_id字段中。由12个字符组成; 4c291856 238d3b 19b2 000001 4字节时间戳 机器ID 进程ID 计数器3333 二、BSON BSON是mongodb中用来标示文档的二进制格式,它既是存储格式,也是命令格式。所有文档都以bson存储在磁盘上,所...

    2024-02-01 04:18:44
  • Android - 文件读写操作 总结

    在Android中的文件放在不同位置,它们的读取方式也有一些不同。本文对android中对资源文件的读取、数据区文件的读取、SD卡文件的读取及RandomAccessFile的方式和方法进行了整理。供参考。

    2024-02-01 04:18:37
  • 编译原理学习:TINY语言词法扫描程序实现 热门推荐

    《编译原理及实现》上的TINY语言词法扫描器的实现。并做了如下改善: 1、允许嵌套注释 2、标识符允许出现数字,但是必需以字母开头(和C语言一样)

    2024-02-01 04:18:32
  • 重定向解决浏览器刷新后数据多次存入的问题

    当在浏览器提交表单, 提交成功后浏览器将跳转到一个新的html页面 提交成功后如果刷新页面 跳转方式如果是转发, 数据库将多存入数据一次原来数据 public class SaveServlet ex...

    2024-02-01 04:18:03
  • 在Vue中使用Tinymce富文本编辑器+上传图片到七牛

    在Vue中使用Tinymce富文本编辑器+上传图片到七牛

    公司官网后台需要做一个上传新闻、公告的功能,自然而然就需要用到了富文本编辑器。UEditor、Simditor、wangEditor、CKEditor、TinyMCE、Quill,这是当前比较热门的几...

    2024-02-01 04:17:48
  • Vue项目性能分析工具--webpack-bundle-analyzer

    Vue项目性能分析工具--webpack-bundle-analyzer

    在优化项目的时候,每次打包后只知道包文件大,却不知道那个文件大,那个文件还有优化的空间,所以,推荐一款工具,只要在项目中安装配置一下,便可以一目了然的呈现出打包后资源所占的比例,接下来上教程: 我的项...

    2024-02-01 04:17:40
  • html改有序列表的序号颜色,CSS3 自定义OL/LI有序列表序号样式

    CSS语言:CSSSCSS确定@import url(https://fonts.googleapis.com/css?family=Rambla:400,400italic,700);html {b...

    2024-02-01 04:17:12
  • 表格与表单

    表格与表单

    表格、表单

    2024-02-01 04:17:04
  • .htaccess的301重定向代码汇总

    很久以前做过一个图片站,很久没有打理了。域名不打算续费了,但是这么多年的权重不能浪费了啊!于是我决定将它301跳转到另一个域名的子域名,在到期之前传递点权重。.htaccess的301重定向方式有以下几种:1.把不带www的域名301重定向到带www的域名

    2024-02-01 04:16:58