CORDIC算法原理详解及其Verilog实现
本文的verilog代码
链接:https://pan.baidu.com/s/1GGbRjxO5CxoIODQAg1l6Lw
提取码:jo0h
*本文的Verilog代码均没有考虑象限问题,MATLAB代码有考虑。
*本文参考博客
[1]https://blog.csdn.net/qq_39210023/article/details/77456031
[2]https://blog.csdn.net/longxuekun1992/article/details/52435024

文章目录

  • CORDIC 简介
  • 算法实现
    • 1.已知坐标(x,y),求其向量对应的相角θ(反正切)和模值
      • 1.1 MATLAB代码
      • 1.2 Verilog代码
      • 1.3 testbench A
    • 2.已知角度θ,求正弦sinθ和余弦cosθ
      • 2.1 MATLAB代码
      • 2.2 Verilog代码
      • 2.3 Testbench B

CORDIC 简介

CORDIC(Coordinate Rotation Digital Computer)坐标旋转数字计算机,是数学与计算机技术交叉产生的一种机器算法,用于解决计算机的数学计算问题。发展到现在,CORDIC算法及其扩展算法大致有三种计算模式:圆周旋转模式、线性旋转模式和双曲线旋转模式,分别用来实现不同的数学运算。本文介绍圆周旋转模式下的CORDIC算法原理及实现过程,另两种模式将分期介绍。

简单来讲,CORDIC利用近似逼近的思想,将计算机中三角函数、开根号、求对数等复杂运算,转化为简单的加减和移位操作。

1)算法描述

如图,XY平面中一点( x 1 , y 1 ) 经圆周旋转θ角度,得到点( x 2 , y 2 ) 。经简单的三角函数关系,可得到:

通过提出因数cosθ,可得:

如果不考虑cosθ,得到“伪旋转”方程:

伪旋转仅实现了正确的角度旋转,但向量模值变为原来的1/cosθ。

2)CORDIC方法

注意!上式已经仅剩加减和移位运算。

可以确定的是,任意旋转角度θ,都可以由上表中的大小不同θi进行多次旋转得到。CORDIC正是利用这一点,将θ角度的旋转分解为从大到小、逐次逼近真实旋转角度的一组旋转,而这些旋转的实现又都可以由加减和移位运算来完成。θi可以预先制成表格,供计算机查找使用。

算法实现

1.已知坐标(x,y),求其向量对应的相角θ(反正切)和模值

思想:把原向量逐次向X正轴进行伪旋转逼近,整个过程的累计旋转角度即为θ,而旋转后的x坐标补偿模值增益K后即为原向量模值。

每次迭代的方程为:

模值总增益K为:

其中d决定旋转方向为逆时针还是顺时针,z为角度累加值。

注意!查找表中所有θi的总和约为99度,因此能实现计算的角度在-99~99度之间。实际算法实现时,我们可预先判断坐标象限,人为将其转化为第一象限内的计算,并在事后补偿为真实值。

1.1 MATLAB代码

%% ***********************************************************************************
%     已知坐标,用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))
%% ***********************************************************************************clear;close all;clc;
% 初始化----------------------------------------
N = 16;  %迭代次数
tan_table = 2.^-(0 : N-1);
angle_LUT = atan(tan_table);K = 1;
for k = 0 : N-1K = K*(1/sqrt(1 + 2^(-2*k)));
endx = 3;
y = sqrt(3);
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;elsephase_shift = pi;endfor 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; %弧度输出endamplitude_out = x*K;  %幅值输出
endangle_out = radian_out*180/pi;  %相角输出</span>

1.2 Verilog代码

采用16级流水的Verilog (未考虑象限问题)

//*********************************************************
//功能1:已知角度θ,求正弦sinθ和余弦cosθ//思想:若向量模值为1,则其x坐标就是余弦值,y坐标就是正弦值。
//利用这一点,从(K,0)处迭代旋转至θ处的单位矢量即可。
//*********************************************************module cordic_A(
input           clk,
input           rst_n,
input   [8:0]   angle,
input           start,output    reg signed[31:0]    Sin,
output  reg signed[31:0]    Cos,
output          finished);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
parameter angle_3 = 32'd466944;      //7.1250度*2^16
parameter angle_4 = 32'd234368;      //3.5763度*2^16
parameter angle_5 = 32'd117312;     //1.7899度*2^16
parameter angle_6 = 32'd58688;      //0.8952度*2^16
parameter angle_7 = 32'd29312;      //0.4476度*2^16
parameter angle_8 = 32'd14656;      //0.2238度*2^16
parameter angle_9 = 32'd7360;      //0.1119度*2^16
parameter angle_10 = 32'd3648;      //0.0560度*2^16
parameter angle_11 = 32'd1856;        //0.0280度*2^16
parameter angle_12 = 32'd896;      //0.0140度*2^16
parameter angle_13 = 32'd448;      //0.0070度*2^16
parameter angle_14 = 32'd256;      //0.0035度*2^16
parameter angle_15 = 32'd128;      //0.0018度*2^16parameter pipeline = 16;
parameter K = 32'h09b74;          //0.607253*2^16,// reg signed [31:0] Sin;
// reg signed [31:0] Cos;reg signed     [31:0]      x0 =0,y0 =0,z0 =0;
reg signed  [31:0]      x1 =0,y1 =0,z1 =0;
reg signed  [31:0]      x2 =0,y2 =0,z2 =0;
reg signed  [31:0]      x3 =0,y3 =0,z3 =0;
reg signed  [31:0]      x4 =0,y4 =0,z4 =0;
reg signed  [31:0]      x5 =0,y5 =0,z5 =0;
reg signed  [31:0]      x6 =0,y6 =0,z6 =0;
reg signed  [31:0]      x7 =0,y7 =0,z7 =0;
reg signed  [31:0]      x8 =0,y8 =0,z8 =0;
reg signed  [31:0]      x9 =0,y9 =0,z9 =0;
reg signed  [31:0]      x10=0,y10=0,z10=0;
reg signed  [31:0]      x11=0,y11=0,z11=0;
reg signed  [31:0]      x12=0,y12=0,z12=0;
reg signed  [31:0]      x13=0,y13=0,z13=0;
reg signed  [31:0]      x14=0,y14=0,z14=0;
reg signed  [31:0]      x15=0,y15=0,z15=0;
reg signed  [31:0]      x16=0,y16=0,z16=0;reg  [4:0]           count;always@(posedge clk or negedge rst_n)beginif(!rst_n)count <= 'b0;else if(start)beginif(count != 5'd18)count <= count + 1'b1;else count <= count;end
endassign finished = (count == 5'd18)?1'b1:1'b0;always@(posedge clk or negedge rst_n)beginif(!rst_n)beginx0 <= 'b0;y0 <= 'b0;z0 <= 'b0;endelse beginx0 <= K;y0 <= 32'd0;z0 <= angle << 16;end
end always@(posedge clk or negedge rst_n)begin//第一次迭代if(!rst_n)beginx1 <= 'b0;y1 <= 'b0;z1 <= 'b0;endelse if(z0[31]) beginx1 <= x0 + y0;y1 <= y0 - x0;z1 <= z0 + angle_0;endelse beginx1 <= x0 - y0;y1 <= y0 + x0;z1 <= z0 - angle_0;        end
end always@(posedge clk or negedge rst_n)begin//第二次迭代if(!rst_n)beginx2 <= 'b0;y2 <= 'b0;z2 <= 'b0;endelse if(z1[31]) beginx2 <= x1 + (y1>>>1);y2 <= y1 - (x1>>>1);z2 <= z1 + angle_1;endelse beginx2 <= x1 - (y1>>>1);y2 <= y1 + (x1>>>1);z2 <= z1 - angle_1;    end
end always@(posedge clk or negedge rst_n)begin//第3次迭代if(!rst_n)beginx3 <= 'b0;y3 <= 'b0;z3 <= 'b0;endelse if(z2[31]) beginx3 <= x2 + (y2>>>2);y3 <= y2 - (x2>>>2);z3 <= z2 + angle_2;endelse beginx3 <= x2 - (y2>>>2);y3 <= y2 + (x2>>>2);z3 <= z2 - angle_2;    end
end always@(posedge clk or negedge rst_n)begin//第4次迭代if(!rst_n)beginx4 <= 'b0;y4 <= 'b0;z4 <= 'b0;endelse if(z3[31]) beginx4 <= x3 + (y3>>>3);y4 <= y3 - (x3>>>3);z4 <= z3 + angle_3;endelse beginx4 <= x3 - (y3>>>3);y4 <= y3 + (x3>>>3);z4 <= z3 - angle_3;    end
end always@(posedge clk or negedge rst_n)begin//第5次迭代if(!rst_n)beginx5 <= 'b0;y5 <= 'b0;z5 <= 'b0;endelse if(z4[31]) beginx5 <= x4 + (y4>>>4);y5 <= y4 - (x4>>>4);z5 <= z4 + angle_4;endelse beginx5 <= x4 - (y4>>>4);y5 <= y4 + (x4>>>4);z5 <= z4 - angle_4;    end
end always@(posedge clk or negedge rst_n)begin//第6次迭代if(!rst_n)beginx6 <= 'b0;y6 <= 'b0;z6 <= 'b0;endelse if(z5[31]) beginx6 <= x5 + (y5>>>5);y6 <= y5 - (x5>>>5);z6 <= z5 + angle_5;endelse beginx6 <= x5 - (y5>>>5);y6 <= y5 + (x5>>>5);z6 <= z5 - angle_5;    end
end always@(posedge clk or negedge rst_n)begin//第7次迭代if(!rst_n)beginx7 <= 'b0;y7 <= 'b0;z7 <= 'b0;endelse if(z6[31]) beginx7 <= x6 + (y6>>>6);y7 <= y6 - (x6>>>6);z7 <= z6 + angle_6;endelse beginx7 <= x6 - (y6>>>6);y7 <= y6 + (x6>>>6);z7 <= z6 - angle_6;    end
end always@(posedge clk or negedge rst_n)begin//第8次迭代if(!rst_n)beginx8 <= 'b0;y8 <= 'b0;z8 <= 'b0;endelse if(z7[31]) beginx8 <= x7 + (y7>>>7);y8 <= y7 - (x7>>>7);z8 <= z7 + angle_7;endelse beginx8 <= x7 - (y7>>>7);y8 <= y7 + (x7>>>7);z8 <= z7 - angle_7;    end
end always@(posedge clk or negedge rst_n)begin//第9次迭代if(!rst_n)beginx9 <= 'b0;y9 <= 'b0;z9 <= 'b0;endelse if(z8[31]) beginx9 <= x8 + (y8>>>8);y9 <= y8 - (x8>>>8);z9 <= z8 + angle_8;endelse beginx9 <= x8 - (y8>>>8);y9 <= y8 + (x8>>>8);z9 <= z8 - angle_8;    end
end always@(posedge clk or negedge rst_n)begin//第10次迭代if(!rst_n)beginx10 <= 'b0;y10 <= 'b0;z10 <= 'b0;endelse if(z9[31]) beginx10 <= x9 + (y9>>>9);y10 <= y9 - (x9>>>9);z10 <= z9 + angle_9;endelse beginx10 <= x9 - (y9>>>9);y10 <= y9 + (x9>>>9);z10 <= z9 - angle_9;  end
end always@(posedge clk or negedge rst_n)begin//第11次迭代if(!rst_n)beginx11 <= 'b0;y11 <= 'b0;z11 <= 'b0;endelse if(z10[31]) beginx11 <= x10 + (y10>>>10);y11 <= y10 - (x10>>>10);z11 <= z10 + angle_10;endelse beginx11 <= x10 - (y10>>>10);y11 <= y10 + (x10>>>10);z11 <= z10 - angle_10; end
end always@(posedge clk or negedge rst_n)begin//第12次迭代if(!rst_n)beginx12 <= 'b0;y12 <= 'b0;z12 <= 'b0;endelse if(z11[31]) beginx12 <= x11 + (y11>>>11);y12 <= y11 - (x11>>>11);z12 <= z11 + angle_11;endelse beginx12 <= x11 - (y11>>>11);y12 <= y11 + (x11>>>11);z12 <= z11 - angle_11; end
end always@(posedge clk or negedge rst_n)begin//第13次迭代if(!rst_n)beginx13 <= 'b0;y13 <= 'b0;z13 <= 'b0;endelse if(z12[31]) beginx13 <= x12 + (y12>>>12);y13 <= y12 - (x12>>>12);z13 <= z12 + angle_12;endelse beginx13 <= x12 - (y12>>>12);y13 <= y12 + (x12>>>12);z13 <= z12 - angle_12; end
end always@(posedge clk or negedge rst_n)begin//第14次迭代if(!rst_n)beginx14 <= 'b0;y14 <= 'b0;z14 <= 'b0;endelse if(z13[31]) beginx14 <= x13 + (y13>>>13);y14 <= y13 - (x13>>>13);z14 <= z13 + angle_13;endelse beginx14 <= x13 - (y13>>>13);y14 <= y13 + (x13>>>13);z14 <= z13 - angle_13; end
end always@(posedge clk or negedge rst_n)begin//第15次迭代if(!rst_n)beginx15 <= 'b0;y15 <= 'b0;z15 <= 'b0;endelse if(z14[31]) beginx15 <= x14 + (y14>>>14);y15 <= y14 - (x14>>>14);z15 <= z14 + angle_14;endelse beginx15 <= x14 - (y14>>>14);y15 <= y14 + (x14>>>14);z15 <= z14 - angle_14; end
end always@(posedge clk or negedge rst_n)begin//第16次迭代if(!rst_n)beginx16 <= 'b0;y16 <= 'b0;z16 <= 'b0;endelse if(z15[31]) beginx16 <= x15 + (y15>>>15);y16 <= y15 - (x15>>>15);z16 <= z15 + angle_15;endelse beginx16 <= x15 - (y15>>>15);y16 <= y15 + (x15>>>15);z16 <= z15 - angle_15; end
end always@(posedge clk or negedge rst_n)beginif(!rst_n)beginCos <= 'b0;Sin <= 'b0;endelse beginSin = y16;Cos = x16;end
end endmodule

1.3 testbench A

输入连续5个时钟上升沿输入60°,30°,45°,90°,30°,看是否能够连续输出相应结果。

`timescale 1ns/1psmodule cordic_Atb();parameter PERIOD = 10;
reg clk;
reg rst_n;
reg [8:0]angle;
reg start;wire   [31:0]         Sin;
wire     [31:0]         Cos;
wire                    finished;initial beginclk = 0;rst_n = 0;start = 0;angle = 'b0;#100 rst_n =1;#10 @(posedge clk) start = 1'b1;angle = 9'd60;#10 @(posedge clk)                angle = 9'd30;#10 @(posedge clk)                 angle = 9'd45;#10 @(posedge clk)                 angle = 9'd90;#10 @(posedge clk)                 angle = 9'd30;#100000 $stop;
endalways #(PERIOD/2) clk = ~clk;cordic_A inst1(.clk(clk),.rst_n(rst_n),.angle(angle),.start(start),.Sin(Sin),.Cos(Cos),.finished(finished));endmodule

由于硬件实现将数据整体左移16位,从而换区更高精度,因此得到的结果需要向右移16位,进行还原。还原后我们发现跟预期的值相等。

2.已知角度θ,求正弦sinθ和余弦cosθ

思想:若向量模值为1,则其x坐标就是余弦值,y坐标就是正弦值。利用这一点,从(K,0)处迭代旋转至θ处的单位矢量即可。

迭代方程及K的计算同第一小节。同时也要注意预先对象限的判断和补偿。

2.1 MATLAB代码

%% ***********************************************************************************
%     已知相角theta,计算其正弦和余弦值。基本公式如下:
%     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))
%% ***********************************************************************************
clear;close all;clc;% 初始化----------------------------------------
N = 16;  %迭代次数
tan_table = 2.^-(0 : N-1);
angle_LUT = atan(tan_table);K = 1;
for k = 0 : N-1K = K*(1/sqrt(1 + 2^(-2*k)));
endtheta = -90;
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;
elsesign_x = 1;sign_y = 1;
endfor 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
endcos_out = sign_x*x*K;  %余弦输出
sin_out = sign_y*y*K;   %正弦输出</span>

2.2 Verilog代码

16级流水的Verilog代码如下:

//*********************************************************
//已知坐标(x,y),求其向量对应的相角θ(反正切)和模值//思想:把原向量逐次向X正轴进行伪旋转逼近.
//整个过程的累计旋转角度即为θ,
//而旋转后的x坐标补偿模值增益K后即为原向量模值。
//*********************************************************module cordic_B(
input                       clk,
input                       rst_n,
input   signed [31:0]       x,
input   signed [31:0]       y,
input                       start,
output  reg signed[31:0]    angle,
output  reg signed[31:0]    mozhi,
output                      finished
);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
parameter angle_3 = 32'd466944;      //7.1250度*2^16
parameter angle_4 = 32'd234368;      //3.5763度*2^16
parameter angle_5 = 32'd117312;     //1.7899度*2^16
parameter angle_6 = 32'd58688;      //0.8952度*2^16
parameter angle_7 = 32'd29312;      //0.4476度*2^16
parameter angle_8 = 32'd14656;      //0.2238度*2^16
parameter angle_9 = 32'd7360;      //0.1119度*2^16
parameter angle_10 = 32'd3648;      //0.0560度*2^16
parameter angle_11 = 32'd1856;        //0.0280度*2^16
parameter angle_12 = 32'd896;      //0.0140度*2^16
parameter angle_13 = 32'd448;      //0.0070度*2^16
parameter angle_14 = 32'd256;      //0.0035度*2^16
parameter angle_15 = 32'd128;      //0.0018度*2^16parameter pipeline = 16;
parameter K = 32'h09b74;          //0.607253*2^16,// reg signed [31:0] Sin;
// reg signed [31:0] Cos;reg signed     [31:0]      x0 =0,y0 =0,z0 =0;
reg signed  [31:0]      x1 =0,y1 =0,z1 =0;
reg signed  [31:0]      x2 =0,y2 =0,z2 =0;
reg signed  [31:0]      x3 =0,y3 =0,z3 =0;
reg signed  [31:0]      x4 =0,y4 =0,z4 =0;
reg signed  [31:0]      x5 =0,y5 =0,z5 =0;
reg signed  [31:0]      x6 =0,y6 =0,z6 =0;
reg signed  [31:0]      x7 =0,y7 =0,z7 =0;
reg signed  [31:0]      x8 =0,y8 =0,z8 =0;
reg signed  [31:0]      x9 =0,y9 =0,z9 =0;
reg signed  [31:0]      x10=0,y10=0,z10=0;
reg signed  [31:0]      x11=0,y11=0,z11=0;
reg signed  [31:0]      x12=0,y12=0,z12=0;
reg signed  [31:0]      x13=0,y13=0,z13=0;
reg signed  [31:0]      x14=0,y14=0,z14=0;
reg signed  [31:0]      x15=0,y15=0,z15=0;
reg signed  [31:0]      x16=0,y16=0,z16=0;reg  [4:0]           count;always@(posedge clk or negedge rst_n)beginif(!rst_n)count <= 'b0;else if(start)beginif(count != 5'd18)count <= count + 1'b1;else count <= count;end
endassign finished = (count == 5'd18)?1'b1:1'b0;always@(posedge clk or negedge rst_n)beginif(!rst_n)beginx0 <= 'b0;y0 <= 'b0;z0 <= 'b0;endelse beginx0 <= x<<<16;y0 <= y<<<16;z0 <= 'b0;end
end always@(posedge clk or negedge rst_n)begin//第一次迭代if(!rst_n)beginx1 <= 'b0;y1 <= 'b0;z1 <= 'b0;endelse if(!y0[31]) begin                 //和A不同的是,每次判断y坐标的正负,从而决定是顺时针还是逆时针旋转。x1 <= x0 + y0;y1 <= y0 - x0;z1 <= z0 + angle_0;endelse beginx1 <= x0 - y0;y1 <= y0 + x0;z1 <= z0 - angle_0;        end
end always@(posedge clk or negedge rst_n)begin//第二次迭代if(!rst_n)beginx2 <= 'b0;y2 <= 'b0;z2 <= 'b0;endelse if(!y1[31]) beginx2 <= x1 + (y1>>>1);y2 <= y1 - (x1>>>1);z2 <= z1 + angle_1;endelse beginx2 <= x1 - (y1>>>1);y2 <= y1 + (x1>>>1);z2 <= z1 - angle_1;   end
end always@(posedge clk or negedge rst_n)begin//第3次迭代if(!rst_n)beginx3 <= 'b0;y3 <= 'b0;z3 <= 'b0;endelse if(!y2[31]) beginx3 <= x2 + (y2>>>2);y3 <= y2 - (x2>>>2);z3 <= z2 + angle_2;endelse beginx3 <= x2 - (y2>>>2);y3 <= y2 + (x2>>>2);z3 <= z2 - angle_2;   end
end always@(posedge clk or negedge rst_n)begin//第4次迭代if(!rst_n)beginx4 <= 'b0;y4 <= 'b0;z4 <= 'b0;endelse if(!y3[31]) beginx4 <= x3 + (y3>>>3);y4 <= y3 - (x3>>>3);z4 <= z3 + angle_3;endelse beginx4 <= x3 - (y3>>>3);y4 <= y3 + (x3>>>3);z4 <= z3 - angle_3;   end
end always@(posedge clk or negedge rst_n)begin//第5次迭代if(!rst_n)beginx5 <= 'b0;y5 <= 'b0;z5 <= 'b0;endelse if(!y4[31]) beginx5 <= x4 + (y4>>>4);y5 <= y4 - (x4>>>4);z5 <= z4 + angle_4;endelse beginx5 <= x4 - (y4>>>4);y5 <= y4 + (x4>>>4);z5 <= z4 - angle_4;   end
end always@(posedge clk or negedge rst_n)begin//第6次迭代if(!rst_n)beginx6 <= 'b0;y6 <= 'b0;z6 <= 'b0;endelse if(!y5[31]) beginx6 <= x5 + (y5>>>5);y6 <= y5 - (x5>>>5);z6 <= z5 + angle_5;endelse beginx6 <= x5 - (y5>>>5);y6 <= y5 + (x5>>>5);z6 <= z5 - angle_5;   end
end always@(posedge clk or negedge rst_n)begin//第7次迭代if(!rst_n)beginx7 <= 'b0;y7 <= 'b0;z7 <= 'b0;endelse if(!y6[31]) beginx7 <= x6 + (y6>>>6);y7 <= y6 - (x6>>>6);z7 <= z6 + angle_6;endelse beginx7 <= x6 - (y6>>>6);y7 <= y6 + (x6>>>6);z7 <= z6 - angle_6;   end
end always@(posedge clk or negedge rst_n)begin//第8次迭代if(!rst_n)beginx8 <= 'b0;y8 <= 'b0;z8 <= 'b0;endelse if(!y7[31]) beginx8 <= x7 + (y7>>>7);y8 <= y7 - (x7>>>7);z8 <= z7 + angle_7;endelse beginx8 <= x7 - (y7>>>7);y8 <= y7 + (x7>>>7);z8 <= z7 - angle_7;   end
end always@(posedge clk or negedge rst_n)begin//第9次迭代if(!rst_n)beginx9 <= 'b0;y9 <= 'b0;z9 <= 'b0;endelse if(!y8[31]) beginx9 <= x8 + (y8>>>8);y9 <= y8 - (x8>>>8);z9 <= z8 + angle_8;endelse beginx9 <= x8 - (y8>>>8);y9 <= y8 + (x8>>>8);z9 <= z8 - angle_8;   end
end always@(posedge clk or negedge rst_n)begin//第10次迭代if(!rst_n)beginx10 <= 'b0;y10 <= 'b0;z10 <= 'b0;endelse if(!y9[31]) beginx10 <= x9 + (y9>>>9);y10 <= y9 - (x9>>>9);z10 <= z9 + angle_9;endelse beginx10 <= x9 - (y9>>>9);y10 <= y9 + (x9>>>9);z10 <= z9 - angle_9; end
end always@(posedge clk or negedge rst_n)begin//第11次迭代if(!rst_n)beginx11 <= 'b0;y11 <= 'b0;z11 <= 'b0;endelse if(!y10[31]) beginx11 <= x10 + (y10>>>10);y11 <= y10 - (x10>>>10);z11 <= z10 + angle_10;endelse beginx11 <= x10 - (y10>>>10);y11 <= y10 + (x10>>>10);z11 <= z10 - angle_10;    end
end always@(posedge clk or negedge rst_n)begin//第12次迭代if(!rst_n)beginx12 <= 'b0;y12 <= 'b0;z12 <= 'b0;endelse if(!y11[31]) beginx12 <= x11 + (y11>>>11);y12 <= y11 - (x11>>>11);z12 <= z11 + angle_11;endelse beginx12 <= x11 - (y11>>>11);y12 <= y11 + (x11>>>11);z12 <= z11 - angle_11;    end
end always@(posedge clk or negedge rst_n)begin//第13次迭代if(!rst_n)beginx13 <= 'b0;y13 <= 'b0;z13 <= 'b0;endelse if(!y12[31]) beginx13 <= x12 + (y12>>>12);y13 <= y12 - (x12>>>12);z13 <= z12 + angle_12;endelse beginx13 <= x12 - (y12>>>12);y13 <= y12 + (x12>>>12);z13 <= z12 - angle_12;    end
end always@(posedge clk or negedge rst_n)begin//第14次迭代if(!rst_n)beginx14 <= 'b0;y14 <= 'b0;z14 <= 'b0;endelse if(!y13[31]) beginx14 <= x13 + (y13>>>13);y14 <= y13 - (x13>>>13);z14 <= z13 + angle_13;endelse beginx14 <= x13 - (y13>>>13);y14 <= y13 + (x13>>>13);z14 <= z13 - angle_13;    end
end always@(posedge clk or negedge rst_n)begin//第15次迭代if(!rst_n)beginx15 <= 'b0;y15 <= 'b0;z15 <= 'b0;endelse if(!y14[31]) beginx15 <= x14 + (y14>>>14);y15 <= y14 - (x14>>>14);z15 <= z14 + angle_14;endelse beginx15 <= x14 - (y14>>>14);y15 <= y14 + (x14>>>14);z15 <= z14 - angle_14;    end
end always@(posedge clk or negedge rst_n)begin//第16次迭代if(!rst_n)beginx16 <= 'b0;y16 <= 'b0;z16 <= 'b0;endelse if(!y15[31]) beginx16 <= x15 + (y15>>>15);y16 <= y15 - (x15>>>15);z16 <= z15 + angle_15;endelse beginx16 <= x15 - (y15>>>15);y16 <= y15 + (x15>>>15);z16 <= z15 - angle_15;    end
end wire[31:0]  mozhi_tmp;
wire[31:0]  mozhi_tmp1;
wire[31:0]  mozhi_tmp2;assign mozhi_tmp = x16>>>6;
assign mozhi_tmp1 = mozhi_tmp+mozhi_tmp+mozhi_tmp+mozhi_tmp+mozhi_tmp+mozhi_tmp+mozhi_tmp;
assign mozhi_tmp2 = x16>>>1;always@(posedge clk or negedge rst_n)beginif(!rst_n)beginmozhi <= 'b0;angle <= 'b0;endelse beginmozhi  = (mozhi_tmp1 + mozhi_tmp2)>>>16;angle   = z16>>>16;end
end endmodule

2.3 Testbench B

Testbench代码如下:

`timescale 1ns/1psmodule cordic_Btb();parameter PERIOD = 10;
reg clk;
reg rst_n;
reg signed [31:0] x;
reg signed [31:0] y;
reg start;
wire signed [31:0]  angle;
wire signed [31:0]  mozhi;
wire finished;
initial beginclk = 0;rst_n = 0;x = 'b0;y = 'b0;start = 0;#100 rst_n = 1;#10 @(posedge clk) start = 1; x = 9'd100 ;  y = 9'd100 ;#10 @(posedge clk)               x = 9'd10;        y = 9'd10;#10 @(posedge clk)                 x = 9'd3 ;        y = 9'd4 ;#10 @(posedge clk)                 x = 9'd6 ;        y = 9'd8 ;#100000 $stop;
endalways #(PERIOD/2) clk = ~clk;cordic_B inst1(.clk(clk),.rst_n(rst_n),.x(x),.y(y),.start(start),.angle(angle),.mozhi(mozhi),.finished(finished));
endmodule

相应仿真波形如下图所示:

可以看到,输入的(x,y)为(100,100)时,其夹角θ \thetaθ=45°,模值近似为141。其他情况同理。

CORDIC算法原理详解及其Verilog实现相关推荐

  1. CRF(条件随机场)与Viterbi(维特比)算法原理详解

    摘自:https://mp.weixin.qq.com/s/GXbFxlExDtjtQe-OPwfokA https://www.cnblogs.com/zhibei/p/9391014.html C ...

  2. TOPSIS(逼近理想解)算法原理详解与代码实现

    写在前面: 个人理解:针对存在多项指标,多个方案的方案评价分析方法,也就是根据已存在的一份数据,判断数据中各个方案的优劣.中心思想是首先确定各项指标的最优理想值(正理想值)和最劣理想值(负理想解),所 ...

  3. 离线强化学习(Offline RL)系列3: (算法篇)策略约束 - BRAC算法原理详解与实现(经验篇)

    论文原文:[Yifan Wu, George Tucker, Ofir Nachum: "Behavior Regularized Offline Reinforcement Learnin ...

  4. 一致性哈希算法原理详解

    一.普通 hash 算法 (取模算法): 在了解一致性哈希算法之前,我们先了解一下缓存中的一个应用场景,了解了这个应用场景之后,再来理解一致性哈希算法,就容易多了,也更能体现出一致性哈希算法的优点,那 ...

  5. DES加解密算法原理详解与实现

    [DES密码编写] 1. Equipment (1) operating system version :WIN 10 (2) CPU instruction set: x 64 (3) softwa ...

  6. 机器学习,深度学习基础算法原理详解(图的搜索、交叉验证、PAC框架、VC-维(持续更新))

    机器学习,深度学习基础算法原理详解(图的搜索.交叉验证.PAC框架.VC-维.支持向量机.核方法(持续更新)) 机器学习,深度学习基础算法原理详解(数据结构部分(持续更新)) 文章目录 1. 图的搜索 ...

  7. XGBoost核心算法原理详解

    XGBoost算法原理详解 前言 boosting和bagging的区别 bagging boosting 提升树-基于残差的训练 学习路径 构造目标函数 Additive Training(叠加式的 ...

  8. DPC密度峰值聚类算法原理详解二

    DPC密度峰值聚类算法原理详解二 1.计算数据点两两之间的距离 1.使用 Numpy 模块查找两点之间的欧几里得距离: 2.使用 distance.euclidean() 函数查找两点之间的欧式距离: ...

  9. Isolation Forest算法原理详解

    本文只介绍原论文中的 Isolation Forest 孤立点检测算法的原理,实际的代码实现详解请参照我的另一篇博客:Isolation Forest算法实现详解. 或者读者可以到我的GitHub上去 ...

最新文章

  1. Finding the Edges (Sobel Operator)
  2. java 对象转json json转对象
  3. mode: 'history', 去掉路由地址的#
  4. html5的新增的标签和废除的标签
  5. 【小朋友才做选择题】跟着团队一起学习人工智能,先人一步掌握最前沿知识
  6. window 如何查看tomcat 实时日志_如何处理生产环境Tomcat的catalina.out日志?
  7. java设计模式观察者模式吗_Java设计模式之观察者模式原理与用法详解
  8. C语言文件路径中的”/“和“\“
  9. 如何经营一家培训机构?
  10. mvc图片上传到服务器
  11. 常用的英文文献引用格式
  12. SketchUp Pro 2021 v21.0.391 草图大师安装说明
  13. Mac/Win Photoshop CC 2018(V19.0)安装破解激活图文教程(附破解补丁)
  14. 韩昊20190912-1 每周例行报告
  15. 谁的java视频教程好_初学Java编程看谁的Java视频教程好一些
  16. 2063:【例1.4】牛吃牧草
  17. 机器学习系列文章-决策树
  18. archlinux安装kde常见的问题(无法登录,黑屏,无法调节亮度等)
  19. 探索式测试--第八章(软件测试的未来)--读书笔记
  20. 【云原生 | Kubernetes 实战】01、K8s-v1.25集群搭建和部署基于网页的 K8s 用户界面 Dashboard

热门文章

  1. SAP ABAP 业务对象 BUS6041 AssetSubCostRev 后续资产成本和收入 BAPI 清单和相关 TCODE
  2. 国科大学习资料--最优化计算方法(王晓)--期末考试试卷1
  3. 超级计算机模拟生命起源,科学家研究发现,地球生命起源与远古碰撞有关,这是怎么回事?...
  4. 理解你的排序操作(stable_sort,sort,partial_sort,nth_element,stable_partition,partition)
  5. 有趣的计算机课作文,一堂有趣的课作文(精选4篇)
  6. 利用C语言实现二叉搜索树的遍历、查找、插入、删除
  7. Android 铃铛简单摇摆动画
  8. 如何让ecshop做淘宝客
  9. Hadoop官网使用教程
  10. 活用async/await,实现一些让Vue更好用的装饰器