shengzetam 发表于 2014-12-15 15:29:49

求代码 关于CORDIC算法的Verilog实现

我是verilog 初学者,现在遇到了要用verilog 实现CORDIC 算法 ,计算sin cos 以及 空间角,有哪位大神可以助一臂之力?

NJ8888 发表于 2014-12-15 16:03:08

明明有IP

shengzetam 发表于 2014-12-15 16:49:13

NJ8888 发表于 2014-12-15 16:03
明明有IP

???{:shocked:}

jlhgold 发表于 2014-12-15 20:54:07

CORDIC很简单 花钱就能买到{:lol:} 如果是项目 买就是

shengzetam 发表于 2014-12-16 14:32:58

jlhgold 发表于 2014-12-15 20:54
CORDIC很简单 花钱就能买到 如果是项目 买就是

我有代码,但是没有注解,有点看不懂的说{:mad:}

GunGun 发表于 2014-12-16 21:12:21

NJ8888 发表于 2014-12-15 16:03
明明有IP

是指Quartus还是Xilinx的有?

只怕有的IP没有License。

GunGun 发表于 2014-12-16 21:20:28

害得我再次确认了一下:Xilinx有,Quartus没有。

shengzetam 发表于 2014-12-17 08:22:17

GunGun 发表于 2014-12-16 21:20
害得我再次确认了一下:Xilinx有,Quartus没有。

我的是quatus的!

GunGun 发表于 2014-12-17 09:38:12

楼上的什么版本?哪来的License?贴个图看一下?!

shengzetam 发表于 2014-12-17 13:42:57

GunGun 发表于 2014-12-17 09:38
楼上的什么版本?哪来的License?贴个图看一下?!

就是这个版本 而且我不知道什么是IP,能解析一下吗?

chenchaoting 发表于 2014-12-17 13:49:06

你要实现什么函数,我可以贴出来

shengzetam 发表于 2014-12-17 13:50:43

chenchaoting 发表于 2014-12-17 13:49
你要实现什么函数,我可以贴出来

就是一个 cordic 算法 来计算cos sin 值的verilog 代码。其实我已经找到代码,但是不是很懂里面的意思。。我想有注释的 代码。。

chenchaoting 发表于 2014-12-17 13:51:31

我也没写注释,把原理看明白就很容易了,你把代码贴出来,我给你注释一下

shengzetam 发表于 2014-12-17 13:56:06

chenchaoting 发表于 2014-12-17 13:51
我也没写注释,把原理看明白就很容易了,你把代码贴出来,我给你注释一下 ...

`define RADIAN_16

/*Bit accuracy for sin and cos

The X and Y values are computed using a `XY_BITS + sign bit accuracy.The format is assumed to be U(1,15) + sign bit
However, the CORDIC algorythm really doesn't care.
*/
`define XY_BITS    16

/*Bit accuracy for theta

The angle can be represented in either degree or radians.This define determines the number of bits used to represent the
angle.Going to a higher number of bits would allow more iterations thus improving accuracy.16 bits is enough for
most applications.
*/
`define THETA_BITS 16

/*Iteration accuracy

This is the number of times the algorithm will iterate.For pipelined options, this is the number of stages.
This number is <= the number of bits used in the angles

*/
`define ITERATIONS 16
`define ITERATION_BITS 4// 2^ITERATION_BITS = ITERATIONS

/* Implementation options

The CORDIC core can be realized in one of three methods:
ITERATE:This option builds a single ROTATOR.The user provides the arguments and gives the core ITERATIONS
            clock cycles to get the result.A signal named init is instantiated to load the input values.It uses the
            least amount of LUTs
PIPELINE: This option can take a new input on every clock and gives results ITERATIONS clock cycles later. It uses the
            most amount of LUTS.
COMBINATORIAL:This option gives a result in a single clock cycle at the expense of very deep logic levels.The
                  combinatorial implementation runs at about 10 mhz while the iterative ones run at about 125 in a
                  Lattice ECP2 device.
*/
//`define ITERATE
`define PIPELINE
//`define COMBINATORIAL

/* CORDIC function
   The CORDIC core works in one of two methods:VECTOR and ROTATE.
   VECTOR:This mode seeks to reduce the Y values and is used to compute an angle given a point.
            Enter the sin and cos of the desired angle and the core calculates the angle.This
            mode computes ARCTAN.
   ROTATE:This mode seeks to reduce the angle.It can be used to compute the sin and cos of a given angle
*/
//`define VECTOR   // computes the arctan and square root
`define ROTATE    // computes sin cos


/* CORDIC GAIN
The CORDIC algorithm has an associated gain that is:

CORDIC_gain = for (i=0;i<n;i++) An = An*SQRT(1+(1/2^2i)
This quickly converges to ~ 1.647 as i goes to infinity.
For 16 bit numbers in the U(1,15) the value is 17'd53955
*** NOTE *** If you change the number representations
               you will have to recompute these values.
*/
`define CORDIC_GAIN 17'd53955
`define CORDIC_1 17'd19896      // CORDIC inverse


//====================   DO NOT EDIT BELOW THIS LINE ======================

`ifdef PIPELINE
`define GENERATE_LOOP
`endif
`ifdef COMBINATORIAL
`define GENERATE_LOOP
`endif


/*Signed shifter
This module does an arbitrary right shift to implement'
the 1/2^i function on signed numbers
*/
module signed_shifter (
input wire [`ITERATION_BITS-1:0] i,
input wire signed [`XY_BITS:0] D,
output reg signed [`XY_BITS:0] Q );
integer j;
always @ *
begin
    Q = D;
    for(j=0;j<i;j=j+1)
      Q = (Q >> 1) | (D[`XY_BITS] << `XY_BITS);
end
endmodule
/*Rotator
This module is the heart of the CORDIC computer and implements the CORDIC algorithm.
Input values x_i, y_i, and z_i are micro computed based on the iteration step
and the arctan of that step.See the description of the CORDIC algorithm for details.

*/
module rotator (
input wire clk,
input wire rst,
`ifdef ITERATE
input wire init,
input wire [`ITERATION_BITS:0] iteration,
input wire signed [`THETA_BITS:0] tangle,
`endif
input wire signed[`XY_BITS:0]    x_i,
input wire signed[`XY_BITS:0]    y_i,
input wire signed[`THETA_BITS:0] z_i,
output wire signed [`XY_BITS:0]    x_o,
output wire signed [`XY_BITS:0]    y_o,
output wire signed [`THETA_BITS:0] z_o
);

`ifdef GENERATE_LOOP
parameter integer iteration = 0;
parameter signed [`THETA_BITS:0] tangle = 0;
`endif
reg signed [`XY_BITS:0] x_1;
reg signed [`XY_BITS:0] y_1;
reg signed [`THETA_BITS:0] z_1;
wire signed [`XY_BITS:0] x_i_shifted;
wire signed [`XY_BITS:0] y_i_shifted;
signed_shifter x_shifter(iteration,x_i,x_i_shifted);
signed_shifter y_shifter(iteration,y_i,y_i_shifted);
`ifdef COMBINATORIAL
always @ *
`endif
`ifdef ITERATE
always @ (posedge clk)
`endif
`ifdef PIPELINE
always @ (posedge clk)
`endif
    if (rst) begin
      x_1 <= 0;
      y_1 <= 0;
      z_1 <= 0;
    end else begin
`ifdef ITERATE
      if (init) begin
      x_1 <= x_i;
      y_1 <= y_i;
      z_1 <= z_i;
      end else
`endif
`ifdef ROTATE
      if (z_i < 0) begin
`endif
`ifdef VECTOR
      if (y_i > 0) begin
`endif
      x_1 <= x_i + y_i_shifted; //shifter(y_1,i); //(y_1 >> i);
      y_1 <= y_i - x_i_shifted; //shifter(x_1,i); //(x_1 >> i);
      z_1 <= z_i + tangle;
      end else begin
      x_1 <= x_i - y_i_shifted; //shifter(y_1,i); //(y_1 >> i);
      y_1 <= y_i + x_i_shifted; //shifter(x_1,i); //(x_1 >> i);
      z_1 <= z_i - tangle;
      end
    end
assign x_o = x_1;
assign y_o = y_1;
assign z_o = z_1;
endmodule
/*               
                     CORDIC
                     
*/
module cordic (
input wire clk,
input wire rst,
`ifdef ITERATE
input wire init,
`endif
input wire signed [`XY_BITS:0]    x_i,
input wire signed [`XY_BITS:0]    y_i,
input wire signed [`THETA_BITS:0] theta_i,

output wire signed [`XY_BITS:0]    x_o,
output wire signed [`XY_BITS:0]    y_o,
output wire signed [`THETA_BITS:0] theta_o
`ifdef VALID_FLAG
,input wire valid_in, output wire valid_out
`endif
);

`ifdef RADIAN_16
/*
arctan table in radian format16 bit + sign bit.
*/
function [`THETA_BITS:0] tanangle;
input i;
begin
    case (i)
    4'b0000: tanangle = 17'd25735 ;   //1/1
    4'b0001: tanangle = 17'd15192;    //1/2
    4'b0010: tanangle = 17'd8027;   //1/4
    4'b0011: tanangle = 17'd4075;   //1/8
    4'b0100: tanangle = 17'd2045;   //1/16
    4'b0101: tanangle = 17'd1024;   //1/32
    4'b0110: tanangle = 17'd512;      //1/64
    4'b0111: tanangle = 17'd256;      //1/128
    4'b1000: tanangle = 17'd128;      //1/256
    4'b1001: tanangle = 17'd64;       //1/512
    4'b1010: tanangle = 17'd32;       //1/1024
    4'b1011: tanangle = 17'd16;       //1/2048
    4'b1100: tanangle = 17'd8;      //1/4096
    4'b1101: tanangle = 17'd4;      //1/8192
    4'b1110: tanangle = 17'd2;      //1/16k
    4'b1111: tanangle = 17'd1;      //1/32k
    endcase
end
endfunction
`endif
`ifdef DEGREE_8_8
/*
   arctan table in degree U(8,8) format 16 bits + sign bit
*/
function [`THETA_BITS:0] tanangle;
input i;
begin
    case (i)
    0: tanangle = 17'd11520;// theta = 45.000000
    1: tanangle = 17'd6800;   // theta = 22.500000
    2: tanangle = 17'd3593;   // theta = 11.250000
    3: tanangle = 17'd1824;   // theta = 5.625000
    4: tanangle = 17'd915;    // theta = 2.812500
    5: tanangle = 17'd458;    // theta = 1.406250
    6: tanangle = 17'd229;    // theta = 0.703125
    7: tanangle = 17'd114;    // theta = 0.351562
    8: tanangle = 17'd57;   // theta = 0.175781
    9: tanangle = 17'd28;   // theta = 0.087891
    10: tanangle = 17'd14;    // theta = 0.043945
    11: tanangle = 17'd7;   // theta = 0.021973
    12: tanangle = 17'd3;   // theta = 0.010986
    13: tanangle = 17'd1;   // theta = 0.005493
    14: tanangle = 17'd0;   // theta = 0.002747
    15: tanangle = 17'd0;   // theta = 0.001373
    endcase
end
endfunction
`endif

`ifdef GENERATE_LOOP
wire signed [`XY_BITS:0] x [`ITERATIONS-1:0];
wire signed [`XY_BITS:0] y [`ITERATIONS-1:0];
wire signed [`THETA_BITS:0] z [`ITERATIONS-1:0];
assign x = x_i;
assign y = y_i;
assign z = theta_i;
assign x_o = x[`ITERATIONS-1];
assign y_o = y[`ITERATIONS-1];
assign theta_o = z[`ITERATIONS-1];
`endif // GENERATE_LOOP

`ifdef VALID_FLAG
wire [`ITERATIONS-1:0] v;
assign valid_out v[`ITERATIONS-1];
always @ (posedge clk or posedge rst)
if (rst) v <= 0;
else begin
         v <= v << 1;
         v <= valid_in;
       end
`endif

`ifdef GENERATE_LOOP
genvar i;
generate for(i=0;i<`ITERATIONS-1;i=i+1)
begin:inst
rotator U (clk,rst,x,y,z,x,y,z);
defparam U.iteration = i;
defparam U.tangle = tanangle(i);
end
endgenerate
`endif

`ifdef ITERATE
reg [`ITERATION_BITS:0] iteration;
wire signed [`XY_BITS:0] x,y,z;
assign x = init ? x_i : x_o;
assign y = init ? y_i : y_o;
assign z = init ? theta_i : theta_o;
always @ (posedge clk or posedge init)
    if (init) iteration <= 0;
    else iteration <= iteration + 1;
rotator U (clk,rst,init,iteration,tanangle(iteration),x,y,z,x_o,y_o,theta_o);
`endif
endmodule

GunGun 发表于 2014-12-17 14:09:55

shengzetam 发表于 2014-12-17 13:42
就是这个版本 而且我不知道什么是IP,能解析一下吗?

知道了,这个版本的可以有。

但V14版本的,不知道跑哪里去了?

chenchaoting 发表于 2014-12-17 14:17:42

本帖最后由 chenchaoting 于 2014-12-17 14:20 编辑

shengzetam 发表于 2014-12-17 13:56
`define RADIAN_16

/*Bit accuracy for sin and cos


你这个程序支持好几种形式的,注释比较复杂,那个常数表就是反正切的结果(弧度制,或者°)再乘以一个位宽,然后就是有一个rotate函数,这个就是进行旋转(其中要根据没次的y 或者z)的结果选择旋转的方向,下面有个iteration =iteration+1就是控制迭代的

chenchaoting 发表于 2014-12-17 14:34:57

`define RADIAN_16

/*Bit accuracy for sin and cos

The X and Y values are computed using a `XY_BITS + sign bit accuracy.The format is assumed to be U(1,15) + sign bit
However, the CORDIC algorythm really doesn't care.
*/
`define XY_BITS    16

/*Bit accuracy for theta

The angle can be represented in either degree or radians.This define determines the number of bits used to represent the
angle.Going to a higher number of bits would allow more iterations thus improving accuracy.16 bits is enough for
most applications.
*/
`define THETA_BITS 16

/*Iteration accuracy

This is the number of times the algorithm will iterate.For pipelined options, this is the number of stages.
This number is <= the number of bits used in the angles

*/
`define ITERATIONS 16
`define ITERATION_BITS 4// 2^ITERATION_BITS = ITERATIONS

/* Implementation options

The CORDIC core can be realized in one of three methods:
ITERATE:This option builds a single ROTATOR.The user provides the arguments and gives the core ITERATIONS
            clock cycles to get the result.A signal named init is instantiated to load the input values.It uses the
            least amount of LUTs
PIPELINE: This option can take a new input on every clock and gives results ITERATIONS clock cycles later. It uses the
            most amount of LUTS.
COMBINATORIAL:This option gives a result in a single clock cycle at the expense of very deep logic levels.The
                  combinatorial implementation runs at about 10 mhz while the iterative ones run at about 125 in a
                  Lattice ECP2 device.
*/
//`define ITERATE
`define PIPELINE
//`define COMBINATORIAL

/* CORDIC function
   The CORDIC core works in one of two methods:VECTOR and ROTATE.
   VECTOR:This mode seeks to reduce the Y values and is used to compute an angle given a point.
            Enter the sin and cos of the desired angle and the core calculates the angle.This
            mode computes ARCTAN.
   ROTATE:This mode seeks to reduce the angle.It can be used to compute the sin and cos of a given angle
*/
//`define VECTOR   // computes the arctan and square root
`define ROTATE    // computes sin cos


/* CORDIC GAIN
The CORDIC algorithm has an associated gain that is:

CORDIC_gain = for (i=0;i<n;i++) An = An*SQRT(1+(1/2^2i)
This quickly converges to ~ 1.647 as i goes to infinity.
For 16 bit numbers in the U(1,15) the value is 17'd53955
*** NOTE *** If you change the number representations
               you will have to recompute these values.
*/
`define CORDIC_GAIN 17'd53955          //
`define CORDIC_1 17'd19896      // CORDIC inverse


//====================   DO NOT EDIT BELOW THIS LINE ======================

`ifdef PIPELINE
`define GENERATE_LOOP
`endif
`ifdef COMBINATORIAL
`define GENERATE_LOOP
`endif


/*Signed shifter
This module does an arbitrary right shift to implement'
the 1/2^i function on signed numbers
*/
module signed_shifter (                           //移位模块
input wire [`ITERATION_BITS-1:0] i,
input wire signed [`XY_BITS:0] D,
output reg signed [`XY_BITS:0] Q );
integer j;
always @ *
begin
    Q = D;
    for(j=0;j<i;j=j+1)
      Q = (Q >> 1) | (D[`XY_BITS] << `XY_BITS);
end
endmodule
/*Rotator
This module is the heart of the CORDIC computer and implements the CORDIC algorithm.
Input values x_i, y_i, and z_i are micro computed based on the iteration step
and the arctan of that step.See the description of the CORDIC algorithm for details.

*/
module rotator (            //旋转模块,调用上面的移位模块。
input wire clk,
input wire rst,
`ifdef ITERATE
input wire init,
input wire [`ITERATION_BITS:0] iteration,
input wire signed [`THETA_BITS:0] tangle,
`endif
input wire signed[`XY_BITS:0]    x_i,
input wire signed[`XY_BITS:0]    y_i,
input wire signed[`THETA_BITS:0] z_i,
output wire signed [`XY_BITS:0]    x_o,
output wire signed [`XY_BITS:0]    y_o,
output wire signed [`THETA_BITS:0] z_o
);

`ifdef GENERATE_LOOP
parameter integer iteration = 0;
parameter signed [`THETA_BITS:0] tangle = 0;
`endif
reg signed [`XY_BITS:0] x_1;
reg signed [`XY_BITS:0] y_1;
reg signed [`THETA_BITS:0] z_1;
wire signed [`XY_BITS:0] x_i_shifted;
wire signed [`XY_BITS:0] y_i_shifted;
signed_shifter x_shifter(iteration,x_i,x_i_shifted);
signed_shifter y_shifter(iteration,y_i,y_i_shifted);
`ifdef COMBINATORIAL
always @ *
`endif
`ifdef ITERATE
always @ (posedge clk)
`endif
`ifdef PIPELINE
always @ (posedge clk)
`endif
    if (rst) begin
      x_1 <= 0;
      y_1 <= 0;
      z_1 <= 0;
    end else begin
`ifdef ITERATE
      if (init) begin
      x_1 <= x_i;
      y_1 <= y_i;
      z_1 <= z_i;
      end else
`endif
`ifdef ROTATE            //旋转模式
      if (z_i < 0) begin
`endif
`ifdef VECTOR            //向量模式
      if (y_i > 0) begin    // 根据>0,<0选择加减
`endif
      x_1 <= x_i + y_i_shifted; //shifter(y_1,i); //(y_1 >> i);   
      y_1 <= y_i - x_i_shifted; //shifter(x_1,i); //(x_1 >> i);
      z_1 <= z_i + tangle;
      end else begin
      x_1 <= x_i - y_i_shifted; //shifter(y_1,i); //(y_1 >> i);
      y_1 <= y_i + x_i_shifted; //shifter(x_1,i); //(x_1 >> i);
      z_1 <= z_i - tangle;
      end
    end
assign x_o = x_1;
assign y_o = y_1;
assign z_o = z_1;
endmodule
/*               
                     CORDIC
                     
*/
module cordic (
input wire clk,
input wire rst,
`ifdef ITERATE
input wire init,
`endif
input wire signed [`XY_BITS:0]    x_i,
input wire signed [`XY_BITS:0]    y_i,
input wire signed [`THETA_BITS:0] theta_i,

output wire signed [`XY_BITS:0]    x_o,
output wire signed [`XY_BITS:0]    y_o,
output wire signed [`THETA_BITS:0] theta_o
`ifdef VALID_FLAG
,input wire valid_in, output wire valid_out
`endif
);

`ifdef RADIAN_16
/*
arctan table in radian format16 bit + sign bit.
*/
function [`THETA_BITS:0] tanangle;
input i;
begin
    case (i)
    4'b0000: tanangle = 17'd25735 ;   //1/1            弧度为单位, 反正切1,再乘以位宽
    4'b0001: tanangle = 17'd15192;    //1/2            弧度为单位, 反正切0.5,再乘以位宽
    4'b0010: tanangle = 17'd8027;   //1/4         
    4'b0011: tanangle = 17'd4075;   //1/8            。。。。
    4'b0100: tanangle = 17'd2045;   //1/16
    4'b0101: tanangle = 17'd1024;   //1/32
    4'b0110: tanangle = 17'd512;      //1/64
    4'b0111: tanangle = 17'd256;      //1/128
    4'b1000: tanangle = 17'd128;      //1/256
    4'b1001: tanangle = 17'd64;       //1/512
    4'b1010: tanangle = 17'd32;       //1/1024
    4'b1011: tanangle = 17'd16;       //1/2048
    4'b1100: tanangle = 17'd8;      //1/4096
    4'b1101: tanangle = 17'd4;      //1/8192
    4'b1110: tanangle = 17'd2;      //1/16k
    4'b1111: tanangle = 17'd1;      //1/32k
    endcase
end
endfunction
`endif
`ifdef DEGREE_8_8
/*
   arctan table in degree U(8,8) format 16 bits + sign bit
*/
function [`THETA_BITS:0] tanangle;
input i;
begin
    case (i)
    0: tanangle = 17'd11520;// theta = 45.000000       单位为°, 反正切1,再乘以位宽
    1: tanangle = 17'd6800;   // theta = 22.500000       反正切0.5,再乘以位宽
    2: tanangle = 17'd3593;   // theta = 11.250000       反正切0.25,再乘以位宽
    3: tanangle = 17'd1824;   // theta = 5.625000         。。。。
    4: tanangle = 17'd915;    // theta = 2.812500
    5: tanangle = 17'd458;    // theta = 1.406250
    6: tanangle = 17'd229;    // theta = 0.703125
    7: tanangle = 17'd114;    // theta = 0.351562
    8: tanangle = 17'd57;   // theta = 0.175781
    9: tanangle = 17'd28;   // theta = 0.087891
    10: tanangle = 17'd14;    // theta = 0.043945
    11: tanangle = 17'd7;   // theta = 0.021973
    12: tanangle = 17'd3;   // theta = 0.010986
    13: tanangle = 17'd1;   // theta = 0.005493
    14: tanangle = 17'd0;   // theta = 0.002747
    15: tanangle = 17'd0;   // theta = 0.001373
    endcase
end
endfunction
`endif

`ifdef GENERATE_LOOP
wire signed [`XY_BITS:0] x [`ITERATIONS-1:0];
wire signed [`XY_BITS:0] y [`ITERATIONS-1:0];
wire signed [`THETA_BITS:0] z [`ITERATIONS-1:0];
assign x = x_i;
assign y = y_i;
assign z = theta_i;
assign x_o = x[`ITERATIONS-1];
assign y_o = y[`ITERATIONS-1];
assign theta_o = z[`ITERATIONS-1];
`endif // GENERATE_LOOP

`ifdef VALID_FLAG
wire [`ITERATIONS-1:0] v;
assign valid_out v[`ITERATIONS-1];
always @ (posedge clk or posedge rst)
if (rst) v <= 0;
else begin
         v <= v << 1;
         v <= valid_in;
       end
`endif

`ifdef GENERATE_LOOP                  
genvar i;
generate for(i=0;i<`ITERATIONS-1;i=i+1)
begin:inst
rotator U (clk,rst,x,y,z,x,y,z);
defparam U.iteration = i;
defparam U.tangle = tanangle(i);
end
endgenerate
`endif

`ifdef ITERATE            
reg [`ITERATION_BITS:0] iteration;
wire signed [`XY_BITS:0] x,y,z;
assign x = init ? x_i : x_o;
assign y = init ? y_i : y_o;//这里把上次的迭代结果传给下一次的x,y
assign z = init ? theta_i : theta_o;
always @ (posedge clk or posedge init)
    if (init) iteration <= 0;
    else iteration <= iteration + 1;//迭代循环
rotator U (clk,rst,init,iteration,tanangle(iteration),x,y,z,x_o,y_o,theta_o);
`endif
endmodule
页: [1]
查看完整版本: 求代码 关于CORDIC算法的Verilog实现