• 使用帅气的cordic算法进行坐标系互转及log10的求解


    参考博客

     https://blog.csdn.net/u010712012/article/details/77755567

    https://blog.csdn.net/Reborn_Lee/article/details/87436090

    参考论文

     基于FPGA的自然对数变换器的设计与实现.pdf

    前言

     众所周知,verilog并不能直接计算cos sin,但信号处理中却可能用到cos sin等函数的求解问题。

    一种足够好的逼近方式为cordic。无需使用乘法操作,只是简单的加减移位操作即可,这就可以很好的使用verilog操作啦。

    cordic算法有旋转模式和向量模式两种,分别可在圆坐标系、线性坐标系、双曲坐标系中使用。

    在旋转模式中,通过使Z逼近0,得到x,y。

    在向量模式中,通过使y逼近0,得到x,z。

    线性坐标系暂时没有用到。

    通过给定不同的初值,则可以求解不同的函数。

    极坐标转直角坐标

    已知(z,r),z表示角度,r表示极径。则可以通过旋转模式求解cos,sin。再乘r则得到实际上的直角坐标系(x,y)。

    算法流程:本次迭代次数为16次,其他次数照着迭代公式写即可,为方便fpga内部计算,数值均放大成整数,角度均放大了2^16次,则计算出来的最终结果也应相应除以2^16次。

     1、 设置迭代次数为16,则x0 = 0.607253,y0 = 0,并输入待计算的角度θ,θ在[-99.7°,99.7°]范围内。 
    2、 根据三个迭代公式进行迭代,i从0至15: 
    xi+1 = xi – d iy i2-i 
    yi+1 = yi + d ix i2-i 
    zi+1 = zi - diθi 
    注:z0 = θ,di与zi同符号。 
    3、 经过16次迭代计算后,得到的x16 和y16分别为cosθ和sinθ。

    计算出的cos和sin再乘r即可得到相应的直角坐标系点(x,y)。

    算法的本质即从45度开始旋转,直到z逼近0。而算法中的K本质上是个定值跟迭代次数有关,即∏cosθi。当迭代16次时,其值为

    0.6072529351。

     以下采用流水线对算法进行实现,可以获得最大的吞吐率。如果想节约资源,自然可以用复用串行迭代。

    原始cordic可以处理的角度范围为[-99.7°,99.7°],要想放大输入角度范围覆盖[-pi,pi],则需要前处理和后处理,使得角度处于第1和第4象限。

    仿真结果如下所示:

    角度输入为33度,则结果为:cos:54959/2^16=0.838607788085938 ,sin:35697/2^16= 0.544692993164063

    而matlab结果为:cos: 0.838670567945424 , sin: 0.544639035015027

    可以看到误差极小。

    代码仅供参考,勿做商业用途。

    `timescale 1ns/1ps
    module cos_sin_cordic (
        input                        i_clk       ,
        input                        i_en        ,
        input    signed    [31:0]    i_angle     ,
        output                       o_en        ,
        output                       o_error     ,
        output             [31:0]    o_cos_x     ,
        output             [31:0]    o_sin_y           
    );
    ////parameter
    parameter p_angle_0  = 2949120, //45°放大2^16
              p_angle_1  = 1740967,
              p_angle_2  = 919879,
              p_angle_3  = 466945,
              p_angle_4  = 234379,
              p_angle_5  = 117304,
              p_angle_6  = 58666,
              p_angle_7  = 29335,
              p_angle_8  = 14668,
              p_angle_9  = 7334,
              p_angle_10 = 3667,
              p_angle_11 = 1833,
              p_angle_12 = 917,
              p_angle_13 = 458,
              p_angle_14 = 229,
              p_angle_15 = 115;
    parameter p_x_initial  = 39797; //0.6072529351放大了2^16次
    parameter p_angle_p90  = 32'sd5898240, //90度放大2^16次
              p_angle_n90  = -32'sd5898240, //-90度
              p_angle_p180 = 32'sd11796480, //180
              p_angle_n180 = -32'sd11796480, //-180
              p_angle_p0    = 32'sd0;
    //角度象限判定 角度范围为[-pi,pi]
    ////象限标识
    //00: 第4象限
    //01:第1象限
    //10:第2象限
    //11:第3象限
    reg [31:0] r_angle = 32'd0;
    reg [1:0] r_quadrant_flag = 2'b00;
    reg r_error = 1'b0; //角度范围输入错误
    always @(posedge i_clk)
    begin
        if ((i_angle < p_angle_n180) || (i_angle > p_angle_p180)) //越界报错
            r_error <= 1'b1;
        else 
            r_error <= 1'b0;
    end 
    always @(posedge i_clk) //角度象限判定
    begin
        if ((i_angle >= p_angle_p0) && (i_angle <= p_angle_p90)) //第1象限
        begin 
            r_angle <= i_angle;
            r_quadrant_flag <= 2'b01;
        end
        else if (i_angle > p_angle_p90) //第2象限
        begin
            r_angle <= i_angle - p_angle_p90;
            r_quadrant_flag <= 2'b10;
        end
        else if ((i_angle < p_angle_p0) && (i_angle >= p_angle_n90)) //第4象限
        begin
            r_angle <= i_angle;
            r_quadrant_flag <= 2'b00;        
        end
        else //第3象限
        begin
            r_angle <= i_angle - p_angle_n90;
            r_quadrant_flag <= 2'b11;
        end
    end
    
    //赋初始值
    reg [31:0] r_x_0 = 32'd0;
    reg [31:0] r_y_0 = 32'd0;
    reg [31:0] r_angle_remain_0 = 32'd0;
    always @(posedge i_clk)
    begin
        r_x_0 <= p_x_initial;
        r_y_0 <= 32'd0;
        r_angle_remain_0 <= r_angle;
    end
    //第1次旋转
    reg [31:0] r_x_1 = 32'd0;
    reg [31:0] r_y_1 = 32'd0;
    reg [31:0] r_angle_remain_1 = 32'd0;
    always @(posedge i_clk)
    begin
        if (r_angle_remain_0[31]) //负数
        begin
            r_x_1 <= r_x_0 + r_y_0;
            r_y_1 <= r_y_0 - r_x_0;
            r_angle_remain_1 <= r_angle_remain_0 + p_angle_0;
        end
        else //角度为正
        begin
            r_x_1 <= r_x_0 - r_y_0;
            r_y_1 <= r_y_0 + r_x_0;
            r_angle_remain_1 <= r_angle_remain_0 - p_angle_0;
        end
    end
    //第2次旋转
    reg [31:0] r_x_2 = 32'd0;
    reg [31:0] r_y_2 = 32'd0;
    reg [31:0] r_angle_remain_2 = 32'd0;
    always @(posedge i_clk)
    begin
        if (r_angle_remain_1[31]) //负数
        begin
            r_x_2 <= r_x_1 + {{1{r_y_1[31]}},r_y_1[31:1]};
            r_y_2 <= r_y_1 - {{1{r_x_1[31]}},r_x_1[31:1]};
            r_angle_remain_2 <= r_angle_remain_1 + p_angle_1;
        end
        else //角度为正
        begin
            r_x_2 <= r_x_1 - {{1{r_y_1[31]}},r_y_1[31:1]};
            r_y_2 <= r_y_1 + {{1{r_x_1[31]}},r_x_1[31:1]};
            r_angle_remain_2 <= r_angle_remain_1 - p_angle_1;
        end
    end
    //第3次旋转
    reg [31:0] r_x_3 = 32'd0;
    reg [31:0] r_y_3 = 32'd0;
    reg [31:0] r_angle_remain_3 = 32'd0;
    always @(posedge i_clk)
    begin
        if (r_angle_remain_2[31]) //负数
        begin
            r_x_3 <= r_x_2 + {{2{r_y_2[31]}},r_y_2[31:2]};
            r_y_3 <= r_y_2 - {{2{r_x_2[31]}},r_x_2[31:2]};
            r_angle_remain_3 <= r_angle_remain_2 + p_angle_2;
        end
        else //角度为正
        begin
            r_x_3 <= r_x_2 - {{2{r_y_2[31]}},r_y_2[31:2]};
            r_y_3 <= r_y_2 + {{2{r_x_2[31]}},r_x_2[31:2]};
            r_angle_remain_3 <= r_angle_remain_2 - p_angle_2;
        end
    end
    //第4次旋转
    reg [31:0] r_x_4 = 32'd0;
    reg [31:0] r_y_4 = 32'd0;
    reg [31:0] r_angle_remain_4 = 32'd0;
    always @(posedge i_clk)
    begin
        if (r_angle_remain_3[31]) //负数
        begin
            r_x_4 <= r_x_3 + {{3{r_y_3[31]}},r_y_3[31:3]};
            r_y_4 <= r_y_3 - {{3{r_x_3[31]}},r_x_3[31:3]};
            r_angle_remain_4 <= r_angle_remain_3 + p_angle_3;
        end
        else //角度为正
        begin
            r_x_4 <= r_x_3 - {{3{r_y_3[31]}},r_y_3[31:3]};
            r_y_4 <= r_y_3 + {{3{r_x_3[31]}},r_x_3[31:3]};
            r_angle_remain_4 <= r_angle_remain_3 - p_angle_3;
        end
    end
    //第5次旋转
    reg [31:0] r_x_5 = 32'd0;
    reg [31:0] r_y_5 = 32'd0;
    reg [31:0] r_angle_remain_5 = 32'd0;
    always @(posedge i_clk)
    begin
        if (r_angle_remain_4[31]) //负数
        begin
            r_x_5 <= r_x_4 + {{4{r_y_4[31]}},r_y_4[31:4]};
            r_y_5 <= r_y_4 - {{4{r_x_4[31]}},r_x_4[31:4]};
            r_angle_remain_5 <= r_angle_remain_4 + p_angle_4;
        end
        else //角度为正
        begin
            r_x_5 <= r_x_4 - {{4{r_y_4[31]}},r_y_4[31:4]};
            r_y_5 <= r_y_4 + {{4{r_x_4[31]}},r_x_4[31:4]};
            r_angle_remain_5 <= r_angle_remain_4 - p_angle_4;
        end
    end
    //第6次旋转
    reg [31:0] r_x_6 = 32'd0;
    reg [31:0] r_y_6 = 32'd0;
    reg [31:0] r_angle_remain_6 = 32'd0;
    always @(posedge i_clk)
    begin
        if (r_angle_remain_5[31]) //负数
        begin
            r_x_6 <= r_x_5 + {{5{r_y_5[31]}},r_y_5[31:5]};
            r_y_6 <= r_y_5 - {{5{r_x_5[31]}},r_x_5[31:5]};
            r_angle_remain_6 <= r_angle_remain_5 + p_angle_5;
        end
        else //角度为正
        begin
            r_x_6 <= r_x_5 - {{5{r_y_5[31]}},r_y_5[31:5]};
            r_y_6 <= r_y_5 + {{5{r_x_5[31]}},r_x_5[31:5]};
            r_angle_remain_6 <= r_angle_remain_5 - p_angle_5;
        end
    end
    //第7次旋转
    reg [31:0] r_x_7 = 32'd0;
    reg [31:0] r_y_7 = 32'd0;
    reg [31:0] r_angle_remain_7 = 32'd0;
    always @(posedge i_clk)
    begin
        if (r_angle_remain_6[31]) //负数
        begin
            r_x_7 <= r_x_6 + {{6{r_y_6[31]}},r_y_6[31:6]};
            r_y_7 <= r_y_6 - {{6{r_x_6[31]}},r_x_6[31:6]};
            r_angle_remain_7 <= r_angle_remain_6 + p_angle_6;
        end
        else //角度为正
        begin
            r_x_7 <= r_x_6 - {{6{r_y_6[31]}},r_y_6[31:6]};
            r_y_7 <= r_y_6 + {{6{r_x_6[31]}},r_x_6[31:6]};
            r_angle_remain_7 <= r_angle_remain_6 - p_angle_6;
        end
    end
    //第8次旋转
    reg [31:0] r_x_8 = 32'd0;
    reg [31:0] r_y_8 = 32'd0;
    reg [31:0] r_angle_remain_8 = 32'd0;
    always @(posedge i_clk)
    begin
        if (r_angle_remain_7[31]) //负数
        begin
            r_x_8 <= r_x_7 + {{7{r_y_7[31]}},r_y_7[31:7]};
            r_y_8 <= r_y_7 - {{7{r_x_7[31]}},r_x_7[31:7]};
            r_angle_remain_8 <= r_angle_remain_7 + p_angle_7;
        end
        else //角度为正
        begin
            r_x_8 <= r_x_7 - {{7{r_y_7[31]}},r_y_7[31:7]};
            r_y_8 <= r_y_7 + {{7{r_x_7[31]}},r_x_7[31:7]};
            r_angle_remain_8 <= r_angle_remain_7 - p_angle_7;
        end
    end
    //第9次旋转
    reg [31:0] r_x_9 = 32'd0;
    reg [31:0] r_y_9 = 32'd0;
    reg [31:0] r_angle_remain_9 = 32'd0;
    always @(posedge i_clk)
    begin
        if (r_angle_remain_8[31]) //负数
        begin
            r_x_9 <= r_x_8 + {{8{r_y_8[31]}},r_y_8[31:8]};
            r_y_9 <= r_y_8 - {{8{r_x_8[31]}},r_x_8[31:8]};
            r_angle_remain_9 <= r_angle_remain_8 + p_angle_8;
        end
        else //角度为正
        begin
            r_x_9 <= r_x_8 - {{8{r_y_8[31]}},r_y_8[31:8]};
            r_y_9 <= r_y_8 + {{8{r_x_8[31]}},r_x_8[31:8]};
            r_angle_remain_9 <= r_angle_remain_8 - p_angle_8;
        end
    end
    //第10次旋转
    reg [31:0] r_x_10 = 32'd0;
    reg [31:0] r_y_10 = 32'd0;
    reg [31:0] r_angle_remain_10 = 32'd0;
    always @(posedge i_clk)
    begin
        if (r_angle_remain_9[31]) //负数
        begin
            r_x_10 <= r_x_9 + {{9{r_y_9[31]}},r_y_9[31:9]};
            r_y_10 <= r_y_9 - {{9{r_x_9[31]}},r_x_9[31:9]};
            r_angle_remain_10 <= r_angle_remain_9 + p_angle_9;
        end
        else //角度为正
        begin
            r_x_10 <= r_x_9 - {{9{r_y_9[31]}},r_y_9[31:9]};
            r_y_10 <= r_y_9 + {{9{r_x_9[31]}},r_x_9[31:9]};
            r_angle_remain_10 <= r_angle_remain_9 - p_angle_9;
        end
    end
    //第11次旋转
    reg [31:0] r_x_11 = 32'd0;
    reg [31:0] r_y_11 = 32'd0;
    reg [31:0] r_angle_remain_11 = 32'd0;
    always @(posedge i_clk)
    begin
        if (r_angle_remain_10[31]) //负数
        begin
            r_x_11 <= r_x_10 + {{10{r_y_10[31]}},r_y_10[31:10]};
            r_y_11 <= r_y_10 - {{10{r_x_10[31]}},r_x_10[31:10]};
            r_angle_remain_11 <= r_angle_remain_10 + p_angle_10;
        end
        else //角度为正
        begin
            r_x_11 <= r_x_10 - {{10{r_y_10[31]}},r_y_10[31:10]};
            r_y_11 <= r_y_10 + {{10{r_x_10[31]}},r_x_10[31:10]};
            r_angle_remain_11 <= r_angle_remain_10 - p_angle_10;
        end
    end
    //第12次旋转
    reg [31:0] r_x_12 = 32'd0;
    reg [31:0] r_y_12 = 32'd0;
    reg [31:0] r_angle_remain_12 = 32'd0;
    always @(posedge i_clk)
    begin
        if (r_angle_remain_11[31]) //负数
        begin
            r_x_12 <= r_x_11 + {{11{r_y_11[31]}},r_y_11[31:11]};
            r_y_12 <= r_y_11 - {{11{r_x_11[31]}},r_x_11[31:11]};
            r_angle_remain_12 <= r_angle_remain_11 + p_angle_11;
        end
        else //角度为正
        begin
            r_x_12 <= r_x_11 - {{11{r_y_11[31]}},r_y_11[31:11]};
            r_y_12 <= r_y_11 + {{11{r_x_11[31]}},r_x_11[31:11]};
            r_angle_remain_12 <= r_angle_remain_11 - p_angle_11;
        end
    end
    //第13次旋转
    reg [31:0] r_x_13 = 32'd0;
    reg [31:0] r_y_13 = 32'd0;
    reg [31:0] r_angle_remain_13 = 32'd0;
    always @(posedge i_clk)
    begin
        if (r_angle_remain_12[31]) //负数
        begin
            r_x_13 <= r_x_12 + {{12{r_y_12[31]}},r_y_12[31:12]};
            r_y_13 <= r_y_12 - {{12{r_x_12[31]}},r_x_12[31:12]};
            r_angle_remain_13 <= r_angle_remain_12 + p_angle_12;
        end
        else //角度为正
        begin
            r_x_13 <= r_x_12 - {{12{r_y_12[31]}},r_y_12[31:12]};
            r_y_13 <= r_y_12 + {{12{r_x_12[31]}},r_x_12[31:12]};
            r_angle_remain_13 <= r_angle_remain_12 - p_angle_12;
        end
    end
    //第14次旋转
    reg [31:0] r_x_14 = 32'd0;
    reg [31:0] r_y_14 = 32'd0;
    reg [31:0] r_angle_remain_14 = 32'd0;
    always @(posedge i_clk)
    begin
        if (r_angle_remain_13[31]) //负数
        begin
            r_x_14 <= r_x_13 + {{13{r_y_13[31]}},r_y_13[31:13]};
            r_y_14 <= r_y_13 - {{13{r_x_13[31]}},r_x_13[31:13]};
            r_angle_remain_14 <= r_angle_remain_13 + p_angle_13;
        end
        else //角度为正
        begin
            r_x_14 <= r_x_13 - {{13{r_y_13[31]}},r_y_13[31:13]};
            r_y_14 <= r_y_13 + {{13{r_x_13[31]}},r_x_13[31:13]};
            r_angle_remain_14 <= r_angle_remain_13 - p_angle_13;
        end
    end
    //第15次旋转
    reg [31:0] r_x_15 = 32'd0;
    reg [31:0] r_y_15 = 32'd0;
    reg [31:0] r_angle_remain_15 = 32'd0;
    always @(posedge i_clk)
    begin
        if (r_angle_remain_14[31]) //负数
        begin
            r_x_15 <= r_x_14 + {{14{r_y_14[31]}},r_y_14[31:14]};
            r_y_15 <= r_y_14 - {{14{r_x_14[31]}},r_x_14[31:14]};
            r_angle_remain_15 <= r_angle_remain_14 + p_angle_14;
        end
        else //角度为正
        begin
            r_x_15 <= r_x_14 - {{14{r_y_14[31]}},r_y_14[31:14]};
            r_y_15 <= r_y_14 + {{14{r_x_14[31]}},r_x_14[31:14]};
            r_angle_remain_15 <= r_angle_remain_14 - p_angle_14;
        end
    end
    //第16次旋转
    reg [31:0] r_x_16 = 32'd0;
    reg [31:0] r_y_16 = 32'd0;
    reg [31:0] r_angle_remain_16 = 32'd0;
    always @(posedge i_clk)
    begin
        if (r_angle_remain_15[31]) //负数
        begin
            r_x_16 <= r_x_15 + {{15{r_y_15[31]}},r_y_15[31:15]};
            r_y_16 <= r_y_15 - {{15{r_x_15[31]}},r_x_15[31:15]};
            r_angle_remain_16 <= r_angle_remain_15 + p_angle_15;
        end
        else //角度为正
        begin
            r_x_16 <= r_x_15 - {{15{r_y_15[31]}},r_y_15[31:15]};
            r_y_16 <= r_y_15 + {{15{r_x_15[31]}},r_x_15[31:15]};
            r_angle_remain_16 <= r_angle_remain_15 - p_angle_15;
        end
    end
    //计算结果转化为真实结果
    //flag延迟16+1+1
    reg [31:0] r_cos_x;
    reg [31:0] r_sin_y;
    reg [16:0] r_quadrant_flag_delay_0 = 17'd0;
    reg [16:0] r_quadrant_flag_delay_1 = 17'd0;
    always @(posedge i_clk)
    begin
        r_quadrant_flag_delay_0 <= {r_quadrant_flag_delay_0[15:0],r_quadrant_flag[0]};
        r_quadrant_flag_delay_1 <= {r_quadrant_flag_delay_1[15:0],r_quadrant_flag[1]};
    end
    wire [1:0] demo;
    assign demo = {r_quadrant_flag_delay_1[16],r_quadrant_flag_delay_0[16]};
    always @(posedge i_clk)
    begin
        case ({r_quadrant_flag_delay_1[16],r_quadrant_flag_delay_0[16]})
            2'b01: //第1象限
            begin
                r_cos_x <= r_x_16;
                r_sin_y <= r_y_16;
            end 
            2'b10: //第2象限
            begin
                r_cos_x <= ~r_y_16 + 1'b1;
                r_sin_y <= r_x_16;
            end
            2'b11: //第3象限
            begin
                r_cos_x <= r_y_16;
                r_sin_y <= ~r_x_16 + 1'b1;
            end
            2'b00: //第4象限
            begin
                r_cos_x <= r_x_16;
                r_sin_y <= r_y_16;
            end
        endcase 
    end
    
    ////使能延迟对齐输出,延迟1+1+16+1
    reg [18:0] r_en_delay = 19'd0;
    always @(posedge i_clk)
    begin
        r_en_delay <= {r_en_delay[17:0],i_en};
    end
    reg [17:0] r_error_delay = 18'd0;
    always @(posedge i_clk)
    begin
        r_error_delay <= {r_error_delay[16:0],r_error};
    end
    //信号输出
    assign o_cos_x = r_cos_x;
    assign o_sin_y = r_sin_y;
    assign o_error = r_error_delay[17];
    assign o_en = r_en_delay[18];
    
    endmodule // end the cos_sin_cordic model;

    直角坐标转极坐标

     已知(x,y)求解(z,r),

    算法流程:

    设置迭代次数为16,则x0 = x,y0 = y,z0 = 0,di与yi的符号相反。表示,经过n次旋转,使Pn靠近x轴。 
    因此,当迭代结束之后,Pn将近似接近x轴,此时yn = 0,可知旋转了θ,即zn = θ = arctan(y/x)。r= xn * ∏cosθi。即r=xn*K。而16次迭代下的K值为0.6072529351。

    迭代公式如下:

    xi+1 = xi – d iy i2-i 
    yi+1 = yi + d ix i2-i 
    zi+1 = zi - diθi 

    仿真结果如下所示。

    x和y均为10000。

    θ = 2949406/2^16 = 45.0044;R = 23291*K=23291* 0.6072529351= 14143.5281114141,跟matlab结果比较:14142.135623731

    误差较小。

    代码如下,勿做商业用途。

    `timescale 1ns/1ps
    module z_r_cordic (
        input               i_clk            ,
        input               i_en             ,
        input     [31:0]    i_x              ,
        input     [31:0]    i_y              ,
        output              o_en             ,
        output    [31:0]    o_angle          ,
        output    [31:0]    o_r           
    );
    ////parameter
    parameter p_angle_0  = 2949120, //45°放大2^16
              p_angle_1  = 1740967,
              p_angle_2  = 919879,
              p_angle_3  = 466945,
              p_angle_4  = 234379,
              p_angle_5  = 117304,
              p_angle_6  = 58666,
              p_angle_7  = 29335,
              p_angle_8  = 14668,
              p_angle_9  = 7334,
              p_angle_10 = 3667,
              p_angle_11 = 1833,
              p_angle_12 = 917,
              p_angle_13 = 458,
              p_angle_14 = 229,
              p_angle_15 = 115;
    
    //赋初始值
    reg [31:0] r_x_0 = 32'd0;
    reg [31:0] r_y_0 = 32'd0;
    reg [31:0] r_angle_remain_0 = 32'd0;
    always @(posedge i_clk)
    begin
        r_x_0 <= i_x;
        r_y_0 <= i_y;
        r_angle_remain_0 <= 32'd0;
    end
    //第1次旋转
    reg [31:0] r_x_1 = 32'd0;
    reg [31:0] r_y_1 = 32'd0;
    reg [31:0] r_angle_remain_1 = 32'd0;
    always @(posedge i_clk)
    begin
        if (r_y_0[31]) //负数
        begin
            r_x_1 <= r_x_0 - r_y_0;
            r_y_1 <= r_y_0 + r_x_0;
            r_angle_remain_1 <= r_angle_remain_0 - p_angle_0;
        end
        else //角度为正
        begin
            r_x_1 <= r_x_0 + r_y_0;
            r_y_1 <= r_y_0 - r_x_0;
            r_angle_remain_1 <= r_angle_remain_0 + p_angle_0;
        end
    end
    //第2次旋转
    reg  [31:0] r_x_2 = 32'd0;
    reg  [31:0] r_y_2 = 32'd0;
    reg  [31:0] r_angle_remain_2 = 32'd0;
    always @(posedge i_clk)
    begin
        if (r_y_1[31]) //负数
        begin
            r_x_2 <= r_x_1 - {{1{r_y_1[31]}},r_y_1[31:1]};
            r_y_2 <= r_y_1 + {{1{r_x_1[31]}},r_x_1[31:1]};
            r_angle_remain_2 <= r_angle_remain_1 - p_angle_1;
        end
        else //角度为正
        begin
            r_x_2 <= r_x_1 + {{1{r_y_1[31]}},r_y_1[31:1]};
            r_y_2 <= r_y_1 - {{1{r_x_1[31]}},r_x_1[31:1]};
            r_angle_remain_2 <= r_angle_remain_1 + p_angle_1;
        end
    end
    //第3次旋转
    reg [31:0] r_x_3 = 32'd0;
    reg [31:0] r_y_3 = 32'd0;
    reg [31:0] r_angle_remain_3 = 32'd0;
    always @(posedge i_clk)
    begin
        if (r_y_2[31]) //负数
        begin
            r_x_3 <= r_x_2 - {{2{r_y_2[31]}},r_y_2[31:2]};
            r_y_3 <= r_y_2 + {{2{r_x_2[31]}},r_x_2[31:2]};
            r_angle_remain_3 <= r_angle_remain_2 - p_angle_2;
        end
        else //角度为正
        begin
            r_x_3 <= r_x_2 + {{2{r_y_2[31]}},r_y_2[31:2]};
            r_y_3 <= r_y_2 - {{2{r_x_2[31]}},r_x_2[31:2]};
            r_angle_remain_3 <= r_angle_remain_2 + p_angle_2;
        end
    end
    //第4次旋转
    reg [31:0] r_x_4 = 32'd0;
    reg [31:0] r_y_4 = 32'd0;
    reg [31:0] r_angle_remain_4 = 32'd0;
    always @(posedge i_clk)
    begin
        if (r_y_3[31]) //负数
        begin
            r_x_4 <= r_x_3 - {{3{r_y_3[31]}},r_y_3[31:3]};
            r_y_4 <= r_y_3 + {{3{r_x_3[31]}},r_x_3[31:3]};
            r_angle_remain_4 <= r_angle_remain_3 - p_angle_3;
        end
        else //角度为正
        begin
            r_x_4 <= r_x_3 + {{3{r_y_3[31]}},r_y_3[31:3]};
            r_y_4 <= r_y_3 - {{3{r_x_3[31]}},r_x_3[31:3]};
            r_angle_remain_4 <= r_angle_remain_3 + p_angle_3;
        end
    end
    //第5次旋转
    reg [31:0] r_x_5 = 32'd0;
    reg [31:0] r_y_5 = 32'd0;
    reg [31:0] r_angle_remain_5 = 32'd0;
    always @(posedge i_clk)
    begin
        if (r_y_4[31]) //负数
        begin
            r_x_5 <= r_x_4 - {{4{r_y_4[31]}},r_y_4[31:4]};
            r_y_5 <= r_y_4 + {{4{r_x_4[31]}},r_x_4[31:4]};
            r_angle_remain_5 <= r_angle_remain_4 - p_angle_4;
        end
        else //角度为正
        begin
            r_x_5 <= r_x_4 + {{4{r_y_4[31]}},r_y_4[31:4]};
            r_y_5 <= r_y_4 - {{4{r_x_4[31]}},r_x_4[31:4]};
            r_angle_remain_5 <= r_angle_remain_4 + p_angle_4;
        end
    end
    //第6次旋转
    reg [31:0] r_x_6 = 32'd0;
    reg [31:0] r_y_6 = 32'd0;
    reg [31:0] r_angle_remain_6 = 32'd0;
    always @(posedge i_clk)
    begin
        if (r_y_5[31]) //负数
        begin
            r_x_6 <= r_x_5 - {{5{r_y_5[31]}},r_y_5[31:5]};
            r_y_6 <= r_y_5 + {{5{r_x_5[31]}},r_x_5[31:5]};
            r_angle_remain_6 <= r_angle_remain_5 - p_angle_5;
        end
        else //角度为正
        begin
            r_x_6 <= r_x_5 + {{5{r_y_5[31]}},r_y_5[31:5]};
            r_y_6 <= r_y_5 - {{5{r_x_5[31]}},r_x_5[31:5]};
            r_angle_remain_6 <= r_angle_remain_5 + p_angle_5;
        end
    end
    //第7次旋转
    reg [31:0] r_x_7 = 32'd0;
    reg [31:0] r_y_7 = 32'd0;
    reg [31:0] r_angle_remain_7 = 32'd0;
    always @(posedge i_clk)
    begin
        if (r_y_6[31]) //负数
        begin
            r_x_7 <= r_x_6 - {{6{r_y_6[31]}},r_y_6[31:6]};
            r_y_7 <= r_y_6 + {{6{r_x_6[31]}},r_x_6[31:6]};
            r_angle_remain_7 <= r_angle_remain_6 - p_angle_6;
        end
        else //角度为正
        begin
            r_x_7 <= r_x_6 + {{6{r_y_6[31]}},r_y_6[31:6]};
            r_y_7 <= r_y_6 - {{6{r_x_6[31]}},r_x_6[31:6]};
            r_angle_remain_7 <= r_angle_remain_6 + p_angle_6;
        end
    end
    //第8次旋转
    reg [31:0] r_x_8 = 32'd0;
    reg [31:0] r_y_8 = 32'd0;
    reg [31:0] r_angle_remain_8 = 32'd0;
    always @(posedge i_clk)
    begin
        if (r_y_7[31]) //负数
        begin
            r_x_8 <= r_x_7 - {{7{r_y_7[31]}},r_y_7[31:7]};
            r_y_8 <= r_y_7 + {{7{r_x_7[31]}},r_x_7[31:7]};
            r_angle_remain_8 <= r_angle_remain_7 - p_angle_7;
        end
        else //角度为正
        begin
            r_x_8 <= r_x_7 + {{7{r_y_7[31]}},r_y_7[31:7]};
            r_y_8 <= r_y_7 - {{7{r_x_7[31]}},r_x_7[31:7]};
            r_angle_remain_8 <= r_angle_remain_7 + p_angle_7;
        end
    end
    //第9次旋转
    reg [31:0] r_x_9 = 32'd0;
    reg [31:0] r_y_9 = 32'd0;
    reg [31:0] r_angle_remain_9 = 32'd0;
    always @(posedge i_clk)
    begin
        if (r_y_8[31]) //负数
        begin
            r_x_9 <= r_x_8 - {{8{r_y_8[31]}},r_y_8[31:8]};
            r_y_9 <= r_y_8 + {{8{r_x_8[31]}},r_x_8[31:8]};
            r_angle_remain_9 <= r_angle_remain_8 - p_angle_8;
        end
        else //角度为正
        begin
            r_x_9 <= r_x_8 + {{8{r_y_8[31]}},r_y_8[31:8]};
            r_y_9 <= r_y_8 - {{8{r_x_8[31]}},r_x_8[31:8]};
            r_angle_remain_9 <= r_angle_remain_8 + p_angle_8;
        end
    end
    //第10次旋转
    reg [31:0] r_x_10 = 32'd0;
    reg [31:0] r_y_10 = 32'd0;
    reg [31:0] r_angle_remain_10 = 32'd0;
    always @(posedge i_clk)
    begin
        if (r_y_9[31]) //负数
        begin
            r_x_10 <= r_x_9 - {{9{r_y_9[31]}},r_y_9[31:9]};
            r_y_10 <= r_y_9 + {{9{r_x_9[31]}},r_x_9[31:9]};
            r_angle_remain_10 <= r_angle_remain_9 - p_angle_9;
        end
        else //角度为正
        begin
            r_x_10 <= r_x_9 + {{9{r_y_9[31]}},r_y_9[31:9]};
            r_y_10 <= r_y_9 - {{9{r_x_9[31]}},r_x_9[31:9]};
            r_angle_remain_10 <= r_angle_remain_9 + p_angle_9;
        end
    end
    //第11次旋转
    reg [31:0] r_x_11 = 32'd0;
    reg [31:0] r_y_11 = 32'd0;
    reg [31:0] r_angle_remain_11 = 32'd0;
    always @(posedge i_clk)
    begin
        if (r_y_10[31]) //负数
        begin
            r_x_11 <= r_x_10 - {{10{r_y_10[31]}},r_y_10[31:10]};
            r_y_11 <= r_y_10 + {{10{r_x_10[31]}},r_x_10[31:10]};
            r_angle_remain_11 <= r_angle_remain_10 - p_angle_10;
        end
        else //角度为正
        begin
            r_x_11 <= r_x_10 + {{10{r_y_10[31]}},r_y_10[31:10]};
            r_y_11 <= r_y_10 - {{10{r_x_10[31]}},r_x_10[31:10]};
            r_angle_remain_11 <= r_angle_remain_10 + p_angle_10;
        end
    end
    //第12次旋转
    reg [31:0] r_x_12 = 32'd0;
    reg [31:0] r_y_12 = 32'd0;
    reg [31:0] r_angle_remain_12 = 32'd0;
    always @(posedge i_clk)
    begin
        if (r_y_11[31]) //负数
        begin
            r_x_12 <= r_x_11 - {{11{r_y_11[31]}},r_y_11[31:11]};
            r_y_12 <= r_y_11 + {{11{r_x_11[31]}},r_x_11[31:11]};
            r_angle_remain_12 <= r_angle_remain_11 - p_angle_11;
        end
        else //角度为正
        begin
            r_x_12 <= r_x_11 + {{11{r_y_11[31]}},r_y_11[31:11]};
            r_y_12 <= r_y_11 - {{11{r_x_11[31]}},r_x_11[31:11]};
            r_angle_remain_12 <= r_angle_remain_11 + p_angle_11;
        end
    end
    //第13次旋转
    reg [31:0] r_x_13 = 32'd0;
    reg [31:0] r_y_13 = 32'd0;
    reg [31:0] r_angle_remain_13 = 32'd0;
    always @(posedge i_clk)
    begin
        if (r_y_12[31]) //负数
        begin
            r_x_13 <= r_x_12 - {{12{r_y_12[31]}},r_y_12[31:12]};
            r_y_13 <= r_y_12 + {{12{r_x_12[31]}},r_x_12[31:12]};
            r_angle_remain_13 <= r_angle_remain_12 - p_angle_12;
        end
        else //角度为正
        begin
            r_x_13 <= r_x_12 + {{12{r_y_12[31]}},r_y_12[31:12]};
            r_y_13 <= r_y_12 - {{12{r_x_12[31]}},r_x_12[31:12]};
            r_angle_remain_13 <= r_angle_remain_12 + p_angle_12;
        end
    end
    //第14次旋转
    reg [31:0] r_x_14 = 32'd0;
    reg [31:0] r_y_14 = 32'd0;
    reg [31:0] r_angle_remain_14 = 32'd0;
    always @(posedge i_clk)
    begin
        if (r_y_13[31]) //负数
        begin
            r_x_14 <= r_x_13 - {{13{r_y_13[31]}},r_y_13[31:13]};
            r_y_14 <= r_y_13 + {{13{r_x_13[31]}},r_x_13[31:13]};
            r_angle_remain_14 <= r_angle_remain_13 - p_angle_13;
        end
        else //角度为正
        begin
            r_x_14 <= r_x_13 + {{13{r_y_13[31]}},r_y_13[31:13]};
            r_y_14 <= r_y_13 - {{13{r_x_13[31]}},r_x_13[31:13]};
            r_angle_remain_14 <= r_angle_remain_13 + p_angle_13;
        end
    end
    //第15次旋转
    reg [31:0] r_x_15 = 32'd0;
    reg [31:0] r_y_15 = 32'd0;
    reg [31:0] r_angle_remain_15 = 32'd0;
    always @(posedge i_clk)
    begin
        if (r_y_14[31]) //负数
        begin
            r_x_15 <= r_x_14 - {{14{r_y_14[31]}},r_y_14[31:14]};
            r_y_15 <= r_y_14 + {{14{r_x_14[31]}},r_x_14[31:14]};
            r_angle_remain_15 <= r_angle_remain_14 - p_angle_14;
        end
        else //角度为正
        begin
            r_x_15 <= r_x_14 + {{14{r_y_14[31]}},r_y_14[31:14]};
            r_y_15 <= r_y_14 - {{14{r_x_14[31]}},r_x_14[31:14]};
            r_angle_remain_15 <= r_angle_remain_14 + p_angle_14;
        end
    end
    //第16次旋转
    reg [31:0] r_x_16 = 32'd0;
    reg [31:0] r_y_16 = 32'd0;
    reg [31:0] r_angle_remain_16 = 32'd0;
    always @(posedge i_clk)
    begin
        if (r_y_14[31]) //负数
        begin
            r_x_16 <= r_x_15 - {{15{r_y_15[31]}},r_y_15[31:15]};
            r_y_16 <= r_y_15 + {{15{r_x_15[31]}},r_x_15[31:15]};
            r_angle_remain_16 <= r_angle_remain_15 - p_angle_15;
        end
        else //角度为正
        begin
            r_x_16 <= r_x_15 + {{15{r_y_15[31]}},r_y_15[31:15]};
            r_y_16 <= r_y_15 - {{15{r_x_15[31]}},r_x_15[31:15]};
            r_angle_remain_16 <= r_angle_remain_15 + p_angle_15;
        end
    end
    ////使能延迟对齐输出
    reg [16:0] r_en_delay = 17'd0;
    always @(posedge i_clk)
    begin
        r_en_delay <= {r_en_delay[15:0],i_en};
    end
    ////信号输出
    assign o_angle = r_angle_remain_16;
    assign o_r = r_x_16;
    assign o_en = r_en_delay[16];
    
    endmodule // end the z_r_cordic model;

    双曲反正切的妙用

     双曲反正切有啥用呢,如果你想求log10,冥思苦想,这玩意咋用verilog求?而我们知道如下公式:

    则log10就可以转化为求解arctanh的值。而我们知道,arctanh是可以用cordic在双曲模式下求解其值的。所以,log就可以用cordic求解。

    在双曲模式下的算法迭代跟其他的不一样,涉及到收敛问题,且从N为4开始,每当3k+1的项需要重复迭代。即1,2,3,4,4,5,6.....12,13,13,14.....

    而同时简单的正数迭代,y和x的取值范围十分有限,对于arctanh((r-1)/(r+1))的r最大值仅仅为9,简直是不可用的。

    还好前人早已想到了这个问题,请参考论文,需要添加负数次的迭代,扩大定义域。

    算法过程:

    1.取x=r+1,y=r-1,z=0。当Y迭代逼近0的时候,z的值即为arctanh((r-1)/(r+1))的值。取迭代次数为16次的时候,N=-5起始迭代。则可以事先求解出相应的arctanh值作为常量供迭代方程加减。

    2.迭代公式,选取从N=-5处开始迭代,则有

     3.编写verilog代码。

    仿真一下看看。

    r=10仿真结果如下所示:x,y首先均左移8位。

    log10(10) = 71047/2^16*0.86858896 = 0.9416

    log10(100) = 125429/2^16*0.86858896 = 1.6624

    log10(1000) =225544/2^16*0.86858896 = 2.9893

    log10(10000) = 299021/2^16*0.86858896 = 3.9631

    有一定的误差,跟迭代次数和迭代输入值x,y有关

     注意事项:(1)处理中间结果的越界问题,位宽需要注意。

                       (2)如果r输入是个很小的数,比如10,可能还没迭代两次,y就到0了,必然导致结果的误差过大,则可以放大x和y,毕竟我们知道arctanh(y/x)=arctanh(y*k/(x*k))的。

                                所以结果并不会发生改变,但可以使得迭代更多次,保证精度。当然预先做个数值范围判定移位更佳。

                       (3)算术移位的问题,必须定义signed,否则会有问题的。还是老实使用拼接截位操作得好。

    以上只是对算法进行了功能的实现,侧重点并不在资源量的最优。

    以上。

  • 相关阅读:
    手写RPC
    随机生成6位的字符串验证码,要求包含数字,大小写字母
    输出学习阶段目标
    吃货联盟
    判断是否为整数
    实现一个登录注册功能
    作业1
    年龄异常
    作业2
    作业1
  • 原文地址:https://www.cnblogs.com/kingstacker/p/11024242.html
Copyright © 2020-2023  润新知