├── manual.pdf ├── tb_cordic.v └── cordic.v /manual.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/freecores/verilog_cordic_core/HEAD/manual.pdf -------------------------------------------------------------------------------- /tb_cordic.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns/1ns 2 | /* 3 | CORDIC testbench 4 | 5 | This testbench assumes the default settings for `defines 6 | in the cordic.v file. If you change any of the defaults 7 | you may have to make modifications to this file as well. 8 | 9 | This testbench uses `defines from the cordic.v file 10 | make sure you have the `include path set correctly for your 11 | environment. 12 | */ 13 | `include "cordic.v" 14 | module tb (); 15 | 16 | wire [`XY_BITS:0] x_o,y_o; 17 | wire [`THETA_BITS:0] theta_o; 18 | reg [`XY_BITS:0] x_i,y_i; 19 | reg [`THETA_BITS:0] theta_i; // angle in radians 20 | reg clock,reset; 21 | reg init; 22 | 23 | cordic UUT (.clk(clock),.rst(reset), 24 | `ifdef ITERATE 25 | .init(init), 26 | `endif 27 | .x_i(x_i),.y_i(y_i),.theta_i(theta_i), 28 | .x_o(x_o),.y_o(y_o),.theta_o(theta_o)); 29 | 30 | integer i,j,k; 31 | real a_i,a_o,a_e; 32 | real rx,ry,rex,rey; 33 | 34 | reg signed [`XY_BITS:0] ex,ey; 35 | 36 | reg signed [16:0] x [90:0]; 37 | reg signed [16:0] y [90:0]; 38 | reg signed [16:0] z [90:0]; 39 | 40 | task show_vector_results; 41 | input integer j; 42 | input [`THETA_BITS:0] theta; 43 | begin 44 | a_i = (j * 3.14) / 180; 45 | a_o = theta; 46 | a_o = a_o / 32768; 47 | if (a_o > a_i) a_e = a_o - a_i; else a_e = a_i - a_o; 48 | if (a_e > 0.001) 49 | $display("angle %f computed %f error %f",a_i,a_o,a_o - a_i); 50 | else 51 | $display("angle %f computed %f",a_i,a_o); 52 | end 53 | endtask 54 | 55 | task show_rotate_results; 56 | input integer j; 57 | input [`XY_BITS:0] lx; 58 | input [`XY_BITS:0] ly; 59 | begin 60 | rx = lx;// / 65535; 61 | ry = ly;// / 65535; 62 | rx = rx / 32768; //65535; 63 | ry = ry / 32768; //65535; 64 | if (lx > x[j]) ex = lx - x[j]; else ex = x[j] - lx; 65 | if (ly > y[j]) ey = ly - y[j]; else ey = y[j] - ly; 66 | if (ex > 10 || ey > 10) 67 | $display("Angle: %d sin = %f cos = %f errors %d %d",j,ry,rx,ey,ex); 68 | else 69 | $display("Angle: %d sin = %f cos = %f",j,ry,rx); 70 | end 71 | endtask 72 | 73 | task show_results; 74 | input integer j; 75 | input [`XY_BITS:0] lx; 76 | input [`XY_BITS:0] ly; 77 | input [`THETA_BITS:0] ltheta; 78 | begin 79 | `ifdef VECTOR 80 | show_vector_results(j,ltheta); 81 | `endif 82 | `ifdef ROTATE 83 | show_rotate_results(j,lx,ly); 84 | `endif 85 | end 86 | endtask 87 | initial begin 88 | $display("starting simulation"); 89 | `ifdef PIPELINE 90 | $display("PIPELINE configuration"); 91 | `endif 92 | `ifdef ITERATE 93 | $display("ITERATE configuration"); 94 | `endif 95 | `ifdef COMBINATORIAL 96 | $display("COMBINATORIAL configuration"); 97 | `endif 98 | 99 | // The following table is computed for U(1,15) format numbers 100 | // The angle data z[] is in radians 101 | x[0] <= 17'd32768; y[0] <= 17'd0; z[0] <= 17'd0; 102 | x[1] <= 17'd32763; y[1] <= 17'd571; z[1] <= 17'd571; 103 | x[2] <= 17'd32748; y[2] <= 17'd1143; z[2] <= 17'd1143; 104 | x[3] <= 17'd32723; y[3] <= 17'd1714; z[3] <= 17'd1715; 105 | x[4] <= 17'd32688; y[4] <= 17'd2285; z[4] <= 17'd2287; 106 | x[5] <= 17'd32643; y[5] <= 17'd2855; z[5] <= 17'd2859; 107 | x[6] <= 17'd32588; y[6] <= 17'd3425; z[6] <= 17'd3431; 108 | x[7] <= 17'd32523; y[7] <= 17'd3993; z[7] <= 17'd4003; 109 | x[8] <= 17'd32449; y[8] <= 17'd4560; z[8] <= 17'd4575; 110 | x[9] <= 17'd32364; y[9] <= 17'd5126; z[9] <= 17'd5147; 111 | x[10] <= 17'd32270; y[10] <= 17'd5690; z[10] <= 17'd5719; 112 | x[11] <= 17'd32165; y[11] <= 17'd6252; z[11] <= 17'd6291; 113 | x[12] <= 17'd32051; y[12] <= 17'd6812; z[12] <= 17'd6862; 114 | x[13] <= 17'd31928; y[13] <= 17'd7371; z[13] <= 17'd7434; 115 | x[14] <= 17'd31794; y[14] <= 17'd7927; z[14] <= 17'd8006; 116 | x[15] <= 17'd31651; y[15] <= 17'd8480; z[15] <= 17'd8578; 117 | x[16] <= 17'd31498; y[16] <= 17'd9032; z[16] <= 17'd9150; 118 | x[17] <= 17'd31336; y[17] <= 17'd9580; z[17] <= 17'd9722; 119 | x[18] <= 17'd31164; y[18] <= 17'd10125; z[18] <= 17'd10294; 120 | x[19] <= 17'd30982; y[19] <= 17'd10668; z[19] <= 17'd10866; 121 | x[20] <= 17'd30791; y[20] <= 17'd11207; z[20] <= 17'd11438; 122 | x[21] <= 17'd30591; y[21] <= 17'd11743; z[21] <= 17'd12010; 123 | x[22] <= 17'd30381; y[22] <= 17'd12275; z[22] <= 17'd12582; 124 | x[23] <= 17'd30163; y[23] <= 17'd12803; z[23] <= 17'd13153; 125 | x[24] <= 17'd29935; y[24] <= 17'd13327; z[24] <= 17'd13725; 126 | x[25] <= 17'd29697; y[25] <= 17'd13848; z[25] <= 17'd14297; 127 | x[26] <= 17'd29451; y[26] <= 17'd14364; z[26] <= 17'd14869; 128 | x[27] <= 17'd29196; y[27] <= 17'd14876; z[27] <= 17'd15441; 129 | x[28] <= 17'd28932; y[28] <= 17'd15383; z[28] <= 17'd16013; 130 | x[29] <= 17'd28659; y[29] <= 17'd15886; z[29] <= 17'd16585; 131 | x[30] <= 17'd28377; y[30] <= 17'd16383; z[30] <= 17'd17157; 132 | x[31] <= 17'd28087; y[31] <= 17'd16876; z[31] <= 17'd17729; 133 | x[32] <= 17'd27788; y[32] <= 17'd17364; z[32] <= 17'd18301; 134 | x[33] <= 17'd27481; y[33] <= 17'd17846; z[33] <= 17'd18873; 135 | x[34] <= 17'd27165; y[34] <= 17'd18323; z[34] <= 17'd19444; 136 | x[35] <= 17'd26841; y[35] <= 17'd18794; z[35] <= 17'd20016; 137 | x[36] <= 17'd26509; y[36] <= 17'd19260; z[36] <= 17'd20588; 138 | x[37] <= 17'd26169; y[37] <= 17'd19720; z[37] <= 17'd21160; 139 | x[38] <= 17'd25821; y[38] <= 17'd20173; z[38] <= 17'd21732; 140 | x[39] <= 17'd25465; y[39] <= 17'd20621; z[39] <= 17'd22304; 141 | x[40] <= 17'd25101; y[40] <= 17'd21062; z[40] <= 17'd22876; 142 | x[41] <= 17'd24730; y[41] <= 17'd21497; z[41] <= 17'd23448; 143 | x[42] <= 17'd24351; y[42] <= 17'd21926; z[42] <= 17'd24020; 144 | x[43] <= 17'd23964; y[43] <= 17'd22347; z[43] <= 17'd24592; 145 | x[44] <= 17'd23571; y[44] <= 17'd22762; z[44] <= 17'd25164; 146 | x[45] <= 17'd23170; y[45] <= 17'd23170; z[45] <= 17'd25735; 147 | x[46] <= 17'd22762; y[46] <= 17'd23571; z[46] <= 17'd26307; 148 | x[47] <= 17'd22347; y[47] <= 17'd23964; z[47] <= 17'd26879; 149 | x[48] <= 17'd21926; y[48] <= 17'd24351; z[48] <= 17'd27451; 150 | x[49] <= 17'd21497; y[49] <= 17'd24730; z[49] <= 17'd28023; 151 | x[50] <= 17'd21062; y[50] <= 17'd25101; z[50] <= 17'd28595; 152 | x[51] <= 17'd20621; y[51] <= 17'd25465; z[51] <= 17'd29167; 153 | x[52] <= 17'd20173; y[52] <= 17'd25821; z[52] <= 17'd29739; 154 | x[53] <= 17'd19720; y[53] <= 17'd26169; z[53] <= 17'd30311; 155 | x[54] <= 17'd19260; y[54] <= 17'd26509; z[54] <= 17'd30883; 156 | x[55] <= 17'd18794; y[55] <= 17'd26841; z[55] <= 17'd31455; 157 | x[56] <= 17'd18323; y[56] <= 17'd27165; z[56] <= 17'd32026; 158 | x[57] <= 17'd17846; y[57] <= 17'd27481; z[57] <= 17'd32598; 159 | x[58] <= 17'd17364; y[58] <= 17'd27788; z[58] <= 17'd33170; 160 | x[59] <= 17'd16876; y[59] <= 17'd28087; z[59] <= 17'd33742; 161 | x[60] <= 17'd16384; y[60] <= 17'd28377; z[60] <= 17'd34314; 162 | x[61] <= 17'd15886; y[61] <= 17'd28659; z[61] <= 17'd34886; 163 | x[62] <= 17'd15383; y[62] <= 17'd28932; z[62] <= 17'd35458; 164 | x[63] <= 17'd14876; y[63] <= 17'd29196; z[63] <= 17'd36030; 165 | x[64] <= 17'd14364; y[64] <= 17'd29451; z[64] <= 17'd36602; 166 | x[65] <= 17'd13848; y[65] <= 17'd29697; z[65] <= 17'd37174; 167 | x[66] <= 17'd13327; y[66] <= 17'd29935; z[66] <= 17'd37746; 168 | x[67] <= 17'd12803; y[67] <= 17'd30163; z[67] <= 17'd38317; 169 | x[68] <= 17'd12275; y[68] <= 17'd30381; z[68] <= 17'd38889; 170 | x[69] <= 17'd11743; y[69] <= 17'd30591; z[69] <= 17'd39461; 171 | x[70] <= 17'd11207; y[70] <= 17'd30791; z[70] <= 17'd40033; 172 | x[71] <= 17'd10668; y[71] <= 17'd30982; z[71] <= 17'd40605; 173 | x[72] <= 17'd10125; y[72] <= 17'd31164; z[72] <= 17'd41177; 174 | x[73] <= 17'd9580; y[73] <= 17'd31336; z[73] <= 17'd41749; 175 | x[74] <= 17'd9032; y[74] <= 17'd31498; z[74] <= 17'd42321; 176 | x[75] <= 17'd8480; y[75] <= 17'd31651; z[75] <= 17'd42893; 177 | x[76] <= 17'd7927; y[76] <= 17'd31794; z[76] <= 17'd43465; 178 | x[77] <= 17'd7371; y[77] <= 17'd31928; z[77] <= 17'd44037; 179 | x[78] <= 17'd6812; y[78] <= 17'd32051; z[78] <= 17'd44608; 180 | x[79] <= 17'd6252; y[79] <= 17'd32165; z[79] <= 17'd45180; 181 | x[80] <= 17'd5690; y[80] <= 17'd32270; z[80] <= 17'd45752; 182 | x[81] <= 17'd5126; y[81] <= 17'd32364; z[81] <= 17'd46324; 183 | x[82] <= 17'd4560; y[82] <= 17'd32449; z[82] <= 17'd46896; 184 | x[83] <= 17'd3993; y[83] <= 17'd32523; z[83] <= 17'd47468; 185 | x[84] <= 17'd3425; y[84] <= 17'd32588; z[84] <= 17'd48040; 186 | x[85] <= 17'd2855; y[85] <= 17'd32643; z[85] <= 17'd48612; 187 | x[86] <= 17'd2285; y[86] <= 17'd32688; z[86] <= 17'd49184; 188 | x[87] <= 17'd1714; y[87] <= 17'd32723; z[87] <= 17'd49756; 189 | x[88] <= 17'd1143; y[88] <= 17'd32748; z[88] <= 17'd50328; 190 | x[89] <= 17'd571; y[89] <= 17'd32763; z[89] <= 17'd50899; 191 | x[90] <= 17'd0; y[90] <= 17'd32768; z[90] <= 17'd51471; 192 | 193 | clock <= 0; 194 | init <= 0; 195 | reset <= 1; 196 | x_i <= 0; 197 | y_i <= 0; 198 | theta_i <= 0; 199 | #1 clock <= 1; 200 | #1 clock <= 0; 201 | reset <= 0; 202 | 203 | for (j=0;j<=90;j = j+1) begin // test 91 different angles, 0 to 90 degrees 204 | `ifdef ROTATE // compute sin and cos 205 | x_i <= `CORDIC_1; 206 | y_i <= 0; 207 | theta_i <= z[j]; 208 | `endif 209 | `ifdef VECTOR // compute the arctan 210 | x_i <= x[j]; 211 | y_i <= y[j]; 212 | theta_i <= 0; 213 | `endif 214 | 215 | 216 | `ifdef ITERATE 217 | init <= 1; // load the value into the rotator 218 | #1 clock <= 1; 219 | #1 clock <= 0; 220 | init <= 0; 221 | for(i=0;i<`ITERATIONS;i = i+1) begin // iterate on the value 222 | #1 clock <= 1; 223 | #1 clock <= 0; 224 | end 225 | show_results(j,x_o,y_o,theta_o); 226 | `endif 227 | 228 | 229 | `ifdef COMBINATORIAL 230 | #1; // give a little time to view the waveform... 231 | show_results(j,x_o,y_o,theta_o); 232 | `endif 233 | 234 | `ifdef PIPELINE 235 | #1 clock <= 1; 236 | #1 clock <= 0; 237 | if (j >= (`ITERATIONS-2)) begin // wait until the results start popping out 238 | show_results((j-(`ITERATIONS-2)),x_o,y_o,theta_o); 239 | end 240 | if (j == 90) // now flush the pipe 241 | for(i=0;i<(`ITERATIONS-2);i = i+1) begin 242 | #1 clock <= 1; 243 | #1 clock <= 0; 244 | show_results((90-`ITERATIONS+3+i),x_o,y_o,theta_o); 245 | end 246 | `endif 247 | 248 | 249 | end 250 | for(i=0;i<16;i=i+1) // dump a few extra clock just for grins 251 | #1 clock <= ~clock; 252 | end 253 | 254 | endmodule 255 | -------------------------------------------------------------------------------- /cordic.v: -------------------------------------------------------------------------------- 1 | /* file: cordic.v 2 | author: Dale Drinkard 3 | release: 08/06/2008 4 | 5 | brief: 6 | 7 | First Quadrant CORDIC 8 | 9 | This is a self contained, configurable CORDIC generator 10 | The user can modify the `defines below to customize the code generation. 11 | This code is for the first quadrant, but is easily extended to the full 12 | circle by first doing a coarse rotation. For example, to compute the 13 | arctan of -y/x, in the second quadrant, feed the cordic function y/x and 14 | then add 90 degrees (or pi/2 if using radian mode) to the result. When 15 | computing sin and cos of an angle, coarse rotate the angle into the first quadrant 16 | by subtracting the appropriate number of 90 (or pi/2) increments to get the angle in 17 | the first quadrant, keep track of this value, feed the cordic the angle. Then 18 | simply change the sign of the results based on this stored number. 19 | 20 | To use the core comment/uncomment the `defines below. The user can change the number 21 | of bits that represent the x,y, and theta values. The core can operate in either radian 22 | or degree mode. 23 | **NOTE** Even though there are allowances for changeing many parameters of the code, it is 24 | strongly advised that the user understand the CORDIC algorythm before monkeying with these 25 | settings. By default, the core uses 16+sign (17 bit) numbers for x,y, and theta, and iterates 16 26 | times in the algorythm. There are two arctan function tables,one for radian and one for degree 27 | mode. If more iterations or higher precision calculations are desired then a new arctan table will 28 | need to be computed. 29 | 30 | 31 | The core will operate in one 32 | of two modes: 33 | 34 | 35 | ROTATE: In this mode the user supplies a X and Y cartesian vector and an angle. The 36 | CORDIC rotator seeks to reduce the angle to zero by rotating the vector. 37 | 38 | To compute the cos and sin of the angle, set the inputs as follows: 39 | 40 | y_in = 0; 41 | x_in = `CORDIC_1 42 | theta_in = the input angle 43 | 44 | on completion: 45 | 46 | y_out = sin 47 | x_out = cos 48 | 49 | The `CORDIC_1 above is the inverse of the cordic gain... or ~0.603 50 | The input angle depends on whether you build in radian or degree mode 51 | see the description of the `defines below. 52 | 53 | 54 | VECTOR: In this mode the user supplies the tangent value in x and y and the rotator 55 | seeks to minimize the y value, thus computing the angle. 56 | 57 | To compute the arctan set the inputs as follows 58 | 59 | y_in and x_in such that y/x = the tangent value for which you wish to find the angle 60 | theta_in = 0; 61 | 62 | on completion 63 | 64 | theta_out = the angle 65 | 66 | 67 | 68 | */ 69 | 70 | /* data valid flag 71 | 72 | The iterative CORDIC implementations take a predetermined number of clock cycles to complete 73 | If the VALID_FLAG is defined the core instantiates a dvalid_in and dvalid_out signal. This 74 | signal makes no sense in the COMBINATORIAL mode. 75 | */ 76 | // `define VALID_FLAG 77 | 78 | /* Angle mode 79 | 80 | The CORDIC can work with the angle expressed in radians or degrees 81 | Uncomment the appropriate `define below. 82 | RADIAN_16 uses 16 bit values (+ sign bit for 17 bit accuracy). angle information 83 | is in the format U(1,15) where bit 16 is the sign bit, bit 15 is the whole number part 84 | and bits [14:0] are the fractional parts. 85 | DEGREE_8_8 uses U(8,8) + a sign bit where bit 16 = the sign bit, [15:8] = the whole number part 86 | and [7:0] = the fractional. 87 | 88 | The user can define other formats by creating a new tanangle function 89 | */ 90 | // `define DEGREE_8_8 91 | `define RADIAN_16 92 | 93 | /* Bit accuracy for sin and cos 94 | 95 | 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 96 | However, the CORDIC algorythm really doesn't care. 97 | */ 98 | `define XY_BITS 16 99 | 100 | /* Bit accuracy for theta 101 | 102 | The angle can be represented in either degree or radians. This define determines the number of bits used to represent the 103 | angle. Going to a higher number of bits would allow more iterations thus improving accuracy. 16 bits is enough for 104 | most applications. 105 | */ 106 | `define THETA_BITS 16 107 | 108 | /* Iteration accuracy 109 | 110 | This is the number of times the algorithm will iterate. For pipelined options, this is the number of stages. 111 | This number is <= the number of bits used in the angles 112 | 113 | */ 114 | `define ITERATIONS 16 115 | `define ITERATION_BITS 4 // 2^ITERATION_BITS = ITERATIONS 116 | 117 | /* Implementation options 118 | 119 | The CORDIC core can be realized in one of three methods: 120 | ITERATE: This option builds a single ROTATOR. The user provides the arguments and gives the core ITERATIONS 121 | clock cycles to get the result. A signal named init is instantiated to load the input values. It uses the 122 | least amount of LUTs 123 | PIPELINE: This option can take a new input on every clock and gives results ITERATIONS clock cycles later. It uses the 124 | most amount of LUTS. 125 | COMBINATORIAL: This option gives a result in a single clock cycle at the expense of very deep logic levels. The 126 | combinatorial implementation runs at about 10 mhz while the iterative ones run at about 125 in a 127 | Lattice ECP2 device. 128 | */ 129 | //`define ITERATE 130 | `define PIPELINE 131 | //`define COMBINATORIAL 132 | 133 | /* CORDIC function 134 | The CORDIC core works in one of two methods: VECTOR and ROTATE. 135 | VECTOR: This mode seeks to reduce the Y values and is used to compute an angle given a point. 136 | Enter the sin and cos of the desired angle and the core calculates the angle. This 137 | mode computes ARCTAN. 138 | ROTATE: This mode seeks to reduce the angle. It can be used to compute the sin and cos of a given angle 139 | */ 140 | //`define VECTOR // computes the arctan and square root 141 | `define ROTATE // computes sin cos 142 | 143 | 144 | /* CORDIC GAIN 145 | The CORDIC algorithm has an associated gain that is: 146 | 147 | CORDIC_gain = for (i=0;i> 1) | (D[`XY_BITS] << `XY_BITS); 179 | end 180 | endmodule 181 | /* Rotator 182 | This module is the heart of the CORDIC computer and implements the CORDIC algorithm. 183 | Input values x_i, y_i, and z_i are micro computed based on the iteration step 184 | and the arctan of that step. See the description of the CORDIC algorithm for details. 185 | 186 | */ 187 | module rotator ( 188 | input wire clk, 189 | input wire rst, 190 | `ifdef ITERATE 191 | input wire init, 192 | input wire [`ITERATION_BITS:0] iteration, 193 | input wire signed [`THETA_BITS:0] tangle, 194 | `endif 195 | input wire signed [`XY_BITS:0] x_i, 196 | input wire signed [`XY_BITS:0] y_i, 197 | input wire signed [`THETA_BITS:0] z_i, 198 | output wire signed [`XY_BITS:0] x_o, 199 | output wire signed [`XY_BITS:0] y_o, 200 | output wire signed [`THETA_BITS:0] z_o 201 | ); 202 | 203 | `ifdef GENERATE_LOOP 204 | parameter integer iteration = 0; 205 | parameter signed [`THETA_BITS:0] tangle = 0; 206 | `endif 207 | reg signed [`XY_BITS:0] x_1; 208 | reg signed [`XY_BITS:0] y_1; 209 | reg signed [`THETA_BITS:0] z_1; 210 | wire signed [`XY_BITS:0] x_i_shifted; 211 | wire signed [`XY_BITS:0] y_i_shifted; 212 | signed_shifter x_shifter(iteration,x_i,x_i_shifted); 213 | signed_shifter y_shifter(iteration,y_i,y_i_shifted); 214 | `ifdef COMBINATORIAL 215 | always @ * 216 | `endif 217 | `ifdef ITERATE 218 | always @ (posedge clk) 219 | `endif 220 | `ifdef PIPELINE 221 | always @ (posedge clk) 222 | `endif 223 | if (rst) begin 224 | x_1 <= 0; 225 | y_1 <= 0; 226 | z_1 <= 0; 227 | end else begin 228 | `ifdef ITERATE 229 | if (init) begin 230 | x_1 <= x_i; 231 | y_1 <= y_i; 232 | z_1 <= z_i; 233 | end else 234 | `endif 235 | `ifdef ROTATE 236 | if (z_i < 0) begin 237 | `endif 238 | `ifdef VECTOR 239 | if (y_i > 0) begin 240 | `endif 241 | x_1 <= x_i + y_i_shifted; //shifter(y_1,i); //(y_1 >> i); 242 | y_1 <= y_i - x_i_shifted; //shifter(x_1,i); //(x_1 >> i); 243 | z_1 <= z_i + tangle; 244 | end else begin 245 | x_1 <= x_i - y_i_shifted; //shifter(y_1,i); //(y_1 >> i); 246 | y_1 <= y_i + x_i_shifted; //shifter(x_1,i); //(x_1 >> i); 247 | z_1 <= z_i - tangle; 248 | end 249 | end 250 | assign x_o = x_1; 251 | assign y_o = y_1; 252 | assign z_o = z_1; 253 | endmodule 254 | /* 255 | CORDIC 256 | 257 | */ 258 | module cordic ( 259 | input wire clk, 260 | input wire rst, 261 | `ifdef ITERATE 262 | input wire init, 263 | `endif 264 | input wire signed [`XY_BITS:0] x_i, 265 | input wire signed [`XY_BITS:0] y_i, 266 | input wire signed [`THETA_BITS:0] theta_i, 267 | 268 | output wire signed [`XY_BITS:0] x_o, 269 | output wire signed [`XY_BITS:0] y_o, 270 | output wire signed [`THETA_BITS:0] theta_o 271 | `ifdef VALID_FLAG 272 | ,input wire valid_in, output wire valid_out 273 | `endif 274 | ); 275 | 276 | `ifdef RADIAN_16 277 | /* 278 | arctan table in radian format 16 bit + sign bit. 279 | */ 280 | function [`THETA_BITS:0] tanangle; 281 | input [3:0] i; 282 | begin 283 | case (i) 284 | 4'b0000: tanangle = 17'd25735 ; // 1/1 285 | 4'b0001: tanangle = 17'd15192; // 1/2 286 | 4'b0010: tanangle = 17'd8027; // 1/4 287 | 4'b0011: tanangle = 17'd4075; // 1/8 288 | 4'b0100: tanangle = 17'd2045; // 1/16 289 | 4'b0101: tanangle = 17'd1024; // 1/32 290 | 4'b0110: tanangle = 17'd512; // 1/64 291 | 4'b0111: tanangle = 17'd256; // 1/128 292 | 4'b1000: tanangle = 17'd128; // 1/256 293 | 4'b1001: tanangle = 17'd64; // 1/512 294 | 4'b1010: tanangle = 17'd32; // 1/1024 295 | 4'b1011: tanangle = 17'd16; // 1/2048 296 | 4'b1100: tanangle = 17'd8; // 1/4096 297 | 4'b1101: tanangle = 17'd4; // 1/8192 298 | 4'b1110: tanangle = 17'd2; // 1/16k 299 | 4'b1111: tanangle = 17'd1; // 1/32k 300 | endcase 301 | end 302 | endfunction 303 | `endif 304 | `ifdef DEGREE_8_8 305 | /* 306 | arctan table in degree U(8,8) format 16 bits + sign bit 307 | */ 308 | function [`THETA_BITS:0] tanangle; 309 | input [3:0] i; 310 | begin 311 | case (i) 312 | 0: tanangle = 17'd11520; // theta = 45.000000 313 | 1: tanangle = 17'd6800; // theta = 22.500000 314 | 2: tanangle = 17'd3593; // theta = 11.250000 315 | 3: tanangle = 17'd1824; // theta = 5.625000 316 | 4: tanangle = 17'd915; // theta = 2.812500 317 | 5: tanangle = 17'd458; // theta = 1.406250 318 | 6: tanangle = 17'd229; // theta = 0.703125 319 | 7: tanangle = 17'd114; // theta = 0.351562 320 | 8: tanangle = 17'd57; // theta = 0.175781 321 | 9: tanangle = 17'd28; // theta = 0.087891 322 | 10: tanangle = 17'd14; // theta = 0.043945 323 | 11: tanangle = 17'd7; // theta = 0.021973 324 | 12: tanangle = 17'd3; // theta = 0.010986 325 | 13: tanangle = 17'd1; // theta = 0.005493 326 | 14: tanangle = 17'd0; // theta = 0.002747 327 | 15: tanangle = 17'd0; // theta = 0.001373 328 | endcase 329 | end 330 | endfunction 331 | `endif 332 | 333 | `ifdef GENERATE_LOOP 334 | wire signed [`XY_BITS:0] x [`ITERATIONS-1:0]; 335 | wire signed [`XY_BITS:0] y [`ITERATIONS-1:0]; 336 | wire signed [`THETA_BITS:0] z [`ITERATIONS-1:0]; 337 | assign x[0] = x_i; 338 | assign y[0] = y_i; 339 | assign z[0] = theta_i; 340 | assign x_o = x[`ITERATIONS-1]; 341 | assign y_o = y[`ITERATIONS-1]; 342 | assign theta_o = z[`ITERATIONS-1]; 343 | `endif // GENERATE_LOOP 344 | 345 | `ifdef VALID_FLAG 346 | wire [`ITERATIONS-1:0] v; 347 | assign valid_out v[`ITERATIONS-1]; 348 | always @ (posedge clk or posedge rst) 349 | if (rst) v <= 0; 350 | else begin 351 | v <= v << 1; 352 | v[0] <= valid_in; 353 | end 354 | `endif 355 | 356 | `ifdef GENERATE_LOOP 357 | genvar i; 358 | generate for(i=0;i<`ITERATIONS-1;i=i+1) begin 359 | rotator U (clk,rst,x[i],y[i],z[i],x[i+1],y[i+1],z[i+1]); 360 | defparam U.iteration = i; 361 | defparam U.tangle = tanangle(i); 362 | end 363 | endgenerate 364 | `endif 365 | 366 | `ifdef ITERATE 367 | reg [`ITERATION_BITS:0] iteration; 368 | wire signed [`XY_BITS:0] x,y,z; 369 | assign x = init ? x_i : x_o; 370 | assign y = init ? y_i : y_o; 371 | assign z = init ? theta_i : theta_o; 372 | always @ (posedge clk or posedge init) 373 | if (init) iteration <= 0; 374 | else iteration <= iteration + 1; 375 | rotator U (clk,rst,init,iteration,tanangle(iteration),x,y,z,x_o,y_o,theta_o); 376 | `endif 377 | endmodule 378 | 379 | 380 | --------------------------------------------------------------------------------