热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

cordicsinx代码_使用CORDIC算法求解角度正余弦及Verilog实现

本文是用于记录在了解和学习CORDIC算法期间的收获,以供日后自己及他人参考;并且附上了使用Verilog实现CORDIC算法求解角度的正弦和余弦的代码

本文是用于记录在了解和学习CORDIC算法期间的收获,以供日后自己及他人参考;并且附上了使用Verilog实现CORDIC算法求解角度的正弦和余弦的代码、简单的testbench测试代码、以及在Modelsim下的仿真结果。

本文主要参考了:

感谢!

-------------------------------------------------------------------------------------------------------------

1、算法简介

CORDIC(Coordinate Rotation Digital Computer)算法即坐标旋转数字计算方法,是J.D.Volder1于1959年首次提出,主要用于三角函数、双曲线、指数、对数的计算。该算法通过基本的加和移位运算代替乘法运算,使得矢量的旋转和定向的计算不再需要三角函数、乘法、开方、反三角、指数等函数,计算向量长度并能把直角坐标系转换为极坐标系。因为Cordic 算法只用了移位和加法,很容易用纯硬件来实现,非常适合FPGA实现。

CORDIC算法是天平称重思想在数值运算领域的杰出范例。核心的思想是把非线性的问题变成了线性的迭代问题【4】。

CORDIC算法完成坐标或向量的平面旋转(下图以逆时针旋转为例)。

f67c120755aa642ba7e2124701266c4c.png

旋转后,可得如下向量:

07d65eb4247ca7d7ad41ad40ac9834a5.png

旋转的角度θ经过多次旋转得到的(步步逼近,接近二分查找法),每次旋转一小角度。单步旋转定义如下公式:

13831757cf1cbd88a545a3aa6a3ec80c.png

公式(2)提取cosθ,可修改为:

56b148689a43dafd74aed49499865395.png

修改后的公式把乘法次数从4次改为3次,剩下的乘法运算可以通过选择每次旋转的角度去除,将每一步的正切值选为2的指数(二分查找法),除以2的指数可以通过右移操作完成(verilog)。

每次旋转的角度可以表示为:

a024a552431ccb557c7a1a91ba12d6c7.png

所有迭代角度累加值等于最终需要的旋转角度θ:

005cd6058f2fb6a3b51b962fb89d6363.png

这里Sn为1或者-1,根据旋转方向确定(后面有确定方法,公式(15)),顺时针为-1,逆时针为1。

18b3bb56946cc6b3b1a9637fbc02184f.png

可以得到如下公式:

a2c530557f56752584892ec1396cec0c.png

结合公式(3)和(7),得到公式(8):

36d9c6fcecbce10a73979267e677fb4c.png

到这里,除了余弦值这个系数,算法只要通过简单的移位和加法操作完成。而这个系数可以通过预先计算最终值消掉。首先重新重写这个系数如下:

4838c8b6922efedd40daa48342f56697.png

第二步计算所有的余弦值并相乘,这个值K称为增益系数。

5f958ebc0f5ae89f08ac34d3d64cf0a3.png

由于K值是常量,我们可以先忽略它。

e2ea2c630084131a75e10bf122269dda.png

faeecfe2cf4d5a50607191ff3fa91790.png

到这里我们发现,算法只剩下移位和加减法,这就非常适合硬件实现了,为硬件快速计算三角函数提供了一种新的算法。在进行迭代运算时,需要引入一个新的变量Z,表示需要旋转的角度θ中还没有旋转的角度。

b75998f3946012fd3275bafcce2d68f3.png

这里,我们可以把前面提到确定旋转方向的方法介绍了,就是通过这个变量Z的符号确定。

eb19829968205e84e13c785f7c09f78a.png

a39422859a47392ce4b365d210bfe103.png

通过公式(5)和(15),将未旋转的角度变为0。

一个类编程风格的结构如下,反正切值是预先计算好的。

9c0b6c3b011d6a020293068f83618c3e.png

1.1 旋转模式

旋转模式下,CORDIC算法驱动Z变为0,结合公式(13)和(16),算法的核心计算如下:

7bb141ca143b211f159596122f9fb061.png

一种特殊情况是,另初始值如下:

5287676d36f06881a231127e9e6754e5.png

因此,旋转模式下CORDIC算法可以计算一个输入角度的正弦值和余弦值。

1.2 向量模式

向量模式下,有两种特例:

b18f4a32103638c4bde4cd4804c03c1a.png

因此,向量模式下CORDIC算法可以用来计算输入向量的模和反正切,也能开方计算,并可以将直角坐标转换为极坐标。

2、硬件算法实现

根据【5】,可以看到CORDIC迭代算法的一种直接实现方式是反馈结构,此结构只设计一级CORDIC运算迭代单元、然后在系统时钟的驱动下,将本级的输出作为本级的输入,通过同一级迭代完成运算。这种方法硬件开销小、但控制相对复杂。

所以根据【1】、【2】,使用流水线结构实现了CORDIC迭代算法、求取了角度的正弦和余弦值。

下面分段介绍下各部分代码:

首先是角度的表示,进行了宏定义,360读用16位二进制表示2^16,每一度为2^16/360。

//360°--2^16,phase_in = 16bits (input [15:0] phase_in)//1°--2^16/360

`define rot0 16'h2000 //45

`define rot1 16'h12e4 //26.5651

`define rot2 16'h09fb //14.0362

`define rot3 16'h0511 //7.1250

`define rot4 16'h028b //3.5763

`define rot5 16'h0145 //1.7899

`define rot6 16'h00a3 //0.8952

`define rot7 16'h0051 //0.4476

`define rot8 16'h0028 //0.2238

`define rot9 16'h0014 //0.1119

`define rot10 16'h000a //0.0560

`define rot11 16'h0005 //0.0280

`define rot12 16'h0003 //0.0140

`define rot13 16'h0002 //0.0070

`define rot14 16'h0001 //0.0035

`define rot15 16'h0000 //0.0018

然后是流水线级数定义、增益放大倍数以及中间结果位宽定义。流水线级数16,为了满足精度要求,有文献指出流水线级数必须大于等于角度位宽16(针对正弦余弦计算的CORDIC算法优化及其FPGA实现)。增益放大2^16,为了避免溢出状况中间结果(x,y,z)定义为17为,最高位作为符号位判断,1为负数,0为正数。

modulecordic

(inputclk,

input [15:0] phase_in,output reg signed [16:0] eps,output reg signed [16:0] sin,output reg signed [16:0] cos

);parameter PIPELINE = 16;parameter K = 16'h9b74;

//gian k=0.607253*2^16,9b74,n means the number pipeline//pipeline 16-level//maybe overflow,matlab result not overflow//MSB is signed bit,transform the sin and cos according to phase_in[15:14]

reg signed [16:0] x0=0,y0=0,z0=0;reg signed [16:0] x1=0,y1=0,z1=0;reg signed [16:0] x2=0,y2=0,z2=0;reg signed [16:0] x3=0,y3=0,z3=0;reg signed [16:0] x4=0,y4=0,z4=0;reg signed [16:0] x5=0,y5=0,z5=0;reg signed [16:0] x6=0,y6=0,z6=0;reg signed [16:0] x7=0,y7=0,z7=0;reg signed [16:0] x8=0,y8=0,z8=0;reg signed [16:0] x9=0,y9=0,z9=0;reg signed [16:0] x10=0,y10=0,z10=0;reg signed [16:0] x11=0,y11=0,z11=0;reg signed [16:0] x12=0,y12=0,z12=0;reg signed [16:0] x13=0,y13=0,z13=0;reg signed [16:0] x14=0,y14=0,z14=0;reg signed [16:0] x15=0,y15=0,z15=0;reg signed [16:0] x16=0,y16=0,z16=0;

还需要定义memory型寄存器数组并初始化为0,用于寄存输入角度高2位的值。

reg [1:0] quadrant [PIPELINE:0];integeri;initial

begin

for(i&#61;0;i<&#61;PIPELINE;i&#61;i&#43;1)

quadrant[i]&#61; 2&#39;b0;

end

接着&#xff0c;是对输入角度象限处理&#xff0c;将角度都转换到第一象限&#xff0c;方便处理。输入角度值最高两位赋值0&#xff0c;即转移到第一象限[0°,90°]。此外&#xff0c;完成x0&#xff0c;y0和z0的初始化&#xff0c;并增加一位符号位。

always &#64; (posedge clk)//stage 0,not pipeline

beginx0<&#61; {1&#39;b0,K}; //add one signed bit,0 means positive

y0 <&#61; 17&#39;b0;

z0 <&#61; {3&#39;b0,phase_in[13:0]};//control the phase_in to the range[0-Pi/2]

end

接下来根据剩余待旋转角度z的符号位进行16次迭代处理&#xff0c;即完成16级流水线处理。

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

always &#64; (posedge clk)//stage 1

begin

if(z0[16])//the diff is negative so clockwise

beginx1<&#61; x0 &#43;y0;

y1<&#61; x0 -y0;

z1<&#61; z0 &#43;&#96;rot0;end

else

beginx1<&#61; x0 - y0;//x1 <&#61; x0;

y1 <&#61; x0 &#43; y0;//y1 <&#61; x0;

z1 <&#61; z0 - &#96;rot0;//reversal 45

end

end

always &#64; (posedge clk)//stage 2

begin

if(z1[16])//the diff is negative so clockwise

beginx2<&#61; x1 &#43; (y1>>>4&#39;d1);

y2 <&#61; y1 - (x1>>>4&#39;d1);

z2 <&#61; z1 &#43; &#96;rot1;//clockwise 26

end

else

beginx2<&#61; x1 - (y1>>>4&#39;d1);

y2 <&#61; y1 &#43; (x1>>>4&#39;d1);

z2 <&#61; z1 - &#96;rot1;//anti-clockwise 26

end

end

always &#64; (posedge clk)//stage 3

begin

if(z2[16])//the diff is negative so clockwise

beginx3<&#61; x2 &#43; (y2>>>4&#39;d2); //right shift n bits,divide 2^n

y3 <&#61; y2 - (x2>>>4&#39;d2); //left adds n bits of MSB,in first quadrant x or y are positive,MSB &#61;0 &#xff1f;&#xff1f;

z3 <&#61; z2 &#43; &#96;rot2;//clockwise 14//difference of positive and negtive number and no round(4,5)

end

else

beginx3<&#61; x2 - (y2>>>4&#39;d2);

y3 <&#61; y2 &#43; (x2>>>4&#39;d2);

z3 <&#61; z2 - &#96;rot2;//anti-clockwise 14

end

end

always &#64; (posedge clk)//stage 4

begin

if(z3[16])beginx4<&#61; x3 &#43; (y3>>>4&#39;d3);

y4 <&#61; y3 - (x3>>>4&#39;d3);

z4 <&#61; z3 &#43; &#96;rot3;//clockwise 7

end

else

beginx4<&#61; x3 - (y3>>>4&#39;d3);

y4 <&#61; y3 &#43; (x3>>>4&#39;d3);

z4 <&#61; z3 - &#96;rot3;//anti-clockwise 7

end

end

always &#64; (posedge clk)//stage 5

begin

if(z4[16])beginx5<&#61; x4 &#43; (y4>>>4&#39;d4);

y5 <&#61; y4 - (x4>>>4&#39;d4);

z5 <&#61; z4 &#43; &#96;rot4;//clockwise 3

end

else

beginx5<&#61; x4 - (y4>>>4&#39;d4);

y5 <&#61; y4 &#43; (x4>>>4&#39;d4);

z5 <&#61; z4 - &#96;rot4;//anti-clockwise 3

end

end

always &#64; (posedge clk)//STAGE 6

begin

if(z5[16])beginx6<&#61; x5 &#43; (y5>>>4&#39;d5);

y6 <&#61; y5 - (x5>>>4&#39;d5);

z6 <&#61; z5 &#43; &#96;rot5;//clockwise 1

end

else

beginx6<&#61; x5 - (y5>>>4&#39;d5);

y6 <&#61; y5 &#43; (x5>>>4&#39;d5);

z6 <&#61; z5 - &#96;rot5;//anti-clockwise 1

end

end

always &#64; (posedge clk)//stage 7

begin

if(z6[16])beginx7<&#61; x6 &#43; (y6>>>4&#39;d6);

y7 <&#61; y6 - (x6>>>4&#39;d6);

z7 <&#61; z6 &#43;&#96;rot6;end

else

beginx7<&#61; x6 - (y6>>>4&#39;d6);

y7 <&#61; y6 &#43; (x6>>>4&#39;d6);

z7 <&#61; z6 -&#96;rot6;end

end

always &#64; (posedge clk)//stage 8

begin

if(z7[16])beginx8<&#61; x7 &#43; (y7>>>4&#39;d7);

y8 <&#61; y7 - (x7>>>4&#39;d7);

z8 <&#61; z7 &#43;&#96;rot7;end

else

beginx8<&#61; x7 - (y7>>>4&#39;d7);

y8 <&#61; y7 &#43; (x7>>>4&#39;d7);

z8 <&#61; z7 -&#96;rot7;end

end

always &#64; (posedge clk)//stage 9

begin

if(z8[16])beginx9<&#61; x8 &#43; (y8>>>4&#39;d8);

y9 <&#61; y8 - (x8>>>4&#39;d8);

z9 <&#61; z8 &#43;&#96;rot8;end

else

beginx9<&#61; x8 - (y8>>>4&#39;d8);

y9 <&#61; y8 &#43; (x8>>>4&#39;d8);

z9 <&#61; z8 -&#96;rot8;end

end

always &#64; (posedge clk)//stage 10

begin

if(z9[16])beginx10<&#61; x9 &#43; (y9>>>4&#39;d9);

y10 <&#61; y9 - (x9>>>4&#39;d9);

z10 <&#61; z9 &#43;&#96;rot9;end

else

beginx10<&#61; x9 - (y9>>>4&#39;d9);

y10 <&#61; y9 &#43; (x9>>>4&#39;d9);

z10 <&#61; z9 -&#96;rot9;end

end

always &#64; (posedge clk)//stage 11

begin

if(z10[16])beginx11<&#61; x10 &#43; (y10>>>4&#39;d10);

y11 <&#61; y10 - (x10>>>4&#39;d10);

z11 <&#61; z10 &#43;&#96;rot10;end

else

beginx11<&#61; x10 - (y10>>>4&#39;d10);

y11 <&#61; y10 &#43; (x10>>>4&#39;d10);

z11 <&#61; z10 -&#96;rot10;end

end

always &#64; (posedge clk)//stage 12

begin

if(z11[16])beginx12<&#61; x11 &#43; (y11>>>4&#39;d11);

y12 <&#61; y11 - (x11>>>4&#39;d11);

z12 <&#61; z11 &#43;&#96;rot11;end

else

beginx12<&#61; x11 - (y11>>>4&#39;d11);

y12 <&#61; y11 &#43; (x11>>>4&#39;d11);

z12 <&#61; z11 -&#96;rot11;end

end

always &#64; (posedge clk)//stage 13

begin

if(z12[16])beginx13<&#61; x12 &#43; (y12>>>4&#39;d12);

y13 <&#61; y12 - (x12>>>4&#39;d12);

z13 <&#61; z12 &#43;&#96;rot12;end

else

beginx13<&#61; x12 - (y12>>>4&#39;d12);

y13 <&#61; y12 &#43; (x12>>>4&#39;d12);

z13 <&#61; z12 -&#96;rot12;end

end

always &#64; (posedge clk)//stage 14

begin

if(z13[16])beginx14<&#61; x13 &#43; (y13>>>4&#39;d13);

y14 <&#61; y13 - (x13>>>4&#39;d13);

z14 <&#61; z13 &#43;&#96;rot13;end

else

beginx14<&#61; x13 - (y13>>>4&#39;d13);

y14 <&#61; y13 &#43; (x13>>>4&#39;d13);

z14 <&#61; z13 -&#96;rot13;end

end

always &#64; (posedge clk)//stage 15

begin

if(z14[16])beginx15<&#61; x14 &#43; (y14>>>4&#39;d14);

y15 <&#61; y14 - (x14>>>4&#39;d14);

z15 <&#61; z14 &#43;&#96;rot14;end

else

beginx15<&#61; x14 - (y14>>>4&#39;d14);

y15 <&#61; y14 &#43; (x14>>>4&#39;d14);

z15 <&#61; z14 -&#96;rot14;end

end

always &#64; (posedge clk)//stage 16

begin

if(z15[16])beginx16<&#61; x15 &#43; (y15>>>4&#39;d15);

y16 <&#61; y15 - (x15>>>4&#39;d15);

z16 <&#61; z15 &#43;&#96;rot15;end

else

beginx16<&#61; x15 - (y15>>>4&#39;d15);

y16 <&#61; y15 &#43; (x15>>>4&#39;d15);

z16 <&#61; z15 -&#96;rot15;end

end

View Code

其中使用到了算数右移(>>>)运算、所以在之前声明时将相应的reg/wire均声明为signed类型。这一点在【1】的最后也有说明。

需要注意的是这里的算数移位运算(这一运算的详细过程在【3】中进行了说明)&#xff0c;与之区分的是逻辑移位运算。

二者规则为&#xff1a;

逻辑左移和右移&#xff0c;空出的位均补零。

算数左移与逻辑左移相同&#xff0c;都在低位补零&#xff1b;算数右移、移出的高位比特使用符号位填充(0正1负)

举例说明&#xff0c;对8&#39;b_1011_0111进行逻辑、算数移位的结果如下图所示&#xff1a;

f467200798117046ef71b2750d7767cd.png

比如这里的原数值是8&#39;b10110111、为负数(补码形式)、换算成十进制为-73.

算数右移一位之后的结果是8&#39;b11011011、由补码换算成原码再换算为十进制为-37.

由于进行了象限的转换&#xff0c;最终流水结果需要根据象限进行转换为正确的值。这里寄存17次高2位角度输入值&#xff0c;配合流水线结果用于象限判断&#xff0c;并完成转换。

//according to the pipeline,register phase_in[15:14]

always &#64; (posedgeclk)beginquadrant[0] <&#61; phase_in[15:14];

quadrant[1] <&#61; quadrant[0];

quadrant[2] <&#61; quadrant[1];

quadrant[3] <&#61; quadrant[2];

quadrant[4] <&#61; quadrant[3];

quadrant[5] <&#61; quadrant[4];

quadrant[6] <&#61; quadrant[5];

quadrant[7] <&#61; quadrant[6];

quadrant[8] <&#61; quadrant[7];

quadrant[9] <&#61; quadrant[8];

quadrant[10] <&#61; quadrant[9];

quadrant[11] <&#61; quadrant[10];

quadrant[12] <&#61; quadrant[11];

quadrant[13] <&#61; quadrant[12];

quadrant[14] <&#61; quadrant[13];

quadrant[15] <&#61; quadrant[14];

quadrant[16] <&#61; quadrant[15];end

最后&#xff0c;根据寄存的高2位角度输入值&#xff0c;利用三角函数关系&#xff0c;得出最后的结果&#xff0c;其中负数进行了补码操作。

//alter register, according to quadrant[16] to transform the result to the right result

always &#64; (posedgeclk)

eps<&#61;z16;always &#64; (posedge clk) begin

case(quadrant[16]) //or 15

2&#39;b00:begin //if the phase is in first quadrant,the sin(X)&#61;sin(A),cos(X)&#61;cos(A)

cos <&#61;x16;

sin<&#61;y16;end

2&#39;b01:begin //if the phase is in second quadrant,the sin(X)&#61;sin(A&#43;90)&#61;cosA,cos(X)&#61;cos(A&#43;90)&#61;-sinA

cos <&#61; ~(y16) &#43; 1&#39;b1;//-sin

sin <&#61; x16;//cos

end

2&#39;b10:begin //if the phase is in third quadrant,the sin(X)&#61;sin(A&#43;180)&#61;-sinA,cos(X)&#61;cos(A&#43;180)&#61;-cosA

cos <&#61; ~(x16) &#43; 1&#39;b1;//-cos

sin <&#61; ~(y16) &#43; 1&#39;b1;//-sin

end

2&#39;b11:begin //if the phase is in forth quadrant,the sin(X)&#61;sin(A&#43;270)&#61;-cosA,cos(X)&#61;cos(A&#43;270)&#61;sinA

cos <&#61; y16;//sin

sin <&#61; ~(x16) &#43; 1&#39;b1;//-cos

end

endcase

end

完整代码&#xff1a;

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

//360°--2^16,phase_in &#61; 16bits (input [15:0] phase_in)//1°--2^16/360

&#96;define rot0 16&#39;h2000 //45

&#96;define rot1 16&#39;h12e4 //26.5651

&#96;define rot2 16&#39;h09fb //14.0362

&#96;define rot3 16&#39;h0511 //7.1250

&#96;define rot4 16&#39;h028b //3.5763

&#96;define rot5 16&#39;h0145 //1.7899

&#96;define rot6 16&#39;h00a3 //0.8952

&#96;define rot7 16&#39;h0051 //0.4476

&#96;define rot8 16&#39;h0028 //0.2238

&#96;define rot9 16&#39;h0014 //0.1119

&#96;define rot10 16&#39;h000a //0.0560

&#96;define rot11 16&#39;h0005 //0.0280

&#96;define rot12 16&#39;h0003 //0.0140

&#96;define rot13 16&#39;h0002 //0.0070

&#96;define rot14 16&#39;h0001 //0.0035

&#96;define rot15 16&#39;h0000 //0.0018

modulecordic

(inputclk,//input rst_n,//input ena,

input [15:0] phase_in,output reg signed [16:0] eps,output reg signed [16:0] sin,output reg signed [16:0] cos

);parameter PIPELINE &#61; 16;//parameter K &#61; 16&#39;h4dba;//k&#61;0.607253*2^15

parameter K &#61; 16&#39;h9b74;//gian k&#61;0.607253*2^16,9b74,n means the number pipeline

//pipeline 16-level//maybe overflow,matlab result not overflow//MSB is signed bit,transform the sin and cos according to phase_in[15:14]

reg signed [16:0] x0&#61;0,y0&#61;0,z0&#61;0;reg signed [16:0] x1&#61;0,y1&#61;0,z1&#61;0;reg signed [16:0] x2&#61;0,y2&#61;0,z2&#61;0;reg signed [16:0] x3&#61;0,y3&#61;0,z3&#61;0;reg signed [16:0] x4&#61;0,y4&#61;0,z4&#61;0;reg signed [16:0] x5&#61;0,y5&#61;0,z5&#61;0;reg signed [16:0] x6&#61;0,y6&#61;0,z6&#61;0;reg signed [16:0] x7&#61;0,y7&#61;0,z7&#61;0;reg signed [16:0] x8&#61;0,y8&#61;0,z8&#61;0;reg signed [16:0] x9&#61;0,y9&#61;0,z9&#61;0;reg signed [16:0] x10&#61;0,y10&#61;0,z10&#61;0;reg signed [16:0] x11&#61;0,y11&#61;0,z11&#61;0;reg signed [16:0] x12&#61;0,y12&#61;0,z12&#61;0;reg signed [16:0] x13&#61;0,y13&#61;0,z13&#61;0;reg signed [16:0] x14&#61;0,y14&#61;0,z14&#61;0;reg signed [16:0] x15&#61;0,y15&#61;0,z15&#61;0;reg signed [16:0] x16&#61;0,y16&#61;0,z16&#61;0;reg [1:0] quadrant [PIPELINE:0];integeri;initial

begin

for(i&#61;0;i<&#61;PIPELINE;i&#61;i&#43;1)

quadrant[i]&#61; 2&#39;b0;

end

always &#64; (posedge clk)//stage 0,not pipeline

beginx0<&#61; {1&#39;b0,K}; //add one signed bit,0 means positive

y0 <&#61; 17&#39;b0;

z0 <&#61; {3&#39;b0,phase_in[13:0]};//control the phase_in to the range[0-Pi/2]

end

always &#64; (posedge clk)//stage 1

begin

if(z0[16])//the diff is negative so clockwise

beginx1<&#61; x0 &#43;y0;

y1<&#61; x0 -y0;

z1<&#61; z0 &#43;&#96;rot0;end

else

beginx1<&#61; x0 - y0;//x1 <&#61; x0;

y1 <&#61; x0 &#43; y0;//y1 <&#61; x0;

z1 <&#61; z0 - &#96;rot0;//reversal 45

end

end

always &#64; (posedge clk)//stage 2

begin

if(z1[16])//the diff is negative so clockwise

beginx2<&#61; x1 &#43; (y1>>>4&#39;d1);

y2 <&#61; y1 - (x1>>>4&#39;d1);

z2 <&#61; z1 &#43; &#96;rot1;//clockwise 26

end

else

beginx2<&#61; x1 - (y1>>>4&#39;d1);

y2 <&#61; y1 &#43; (x1>>>4&#39;d1);

z2 <&#61; z1 - &#96;rot1;//anti-clockwise 26

end

end

always &#64; (posedge clk)//stage 3

begin

if(z2[16])//the diff is negative so clockwise

beginx3<&#61; x2 &#43; (y2>>>4&#39;d2); //right shift n bits,divide 2^n

y3 <&#61; y2 - (x2>>>4&#39;d2); //left adds n bits of MSB,in first quadrant x or y are positive,MSB &#61;0 &#xff1f;&#xff1f;

z3 <&#61; z2 &#43; &#96;rot2;//clockwise 14//difference of positive and negtive number and no round(4,5)

end

else

beginx3<&#61; x2 - (y2>>>4&#39;d2);

y3 <&#61; y2 &#43; (x2>>>4&#39;d2);

z3 <&#61; z2 - &#96;rot2;//anti-clockwise 14

end

end

always &#64; (posedge clk)//stage 4

begin

if(z3[16])beginx4<&#61; x3 &#43; (y3>>>4&#39;d3);

y4 <&#61; y3 - (x3>>>4&#39;d3);

z4 <&#61; z3 &#43; &#96;rot3;//clockwise 7

end

else

beginx4<&#61; x3 - (y3>>>4&#39;d3);

y4 <&#61; y3 &#43; (x3>>>4&#39;d3);

z4 <&#61; z3 - &#96;rot3;//anti-clockwise 7

end

end

always &#64; (posedge clk)//stage 5

begin

if(z4[16])beginx5<&#61; x4 &#43; (y4>>>4&#39;d4);

y5 <&#61; y4 - (x4>>>4&#39;d4);

z5 <&#61; z4 &#43; &#96;rot4;//clockwise 3

end

else

beginx5<&#61; x4 - (y4>>>4&#39;d4);

y5 <&#61; y4 &#43; (x4>>>4&#39;d4);

z5 <&#61; z4 - &#96;rot4;//anti-clockwise 3

end

end

always &#64; (posedge clk)//STAGE 6

begin

if(z5[16])beginx6<&#61; x5 &#43; (y5>>>4&#39;d5);

y6 <&#61; y5 - (x5>>>4&#39;d5);

z6 <&#61; z5 &#43; &#96;rot5;//clockwise 1

end

else

beginx6<&#61; x5 - (y5>>>4&#39;d5);

y6 <&#61; y5 &#43; (x5>>>4&#39;d5);

z6 <&#61; z5 - &#96;rot5;//anti-clockwise 1

end

end

always &#64; (posedge clk)//stage 7

begin

if(z6[16])beginx7<&#61; x6 &#43; (y6>>>4&#39;d6);

y7 <&#61; y6 - (x6>>>4&#39;d6);

z7 <&#61; z6 &#43;&#96;rot6;end

else

beginx7<&#61; x6 - (y6>>>4&#39;d6);

y7 <&#61; y6 &#43; (x6>>>4&#39;d6);

z7 <&#61; z6 -&#96;rot6;end

end

always &#64; (posedge clk)//stage 8

begin

if(z7[16])beginx8<&#61; x7 &#43; (y7>>>4&#39;d7);

y8 <&#61; y7 - (x7>>>4&#39;d7);

z8 <&#61; z7 &#43;&#96;rot7;end

else

beginx8<&#61; x7 - (y7>>>4&#39;d7);

y8 <&#61; y7 &#43; (x7>>>4&#39;d7);

z8 <&#61; z7 -&#96;rot7;end

end

always &#64; (posedge clk)//stage 9

begin

if(z8[16])beginx9<&#61; x8 &#43; (y8>>>4&#39;d8);

y9 <&#61; y8 - (x8>>>4&#39;d8);

z9 <&#61; z8 &#43;&#96;rot8;end

else

beginx9<&#61; x8 - (y8>>>4&#39;d8);

y9 <&#61; y8 &#43; (x8>>>4&#39;d8);

z9 <&#61; z8 -&#96;rot8;end

end

always &#64; (posedge clk)//stage 10

begin

if(z9[16])beginx10<&#61; x9 &#43; (y9>>>4&#39;d9);

y10 <&#61; y9 - (x9>>>4&#39;d9);

z10 <&#61; z9 &#43;&#96;rot9;end

else

beginx10<&#61; x9 - (y9>>>4&#39;d9);

y10 <&#61; y9 &#43; (x9>>>4&#39;d9);

z10 <&#61; z9 -&#96;rot9;end

end

always &#64; (posedge clk)//stage 11

begin

if(z10[16])beginx11<&#61; x10 &#43; (y10>>>4&#39;d10);

y11 <&#61; y10 - (x10>>>4&#39;d10);

z11 <&#61; z10 &#43;&#96;rot10;end

else

beginx11<&#61; x10 - (y10>>>4&#39;d10);

y11 <&#61; y10 &#43; (x10>>>4&#39;d10);

z11 <&#61; z10 -&#96;rot10;end

end

always &#64; (posedge clk)//stage 12

begin

if(z11[16])beginx12<&#61; x11 &#43; (y11>>>4&#39;d11);

y12 <&#61; y11 - (x11>>>4&#39;d11);

z12 <&#61; z11 &#43;&#96;rot11;end

else

beginx12<&#61; x11 - (y11>>>4&#39;d11);

y12 <&#61; y11 &#43; (x11>>>4&#39;d11);

z12 <&#61; z11 -&#96;rot11;end

end

always &#64; (posedge clk)//stage 13

begin

if(z12[16])beginx13<&#61; x12 &#43; (y12>>>4&#39;d12);

y13 <&#61; y12 - (x12>>>4&#39;d12);

z13 <&#61; z12 &#43;&#96;rot12;end

else

beginx13<&#61; x12 - (y12>>>4&#39;d12);

y13 <&#61; y12 &#43; (x12>>>4&#39;d12);

z13 <&#61; z12 -&#96;rot12;end

end

always &#64; (posedge clk)//stage 14

begin

if(z13[16])beginx14<&#61; x13 &#43; (y13>>>4&#39;d13);

y14 <&#61; y13 - (x13>>>4&#39;d13);

z14 <&#61; z13 &#43;&#96;rot13;end

else

beginx14<&#61; x13 - (y13>>>4&#39;d13);

y14 <&#61; y13 &#43; (x13>>>4&#39;d13);

z14 <&#61; z13 -&#96;rot13;end

end

always &#64; (posedge clk)//stage 15

begin

if(z14[16])beginx15<&#61; x14 &#43; (y14>>>4&#39;d14);

y15 <&#61; y14 - (x14>>>4&#39;d14);

z15 <&#61; z14 &#43;&#96;rot14;end

else

beginx15<&#61; x14 - (y14>>>4&#39;d14);

y15 <&#61; y14 &#43; (x14>>>4&#39;d14);

z15 <&#61; z14 -&#96;rot14;end

end

always &#64; (posedge clk)//stage 16

begin

if(z15[16])beginx16<&#61; x15 &#43; (y15>>>4&#39;d15);

y16 <&#61; y15 - (x15>>>4&#39;d15);

z16 <&#61; z15 &#43;&#96;rot15;end

else

beginx16<&#61; x15 - (y15>>>4&#39;d15);

y16 <&#61; y15 &#43; (x15>>>4&#39;d15);

z16 <&#61; z15 -&#96;rot15;end

end

//according to the pipeline,register phase_in[15:14]

always &#64; (posedgeclk)beginquadrant[0] <&#61; phase_in[15:14];

quadrant[1] <&#61; quadrant[0];

quadrant[2] <&#61; quadrant[1];

quadrant[3] <&#61; quadrant[2];

quadrant[4] <&#61; quadrant[3];

quadrant[5] <&#61; quadrant[4];

quadrant[6] <&#61; quadrant[5];

quadrant[7] <&#61; quadrant[6];

quadrant[8] <&#61; quadrant[7];

quadrant[9] <&#61; quadrant[8];

quadrant[10] <&#61; quadrant[9];

quadrant[11] <&#61; quadrant[10];

quadrant[12] <&#61; quadrant[11];

quadrant[13] <&#61; quadrant[12];

quadrant[14] <&#61; quadrant[13];

quadrant[15] <&#61; quadrant[14];

quadrant[16] <&#61; quadrant[15];end

//alter register, according to quadrant[16] to transform the result to the right result

always &#64; (posedgeclk)

eps<&#61;z16;always &#64; (posedge clk) begin

case(quadrant[16]) //or 15

2&#39;b00:begin //if the phase is in first quadrant,the sin(X)&#61;sin(A),cos(X)&#61;cos(A)

cos <&#61;x16;

sin<&#61;y16;end

2&#39;b01:begin //if the phase is in second quadrant,the sin(X)&#61;sin(A&#43;90)&#61;cosA,cos(X)&#61;cos(A&#43;90)&#61;-sinA

cos <&#61; ~(y16) &#43; 1&#39;b1;//-sin

sin <&#61; x16;//cos

end

2&#39;b10:begin //if the phase is in third quadrant,the sin(X)&#61;sin(A&#43;180)&#61;-sinA,cos(X)&#61;cos(A&#43;180)&#61;-cosA

cos <&#61; ~(x16) &#43; 1&#39;b1;//-cos

sin <&#61; ~(y16) &#43; 1&#39;b1;//-sin

end

2&#39;b11:begin //if the phase is in forth quadrant,the sin(X)&#61;sin(A&#43;270)&#61;-cosA,cos(X)&#61;cos(A&#43;270)&#61;sinA

cos <&#61; y16;//sin

sin <&#61; ~(x16) &#43; 1&#39;b1;//-cos

end

endcase

end

endmodule

Whole Code

testbench测试代码&#xff1a;

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

&#96;timescale 1 ps/ 1psmodulecordic_tb;//test vector input registers

regarst;regclk;reg [15:0] phase &#61; 16&#39;h2000;

//wires

wire signed [16:0] cosine_out;wire signed [7:0] eps_out;wire signed [16:0] sine_out;//localparam coef&#61;1000;//assign statements (if any)

cordic i1 (//port map - connection between master ports and signals/registers

.clk(clk),

.cos(cosine_out),

.eps(eps_out),

.phase_in(phase),

.sin(sine_out)

);initial

beginclk&#61;0;

#(10000*coef) $stop;end

always #(5*coef) clk&#61;~clk;//always &#64;(negedgeclk)beginphase&#61;phase&#43;16&#39;h0100;

end

endmodule

Testbench

3、Modelsim仿真结果

10979bd16139c7858863c07df23b7303.png

仿真结果的补充说明&#xff1a;

(1)程序全程未使用复位信号&#xff0c;testbench中第一个计算的角度为16&#39;h2000也就是45度&#xff0c;如果以图示时刻为0时刻、仿真结果对应的波形即分别为sin(x&#43;π/4)和cos(x&#43;π/4)的波形。作为参考&#xff0c;0.5*√2*65535≈46340.

(2)关于运算过程中的位数溢出

根据仿真结果&#xff0c;本测试例下&#xff0c;x4出现过16位位数溢出。

(3)关于流水线设计的理解

前文提到过实现CORDIC迭代算法时可以使用反馈结构(只使用一级)、也可以使用流水线结构(多级)&#xff0c;如果任务是只单独计算一个角度的正弦或者余弦值&#xff0c;那么所需要的迭代次数或者说消耗的时钟周期数量其实是相同的&#xff0c;本设计中为16个时钟。

流水线结构的威力是在连续、源源不断地计算一组多个角度的正余弦值的时候才展现出来&#xff0c;当初始流水线被填满之后&#xff0c;每经过一个时钟周期、都会在输出上获得一个更新的角度的正余弦结果值&#xff0c;上图仿真结果图中黄色cursor左侧的时间段内、流水线即被逐步填满。

换句话说&#xff0c;如果现在的任务是要计算n个角度的正余弦值、计算一个角度需要的迭代次数为x&#xff0c;反馈结构需要的时长为(n*x)个时钟周期&#xff0c;流水线结构只需要(n&#43;x-1)个时钟周期。



推荐阅读
  • 本文整理了Java中org.apache.solr.common.SolrDocument.setField()方法的一些代码示例,展示了SolrDocum ... [详细]
  • 如何用UE4制作2D游戏文档——计算篇
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了如何用UE4制作2D游戏文档——计算篇相关的知识,希望对你有一定的参考价值。 ... [详细]
  • 本文详细介绍了Java中vector的使用方法和相关知识,包括vector类的功能、构造方法和使用注意事项。通过使用vector类,可以方便地实现动态数组的功能,并且可以随意插入不同类型的对象,进行查找、插入和删除操作。这篇文章对于需要频繁进行查找、插入和删除操作的情况下,使用vector类是一个很好的选择。 ... [详细]
  • 猜字母游戏
    猜字母游戏猜字母游戏——设计数据结构猜字母游戏——设计程序结构猜字母游戏——实现字母生成方法猜字母游戏——实现字母检测方法猜字母游戏——实现主方法1猜字母游戏——设计数据结构1.1 ... [详细]
  • 本文讨论了clone的fork与pthread_create创建线程的不同之处。进程是一个指令执行流及其执行环境,其执行环境是一个系统资源的集合。在调用系统调用fork创建一个进程时,子进程只是完全复制父进程的资源,这样得到的子进程独立于父进程,具有良好的并发性。但是二者之间的通讯需要通过专门的通讯机制,另外通过fork创建子进程系统开销很大。因此,在某些情况下,使用clone或pthread_create创建线程可能更加高效。 ... [详细]
  • 本文介绍了操作系统的定义和功能,包括操作系统的本质、用户界面以及系统调用的分类。同时还介绍了进程和线程的区别,包括进程和线程的定义和作用。 ... [详细]
  • EzPP 0.2发布,新增YAML布局渲染功能
    EzPP发布了0.2.1版本,新增了YAML布局渲染功能,可以将YAML文件渲染为图片,并且可以复用YAML作为模版,通过传递不同参数生成不同的图片。这个功能可以用于绘制Logo、封面或其他图片,让用户不需要安装或卸载Photoshop。文章还提供了一个入门例子,介绍了使用ezpp的基本渲染方法,以及如何使用canvas、text类元素、自定义字体等。 ... [详细]
  • 使用圣杯布局模式实现网站首页的内容布局
    本文介绍了使用圣杯布局模式实现网站首页的内容布局的方法,包括HTML部分代码和实例。同时还提供了公司新闻、最新产品、关于我们、联系我们等页面的布局示例。商品展示区包括了车里子和农家生态土鸡蛋等产品的价格信息。 ... [详细]
  • 开源Keras Faster RCNN模型介绍及代码结构解析
    本文介绍了开源Keras Faster RCNN模型的环境需求和代码结构,包括FasterRCNN源码解析、RPN与classifier定义、data_generators.py文件的功能以及损失计算。同时提供了该模型的开源地址和安装所需的库。 ... [详细]
  • 本文讨论了如何使用GStreamer来删除H264格式视频文件中的中间部分,而不需要进行重编码。作者提出了使用gst_element_seek(...)函数来实现这个目标的思路,并提到遇到了一个解决不了的BUG。文章还列举了8个解决方案,希望能够得到更好的思路。 ... [详细]
  • 本文整理了Java中java.lang.NoSuchMethodError.getMessage()方法的一些代码示例,展示了NoSuchMethodErr ... [详细]
  • Python已成为全球最受欢迎的编程语言之一,然而Python程序的安全运行存在一定的风险。本文介绍了Python程序安全运行需要满足的三个条件,即系统路径上的每个条目都处于安全的位置、"主脚本"所在的目录始终位于系统路径中、若python命令使用-c和-m选项,调用程序的目录也必须是安全的。同时,文章还提出了一些预防措施,如避免将下载文件夹作为当前工作目录、使用pip所在路径而不是直接使用python命令等。对于初学Python的读者来说,这些内容将有所帮助。 ... [详细]
  • 本文整理了Java中org.apache.pig.backend.executionengine.ExecException.<init>()方法的一些代码 ... [详细]
  • 学习一门编程语言,除了语法,最重要的是学习解决问题。很多时候单凭自己的能力确实无法做到完美解决,所以无论是搜索引擎、社区、文档还是博客&# ... [详细]
  • 给定一个二维平面上的一些点,通过计算曼哈顿距离,求连接所有点的最小总费用。只有任意两点之间有且仅有一条简单路径时,才认为所有点都已连接。给出了几个示例并给出了对应的输出。 ... [详细]
author-avatar
happy农村人9_624
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有