Cordic算法——verilog实现

Cordic算法——verilog实现
上两篇博文做了理论分析和实现,但是所用到的变量依然是浮点型,而cordic真正的用处是基于FPGA等只能处理定点的平台。只需将满足精度的浮点数,放大2^n倍,取整,再进行处理。

  1. 旋转模式

假设要通过FPGA计算极坐标(55.6767°,1)的直角坐标。首先,角度值为浮点数,需要进行放大处理,放大10000倍。则预设的旋转角度同样要放大10000倍。

实现伪旋转(忽略模长补偿因子)的代码如下所示,注意,因为是整型运算,起始旋转时x放大了2^15,放大倍数决定计算精度,满足需求即可。最后得到的x,y在缩小2^15,即得到伪旋转后的x,y。最后进行模长波长运算(因为是浮点,同样需要放大)。

#include <stdio.h>
#include <stdlib.h>

int cordic_c(int a,int r);  
int x = 32768, y = 0;       //以X轴为旋转起始点,放大倍数2^15

int main(viod)
{

    int remain = cordic_c(556767,1);        //极坐标值(极角,极径)
    printf("旋转角度误差:%d, 直角坐标:x = %d, y = %d\n",remain,x,y);
    return 0;
}

int cordic_c(int a,int r)
{
    const int theta[] = {450000,265651,140362,71250,35763,17899,8952,4476,2238,1119,560,280,140,70,35,17,9,4,2,1}; //旋转角度

    int i = 0;
    int x_temp = 0, y_temp = 0;
    int angle_new = 0;      //旋转后终止角度
    int angle_remain = a;   //旋转后,剩余角度
    char detection;             //旋转方向

    for( i=0; i<20;i++)
    {
        if(angle_remain > 0)
        {
            angle_new = angle_new + theta[i];
            angle_remain = a - angle_new;
            x_temp = (x - (y >>i));
            y_temp = (y + (x >> i));
            x = x_temp;
            y = y_temp;
            detection = '+';
        }
        else
        {
            angle_new = angle_new - theta[i];
            angle_remain = a - angle_new;
            x_temp = (x + (y>>i));
            y_temp = (y - (x>>i));
            x = x_temp;
            y = y_temp;
            detection = '-'; 
        }
        printf(" x = %-8d, y = %-8d, 旋转次数 = %-8d 旋转角度 = %-12d  旋转方向:%-8c  终点角度 = %-8d\n", x,y,i+1, theta[i],detection,angle_new);
    }
    x = r*x;
    y = r*y;
    return angle_remain;
}


完整的FPGA实现过程,包含预处理和后处理,支持{-π,π}的角度,采用流水线方式实现,Verilog完整代码如下,注意在移位过程中要用算术移位(>>>),才能保证带符号的数正确移位:

/****************************************************/
//预处理
module Cordic_Pre(
                clk,
                rst_n,
                phi,    

                phi_pre,
                quadrant_flag
                );

/****************************************************/

    input                   clk;
    input                   rst_n;
    input   signed  [23:0]  phi;    

    output  signed  [23:0]  phi_pre;                        //预处理后的角度值
    output          [1:0]   quadrant_flag;                  //象限标记

/****************************************************/

    parameter               ANGLE_P90   = 24'sd90_0000,     //输入角度范围{-pi,pi},角度值放大了10000倍
                            ANGLE_N90   = -24'sd90_0000,
                            ANGLE_0     = 24'sd00_0000;

/****************************************************/

    reg     signed  [23:0]  phi_pre_r;
    reg             [1:0]   quadrant_flag_r;     

/****************************************************/

    always @(posedge clk or negedge rst_n)
        begin
            if(rst_n == 1'b0)
                begin
                    phi_pre_r <= 24'sd0;
                    quadrant_flag_r <= 2'b00;
                end
            else if(phi >= ANGLE_0 && phi <= ANGLE_P90)     //第一象限
                begin
                    phi_pre_r <= phi;
                    quadrant_flag_r <= 2'b01;           
                end
            else if(phi > ANGLE_P90 )                       //第二象限          
                begin
                    phi_pre_r <= phi - ANGLE_P90;
                    quadrant_flag_r <= 2'b10;
                end
            else if(phi < ANGLE_0 && phi >= ANGLE_N90)      //第四象限          
                begin
                    phi_pre_r <= phi;
                    quadrant_flag_r <= 2'b00;
                end
            else
                begin                                       //第三象限
                    phi_pre_r <= phi - ANGLE_N90;
                    quadrant_flag_r <= 2'b11;
                end
        end

/****************************************************/

    assign  phi_pre         = phi_pre_r;
    assign  quadrant_flag   = quadrant_flag_r;

/****************************************************/

endmodule
我的设计要求精度较高,所以采用20次旋转,旋转过程的代码如下:

/****************************************************/

module  Cordic_Rotate(
                    clk,
                    rst_n,
                    phi_pre,
                    quadrant_flag,

                    ret_x,
                    ret_y,
                    quadrant
                    );

/****************************************************/

    input                   clk;
    input                   rst_n;
    input   signed  [23:0]  phi_pre;
    input           [1:0]   quadrant_flag;

    output  signed  [16:0]  ret_x;
    output  signed  [16:0]  ret_y;
    output          [1:0]   quadrant;
/****************************************************/

    parameter               X_ORIGN     = 17'sd32768;   //旋转时x的起始大小,根据精度要求而定。
    //每次旋转的固定角度值
    parameter               ANGLE_1     = 24'sd450000,  ANGLE_2     = 24'sd265651,
                            ANGLE_3     = 24'sd140362,  ANGLE_4     = 24'sd71250,
                            ANGLE_5     = 24'sd35763,   ANGLE_6     = 24'sd17899,
                            ANGLE_7     = 24'sd8952,    ANGLE_8     = 24'sd4476,
                            ANGLE_9     = 24'sd2238,    ANGLE_10    = 24'sd1119,
                            ANGLE_11    = 24'sd560,     ANGLE_12    = 24'sd280,
                            ANGLE_13    = 24'sd140,     ANGLE_14    = 24'sd70,
                            ANGLE_15    = 24'sd35,      ANGLE_16    = 24'sd17,
                            ANGLE_17    = 24'sd9,       ANGLE_18    = 24'sd4,
                            ANGLE_19    = 24'sd2,       ANGLE_20    = 24'sd1;

/****************************************************/

    reg     signed  [16:0]  x_r             [20:0];
    reg     signed  [16:0]  y_r             [20:0];
    reg     signed  [23:0]  angle_remain    [20:0];
    reg     signed  [1:0]   quadrant_r      [20:0];

/****************************************************/
//旋转的流水线过程
    always @(posedge clk or negedge rst_n)
        begin
            if(rst_n == 1'b0)
                begin
                    x_r[0] <= 17'sd0;
                    y_r[0] <= 17'sd0;
                    angle_remain[0] <= 24'sd0;
                end
            else
                begin
                    x_r[0] <= X_ORIGN;               
                    y_r[0] <= 17'sd0;
                    angle_remain[0] <= phi_pre;
                end
        end
    //第1次旋转 
    always @(posedge clk or negedge rst_n)
        begin
            if(rst_n == 1'b0)
                begin
                    x_r[1] <= 17'sd0;
                    y_r[1] <= 17'sd0;
                    angle_remain[1] <= 24'sd0;
                end

            else if(angle_remain[0] > 24'sd0)
                begin
                    x_r[1] <= x_r[0] - y_r[0];
                    y_r[1] <= y_r[0] + x_r[0];
                    angle_remain[1] <= angle_remain[0] - ANGLE_1;
                end
            else
                begin
                    x_r[1] <= x_r[0] + y_r[0];
                    y_r[1] <= y_r[0] - x_r[0];
                    angle_remain[1] <= angle_remain[0] + ANGLE_1;
                end
        end
    //第2次旋转     
    always @(posedge clk or negedge rst_n)
        begin
            if(rst_n == 1'b0)
                begin
                    x_r[2] <= 17'sd0;
                    y_r[2] <= 17'sd0;
                    angle_remain[2] <= 24'sd0;
                end
            else if(angle_remain[1] > 24'sd0)                           //比较时,符号标记s必须带上,对结果有影响
                begin
                    x_r[2] <= x_r[1] - (y_r[1] >>> 1);              
                    y_r[2] <= y_r[1] + (x_r[1] >>> 1);                  //二元加的优先级高于算术移位
                    angle_remain[2] <= angle_remain[1] - ANGLE_2;
                end
            else
                begin
                    x_r[2] <= x_r[1] + (y_r[1] >>> 1);
                    y_r[2] <= y_r[1] - (x_r[1] >>> 1);
                    angle_remain[2] <= angle_remain[1] + ANGLE_2;
                end
        end
    //第3次旋转     
    always @(posedge clk or negedge rst_n)
        begin
            if(rst_n == 1'b0)
                begin
                    x_r[3] <= 17'sd0;
                    y_r[3] <= 17'sd0;
                    angle_remain[3] <= 24'sd0;
                end
            else if(angle_remain[2] > 24'sd0)
                begin
                    x_r[3] <= x_r[2] - (y_r[2] >>> 2);
                    y_r[3] <= y_r[2] + (x_r[2] >>> 2);
                    angle_remain[3] <= angle_remain[2] - ANGLE_3;
                end
            else
                begin
                    x_r[3] <= x_r[2] + (y_r[2] >>> 2);
                    y_r[3] <= y_r[2] - (x_r[2] >>> 2);
                    angle_remain[3] <= angle_remain[2] + ANGLE_3;
                end
        end
    //第4次旋转     
    always @(posedge clk or negedge rst_n)
        begin
            if(rst_n == 1'b0)
                begin
                    x_r[4] <= 17'sd0;
                    y_r[4] <= 17'sd0;
                    angle_remain[4] <= 24'sd0;
                end
            else if(angle_remain[3] > 24'sd0)
                begin
                    x_r[4] <= x_r[3] - (y_r[3] >>> 3);
                    y_r[4] <= y_r[3] + (x_r[3] >>> 3);
                    angle_remain[4] <= angle_remain[3] - ANGLE_4;
                end
            else
                begin
                    x_r[4] <= x_r[3] + (y_r[3] >>> 3);
                    y_r[4] <= y_r[3] - (x_r[3] >>> 3);
                    angle_remain[4] <= angle_remain[3] + ANGLE_4;
                end
        end
    //第5次旋转     
    always @(posedge clk or negedge rst_n)
        begin
            if(rst_n == 1'b0)
                begin
                    x_r[5] <= 17'sd0;
                    y_r[5] <= 17'sd0;
                    angle_remain[5] <= 24'sd0;
                end
            else if(angle_remain[4] > 24'sd0)
                begin
                    x_r[5] <= x_r[4] - (y_r[4] >>> 4);
                    y_r[5] <= y_r[4] + (x_r[4] >>> 4);
                    angle_remain[5] <= angle_remain[4] - ANGLE_5;
                end
            else
                begin
                    x_r[5] <= x_r[4] + (y_r[4] >>> 4);
                    y_r[5] <= y_r[4] - (x_r[4] >>> 4);
                    angle_remain[5] <= angle_remain[4] + ANGLE_5;
                end
        end
    //第6次旋转     
    always @(posedge clk or negedge rst_n)
        begin
            if(rst_n == 1'b0)
                begin
                    x_r[6] <= 17'sd0;
                    y_r[6] <= 17'sd0;
                    angle_remain[6] <= 24'sd0;
                end
            else if(angle_remain[5] > 24'sd0)
                begin
                    x_r[6] <= x_r[5] - (y_r[5] >>> 5);
                    y_r[6] <= y_r[5] + (x_r[5] >>> 5);
                    angle_remain[6] <= angle_remain[5] - ANGLE_6;
                end
            else
                begin
                    x_r[6] <= x_r[5] + (y_r[5] >>> 5);
                    y_r[6] <= y_r[5] - (x_r[5] >>> 5);
                    angle_remain[6] <= angle_remain[5] + ANGLE_6;
                end
        end
    //第7次旋转 
    always @(posedge clk or negedge rst_n)
        begin
            if(rst_n == 1'b0)
                begin
                    x_r[7] <= 17'sd0;
                    y_r[7] <= 17'sd0;
                    angle_remain[7] <= 24'sd0;
                end
            else if(angle_remain[6] > 24'sd0)
                begin
                    x_r[7] <= x_r[6] - (y_r[6] >>> 6);
                    y_r[7] <= y_r[6] + (x_r[6] >>> 6);
                    angle_remain[7] <= angle_remain[6] - ANGLE_7;
                end
            else
                begin
                    x_r[7] <= x_r[6] + (y_r[6] >>> 6);
                    y_r[7] <= y_r[6] - (x_r[6] >>> 6);
                    angle_remain[7] <= angle_remain[6] + ANGLE_7;
                end
        end
    //第8次旋转 
    always @(posedge clk or negedge rst_n)
        begin
            if(rst_n == 1'b0)
                begin
                    x_r[8] <= 17'sd0;
                    y_r[8] <= 17'sd0;
                    angle_remain[8] <= 24'sd0;
                end
            else if(angle_remain[7] > 24'sd0)
                begin
                    x_r[8] <= x_r[7] - (y_r[7] >>> 7);
                    y_r[8] <= y_r[7] + (x_r[7] >>> 7);
                    angle_remain[8] <= angle_remain[7] - ANGLE_8;
                end
            else
                begin
                    x_r[8] <= x_r[7] + (y_r[7] >>> 7);
                    y_r[8] <= y_r[7] - (x_r[7] >>> 7);
                    angle_remain[8] <= angle_remain[7] + ANGLE_8;
                end
        end
    //第9次旋转 
    always @(posedge clk or negedge rst_n)
        begin
            if(rst_n == 1'b0)
                begin
                    x_r[9] <= 17'sd0;
                    y_r[9] <= 17'sd0;
                    angle_remain[9] <= 24'sd0;
                end
            else if(angle_remain[8] > 24'sd0)
                begin
                    x_r[9] <= x_r[8] - (y_r[8] >>> 8);
                    y_r[9] <= y_r[8] + (x_r[8] >>> 8);
                    angle_remain[9] <= angle_remain[8] - ANGLE_9;
                end
            else
                begin
                    x_r[9] <= x_r[8] + (y_r[8] >>> 8);
                    y_r[9] <= y_r[8] - (x_r[8] >>> 8);
                    angle_remain[9] <= angle_remain[8] + ANGLE_9;
                end
        end
    //第10次旋转    
    always @(posedge clk or negedge rst_n)
        begin
            if(rst_n == 1'b0)
                begin
                    x_r[10] <= 17'sd0;
                    y_r[10] <= 17'sd0;
                    angle_remain[10] <= 24'sd0;
                end
            else if(angle_remain[9] > 24'sd0)
                begin
                    x_r[10] <= x_r[9] - (y_r[9] >>> 9);
                    y_r[10] <= y_r[9] + (x_r[9] >>> 9);
                    angle_remain[10] <= angle_remain[9] - ANGLE_10;
                end
            else
                begin
                    x_r[10] <= x_r[9] + (y_r[9] >>> 9);
                    y_r[10] <= y_r[9] - (x_r[9] >>> 9);
                    angle_remain[10] <= angle_remain[9] + ANGLE_10;
                end
        end
    //第11次旋转    
    always @(posedge clk or negedge rst_n)
        begin
            if(rst_n == 1'b0)
                begin
                    x_r[11] <= 17'sd0;
                    y_r[11] <= 17'sd0;
                    angle_remain[11] <= 24'sd0;
                end
            else if(angle_remain[10] > 24'sd0)
                begin
                    x_r[11] <= x_r[10] - (y_r[10] >>> 10);
                    y_r[11] <= y_r[10] + (x_r[10] >>> 10);
                    angle_remain[11] <= angle_remain[10] - ANGLE_11;
                end
            else
                begin
                    x_r[11] <= x_r[10] + (y_r[10] >>> 10);
                    y_r[11] <= y_r[10] - (x_r[10] >>> 10);
                    angle_remain[11] <= angle_remain[10] + ANGLE_11;
                end
        end
    //第12次旋转    
    always @(posedge clk or negedge rst_n)
        begin
            if(rst_n == 1'b0)
                begin
                    x_r[12] <= 17'sd0;
                    y_r[12] <= 17'sd0;
                    angle_remain[12] <= 24'sd0;
                end
            else if(angle_remain[11] > 24'sd0)
                begin
                    x_r[12] <= x_r[11] - (y_r[11] >>> 11);
                    y_r[12] <= y_r[11] + (x_r[11] >>> 11);
                    angle_remain[12] <= angle_remain[11] - ANGLE_12;
                end
            else
                begin
                    x_r[12] <= x_r[11] + (y_r[11] >>> 11);
                    y_r[12] <= y_r[11] - (x_r[11] >>> 11);
                    angle_remain[12] <= angle_remain[11] + ANGLE_12;
                end
        end
    //第13次旋转
    always @(posedge clk or negedge rst_n)
        begin
            if(rst_n == 1'b0)
                begin
                    x_r[13] <= 17'sd0;
                    y_r[13] <= 17'sd0;
                    angle_remain[13] <= 24'sd0;
                end
            else if(angle_remain[12] > 24'sd0)
                begin
                    x_r[13] <= x_r[12] - (y_r[12] >>> 12);
                    y_r[13] <= y_r[12] + (x_r[12] >>> 12);
                    angle_remain[13] <= angle_remain[10] - ANGLE_13;
                end
            else
                begin
                    x_r[13] <= x_r[12] + (y_r[12] >>> 12);
                    y_r[13] <= y_r[12] - (x_r[12] >>> 12);
                    angle_remain[13] <= angle_remain[12] + ANGLE_13;
                end
        end
    //第14次旋转    
    always @(posedge clk or negedge rst_n)
        begin
            if(rst_n == 1'b0)
                begin
                    x_r[14] <= 17'sd0;
                    y_r[14] <= 17'sd0;
                    angle_remain[14] <= 24'sd0;
                end
            else if(angle_remain[13] > 24'sd0)
                begin
                    x_r[14] <= x_r[13] - (y_r[13] >>> 13);
                    y_r[14] <= y_r[13] + (x_r[13] >>> 13);
                    angle_remain[14] <= angle_remain[13] - ANGLE_14;
                end
            else
                begin
                    x_r[14] <= x_r[13] + (y_r[13] >>> 13);
                    y_r[14] <= y_r[13] - (x_r[13] >>> 13);
                    angle_remain[14] <= angle_remain[13] + ANGLE_14;
                end
        end
    //第15次旋转    
    always @(posedge clk or negedge rst_n)
        begin
            if(rst_n == 1'b0)
                begin
                    x_r[15] <= 17'sd0;
                    y_r[15] <= 17'sd0;
                    angle_remain[15] <= 24'sd0;
                end
            else if(angle_remain[14] > 24'sd0)
                begin
                    x_r[15] <= x_r[14] - (y_r[14] >>> 14);
                    y_r[15] <= y_r[14] + (x_r[14] >>> 14);
                    angle_remain[15] <= angle_remain[14] - ANGLE_15;
                end
            else
                begin
                    x_r[15] <= x_r[14] + (y_r[14] >>> 14);
                    y_r[15] <= y_r[14] - (x_r[14] >>> 14);
                    angle_remain[15] <= angle_remain[14] + ANGLE_15;
                end
        end 
    //第16次旋转    
    always @(posedge clk or negedge rst_n)
        begin
            if(rst_n == 1'b0)
                begin
                    x_r[16] <= 17'sd0;
                    y_r[16] <= 17'sd0;
                    angle_remain[16] <= 24'sd0;
                end
            else if(angle_remain[15] > 24'sd0)
                begin
                    x_r[16] <= x_r[15] - (y_r[15] >>> 15);
                    y_r[16] <= y_r[15] + (x_r[15] >>> 15);
                    angle_remain[16] <= angle_remain[15] - ANGLE_16;
                end
            else
                begin
                    x_r[16] <= x_r[15] + (y_r[15] >>> 15);
                    y_r[16] <= y_r[15] - (x_r[15] >>> 15);
                    angle_remain[16] <= angle_remain[15] + ANGLE_16;
                end
        end 
    //第17次旋转    
    always @(posedge clk or negedge rst_n)
        begin
            if(rst_n == 1'b0)
                begin
                    x_r[17] <= 17'sd0;
                    y_r[17] <= 17'sd0;
                    angle_remain[17] <= 24'sd0;
                end
            else if(angle_remain[16] > 24'sd0)
                begin
                    x_r[17] <= x_r[16] - (y_r[16] >>> 16);
                    y_r[17] <= y_r[16] + (x_r[16] >>> 16);
                    angle_remain[17] <= angle_remain[16] - ANGLE_17;
                end
            else
                begin
                    x_r[17] <= x_r[16] + (y_r[16] >>> 16);
                    y_r[17] <= y_r[16] - (x_r[16] >>> 16);
                    angle_remain[17] <= angle_remain[16] + ANGLE_17;
                end
        end 
    //第18次旋转
    always @(posedge clk or negedge rst_n)
        begin
            if(rst_n == 1'b0)
                begin
                    x_r[18] <= 17'sd0;
                    y_r[18] <= 17'sd0;
                    angle_remain[18] <= 24'sd0;
                end
            else if(angle_remain[17] > 24'sd0)
                begin
                    x_r[18] <= x_r[17] - (y_r[17] >>> 17);
                    y_r[18] <= y_r[17] + (x_r[17] >>> 17);
                    angle_remain[18] <= angle_remain[17] - ANGLE_18;
                end
            else
                begin
                    x_r[18] <= x_r[17] + (y_r[17] >>> 17);
                    y_r[18] <= y_r[17] - (x_r[17] >>> 17);
                    angle_remain[18] <= angle_remain[17] + ANGLE_18;
                end
        end 
    //第19次旋转
    always @(posedge clk or negedge rst_n)
        begin
            if(rst_n == 1'b0)
                begin
                    x_r[19] <= 17'sd0;
                    y_r[19] <= 17'sd0;
                    angle_remain[19] <= 24'sd0;
                end
            else if(angle_remain[18] > 24'sd0)
                begin
                    x_r[19] <= x_r[18] - (y_r[15] >>> 18);
                    y_r[19] <= y_r[18] + (x_r[15] >>> 18);
                    angle_remain[19] <= angle_remain[18] - ANGLE_19;
                end
            else
                begin
                    x_r[19] <= x_r[18] + (y_r[18] >>> 18);
                    y_r[19] <= y_r[18] - (x_r[18] >>> 18);
                    angle_remain[19] <= angle_remain[18] + ANGLE_19;
                end
        end 
    //第20次旋转    
    always @(posedge clk or negedge rst_n)
        begin
            if(rst_n == 1'b0)
                begin
                    x_r[20] <= 17'sd0;
                    y_r[20] <= 17'sd0;
                    angle_remain[20] <= 24'sd0;
                end
            else if(angle_remain[19] > 24'sd0)
                begin
                    x_r[20] <= x_r[19] - (y_r[19] >>> 19);
                    y_r[20] <= y_r[19] + (x_r[19] >>> 19);
                    angle_remain[20] <= angle_remain[19] - ANGLE_20;
                end
            else
                begin
                    x_r[20] <= x_r[19] + (y_r[19] >>> 19);
                    y_r[20] <= y_r[19] - (x_r[19] >>> 19);
                    angle_remain[20] <= angle_remain[19] + ANGLE_20;
                end
        end 
/****************************************************/
//每个phi值的所在现象的流水线延迟
    always @(posedge clk or negedge rst_n)
        begin
            if(rst_n == 1'b0)
                begin
                    quadrant_r[0] <= 2'b00;         //不能合并着写
                    quadrant_r[1] <= 2'b00;
                    quadrant_r[2] <= 2'b00;
                    quadrant_r[3] <= 2'b00;
                    quadrant_r[4] <= 2'b00;
                    quadrant_r[5] <= 2'b00;
                    quadrant_r[6] <= 2'b00;
                    quadrant_r[7] <= 2'b00;
                    quadrant_r[8] <= 2'b00;
                    quadrant_r[9] <= 2'b00;
                    quadrant_r[10] <= 2'b00;
                    quadrant_r[11] <= 2'b00;
                    quadrant_r[12] <= 2'b00;
                    quadrant_r[13] <= 2'b00;
                    quadrant_r[14] <= 2'b00;
                    quadrant_r[15] <= 2'b00;
                    quadrant_r[16] <= 2'b00;
                    quadrant_r[17] <= 2'b00;
                    quadrant_r[18] <= 2'b00;
                    quadrant_r[19] <= 2'b00;
                    quadrant_r[20] <= 2'b00;
                end
            else
                begin
                    quadrant_r[0]   <= quadrant_flag;
                    quadrant_r[1]   <= quadrant_r[0];
                    quadrant_r[2]   <= quadrant_r[1];
                    quadrant_r[3]   <= quadrant_r[2];
                    quadrant_r[4]   <= quadrant_r[3];
                    quadrant_r[5]   <= quadrant_r[4];
                    quadrant_r[6]   <= quadrant_r[5];
                    quadrant_r[7]   <= quadrant_r[6];
                    quadrant_r[8]   <= quadrant_r[7];
                    quadrant_r[9]   <= quadrant_r[8];
                    quadrant_r[10]  <= quadrant_r[9];
                    quadrant_r[11]  <= quadrant_r[10];
                    quadrant_r[12]  <= quadrant_r[11];
                    quadrant_r[13]  <= quadrant_r[12];
                    quadrant_r[14]  <= quadrant_r[13];
                    quadrant_r[15]  <= quadrant_r[14];
                    quadrant_r[16]  <= quadrant_r[15];
                    quadrant_r[17]  <= quadrant_r[16];
                    quadrant_r[18]  <= quadrant_r[17];
                    quadrant_r[19]  <= quadrant_r[18];
                    quadrant_r[20]  <= quadrant_r[19];
                end

        end

/****************************************************/  
    assign ret_x    = x_r[20];
    assign ret_y    = y_r[20];
    assign quadrant = quadrant_r[20];
/****************************************************/
endmodule
后处理将象限变换过的坐标还原:

/****************************************************/

module  Cordic_Post(
                    clk,
                    rst_n,
                    ret_x,
                    ret_y,
                    quadrant,

                    sin_phi,
                    cos_phi
                    );

/****************************************************/
    input                   clk;
    input                   rst_n;
    input   signed  [16:0]  ret_x;
    input   signed  [16:0]  ret_y;
    input           [1:0]   quadrant;

    output  signed  [16:0]  sin_phi;
    output  signed  [16:0]  cos_phi;

/****************************************************/  

    reg     signed  [16:0]  sin_phi_r;
    reg     signed  [16:0]  cos_phi_r;

/****************************************************/

    always @(posedge clk or negedge rst_n)
        begin
            if(rst_n == 1'b0)
                begin
                    sin_phi_r <= 17'sd0;
                    cos_phi_r <= 17'sd0;
                end
            else
                case(quadrant)                  //根据原始角度所在象限,还原其三角函数值sin_phi和cos_phi
                    2'd01:                      //若再乘上极径和模长补偿因子,则实现直角坐标系变换
                        begin
                            cos_phi_r <= ret_x;
                            sin_phi_r <= ret_y;                         
                        end
                    2'd10:
                        begin
                            cos_phi_r <= ~ret_y + 1'b1;
                            sin_phi_r <= ret_x;
                        end
                    2'd11:
                        begin
                            cos_phi_r <= ret_y;
                            sin_phi_r <= ~ret_x + 1'b1;
                        end 
                    2'd00:
                        begin
                            cos_phi_r <= ret_x;
                            sin_phi_r <= ret_y;
                        end
                    default:
                        begin
                            sin_phi_r <= 17'sd0;
                            cos_phi_r <= 17'sd0;
                        end
                endcase

        end

/****************************************************/
    assign  sin_phi = sin_phi_r;
    assign  cos_phi = cos_phi_r;
/****************************************************/
endmodule

在四个象限分别选取一个角度进行仿真,仿真结果如下图所示:

角度从输入到转换完毕,一共延时21个时钟周期。正好是预处理(1个周期)+旋转(20个周期)的结果。

原文链接:http://www.cnblogs.com/rouwawa/p/7102173.html

### 回答1: Cordic算法Verilog实现是一种数字信号处理技术,用于计算三角函数、指数函数、对数函数等数学函数。它可以在FPGA、ASIC等数字电路中实现高速、低功耗的计算。Cordic算法Verilog实现需要设计一个模块,包括输入数据、输出数据、旋转角度、旋转方向等参数。该模块可以通过Verilog语言编写,并通过仿真和综合工具进行验证和优化。在实现过程中,需要注意数据精度、计算速度、资源占用等问题,以满足实际应用需求。 ### 回答2: CORDIC算法是一种在数字信号处理中常用的算法,主要用于计算一些复杂的数学函数,比如正弦、余弦、反正切等。在使用CORDIC算法实现这些函数时,最常用的就是CORDIC旋转模式,因此,在实现CORDIC算法时,我们需要实现旋转模式的计算。同时,在使用CORDIC算法时,高精度的计算也是必需的,因此,我们还需要考虑如何实现高精度的运算。 Verilog是一种常用的数字电路语言,它被广泛应用于数字信号处理和通信领域,因此,我们可以使用Verilog实现CORDIC算法。在Verilog实现CORDIC算法时,我们需要考虑以下几个方面: 1. CORDIC旋转模式的实现实现CORDIC旋转模式的关键在于实现旋转矩阵的乘法,这可以通过使用位移运算和加减运算来实现。具体地,我们可以使用一个32位的寄存器来保存旋转矩阵,然后,在每一次旋转中,将旋转矩阵右移相应的位数,将旋转角度加到寄存器的最高位上,最后再将结果输出。 2. 高精度的加减运算的实现。为了实现高精度的计算,我们通常采用多周期运算的方法,将加减运算拆分成多个时钟周期进行,以确保精度。具体地,我们可以使用一个寄存器来保存运算结果,然后在每个时钟周期中,从源寄存器中读取数据,进行加减运算,并将结果写入目标寄存器中。如果当前的结果超过了寄存器的位宽,则需要进行进位或退位操作。 3. 测试和调试方法的实现。在实现CORDIC算法时,测试和调试是非常重要的,因为只有通过测试和调试,才能确保算法的正确性。为了测试和调试,我们可以使用仿真工具,在仿真过程中观察每一个数据的变化,以确保算法的正确性。同时,我们也可以使用调试工具来跟踪代码的执行过程,在出现错误时进行定位和修复。 综上所述,CORDIC算法Verilog实现需要考虑旋转模式、高精度的加减运算和测试/调试方法等方面,只有在各个方面都充分考虑和实现的情况下,才能保证算法的正确性和可靠性。 ### 回答3: CORDIC算法是一种用于计算三角函数和其他复杂函数的迭代算法。它的实现可以采用各种不同的方式,如软件实现和硬件实现。其中,硬件实现可以使用FPGA和ASIC等专用电路,也可以使用数字信号处理器(DSP)这样的通用硬件加速器。 在Verilog实现CORDIC算法可以帮助我们加速计算速度,同时也可以保证计算精度。要实现CORDIC算法,我们需要首先了解该算法的原理。CORDIC算法的核心是一个循环迭代过程,该过程反复执行三个基本操作:旋转、缩放和比较。通过这些操作,可以将一个任意角度的旋转转换为一系列基本旋转角度的和,从而得到正确的三角函数值。 具体地说,在Verilog实现CORDIC算法的过程中,我们需要定义输入角度、旋转方向、旋转精度和输出结果等各种参数。并且,我们需要采用逐个旋转的方式来计算三角函数值,这需要使用一个迭代器来完成。在每个迭代步骤中,我们需要计算旋转角度,并且判断旋转方向和旋转精度的大小。然后,我们需要计算旋转矩阵,并将输入向量和旋转矩阵进行相乘,得到新的输入向量。这个过程需要采用乘法器、加法器等基本数学运算来完成。 当完成所有的迭代步骤后,我们就可以得到最终的三角函数值了。需要注意的是,为了保证计算精度,我们需要使用固定点数格式来存储输入和输出值,并且需要进行位移和舍入等处理。另外,我们也需要使用多个迭代器来实现并行计算,这可以帮助我们加速计算速度。 总之,Verilog实现CORDIC算法需要掌握多种硬件加速器的设计技术,并且需要了解相关的数字信号处理原理。在实现过程中,我们需要注意各种精度误差和计算速度的问题,并且需要进行适当的优化,以便获得最佳的计算效果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值