• cordic算法的verilog实现及modelsim仿真


    1. 算法介绍

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

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

    image

    旋转后,可得如下向量:

    image

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

    image

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

    image

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

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

    image

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

    image

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

    image

    可以得到如下公式:

    image

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

    image

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

    image

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

    image

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

    image

    image

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

    image 

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

    image

    image

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

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

    image

    1.1 旋转模式

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

    image

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

    image

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

    1.2 向量模式

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

    image

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

    算法介绍:http://en.wikipedia.org/wiki/Cordichttp://blog.csdn.net/liyuanbhu/article/details/8458769

    2. matlab实现

    根据算法原理,利用维基百科中给的程序,在matlab中跑了一遍,对算法有了一定程度的了解。

    程序如下:

     1 function v = cordic(beta,n)
     2 % This function computes v = [cos(beta), sin(beta)] (beta in radians)
     3 % using n iterations. Increasing n will increase the precision.
     4  
     5 if beta < -pi/2 || beta > pi/2
     6     if beta < 0
     7         v = cordic(beta + pi, n);
     8     else
     9         v = cordic(beta - pi, n);
    10     end
    11     v = -v; % flip the sign for second or third quadrant
    12 %     return
    13 end
    14  
    15 % Initialization of tables of constants used by CORDIC
    16 % need a table of arctangents of negative powers of two, in radians:
    17 % angles = atan(2.^-(0:27));
    18 angles =  [  ...
    19     0.78539816339745   0.46364760900081   0.24497866312686   0.12435499454676 ...
    20     0.06241880999596   0.03123983343027   0.01562372862048   0.00781234106010 ...
    21     0.00390623013197   0.00195312251648   0.00097656218956   0.00048828121119 ...
    22     0.00024414062015   0.00012207031189   0.00006103515617   0.00003051757812 ...
    23     0.00001525878906   0.00000762939453   0.00000381469727   0.00000190734863 ...
    24     0.00000095367432   0.00000047683716   0.00000023841858   0.00000011920929 ...
    25     0.00000005960464   0.00000002980232   0.00000001490116   0.00000000745058 ];
    26 % and a table of products of reciprocal lengths of vectors [1, 2^-2j]:
    27 Kvalues = [ ...
    28     0.70710678118655   0.63245553203368   0.61357199107790   0.60883391251775 ...
    29     0.60764825625617   0.60735177014130   0.60727764409353   0.60725911229889 ...
    30     0.60725447933256   0.60725332108988   0.60725303152913   0.60725295913894 ...
    31     0.60725294104140   0.60725293651701   0.60725293538591   0.60725293510314 ...
    32     0.60725293503245   0.60725293501477   0.60725293501035   0.60725293500925 ...
    33     0.60725293500897   0.60725293500890   0.60725293500889   0.60725293500888 ];
    34 Kn = Kvalues(min(n, length(Kvalues)));
    35  
    36 % Initialize loop variables:
    37 v = [1;0]; % start with 2-vector cosine and sine of zero
    38 poweroftwo = 1;
    39 angle = angles(1);
    40  
    41 % Iterations
    42 for j = 0:n-1;
    43     if beta < 0
    44         sigma = -1;
    45     else
    46         sigma = 1;
    47     end
    48     factor = sigma * poweroftwo;
    49     R = [1, -factor; factor, 1];
    50     v = R * v; % 2-by-2 matrix multiply
    51     beta = beta - sigma * angle; % update the remaining angle
    52     poweroftwo = poweroftwo / 2;
    53     % update the angle from table, or eventually by just dividing by
    54     % two,(a=arctan(a),a is small enough)
    55     if j+2 > length(angles)
    56         angle = angle / 2;
    57     else
    58         angle = angles(j+2);
    59     end
    60 end
    61  
    62 % Adjust length of output vector to be [cos(beta), sin(beta)]:
    63 v = v * Kn;
    64 return
    65 end
    cordic_matlab

    3. 硬件实现

    实现主要参考了相关作者的代码,然后对其进行了修改,最终实现了16级的流水线,设计完成旋转模式下正弦值和余弦值的计算。

    http://www.cnblogs.com/qiweiwang/archive/2010/07/28/1787021.htmlhttp://www.amobbs.com/forum.php?mod=viewthread&tid=5513050&highlight=cordic

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

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

     1 //360°--2^16,phase_in = 16bits (input [15:0] phase_in)
     2 //1°--2^16/360
     3 `define rot0  16'h2000    //45
     4 `define rot1  16'h12e4    //26.5651
     5 `define rot2  16'h09fb    //14.0362
     6 `define rot3  16'h0511    //7.1250
     7 `define rot4  16'h028b    //3.5763
     8 `define rot5  16'h0145    //1.7899
     9 `define rot6  16'h00a3    //0.8952
    10 `define rot7  16'h0051    //0.4476
    11 `define rot8  16'h0028    //0.2238
    12 `define rot9  16'h0014    //0.1119
    13 `define rot10 16'h000a    //0.0560
    14 `define rot11 16'h0005    //0.0280
    15 `define rot12 16'h0003    //0.0140
    16 `define rot13 16'h0001    //0.0070
    17 `define rot14 16'h0001    //0.0035
    18 `define rot15 16'h0000    //0.0018
    View Code

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

     1 parameter PIPELINE = 16;
     2 //parameter K = 16'h4dba;//k=0.607253*2^15
     3 parameter K = 16'h9b74;//gian k=0.607253*2^16,9b74,n means the number pipeline
     4 //pipeline 16-level    //maybe overflow,matlab result not overflow
     5 //MSB is signed bit,transform the sin and cos according to phase_in[15:14]
     6 reg [16:0] x0=0,y0=0,z0=0;
     7 reg [16:0] x1=0,y1=0,z1=0;
     8 reg [16:0] x2=0,y2=0,z2=0;
     9 reg [16:0] x3=0,y3=0,z3=0;
    10 reg [16:0] x4=0,y4=0,z4=0;
    11 reg [16:0] x5=0,y5=0,z5=0;
    12 reg [16:0] x6=0,y6=0,z6=0;
    13 reg [16:0] x7=0,y7=0,z7=0;
    14 reg [16:0] x8=0,y8=0,z8=0;
    15 reg [16:0] x9=0,y9=0,z9=0;
    16 reg [16:0] x10=0,y10=0,z10=0;
    17 reg [16:0] x11=0,y11=0,z11=0;
    18 reg [16:0] x12=0,y12=0,z12=0;
    19 reg [16:0] x13=0,y13=0,z13=0;
    20 reg [16:0] x14=0,y14=0,z14=0;
    21 reg [16:0] x15=0,y15=0,z15=0;
    22 reg [16:0] x16=0,y16=0,z16=0;
    View Code

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

    1 reg [1:0] quadrant [PIPELINE:0];
    2 integer i;
    3 initial
    4 begin
    5     for(i=0;i<=PIPELINE;i=i+1)
    6     quadrant[i] = 2'b0;
    7 end
    View Code

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

    1 //phase_in[15:14] determines which quadrant the angle is.
    2 //00 means first;01 means second;00 means third;00 means fourth
    3 //initialization: x0 = K,y0 = 0,z0 = phase_in,then the last result(x16,y16) = (cos(phase_in),sin(phase_in))  
    4 always @ (posedge clk)//stage 0,not pipeline
    5 begin
    6     x0 <= {1'b0,K}; //add one signed bit,0 means positive
    7     y0 <= 17'b0;
    8     z0 <= {3'b0,phase_in[13:0]};//control the phase_in to the range[0-Pi/2]
    9 end
    View Code

    接下来根据剩余待旋转角度z的符号位进行16次迭代处理,即完成16级流水线处理。迭代公式:x(n+1) <= x(n) + {{n{y(n)[16]}},y(n)[16:n]},n为移位个数。右移之后高位补位,这里补位有一些不理解。移位可能存在负数,且没有四舍五入。按理说第一象限不存在负数,但后续仿真汇总确实有负数出现,但仿真结果良好。

      1 always @ (posedge clk)//stage 1
      2 begin
      3   if(z0[16])//the diff is negative so clockwise
      4   begin
      5       x1 <= x0 + y0;
      6       y1 <= x0 - y0;
      7       z1 <= z0 + `rot0;
      8   end
      9   else
     10   begin
     11       x1 <= x0 - y0;//x1 <= x0;
     12       y1 <= x0 + y0;//y1 <= x0;
     13       z1 <= z0 - `rot0;//reversal 45
     14   end
     15 end
     16 
     17 always @ (posedge clk)//stage 2
     18 begin
     19     if(z1[16])//the diff is negative so clockwise
     20     begin
     21         x2 <= x1 + {y1[16],y1[16:1]};
     22         y2 <= y1 - {x1[16],x1[16:1]};
     23         z2 <= z1 + `rot1;//clockwise 26
     24     end
     25     else
     26     begin
     27         x2 <= x1 - {y1[16],y1[16:1]};
     28         y2 <= y1 + {x1[16],x1[16:1]};
     29         z2 <= z1 - `rot1;//anti-clockwise 26
     30     end
     31 end
     32 
     33 always @ (posedge clk)//stage 3
     34 begin
     35     if(z2[16])//the diff is negative so clockwise
     36     begin
     37         x3 <= x2 + {{2{y2[16]}},y2[16:2]}; //right shift n bits,divide 2^n
     38         y3 <= y2 - {{2{x2[16]}},x2[16:2]}; //left adds n bits of MSB,in first quadrant x or y are positive,MSB =0 ??
     39         z3 <= z2 + `rot2;//clockwise 14    //difference of positive and negtive number and no round(4,5)
     40     end
     41     else
     42     begin
     43         x3 <= x2 - {{2{y2[16]}},y2[16:2]};
     44         y3 <= y2 + {{2{x2[16]}},x2[16:2]};
     45         z3 <= z2 - `rot2;//anti-clockwise 14
     46     end
     47 end
     48 
     49 always @ (posedge clk)//stage 4
     50 begin
     51     if(z3[16])
     52     begin
     53         x4 <= x3 + {{3{y3[16]}},y3[16:3]};
     54         y4 <= y3 - {{3{x3[16]}},x3[16:3]};
     55         z4 <= z3 + `rot3;//clockwise 7
     56     end
     57     else
     58     begin
     59         x4 <= x3 - {{3{y3[16]}},y3[16:3]};
     60         y4 <= y3 + {{3{x3[16]}},x3[16:3]};
     61         z4 <= z3 - `rot3;//anti-clockwise 7
     62     end
     63 end
     64 
     65 always @ (posedge clk)//stage 5
     66 begin
     67     if(z4[16])
     68     begin
     69         x5 <= x4 + {{4{y4[16]}},y4[16:4]};
     70         y5 <= y4 - {{4{x4[16]}},x4[16:4]};
     71         z5 <= z4 + `rot4;//clockwise 3
     72     end
     73     else
     74     begin
     75         x5 <= x4 - {{4{y4[16]}},y4[16:4]};
     76         y5 <= y4 + {{4{x4[16]}},x4[16:4]};
     77         z5 <= z4 - `rot4;//anti-clockwise 3
     78     end
     79 end
     80 
     81 always @ (posedge clk)//STAGE 6
     82 begin
     83     if(z5[16])
     84     begin
     85         x6 <= x5 + {{5{y5[16]}},y5[16:5]};
     86         y6 <= y5 - {{5{x5[16]}},x5[16:5]};
     87         z6 <= z5 + `rot5;//clockwise 1
     88     end
     89     else
     90     begin
     91         x6 <= x5 - {{5{y5[16]}},y5[16:5]};
     92         y6 <= y5 + {{5{x5[16]}},x5[16:5]};
     93         z6 <= z5 - `rot5;//anti-clockwise 1 
     94     end
     95 end
     96 
     97 always @ (posedge clk)//stage 7
     98 begin
     99     if(z6[16])
    100     begin
    101         x7 <= x6 + {{6{y6[16]}},y6[16:6]};
    102         y7 <= y6 - {{6{x6[16]}},x6[16:6]};
    103         z7 <= z6 + `rot6;
    104     end
    105     else
    106     begin
    107         x7 <= x6 - {{6{y6[16]}},y6[16:6]};
    108         y7 <= y6 + {{6{x6[16]}},x6[16:6]};
    109         z7 <= z6 - `rot6;
    110     end
    111 end
    View Code

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

     1 //according to the pipeline,register phase_in[15:14]
     2 always @ (posedge clk)
     3 begin
     4   quadrant[0] <= phase_in[15:14];
     5   quadrant[1] <= quadrant[0];
     6   quadrant[2] <= quadrant[1];
     7   quadrant[3] <= quadrant[2];
     8   quadrant[4] <= quadrant[3];
     9   quadrant[5] <= quadrant[4];
    10   quadrant[6] <= quadrant[5];
    11   quadrant[7] <= quadrant[6];
    12   quadrant[8] <= quadrant[7];
    13   quadrant[9] <= quadrant[8];
    14   quadrant[10] <= quadrant[9];
    15   quadrant[11] <= quadrant[10];
    16   quadrant[12] <= quadrant[11];
    17   quadrant[13] <= quadrant[12];
    18   quadrant[14] <= quadrant[13];
    19   quadrant[15] <= quadrant[14];
    20   quadrant[16] <= quadrant[15];
    21 end
    View Code

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

     1 //alter register, according to quadrant[16] to transform the result to the right result
     2 always @ (posedge clk) begin
     3 eps <= z15;
     4 case(quadrant[16]) //or 15
     5 2'b00:begin //if the phase is in first quadrant,the sin(X)=sin(A),cos(X)=cos(A)
     6         cos <= x16;
     7         sin <= y16;
     8         end
     9 2'b01:begin //if the phase is in second quadrant,the sin(X)=sin(A+90)=cosA,cos(X)=cos(A+90)=-sinA
    10         cos <= ~(y16) + 1'b1;//-sin
    11         sin <= x16;//cos
    12         end
    13 2'b10:begin //if the phase is in third quadrant,the sin(X)=sin(A+180)=-sinA,cos(X)=cos(A+180)=-cosA
    14         cos <= ~(x16) + 1'b1;//-cos
    15         sin <= ~(y16) + 1'b1;//-sin
    16         end
    17 2'b11:begin //if the phase is in forth quadrant,the sin(X)=sin(A+270)=-cosA,cos(X)=cos(A+270)=sinA
    18         cos <= y16;//sin
    19         sin <= ~(x16) + 1'b1;//-cos
    20         end
    21 endcase
    22 end
    View Code

    4. Modelsim仿真结果

    仿真结果应该还是挺理想的。后续需要完成的工作:1.上述红色出现的问题的解决;2.应用cordic算法,完成如FFT的算法。

    后记:

    在3中,迭代公式:x(n+1) <= x(n) + {{n{y(n)[16]}},y(n)[16:n]},上述右移操作都是手动完成:首先最高位增加1位符号位(1为负,0为正),然后手动添加n位符号位(最高位)补齐,即实际上需要完成的算术右移(>>>)。本设计定义的reg为无符号型,在定义时手动添加最高位为符号位。verilog-1995中只有integer为有符号型,reg和wire都是无符号型,只能手动添加扩展位实现有符号运算。而在verilog-2001中reg和wire可以通过保留字signed定义为有符号型。另外,涉及有符号和无符号型的移位操作等可参考下面的文章。

    verilog有符号数详解:http://www.cnblogs.com/LJWJL/p/3481995.html

    Verilog-2001新特性及代码实现:http://www.asic-world.com/verilog/verilog2k.html

    逻辑移位与算术移位区别:http://www.cnblogs.com/yuphone/archive/2010/09/21/1832217.htmlhttp://blog.sina.com.cn/s/blog_65311d330100ij9n.html

    原来的算法实现针对Verilog-1995中reg和wire没有有符号型,也没有verilog-2001中的算术移位而实现的。根据verilog-2001新特性,引入有符号型reg和算术右移,同样实现了前文的结果。代码如下:

      1 `timescale 1 ns/100 ps
      2 //360?°--2^16,phase_in = 16bits (input [15:0] phase_in)
      3 //1?°--2^16/360
      4 `define rot0  16'h2000    //45
      5 `define rot1  16'h12e4    //26.5651
      6 `define rot2  16'h09fb    //14.0362
      7 `define rot3  16'h0511    //7.1250
      8 `define rot4  16'h028b    //3.5763
      9 `define rot5  16'h0145    //1.7899
     10 `define rot6  16'h00a3    //0.8952
     11 `define rot7  16'h0051    //0.4476
     12 `define rot8  16'h0028    //0.2238
     13 `define rot9  16'h0014    //0.1119
     14 `define rot10 16'h000a    //0.0560
     15 `define rot11 16'h0005    //0.0280
     16 `define rot12 16'h0003    //0.0140
     17 `define rot13 16'h0001    //0.0070
     18 `define rot14 16'h0001    //0.0035
     19 `define rot15 16'h0000    //0.0018
     20 
     21 module cordic(
     22 output reg signed [16:0] sin,cos,eps,
     23 input [15:0] phase_in,
     24 input clk
     25 );
     26 parameter PIPELINE = 16;
     27 //parameter K = 16'h4dba;//k=0.607253*2^15
     28 parameter K = 17'h09b74;//gian k=0.607253*2^16,9b74,
     29 //pipeline 16-level    //maybe overflow,matlab result not overflow
     30 //MSB is signed bit,transform the sin and cos according to phase_in[15:14]
     31 reg signed [16:0] x0=0,y0=0,z0=0;
     32 reg signed [16:0] x1=0,y1=0,z1=0;
     33 reg signed [16:0] x2=0,y2=0,z2=0;
     34 reg signed [16:0] x3=0,y3=0,z3=0;
     35 reg signed [16:0] x4=0,y4=0,z4=0;
     36 reg signed [16:0] x5=0,y5=0,z5=0;
     37 reg signed [16:0] x6=0,y6=0,z6=0;
     38 reg signed [16:0] x7=0,y7=0,z7=0;
     39 reg signed [16:0] x8=0,y8=0,z8=0;
     40 reg signed [16:0] x9=0,y9=0,z9=0;
     41 reg signed [16:0] x10=0,y10=0,z10=0;
     42 reg signed [16:0] x11=0,y11=0,z11=0;
     43 reg signed [16:0] x12=0,y12=0,z12=0;
     44 reg signed [16:0] x13=0,y13=0,z13=0;
     45 reg signed [16:0] x14=0,y14=0,z14=0;
     46 reg signed [16:0] x15=0,y15=0,z15=0;
     47 reg signed [16:0] x16=0,y16=0,z16=0;
     48 
     49 reg [1:0] quadrant [PIPELINE:0];
     50 integer i;
     51 initial
     52 begin
     53     for(i=0;i<=PIPELINE;i=i+1)
     54     quadrant[i] = 2'b0;
     55 end
     56 
     57 //phase_in[15:14] determines which quadrant the angle is.
     58 //00 means first;01 means second;00 means third;00 means fourth
     59 //initialization: x0 = K,y0 = 0,z0 = phase_in,then the last result(x16,y16) = (cos(phase_in),sin(phase_in))  
     60 always @ (posedge clk)//stage 0,not pipeline
     61 begin
     62     x0 <= K; //add one signed bit,0 means positive
     63     y0 <= 17'd0;
     64     z0 <= {3'b0,phase_in[13:0]};//control the phase_in to the range[0-Pi/2]
     65 end
     66 //pipeline
     67 //z0[16] = 0,positive
     68 always @ (posedge clk)//stage 1
     69 begin
     70   if(z0[16])//the diff is negative so clockwise
     71   begin
     72       x1 <= x0 + y0;
     73       y1 <= y0 - x0;
     74       z1 <= z0 + `rot0;
     75   end
     76   else
     77   begin
     78       x1 <= x0 - y0;//x1 <= x0;
     79       y1 <= y0 + x0;//y1 <= x0;
     80       z1 <= z0 - `rot0;//reversal 45
     81   end
     82 end
     83 
     84 always @ (posedge clk)//stage 2
     85 begin
     86     if(z1[16])//the diff is negative so clockwise
     87     begin
     88         x2 <= x1 + (y1 >>> 1);
     89         y2 <= y1 - (x1 >>> 1);
     90         z2 <= z1 + `rot1;//clockwise 26
     91     end
     92     else
     93     begin
     94         x2 <= x1 - (y1 >>> 1);
     95         y2 <= y1 + (x1 >>> 1);
     96         z2 <= z1 - `rot1;//anti-clockwise 26
     97     end
     98 end
     99 
    100 always @ (posedge clk)//stage 3
    101 begin
    102     if(z2[16])//the diff is negative so clockwise
    103     begin
    104         x3 <= x2 + (y2 >>> 2); //right shift n bits,divide 2^n,signed extension,Arithmetic shift right
    105         y3 <= y2 - (x2 >>> 2); //left adds n bits of MSB,in first quadrant x or y are positive,MSB =0 ??
    106         z3 <= z2 + `rot2;//clockwise 14    //difference of positive and negtive number and no round(4,5)
    107     end
    108     else
    109     begin
    110         x3 <= x2 - (y2 >>> 2); //Arithmetic shift right
    111         y3 <= y2 + (x2 >>> 2);
    112         z3 <= z2 - `rot2;//anti-clockwise 14
    113     end
    114 end
    115 
    116 always @ (posedge clk)//stage 4
    117 begin
    118     if(z3[16])
    119     begin
    120         x4 <= x3 + (y3 >>> 3);
    121         y4 <= y3 - (x3 >>> 3);
    122         z4 <= z3 + `rot3;//clockwise 7
    123     end
    124     else
    125     begin
    126         x4 <= x3 - (y3 >>> 3);
    127         y4 <= y3 + (x3 >>> 3);
    128         z4 <= z3 - `rot3;//anti-clockwise 7
    129     end
    130 end
    131 
    132 always @ (posedge clk)//stage 5
    133 begin
    134     if(z4[16])
    135     begin
    136         x5 <= x4 + (y4 >>> 4);
    137         y5 <= y4 - (x4 >>> 4);
    138         z5 <= z4 + `rot4;//clockwise 3
    139     end
    140     else
    141     begin
    142         x5 <= x4 - (y4 >>> 4);
    143         y5 <= y4 + (x4 >>> 4);
    144         z5 <= z4 - `rot4;//anti-clockwise 3
    145     end
    146 end
    147 
    148 always @ (posedge clk)//STAGE 6
    149 begin
    150     if(z5[16])
    151     begin
    152         x6 <= x5 + (y5 >>> 5);
    153         y6 <= y5 - (x5 >>> 5);
    154         z6 <= z5 + `rot5;//clockwise 1
    155     end
    156     else
    157     begin
    158         x6 <= x5 - (y5 >>> 5);
    159         y6 <= y5 + (x5 >>> 5);
    160         z6 <= z5 - `rot5;//anti-clockwise 1 
    161     end
    162 end
    163 
    164 always @ (posedge clk)//stage 7
    165 begin
    166     if(z6[16])
    167     begin
    168         x7 <= x6 + (y6 >>> 6);
    169         y7 <= y6 - (x6 >>> 6);
    170         z7 <= z6 + `rot6;
    171     end
    172     else
    173     begin
    174         x7 <= x6 - (y6 >>> 6);
    175         y7 <= y6 + (x6 >>> 6);
    176         z7 <= z6 - `rot6;
    177     end
    178 end
    179 
    180 always @ (posedge clk)//stage 8
    181 begin
    182     if(z7[16])
    183     begin
    184         x8 <= x7 + (y7 >>> 7);
    185         y8 <= y7 - (x7 >>> 7);
    186         z8 <= z7 + `rot7;
    187     end
    188     else
    189     begin
    190         x8 <= x7 - (y7 >>> 7);
    191         y8 <= y7 + (x7 >>> 7);
    192         z8 <= z7 - `rot7;
    193     end
    194 end
    195 
    196 always @ (posedge clk)//stage 9
    197 begin
    198     if(z8[16])
    199     begin
    200         x9 <= x8 + (y8 >>> 8);
    201         y9 <= y8 - (x8 >>> 8);
    202         z9 <= z8 + `rot8;
    203     end
    204     else
    205     begin
    206         x9 <= x8 - (y8 >>> 8);
    207         y9 <= y8 + (x8 >>> 8);
    208         z9 <= z8 - `rot8;
    209     end
    210 end
    211 
    212 always @ (posedge clk)//stage 10
    213 begin
    214     if(z9[16])
    215     begin
    216         x10 <= x9 + (y9 >>> 9);
    217         y10 <= y9 - (x9 >>> 9);
    218         z10 <= z9 + `rot9;
    219     end
    220     else
    221     begin
    222         x10 <= x9 - (y9 >>> 9);
    223         y10 <= y9 + (x9 >>> 9);
    224         z10 <= z9 - `rot9;
    225     end
    226 end
    227 
    228 always @ (posedge clk)//stage 11
    229 begin
    230     if(z10[16])
    231     begin
    232         x11 <= x10 + (y10 >>> 10);
    233         y11 <= y10 - (x10 >>> 10);
    234         z11 <= z10 + `rot10;//clockwise 3
    235     end
    236     else
    237     begin
    238         x11 <= x10 - (y10 >>> 10);
    239         y11 <= y10 + (x10 >>> 10);
    240         z11 <= z10 - `rot10;//anti-clockwise 3
    241     end
    242 end
    243 
    244 always @ (posedge clk)//STAGE 12
    245 begin
    246     if(z11[16])
    247     begin
    248         x12 <= x11 + (y11 >>> 11);
    249         y12 <= y11 - (x11 >>> 11);
    250         z12 <= z11 + `rot11;//clockwise 1
    251     end
    252     else
    253     begin
    254         x12 <= x11 - (y11 >>> 11);
    255         y12 <= y11 + (x11 >>> 11);
    256         z12 <= z11 - `rot11;//anti-clockwise 1 
    257     end
    258 end
    259 
    260 always @ (posedge clk)//stage 13
    261 begin
    262     if(z12[16])
    263     begin
    264         x13 <= x12 + (y12 >>> 12);
    265         y13 <= y12 - (x12 >>> 12);
    266         z13 <= z12 + `rot12;
    267     end
    268     else
    269     begin
    270         x13 <= x12 - (y12 >>> 12);
    271         y13 <= y12 + (x12 >>> 12);
    272         z13 <= z12 - `rot12;
    273     end
    274 end
    275 
    276 always @ (posedge clk)//stage 14
    277 begin
    278     if(z13[16])
    279     begin
    280         x14 <= x13 + (y13 >>> 13);
    281         y14 <= y13 - (x13 >>> 13);
    282         z14 <= z13 + `rot13;
    283     end
    284     else
    285     begin
    286         x14 <= x13 - (y13 >>> 13);
    287         y14 <= y13 + (x13 >>> 13);
    288         z14 <= z13 - `rot13;
    289     end
    290 end
    291 
    292 always @ (posedge clk)//stage 15
    293 begin
    294     if(z14[16])
    295     begin
    296         x15 <= x14 + (y14 >>> 14);
    297         y15 <= y14 - (x14 >>> 14);
    298         z15 <= z14 + `rot14;
    299     end
    300     else
    301     begin
    302         x15 <= x14 - (y14 >>> 14);
    303         y15 <= y14 + (x14 >>> 14);
    304         z15 <= z14 - `rot14;
    305     end
    306 end
    307 
    308 always @ (posedge clk)//stage 16
    309 begin
    310     if(z15[16])
    311     begin
    312         x16 <= x15 + (y15 >>> 15);
    313         y16 <= y15 - (x15 >>> 15);
    314         z16 <= z15 + `rot15;
    315     end
    316     else
    317     begin
    318         x16 <= x15 - (y15 >>> 15);
    319         y16 <= y15 + (x15 >>> 15);
    320         z16 <= z15 - `rot15;
    321     end
    322 end
    323 //according to the pipeline,register phase_in[15:14]
    324 always @ (posedge clk)
    325 begin
    326   quadrant[0] <= phase_in[15:14];
    327   quadrant[1] <= quadrant[0];
    328   quadrant[2] <= quadrant[1];
    329   quadrant[3] <= quadrant[2];
    330   quadrant[4] <= quadrant[3];
    331   quadrant[5] <= quadrant[4];
    332   quadrant[6] <= quadrant[5];
    333   quadrant[7] <= quadrant[6];
    334   quadrant[8] <= quadrant[7];
    335   quadrant[9] <= quadrant[8];
    336   quadrant[10] <= quadrant[9];
    337   quadrant[11] <= quadrant[10];
    338   quadrant[12] <= quadrant[11];
    339   quadrant[13] <= quadrant[12];
    340   quadrant[14] <= quadrant[13];
    341   quadrant[15] <= quadrant[14];
    342   quadrant[16] <= quadrant[15];
    343 end
    344 //alter register, according to quadrant[16] to transform the result to the right result
    345 always @ (posedge clk) begin
    346 eps <= z15;
    347 case(quadrant[16]) //or 15
    348 2'b00:begin //if the phase is in first quadrant,the sin(X)=sin(A),cos(X)=cos(A)
    349         cos <= x16;
    350         sin <= y16;
    351         end
    352 2'b01:begin //if the phase is in second quadrant,the sin(X)=sin(A+90)=cosA,cos(X)=cos(A+90)=-sinA
    353         cos <= ~(y16) + 1'b1;//-sin
    354         sin <= x16;//cos
    355         end
    356 2'b10:begin //if the phase is in third quadrant,the sin(X)=sin(A+180)=-sinA,cos(X)=cos(A+180)=-cosA
    357         cos <= ~(x16) + 1'b1;//-cos
    358         sin <= ~(y16) + 1'b1;//-sin
    359         end
    360 2'b11:begin //if the phase is in forth quadrant,the sin(X)=sin(A+270)=-cosA,cos(X)=cos(A+270)=sinA
    361         cos <= y16;//sin
    362         sin <= ~(x16) + 1'b1;//-cos
    363         end
    364 endcase
    365 end
    366 
    367 endmodule 
    View Code

    另外,代码中可以适当优化下:1.流水线操作时,定义的中间寄存器在定义是可以选择memory型,且可以单独建立module或者task进行封装迭代过程; 2. 最后对高2位角度寄存时,可以利用for语句选择移位寄存器实现,如下所示。

    always @ (posedge clk,negedge rst_n)
    begin
        if(!rst_n)
            for(i=0;i<=PIPELINE;i=i+1)
                quadrant[i]<=2'b00;
        else
            if(ena)
                begin
                    for(i=0;i<PIPELINE;i=i+1)
                        quadrant[i+1]<=quadrant[i];
                    quadrant[0]<=phase_in[7:6];
                end
    end
    移位寄存器寄存角度高2位

    疑问:有一点比较奇怪的是,转移到第一象限后,x和y不该存在负数的情况,但是现在确实有,这一点比较费解,所以将算术右移改为逻辑右移,在函数极值时存在错误。

  • 相关阅读:
    爆炸函数 explode
    创建 hive 用户自定义函数UDF,UDTF,UDAF
    数据仓库
    elasticsearch源码分析及插件开发
    JVM垃圾回收机制
    条件阻塞Condition的应用
    java 线上问题定位工具
    都是套路:高并发系统的降级特技
    java并发编程--Runnable Callable及Future
    什么是XSS攻击?什么是SQL注入攻击?什么是CSRF攻击?
  • 原文地址:https://www.cnblogs.com/aikimi7/p/3929592.html
Copyright © 2020-2023  润新知