URL
https://opencores.org/ocsvn/verilog_cordic_core/verilog_cordic_core/trunk
Subversion Repositories verilog_cordic_core
Compare Revisions
- This comparison shows the changes necessary to convert path
/
- from Rev 3 to Rev 4
- ↔ Reverse comparison
Rev 3 → Rev 4
/tags/rel_1/cordic.v
File deleted
/tags/rel_1/tb_cordic.v
File deleted
/tags/rel_1/manual.pdf
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
tags/rel_1/manual.pdf
Property changes :
Deleted: svn:mime-type
## -1 +0,0 ##
-application/octet-stream
\ No newline at end of property
Index: trunk/tb_cordic.v
===================================================================
--- trunk/tb_cordic.v (revision 3)
+++ trunk/tb_cordic.v (nonexistent)
@@ -1,254 +0,0 @@
-`timescale 1ns/1ns
-/*
- CORDIC testbench
-
- This testbench assumes the default settings for `defines
- in the cordic.v file. If you change any of the defaults
- you may have to make modifications to this file as well.
-
- This testbench uses `defines from the cordic.v file
- make sure you have the `include path set correctly for your
- environment.
-*/
-`include "cordic.v"
-module tb ();
-
- wire [`XY_BITS:0] x_o,y_o;
- wire [`THETA_BITS:0] theta_o;
- reg [`XY_BITS:0] x_i,y_i;
- reg [`THETA_BITS:0] theta_i; // angle in radians
- reg clock,reset;
- reg init;
-
-cordic UUT (.clk(clock),.rst(reset),
-`ifdef ITERATE
- .init(init),
-`endif
- .x_i(x_i),.y_i(y_i),.theta_i(theta_i),
- .x_o(x_o),.y_o(y_o),.theta_o(theta_o));
-
- integer i,j,k;
- real a_i,a_o,a_e;
- real rx,ry,rex,rey;
-
- reg signed [`XY_BITS:0] ex,ey;
-
- reg signed [16:0] x [90:0];
- reg signed [16:0] y [90:0];
- reg signed [16:0] z [90:0];
-
- task show_vector_results;
- input integer j;
- input [`THETA_BITS:0] theta;
- begin
- a_i = (j * 3.14) / 180;
- a_o = theta;
- a_o = a_o / 32768;
- if (a_o > a_i) a_e = a_o - a_i; else a_e = a_i - a_o;
- if (a_e > 0.001)
- $display("angle %f computed %f error %f",a_i,a_o,a_o - a_i);
- else
- $display("angle %f computed %f",a_i,a_o);
- end
- endtask
-
- task show_rotate_results;
- input integer j;
- input [`XY_BITS:0] lx;
- input [`XY_BITS:0] ly;
- begin
- rx = lx;// / 65535;
- ry = ly;// / 65535;
- rx = rx / 32768; //65535;
- ry = ry / 32768; //65535;
- if (lx > x[j]) ex = lx - x[j]; else ex = x[j] - lx;
- if (ly > y[j]) ey = ly - y[j]; else ey = y[j] - ly;
- if (ex > 10 || ey > 10)
- $display("Angle: %d sin = %f cos = %f errors %d %d",j,ry,rx,ey,ex);
- else
- $display("Angle: %d sin = %f cos = %f",j,ry,rx);
- end
- endtask
-
- task show_results;
- input integer j;
- input [`XY_BITS:0] lx;
- input [`XY_BITS:0] ly;
- input [`THETA_BITS:0] ltheta;
- begin
-`ifdef VECTOR
- show_vector_results(j,ltheta);
-`endif
-`ifdef ROTATE
- show_rotate_results(j,lx,ly);
-`endif
- end
- endtask
- initial begin
- $display("starting simulation");
-`ifdef PIPELINE
- $display("PIPELINE configuration");
-`endif
-`ifdef ITERATE
- $display("ITERATE configuration");
-`endif
-`ifdef COMBINATORIAL
- $display("COMBINATORIAL configuration");
-`endif
-
- // The following table is computed for U(1,15) format numbers
- // The angle data z[] is in radians
- x[0] <= 17'd32768; y[0] <= 17'd0; z[0] <= 17'd0;
- x[1] <= 17'd32763; y[1] <= 17'd571; z[1] <= 17'd571;
- x[2] <= 17'd32748; y[2] <= 17'd1143; z[2] <= 17'd1143;
- x[3] <= 17'd32723; y[3] <= 17'd1714; z[3] <= 17'd1715;
- x[4] <= 17'd32688; y[4] <= 17'd2285; z[4] <= 17'd2287;
- x[5] <= 17'd32643; y[5] <= 17'd2855; z[5] <= 17'd2859;
- x[6] <= 17'd32588; y[6] <= 17'd3425; z[6] <= 17'd3431;
- x[7] <= 17'd32523; y[7] <= 17'd3993; z[7] <= 17'd4003;
- x[8] <= 17'd32449; y[8] <= 17'd4560; z[8] <= 17'd4575;
- x[9] <= 17'd32364; y[9] <= 17'd5126; z[9] <= 17'd5147;
- x[10] <= 17'd32270; y[10] <= 17'd5690; z[10] <= 17'd5719;
- x[11] <= 17'd32165; y[11] <= 17'd6252; z[11] <= 17'd6291;
- x[12] <= 17'd32051; y[12] <= 17'd6812; z[12] <= 17'd6862;
- x[13] <= 17'd31928; y[13] <= 17'd7371; z[13] <= 17'd7434;
- x[14] <= 17'd31794; y[14] <= 17'd7927; z[14] <= 17'd8006;
- x[15] <= 17'd31651; y[15] <= 17'd8480; z[15] <= 17'd8578;
- x[16] <= 17'd31498; y[16] <= 17'd9032; z[16] <= 17'd9150;
- x[17] <= 17'd31336; y[17] <= 17'd9580; z[17] <= 17'd9722;
- x[18] <= 17'd31164; y[18] <= 17'd10125; z[18] <= 17'd10294;
- x[19] <= 17'd30982; y[19] <= 17'd10668; z[19] <= 17'd10866;
- x[20] <= 17'd30791; y[20] <= 17'd11207; z[20] <= 17'd11438;
- x[21] <= 17'd30591; y[21] <= 17'd11743; z[21] <= 17'd12010;
- x[22] <= 17'd30381; y[22] <= 17'd12275; z[22] <= 17'd12582;
- x[23] <= 17'd30163; y[23] <= 17'd12803; z[23] <= 17'd13153;
- x[24] <= 17'd29935; y[24] <= 17'd13327; z[24] <= 17'd13725;
- x[25] <= 17'd29697; y[25] <= 17'd13848; z[25] <= 17'd14297;
- x[26] <= 17'd29451; y[26] <= 17'd14364; z[26] <= 17'd14869;
- x[27] <= 17'd29196; y[27] <= 17'd14876; z[27] <= 17'd15441;
- x[28] <= 17'd28932; y[28] <= 17'd15383; z[28] <= 17'd16013;
- x[29] <= 17'd28659; y[29] <= 17'd15886; z[29] <= 17'd16585;
- x[30] <= 17'd28377; y[30] <= 17'd16383; z[30] <= 17'd17157;
- x[31] <= 17'd28087; y[31] <= 17'd16876; z[31] <= 17'd17729;
- x[32] <= 17'd27788; y[32] <= 17'd17364; z[32] <= 17'd18301;
- x[33] <= 17'd27481; y[33] <= 17'd17846; z[33] <= 17'd18873;
- x[34] <= 17'd27165; y[34] <= 17'd18323; z[34] <= 17'd19444;
- x[35] <= 17'd26841; y[35] <= 17'd18794; z[35] <= 17'd20016;
- x[36] <= 17'd26509; y[36] <= 17'd19260; z[36] <= 17'd20588;
- x[37] <= 17'd26169; y[37] <= 17'd19720; z[37] <= 17'd21160;
- x[38] <= 17'd25821; y[38] <= 17'd20173; z[38] <= 17'd21732;
- x[39] <= 17'd25465; y[39] <= 17'd20621; z[39] <= 17'd22304;
- x[40] <= 17'd25101; y[40] <= 17'd21062; z[40] <= 17'd22876;
- x[41] <= 17'd24730; y[41] <= 17'd21497; z[41] <= 17'd23448;
- x[42] <= 17'd24351; y[42] <= 17'd21926; z[42] <= 17'd24020;
- x[43] <= 17'd23964; y[43] <= 17'd22347; z[43] <= 17'd24592;
- x[44] <= 17'd23571; y[44] <= 17'd22762; z[44] <= 17'd25164;
- x[45] <= 17'd23170; y[45] <= 17'd23170; z[45] <= 17'd25735;
- x[46] <= 17'd22762; y[46] <= 17'd23571; z[46] <= 17'd26307;
- x[47] <= 17'd22347; y[47] <= 17'd23964; z[47] <= 17'd26879;
- x[48] <= 17'd21926; y[48] <= 17'd24351; z[48] <= 17'd27451;
- x[49] <= 17'd21497; y[49] <= 17'd24730; z[49] <= 17'd28023;
- x[50] <= 17'd21062; y[50] <= 17'd25101; z[50] <= 17'd28595;
- x[51] <= 17'd20621; y[51] <= 17'd25465; z[51] <= 17'd29167;
- x[52] <= 17'd20173; y[52] <= 17'd25821; z[52] <= 17'd29739;
- x[53] <= 17'd19720; y[53] <= 17'd26169; z[53] <= 17'd30311;
- x[54] <= 17'd19260; y[54] <= 17'd26509; z[54] <= 17'd30883;
- x[55] <= 17'd18794; y[55] <= 17'd26841; z[55] <= 17'd31455;
- x[56] <= 17'd18323; y[56] <= 17'd27165; z[56] <= 17'd32026;
- x[57] <= 17'd17846; y[57] <= 17'd27481; z[57] <= 17'd32598;
- x[58] <= 17'd17364; y[58] <= 17'd27788; z[58] <= 17'd33170;
- x[59] <= 17'd16876; y[59] <= 17'd28087; z[59] <= 17'd33742;
- x[60] <= 17'd16384; y[60] <= 17'd28377; z[60] <= 17'd34314;
- x[61] <= 17'd15886; y[61] <= 17'd28659; z[61] <= 17'd34886;
- x[62] <= 17'd15383; y[62] <= 17'd28932; z[62] <= 17'd35458;
- x[63] <= 17'd14876; y[63] <= 17'd29196; z[63] <= 17'd36030;
- x[64] <= 17'd14364; y[64] <= 17'd29451; z[64] <= 17'd36602;
- x[65] <= 17'd13848; y[65] <= 17'd29697; z[65] <= 17'd37174;
- x[66] <= 17'd13327; y[66] <= 17'd29935; z[66] <= 17'd37746;
- x[67] <= 17'd12803; y[67] <= 17'd30163; z[67] <= 17'd38317;
- x[68] <= 17'd12275; y[68] <= 17'd30381; z[68] <= 17'd38889;
- x[69] <= 17'd11743; y[69] <= 17'd30591; z[69] <= 17'd39461;
- x[70] <= 17'd11207; y[70] <= 17'd30791; z[70] <= 17'd40033;
- x[71] <= 17'd10668; y[71] <= 17'd30982; z[71] <= 17'd40605;
- x[72] <= 17'd10125; y[72] <= 17'd31164; z[72] <= 17'd41177;
- x[73] <= 17'd9580; y[73] <= 17'd31336; z[73] <= 17'd41749;
- x[74] <= 17'd9032; y[74] <= 17'd31498; z[74] <= 17'd42321;
- x[75] <= 17'd8480; y[75] <= 17'd31651; z[75] <= 17'd42893;
- x[76] <= 17'd7927; y[76] <= 17'd31794; z[76] <= 17'd43465;
- x[77] <= 17'd7371; y[77] <= 17'd31928; z[77] <= 17'd44037;
- x[78] <= 17'd6812; y[78] <= 17'd32051; z[78] <= 17'd44608;
- x[79] <= 17'd6252; y[79] <= 17'd32165; z[79] <= 17'd45180;
- x[80] <= 17'd5690; y[80] <= 17'd32270; z[80] <= 17'd45752;
- x[81] <= 17'd5126; y[81] <= 17'd32364; z[81] <= 17'd46324;
- x[82] <= 17'd4560; y[82] <= 17'd32449; z[82] <= 17'd46896;
- x[83] <= 17'd3993; y[83] <= 17'd32523; z[83] <= 17'd47468;
- x[84] <= 17'd3425; y[84] <= 17'd32588; z[84] <= 17'd48040;
- x[85] <= 17'd2855; y[85] <= 17'd32643; z[85] <= 17'd48612;
- x[86] <= 17'd2285; y[86] <= 17'd32688; z[86] <= 17'd49184;
- x[87] <= 17'd1714; y[87] <= 17'd32723; z[87] <= 17'd49756;
- x[88] <= 17'd1143; y[88] <= 17'd32748; z[88] <= 17'd50328;
- x[89] <= 17'd571; y[89] <= 17'd32763; z[89] <= 17'd50899;
- x[90] <= 17'd0; y[90] <= 17'd32768; z[90] <= 17'd51471;
-
- clock <= 0;
- init <= 0;
- reset <= 1;
- x_i <= 0;
- y_i <= 0;
- theta_i <= 0;
- #1 clock <= 1;
- #1 clock <= 0;
- reset <= 0;
-
- for (j=0;j<=90;j = j+1) begin // test 91 different angles, 0 to 90 degrees
-`ifdef ROTATE // compute sin and cos
- x_i <= `CORDIC_1;
- y_i <= 0;
- theta_i <= z[j];
-`endif
-`ifdef VECTOR // compute the arctan
- x_i <= x[j];
- y_i <= y[j];
- theta_i <= 0;
-`endif
-
-
-`ifdef ITERATE
- init <= 1; // load the value into the rotator
- #1 clock <= 1;
- #1 clock <= 0;
- init <= 0;
- for(i=0;i<`ITERATIONS;i = i+1) begin // iterate on the value
- #1 clock <= 1;
- #1 clock <= 0;
- end
- show_results(j,x_o,y_o,theta_o);
-`endif
-
-
-`ifdef COMBINATORIAL
- #1; // give a little time to view the waveform...
- show_results(j,x_o,y_o,theta_o);
-`endif
-
-`ifdef PIPELINE
- #1 clock <= 1;
- #1 clock <= 0;
- if (j >= (`ITERATIONS-2)) begin // wait until the results start popping out
- show_results((j-(`ITERATIONS-2)),x_o,y_o,theta_o);
- end
- if (j == 90) // now flush the pipe
- for(i=0;i<(`ITERATIONS-2);i = i+1) begin
- #1 clock <= 1;
- #1 clock <= 0;
- show_results((90-`ITERATIONS+3+i),x_o,y_o,theta_o);
- end
-`endif
-
-
- end
- for(i=0;i<16;i=i+1) // dump a few extra clock just for grins
- #1 clock <= ~clock;
-end
-
-endmodule
Index: trunk/manual.pdf
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Index: trunk/manual.pdf
===================================================================
--- trunk/manual.pdf (revision 3)
+++ trunk/manual.pdf (nonexistent)
trunk/manual.pdf
Property changes :
Deleted: svn:mime-type
## -1 +0,0 ##
-application/octet-stream
\ No newline at end of property
Index: trunk/cordic.v
===================================================================
--- trunk/cordic.v (revision 3)
+++ trunk/cordic.v (nonexistent)
@@ -1,379 +0,0 @@
-/* file: cordic.v
- author: Dale Drinkard
- release: 08/06/2008
-
- brief:
-
- First Quadrant CORDIC
-
- This is a self contained, configurable CORDIC generator
- The user can modify the `defines below to customize the code generation.
- This code is for the first quadrant, but is easily extended to the full
- circle by first doing a coarse rotation. For example, to compute the
- arctan of -y/x, in the second quadrant, feed the cordic function y/x and
- then add 90 degrees (or pi/2 if using radian mode) to the result. When
- computing sin and cos of an angle, coarse rotate the angle into the first quadrant
- by subtracting the appropriate number of 90 (or pi/2) increments to get the angle in
- the first quadrant, keep track of this value, feed the cordic the angle. Then
- simply change the sign of the results based on this stored number.
-
- To use the core comment/uncomment the `defines below. The user can change the number
- of bits that represent the x,y, and theta values. The core can operate in either radian
- or degree mode.
- **NOTE** Even though there are allowances for changeing many parameters of the code, it is
- strongly advised that the user understand the CORDIC algorythm before monkeying with these
- settings. By default, the core uses 16+sign (17 bit) numbers for x,y, and theta, and iterates 16
- times in the algorythm. There are two arctan function tables,one for radian and one for degree
- mode. If more iterations or higher precision calculations are desired then a new arctan table will
- need to be computed.
-
-
- The core will operate in one
- of two modes:
-
-
- ROTATE: In this mode the user supplies a X and Y cartesian vector and an angle. The
- CORDIC rotator seeks to reduce the angle to zero by rotating the vector.
-
- To compute the cos and sin of the angle, set the inputs as follows:
-
- y_in = 0;
- x_in = `CORDIC_1
- theta_in = the input angle
-
- on completion:
-
- y_out = sin
- x_out = cos
-
- The `CORDIC_1 above is the inverse of the cordic gain... or ~0.603
- The input angle depends on whether you build in radian or degree mode
- see the description of the `defines below.
-
-
- VECTOR: In this mode the user supplies the tangent value in x and y and the rotator
- seeks to minimize the y value, thus computing the angle.
-
- To compute the arctan set the inputs as follows
-
- y_in and x_in such that y/x = the tangent value for which you wish to find the angle
- theta_in = 0;
-
- on completion
-
- theta_out = the angle
-
-
-
-*/
-
-/* data valid flag
-
- The iterative CORDIC implementations take a predetermined number of clock cycles to complete
- If the VALID_FLAG is defined the core instantiates a dvalid_in and dvalid_out signal. This
- signal makes no sense in the COMBINATORIAL mode.
-*/
-// `define VALID_FLAG
-
-/* Angle mode
-
- The CORDIC can work with the angle expressed in radians or degrees
- Uncomment the appropriate `define below.
- RADIAN_16 uses 16 bit values (+ sign bit for 17 bit accuracy). angle information
- is in the format U(1,15) where bit 16 is the sign bit, bit 15 is the whole number part
- and bits [14:0] are the fractional parts.
- DEGREE_8_8 uses U(8,8) + a sign bit where bit 16 = the sign bit, [15:8] = the whole number part
- and [7:0] = the fractional.
-
- The user can define other formats by creating a new tanangle function
-*/
-// `define DEGREE_8_8
-`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> 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 format 16 bit + sign bit.
-*/
-function [`THETA_BITS:0] tanangle;
- input [3:0] 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 [3:0] 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[0] = x_i;
- assign y[0] = y_i;
- assign z[0] = 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[0] <= valid_in;
- end
-`endif
-
-`ifdef GENERATE_LOOP
-genvar i;
-generate for(i=0;i<`ITERATIONS-1;i=i+1) begin
- rotator U (clk,rst,x[i],y[i],z[i],x[i+1],y[i+1],z[i+1]);
- 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
-
-
Index: verilog_cordic_core/trunk/manual.pdf
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Index: verilog_cordic_core/trunk/manual.pdf
===================================================================
--- verilog_cordic_core/trunk/manual.pdf (nonexistent)
+++ verilog_cordic_core/trunk/manual.pdf (revision 4)
verilog_cordic_core/trunk/manual.pdf
Property changes :
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Index: verilog_cordic_core/trunk/cordic.v
===================================================================
--- verilog_cordic_core/trunk/cordic.v (nonexistent)
+++ verilog_cordic_core/trunk/cordic.v (revision 4)
@@ -0,0 +1,379 @@
+/* file: cordic.v
+ author: Dale Drinkard
+ release: 08/06/2008
+
+ brief:
+
+ First Quadrant CORDIC
+
+ This is a self contained, configurable CORDIC generator
+ The user can modify the `defines below to customize the code generation.
+ This code is for the first quadrant, but is easily extended to the full
+ circle by first doing a coarse rotation. For example, to compute the
+ arctan of -y/x, in the second quadrant, feed the cordic function y/x and
+ then add 90 degrees (or pi/2 if using radian mode) to the result. When
+ computing sin and cos of an angle, coarse rotate the angle into the first quadrant
+ by subtracting the appropriate number of 90 (or pi/2) increments to get the angle in
+ the first quadrant, keep track of this value, feed the cordic the angle. Then
+ simply change the sign of the results based on this stored number.
+
+ To use the core comment/uncomment the `defines below. The user can change the number
+ of bits that represent the x,y, and theta values. The core can operate in either radian
+ or degree mode.
+ **NOTE** Even though there are allowances for changeing many parameters of the code, it is
+ strongly advised that the user understand the CORDIC algorythm before monkeying with these
+ settings. By default, the core uses 16+sign (17 bit) numbers for x,y, and theta, and iterates 16
+ times in the algorythm. There are two arctan function tables,one for radian and one for degree
+ mode. If more iterations or higher precision calculations are desired then a new arctan table will
+ need to be computed.
+
+
+ The core will operate in one
+ of two modes:
+
+
+ ROTATE: In this mode the user supplies a X and Y cartesian vector and an angle. The
+ CORDIC rotator seeks to reduce the angle to zero by rotating the vector.
+
+ To compute the cos and sin of the angle, set the inputs as follows:
+
+ y_in = 0;
+ x_in = `CORDIC_1
+ theta_in = the input angle
+
+ on completion:
+
+ y_out = sin
+ x_out = cos
+
+ The `CORDIC_1 above is the inverse of the cordic gain... or ~0.603
+ The input angle depends on whether you build in radian or degree mode
+ see the description of the `defines below.
+
+
+ VECTOR: In this mode the user supplies the tangent value in x and y and the rotator
+ seeks to minimize the y value, thus computing the angle.
+
+ To compute the arctan set the inputs as follows
+
+ y_in and x_in such that y/x = the tangent value for which you wish to find the angle
+ theta_in = 0;
+
+ on completion
+
+ theta_out = the angle
+
+
+
+*/
+
+/* data valid flag
+
+ The iterative CORDIC implementations take a predetermined number of clock cycles to complete
+ If the VALID_FLAG is defined the core instantiates a dvalid_in and dvalid_out signal. This
+ signal makes no sense in the COMBINATORIAL mode.
+*/
+// `define VALID_FLAG
+
+/* Angle mode
+
+ The CORDIC can work with the angle expressed in radians or degrees
+ Uncomment the appropriate `define below.
+ RADIAN_16 uses 16 bit values (+ sign bit for 17 bit accuracy). angle information
+ is in the format U(1,15) where bit 16 is the sign bit, bit 15 is the whole number part
+ and bits [14:0] are the fractional parts.
+ DEGREE_8_8 uses U(8,8) + a sign bit where bit 16 = the sign bit, [15:8] = the whole number part
+ and [7:0] = the fractional.
+
+ The user can define other formats by creating a new tanangle function
+*/
+// `define DEGREE_8_8
+`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> 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 format 16 bit + sign bit.
+*/
+function [`THETA_BITS:0] tanangle;
+ input [3:0] 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 [3:0] 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[0] = x_i;
+ assign y[0] = y_i;
+ assign z[0] = 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[0] <= valid_in;
+ end
+`endif
+
+`ifdef GENERATE_LOOP
+genvar i;
+generate for(i=0;i<`ITERATIONS-1;i=i+1) begin
+ rotator U (clk,rst,x[i],y[i],z[i],x[i+1],y[i+1],z[i+1]);
+ 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
+
+
Index: verilog_cordic_core/trunk/tb_cordic.v
===================================================================
--- verilog_cordic_core/trunk/tb_cordic.v (nonexistent)
+++ verilog_cordic_core/trunk/tb_cordic.v (revision 4)
@@ -0,0 +1,254 @@
+`timescale 1ns/1ns
+/*
+ CORDIC testbench
+
+ This testbench assumes the default settings for `defines
+ in the cordic.v file. If you change any of the defaults
+ you may have to make modifications to this file as well.
+
+ This testbench uses `defines from the cordic.v file
+ make sure you have the `include path set correctly for your
+ environment.
+*/
+`include "cordic.v"
+module tb ();
+
+ wire [`XY_BITS:0] x_o,y_o;
+ wire [`THETA_BITS:0] theta_o;
+ reg [`XY_BITS:0] x_i,y_i;
+ reg [`THETA_BITS:0] theta_i; // angle in radians
+ reg clock,reset;
+ reg init;
+
+cordic UUT (.clk(clock),.rst(reset),
+`ifdef ITERATE
+ .init(init),
+`endif
+ .x_i(x_i),.y_i(y_i),.theta_i(theta_i),
+ .x_o(x_o),.y_o(y_o),.theta_o(theta_o));
+
+ integer i,j,k;
+ real a_i,a_o,a_e;
+ real rx,ry,rex,rey;
+
+ reg signed [`XY_BITS:0] ex,ey;
+
+ reg signed [16:0] x [90:0];
+ reg signed [16:0] y [90:0];
+ reg signed [16:0] z [90:0];
+
+ task show_vector_results;
+ input integer j;
+ input [`THETA_BITS:0] theta;
+ begin
+ a_i = (j * 3.14) / 180;
+ a_o = theta;
+ a_o = a_o / 32768;
+ if (a_o > a_i) a_e = a_o - a_i; else a_e = a_i - a_o;
+ if (a_e > 0.001)
+ $display("angle %f computed %f error %f",a_i,a_o,a_o - a_i);
+ else
+ $display("angle %f computed %f",a_i,a_o);
+ end
+ endtask
+
+ task show_rotate_results;
+ input integer j;
+ input [`XY_BITS:0] lx;
+ input [`XY_BITS:0] ly;
+ begin
+ rx = lx;// / 65535;
+ ry = ly;// / 65535;
+ rx = rx / 32768; //65535;
+ ry = ry / 32768; //65535;
+ if (lx > x[j]) ex = lx - x[j]; else ex = x[j] - lx;
+ if (ly > y[j]) ey = ly - y[j]; else ey = y[j] - ly;
+ if (ex > 10 || ey > 10)
+ $display("Angle: %d sin = %f cos = %f errors %d %d",j,ry,rx,ey,ex);
+ else
+ $display("Angle: %d sin = %f cos = %f",j,ry,rx);
+ end
+ endtask
+
+ task show_results;
+ input integer j;
+ input [`XY_BITS:0] lx;
+ input [`XY_BITS:0] ly;
+ input [`THETA_BITS:0] ltheta;
+ begin
+`ifdef VECTOR
+ show_vector_results(j,ltheta);
+`endif
+`ifdef ROTATE
+ show_rotate_results(j,lx,ly);
+`endif
+ end
+ endtask
+ initial begin
+ $display("starting simulation");
+`ifdef PIPELINE
+ $display("PIPELINE configuration");
+`endif
+`ifdef ITERATE
+ $display("ITERATE configuration");
+`endif
+`ifdef COMBINATORIAL
+ $display("COMBINATORIAL configuration");
+`endif
+
+ // The following table is computed for U(1,15) format numbers
+ // The angle data z[] is in radians
+ x[0] <= 17'd32768; y[0] <= 17'd0; z[0] <= 17'd0;
+ x[1] <= 17'd32763; y[1] <= 17'd571; z[1] <= 17'd571;
+ x[2] <= 17'd32748; y[2] <= 17'd1143; z[2] <= 17'd1143;
+ x[3] <= 17'd32723; y[3] <= 17'd1714; z[3] <= 17'd1715;
+ x[4] <= 17'd32688; y[4] <= 17'd2285; z[4] <= 17'd2287;
+ x[5] <= 17'd32643; y[5] <= 17'd2855; z[5] <= 17'd2859;
+ x[6] <= 17'd32588; y[6] <= 17'd3425; z[6] <= 17'd3431;
+ x[7] <= 17'd32523; y[7] <= 17'd3993; z[7] <= 17'd4003;
+ x[8] <= 17'd32449; y[8] <= 17'd4560; z[8] <= 17'd4575;
+ x[9] <= 17'd32364; y[9] <= 17'd5126; z[9] <= 17'd5147;
+ x[10] <= 17'd32270; y[10] <= 17'd5690; z[10] <= 17'd5719;
+ x[11] <= 17'd32165; y[11] <= 17'd6252; z[11] <= 17'd6291;
+ x[12] <= 17'd32051; y[12] <= 17'd6812; z[12] <= 17'd6862;
+ x[13] <= 17'd31928; y[13] <= 17'd7371; z[13] <= 17'd7434;
+ x[14] <= 17'd31794; y[14] <= 17'd7927; z[14] <= 17'd8006;
+ x[15] <= 17'd31651; y[15] <= 17'd8480; z[15] <= 17'd8578;
+ x[16] <= 17'd31498; y[16] <= 17'd9032; z[16] <= 17'd9150;
+ x[17] <= 17'd31336; y[17] <= 17'd9580; z[17] <= 17'd9722;
+ x[18] <= 17'd31164; y[18] <= 17'd10125; z[18] <= 17'd10294;
+ x[19] <= 17'd30982; y[19] <= 17'd10668; z[19] <= 17'd10866;
+ x[20] <= 17'd30791; y[20] <= 17'd11207; z[20] <= 17'd11438;
+ x[21] <= 17'd30591; y[21] <= 17'd11743; z[21] <= 17'd12010;
+ x[22] <= 17'd30381; y[22] <= 17'd12275; z[22] <= 17'd12582;
+ x[23] <= 17'd30163; y[23] <= 17'd12803; z[23] <= 17'd13153;
+ x[24] <= 17'd29935; y[24] <= 17'd13327; z[24] <= 17'd13725;
+ x[25] <= 17'd29697; y[25] <= 17'd13848; z[25] <= 17'd14297;
+ x[26] <= 17'd29451; y[26] <= 17'd14364; z[26] <= 17'd14869;
+ x[27] <= 17'd29196; y[27] <= 17'd14876; z[27] <= 17'd15441;
+ x[28] <= 17'd28932; y[28] <= 17'd15383; z[28] <= 17'd16013;
+ x[29] <= 17'd28659; y[29] <= 17'd15886; z[29] <= 17'd16585;
+ x[30] <= 17'd28377; y[30] <= 17'd16383; z[30] <= 17'd17157;
+ x[31] <= 17'd28087; y[31] <= 17'd16876; z[31] <= 17'd17729;
+ x[32] <= 17'd27788; y[32] <= 17'd17364; z[32] <= 17'd18301;
+ x[33] <= 17'd27481; y[33] <= 17'd17846; z[33] <= 17'd18873;
+ x[34] <= 17'd27165; y[34] <= 17'd18323; z[34] <= 17'd19444;
+ x[35] <= 17'd26841; y[35] <= 17'd18794; z[35] <= 17'd20016;
+ x[36] <= 17'd26509; y[36] <= 17'd19260; z[36] <= 17'd20588;
+ x[37] <= 17'd26169; y[37] <= 17'd19720; z[37] <= 17'd21160;
+ x[38] <= 17'd25821; y[38] <= 17'd20173; z[38] <= 17'd21732;
+ x[39] <= 17'd25465; y[39] <= 17'd20621; z[39] <= 17'd22304;
+ x[40] <= 17'd25101; y[40] <= 17'd21062; z[40] <= 17'd22876;
+ x[41] <= 17'd24730; y[41] <= 17'd21497; z[41] <= 17'd23448;
+ x[42] <= 17'd24351; y[42] <= 17'd21926; z[42] <= 17'd24020;
+ x[43] <= 17'd23964; y[43] <= 17'd22347; z[43] <= 17'd24592;
+ x[44] <= 17'd23571; y[44] <= 17'd22762; z[44] <= 17'd25164;
+ x[45] <= 17'd23170; y[45] <= 17'd23170; z[45] <= 17'd25735;
+ x[46] <= 17'd22762; y[46] <= 17'd23571; z[46] <= 17'd26307;
+ x[47] <= 17'd22347; y[47] <= 17'd23964; z[47] <= 17'd26879;
+ x[48] <= 17'd21926; y[48] <= 17'd24351; z[48] <= 17'd27451;
+ x[49] <= 17'd21497; y[49] <= 17'd24730; z[49] <= 17'd28023;
+ x[50] <= 17'd21062; y[50] <= 17'd25101; z[50] <= 17'd28595;
+ x[51] <= 17'd20621; y[51] <= 17'd25465; z[51] <= 17'd29167;
+ x[52] <= 17'd20173; y[52] <= 17'd25821; z[52] <= 17'd29739;
+ x[53] <= 17'd19720; y[53] <= 17'd26169; z[53] <= 17'd30311;
+ x[54] <= 17'd19260; y[54] <= 17'd26509; z[54] <= 17'd30883;
+ x[55] <= 17'd18794; y[55] <= 17'd26841; z[55] <= 17'd31455;
+ x[56] <= 17'd18323; y[56] <= 17'd27165; z[56] <= 17'd32026;
+ x[57] <= 17'd17846; y[57] <= 17'd27481; z[57] <= 17'd32598;
+ x[58] <= 17'd17364; y[58] <= 17'd27788; z[58] <= 17'd33170;
+ x[59] <= 17'd16876; y[59] <= 17'd28087; z[59] <= 17'd33742;
+ x[60] <= 17'd16384; y[60] <= 17'd28377; z[60] <= 17'd34314;
+ x[61] <= 17'd15886; y[61] <= 17'd28659; z[61] <= 17'd34886;
+ x[62] <= 17'd15383; y[62] <= 17'd28932; z[62] <= 17'd35458;
+ x[63] <= 17'd14876; y[63] <= 17'd29196; z[63] <= 17'd36030;
+ x[64] <= 17'd14364; y[64] <= 17'd29451; z[64] <= 17'd36602;
+ x[65] <= 17'd13848; y[65] <= 17'd29697; z[65] <= 17'd37174;
+ x[66] <= 17'd13327; y[66] <= 17'd29935; z[66] <= 17'd37746;
+ x[67] <= 17'd12803; y[67] <= 17'd30163; z[67] <= 17'd38317;
+ x[68] <= 17'd12275; y[68] <= 17'd30381; z[68] <= 17'd38889;
+ x[69] <= 17'd11743; y[69] <= 17'd30591; z[69] <= 17'd39461;
+ x[70] <= 17'd11207; y[70] <= 17'd30791; z[70] <= 17'd40033;
+ x[71] <= 17'd10668; y[71] <= 17'd30982; z[71] <= 17'd40605;
+ x[72] <= 17'd10125; y[72] <= 17'd31164; z[72] <= 17'd41177;
+ x[73] <= 17'd9580; y[73] <= 17'd31336; z[73] <= 17'd41749;
+ x[74] <= 17'd9032; y[74] <= 17'd31498; z[74] <= 17'd42321;
+ x[75] <= 17'd8480; y[75] <= 17'd31651; z[75] <= 17'd42893;
+ x[76] <= 17'd7927; y[76] <= 17'd31794; z[76] <= 17'd43465;
+ x[77] <= 17'd7371; y[77] <= 17'd31928; z[77] <= 17'd44037;
+ x[78] <= 17'd6812; y[78] <= 17'd32051; z[78] <= 17'd44608;
+ x[79] <= 17'd6252; y[79] <= 17'd32165; z[79] <= 17'd45180;
+ x[80] <= 17'd5690; y[80] <= 17'd32270; z[80] <= 17'd45752;
+ x[81] <= 17'd5126; y[81] <= 17'd32364; z[81] <= 17'd46324;
+ x[82] <= 17'd4560; y[82] <= 17'd32449; z[82] <= 17'd46896;
+ x[83] <= 17'd3993; y[83] <= 17'd32523; z[83] <= 17'd47468;
+ x[84] <= 17'd3425; y[84] <= 17'd32588; z[84] <= 17'd48040;
+ x[85] <= 17'd2855; y[85] <= 17'd32643; z[85] <= 17'd48612;
+ x[86] <= 17'd2285; y[86] <= 17'd32688; z[86] <= 17'd49184;
+ x[87] <= 17'd1714; y[87] <= 17'd32723; z[87] <= 17'd49756;
+ x[88] <= 17'd1143; y[88] <= 17'd32748; z[88] <= 17'd50328;
+ x[89] <= 17'd571; y[89] <= 17'd32763; z[89] <= 17'd50899;
+ x[90] <= 17'd0; y[90] <= 17'd32768; z[90] <= 17'd51471;
+
+ clock <= 0;
+ init <= 0;
+ reset <= 1;
+ x_i <= 0;
+ y_i <= 0;
+ theta_i <= 0;
+ #1 clock <= 1;
+ #1 clock <= 0;
+ reset <= 0;
+
+ for (j=0;j<=90;j = j+1) begin // test 91 different angles, 0 to 90 degrees
+`ifdef ROTATE // compute sin and cos
+ x_i <= `CORDIC_1;
+ y_i <= 0;
+ theta_i <= z[j];
+`endif
+`ifdef VECTOR // compute the arctan
+ x_i <= x[j];
+ y_i <= y[j];
+ theta_i <= 0;
+`endif
+
+
+`ifdef ITERATE
+ init <= 1; // load the value into the rotator
+ #1 clock <= 1;
+ #1 clock <= 0;
+ init <= 0;
+ for(i=0;i<`ITERATIONS;i = i+1) begin // iterate on the value
+ #1 clock <= 1;
+ #1 clock <= 0;
+ end
+ show_results(j,x_o,y_o,theta_o);
+`endif
+
+
+`ifdef COMBINATORIAL
+ #1; // give a little time to view the waveform...
+ show_results(j,x_o,y_o,theta_o);
+`endif
+
+`ifdef PIPELINE
+ #1 clock <= 1;
+ #1 clock <= 0;
+ if (j >= (`ITERATIONS-2)) begin // wait until the results start popping out
+ show_results((j-(`ITERATIONS-2)),x_o,y_o,theta_o);
+ end
+ if (j == 90) // now flush the pipe
+ for(i=0;i<(`ITERATIONS-2);i = i+1) begin
+ #1 clock <= 1;
+ #1 clock <= 0;
+ show_results((90-`ITERATIONS+3+i),x_o,y_o,theta_o);
+ end
+`endif
+
+
+ end
+ for(i=0;i<16;i=i+1) // dump a few extra clock just for grins
+ #1 clock <= ~clock;
+end
+
+endmodule
Index: verilog_cordic_core/trunk
===================================================================
--- verilog_cordic_core/trunk (nonexistent)
+++ verilog_cordic_core/trunk (revision 4)
verilog_cordic_core/trunk
Property changes :
Added: svn:mergeinfo
## -0,0 +0,0 ##
Index: verilog_cordic_core/web_uploads
===================================================================
--- verilog_cordic_core/web_uploads (nonexistent)
+++ verilog_cordic_core/web_uploads (revision 4)
verilog_cordic_core/web_uploads
Property changes :
Added: svn:mergeinfo
## -0,0 +0,0 ##
Index: verilog_cordic_core/branches
===================================================================
--- verilog_cordic_core/branches (nonexistent)
+++ verilog_cordic_core/branches (revision 4)
verilog_cordic_core/branches
Property changes :
Added: svn:mergeinfo
## -0,0 +0,0 ##
Index: verilog_cordic_core/tags/rel_1/manual.pdf
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Index: verilog_cordic_core/tags/rel_1/manual.pdf
===================================================================
--- verilog_cordic_core/tags/rel_1/manual.pdf (nonexistent)
+++ verilog_cordic_core/tags/rel_1/manual.pdf (revision 4)
verilog_cordic_core/tags/rel_1/manual.pdf
Property changes :
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Index: verilog_cordic_core/tags/rel_1/cordic.v
===================================================================
--- verilog_cordic_core/tags/rel_1/cordic.v (nonexistent)
+++ verilog_cordic_core/tags/rel_1/cordic.v (revision 4)
@@ -0,0 +1,379 @@
+/* file: cordic.v
+ author: Dale Drinkard
+ release: 08/06/2008
+
+ brief:
+
+ First Quadrant CORDIC
+
+ This is a self contained, configurable CORDIC generator
+ The user can modify the `defines below to customize the code generation.
+ This code is for the first quadrant, but is easily extended to the full
+ circle by first doing a coarse rotation. For example, to compute the
+ arctan of -y/x, in the second quadrant, feed the cordic function y/x and
+ then add 90 degrees (or pi/2 if using radian mode) to the result. When
+ computing sin and cos of an angle, coarse rotate the angle into the first quadrant
+ by subtracting the appropriate number of 90 (or pi/2) increments to get the angle in
+ the first quadrant, keep track of this value, feed the cordic the angle. Then
+ simply change the sign of the results based on this stored number.
+
+ To use the core comment/uncomment the `defines below. The user can change the number
+ of bits that represent the x,y, and theta values. The core can operate in either radian
+ or degree mode.
+ **NOTE** Even though there are allowances for changeing many parameters of the code, it is
+ strongly advised that the user understand the CORDIC algorythm before monkeying with these
+ settings. By default, the core uses 16+sign (17 bit) numbers for x,y, and theta, and iterates 16
+ times in the algorythm. There are two arctan function tables,one for radian and one for degree
+ mode. If more iterations or higher precision calculations are desired then a new arctan table will
+ need to be computed.
+
+
+ The core will operate in one
+ of two modes:
+
+
+ ROTATE: In this mode the user supplies a X and Y cartesian vector and an angle. The
+ CORDIC rotator seeks to reduce the angle to zero by rotating the vector.
+
+ To compute the cos and sin of the angle, set the inputs as follows:
+
+ y_in = 0;
+ x_in = `CORDIC_1
+ theta_in = the input angle
+
+ on completion:
+
+ y_out = sin
+ x_out = cos
+
+ The `CORDIC_1 above is the inverse of the cordic gain... or ~0.603
+ The input angle depends on whether you build in radian or degree mode
+ see the description of the `defines below.
+
+
+ VECTOR: In this mode the user supplies the tangent value in x and y and the rotator
+ seeks to minimize the y value, thus computing the angle.
+
+ To compute the arctan set the inputs as follows
+
+ y_in and x_in such that y/x = the tangent value for which you wish to find the angle
+ theta_in = 0;
+
+ on completion
+
+ theta_out = the angle
+
+
+
+*/
+
+/* data valid flag
+
+ The iterative CORDIC implementations take a predetermined number of clock cycles to complete
+ If the VALID_FLAG is defined the core instantiates a dvalid_in and dvalid_out signal. This
+ signal makes no sense in the COMBINATORIAL mode.
+*/
+// `define VALID_FLAG
+
+/* Angle mode
+
+ The CORDIC can work with the angle expressed in radians or degrees
+ Uncomment the appropriate `define below.
+ RADIAN_16 uses 16 bit values (+ sign bit for 17 bit accuracy). angle information
+ is in the format U(1,15) where bit 16 is the sign bit, bit 15 is the whole number part
+ and bits [14:0] are the fractional parts.
+ DEGREE_8_8 uses U(8,8) + a sign bit where bit 16 = the sign bit, [15:8] = the whole number part
+ and [7:0] = the fractional.
+
+ The user can define other formats by creating a new tanangle function
+*/
+// `define DEGREE_8_8
+`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> 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 format 16 bit + sign bit.
+*/
+function [`THETA_BITS:0] tanangle;
+ input [3:0] 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 [3:0] 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[0] = x_i;
+ assign y[0] = y_i;
+ assign z[0] = 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[0] <= valid_in;
+ end
+`endif
+
+`ifdef GENERATE_LOOP
+genvar i;
+generate for(i=0;i<`ITERATIONS-1;i=i+1) begin
+ rotator U (clk,rst,x[i],y[i],z[i],x[i+1],y[i+1],z[i+1]);
+ 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
+
+
Index: verilog_cordic_core/tags/rel_1/tb_cordic.v
===================================================================
--- verilog_cordic_core/tags/rel_1/tb_cordic.v (nonexistent)
+++ verilog_cordic_core/tags/rel_1/tb_cordic.v (revision 4)
@@ -0,0 +1,254 @@
+`timescale 1ns/1ns
+/*
+ CORDIC testbench
+
+ This testbench assumes the default settings for `defines
+ in the cordic.v file. If you change any of the defaults
+ you may have to make modifications to this file as well.
+
+ This testbench uses `defines from the cordic.v file
+ make sure you have the `include path set correctly for your
+ environment.
+*/
+`include "cordic.v"
+module tb ();
+
+ wire [`XY_BITS:0] x_o,y_o;
+ wire [`THETA_BITS:0] theta_o;
+ reg [`XY_BITS:0] x_i,y_i;
+ reg [`THETA_BITS:0] theta_i; // angle in radians
+ reg clock,reset;
+ reg init;
+
+cordic UUT (.clk(clock),.rst(reset),
+`ifdef ITERATE
+ .init(init),
+`endif
+ .x_i(x_i),.y_i(y_i),.theta_i(theta_i),
+ .x_o(x_o),.y_o(y_o),.theta_o(theta_o));
+
+ integer i,j,k;
+ real a_i,a_o,a_e;
+ real rx,ry,rex,rey;
+
+ reg signed [`XY_BITS:0] ex,ey;
+
+ reg signed [16:0] x [90:0];
+ reg signed [16:0] y [90:0];
+ reg signed [16:0] z [90:0];
+
+ task show_vector_results;
+ input integer j;
+ input [`THETA_BITS:0] theta;
+ begin
+ a_i = (j * 3.14) / 180;
+ a_o = theta;
+ a_o = a_o / 32768;
+ if (a_o > a_i) a_e = a_o - a_i; else a_e = a_i - a_o;
+ if (a_e > 0.001)
+ $display("angle %f computed %f error %f",a_i,a_o,a_o - a_i);
+ else
+ $display("angle %f computed %f",a_i,a_o);
+ end
+ endtask
+
+ task show_rotate_results;
+ input integer j;
+ input [`XY_BITS:0] lx;
+ input [`XY_BITS:0] ly;
+ begin
+ rx = lx;// / 65535;
+ ry = ly;// / 65535;
+ rx = rx / 32768; //65535;
+ ry = ry / 32768; //65535;
+ if (lx > x[j]) ex = lx - x[j]; else ex = x[j] - lx;
+ if (ly > y[j]) ey = ly - y[j]; else ey = y[j] - ly;
+ if (ex > 10 || ey > 10)
+ $display("Angle: %d sin = %f cos = %f errors %d %d",j,ry,rx,ey,ex);
+ else
+ $display("Angle: %d sin = %f cos = %f",j,ry,rx);
+ end
+ endtask
+
+ task show_results;
+ input integer j;
+ input [`XY_BITS:0] lx;
+ input [`XY_BITS:0] ly;
+ input [`THETA_BITS:0] ltheta;
+ begin
+`ifdef VECTOR
+ show_vector_results(j,ltheta);
+`endif
+`ifdef ROTATE
+ show_rotate_results(j,lx,ly);
+`endif
+ end
+ endtask
+ initial begin
+ $display("starting simulation");
+`ifdef PIPELINE
+ $display("PIPELINE configuration");
+`endif
+`ifdef ITERATE
+ $display("ITERATE configuration");
+`endif
+`ifdef COMBINATORIAL
+ $display("COMBINATORIAL configuration");
+`endif
+
+ // The following table is computed for U(1,15) format numbers
+ // The angle data z[] is in radians
+ x[0] <= 17'd32768; y[0] <= 17'd0; z[0] <= 17'd0;
+ x[1] <= 17'd32763; y[1] <= 17'd571; z[1] <= 17'd571;
+ x[2] <= 17'd32748; y[2] <= 17'd1143; z[2] <= 17'd1143;
+ x[3] <= 17'd32723; y[3] <= 17'd1714; z[3] <= 17'd1715;
+ x[4] <= 17'd32688; y[4] <= 17'd2285; z[4] <= 17'd2287;
+ x[5] <= 17'd32643; y[5] <= 17'd2855; z[5] <= 17'd2859;
+ x[6] <= 17'd32588; y[6] <= 17'd3425; z[6] <= 17'd3431;
+ x[7] <= 17'd32523; y[7] <= 17'd3993; z[7] <= 17'd4003;
+ x[8] <= 17'd32449; y[8] <= 17'd4560; z[8] <= 17'd4575;
+ x[9] <= 17'd32364; y[9] <= 17'd5126; z[9] <= 17'd5147;
+ x[10] <= 17'd32270; y[10] <= 17'd5690; z[10] <= 17'd5719;
+ x[11] <= 17'd32165; y[11] <= 17'd6252; z[11] <= 17'd6291;
+ x[12] <= 17'd32051; y[12] <= 17'd6812; z[12] <= 17'd6862;
+ x[13] <= 17'd31928; y[13] <= 17'd7371; z[13] <= 17'd7434;
+ x[14] <= 17'd31794; y[14] <= 17'd7927; z[14] <= 17'd8006;
+ x[15] <= 17'd31651; y[15] <= 17'd8480; z[15] <= 17'd8578;
+ x[16] <= 17'd31498; y[16] <= 17'd9032; z[16] <= 17'd9150;
+ x[17] <= 17'd31336; y[17] <= 17'd9580; z[17] <= 17'd9722;
+ x[18] <= 17'd31164; y[18] <= 17'd10125; z[18] <= 17'd10294;
+ x[19] <= 17'd30982; y[19] <= 17'd10668; z[19] <= 17'd10866;
+ x[20] <= 17'd30791; y[20] <= 17'd11207; z[20] <= 17'd11438;
+ x[21] <= 17'd30591; y[21] <= 17'd11743; z[21] <= 17'd12010;
+ x[22] <= 17'd30381; y[22] <= 17'd12275; z[22] <= 17'd12582;
+ x[23] <= 17'd30163; y[23] <= 17'd12803; z[23] <= 17'd13153;
+ x[24] <= 17'd29935; y[24] <= 17'd13327; z[24] <= 17'd13725;
+ x[25] <= 17'd29697; y[25] <= 17'd13848; z[25] <= 17'd14297;
+ x[26] <= 17'd29451; y[26] <= 17'd14364; z[26] <= 17'd14869;
+ x[27] <= 17'd29196; y[27] <= 17'd14876; z[27] <= 17'd15441;
+ x[28] <= 17'd28932; y[28] <= 17'd15383; z[28] <= 17'd16013;
+ x[29] <= 17'd28659; y[29] <= 17'd15886; z[29] <= 17'd16585;
+ x[30] <= 17'd28377; y[30] <= 17'd16383; z[30] <= 17'd17157;
+ x[31] <= 17'd28087; y[31] <= 17'd16876; z[31] <= 17'd17729;
+ x[32] <= 17'd27788; y[32] <= 17'd17364; z[32] <= 17'd18301;
+ x[33] <= 17'd27481; y[33] <= 17'd17846; z[33] <= 17'd18873;
+ x[34] <= 17'd27165; y[34] <= 17'd18323; z[34] <= 17'd19444;
+ x[35] <= 17'd26841; y[35] <= 17'd18794; z[35] <= 17'd20016;
+ x[36] <= 17'd26509; y[36] <= 17'd19260; z[36] <= 17'd20588;
+ x[37] <= 17'd26169; y[37] <= 17'd19720; z[37] <= 17'd21160;
+ x[38] <= 17'd25821; y[38] <= 17'd20173; z[38] <= 17'd21732;
+ x[39] <= 17'd25465; y[39] <= 17'd20621; z[39] <= 17'd22304;
+ x[40] <= 17'd25101; y[40] <= 17'd21062; z[40] <= 17'd22876;
+ x[41] <= 17'd24730; y[41] <= 17'd21497; z[41] <= 17'd23448;
+ x[42] <= 17'd24351; y[42] <= 17'd21926; z[42] <= 17'd24020;
+ x[43] <= 17'd23964; y[43] <= 17'd22347; z[43] <= 17'd24592;
+ x[44] <= 17'd23571; y[44] <= 17'd22762; z[44] <= 17'd25164;
+ x[45] <= 17'd23170; y[45] <= 17'd23170; z[45] <= 17'd25735;
+ x[46] <= 17'd22762; y[46] <= 17'd23571; z[46] <= 17'd26307;
+ x[47] <= 17'd22347; y[47] <= 17'd23964; z[47] <= 17'd26879;
+ x[48] <= 17'd21926; y[48] <= 17'd24351; z[48] <= 17'd27451;
+ x[49] <= 17'd21497; y[49] <= 17'd24730; z[49] <= 17'd28023;
+ x[50] <= 17'd21062; y[50] <= 17'd25101; z[50] <= 17'd28595;
+ x[51] <= 17'd20621; y[51] <= 17'd25465; z[51] <= 17'd29167;
+ x[52] <= 17'd20173; y[52] <= 17'd25821; z[52] <= 17'd29739;
+ x[53] <= 17'd19720; y[53] <= 17'd26169; z[53] <= 17'd30311;
+ x[54] <= 17'd19260; y[54] <= 17'd26509; z[54] <= 17'd30883;
+ x[55] <= 17'd18794; y[55] <= 17'd26841; z[55] <= 17'd31455;
+ x[56] <= 17'd18323; y[56] <= 17'd27165; z[56] <= 17'd32026;
+ x[57] <= 17'd17846; y[57] <= 17'd27481; z[57] <= 17'd32598;
+ x[58] <= 17'd17364; y[58] <= 17'd27788; z[58] <= 17'd33170;
+ x[59] <= 17'd16876; y[59] <= 17'd28087; z[59] <= 17'd33742;
+ x[60] <= 17'd16384; y[60] <= 17'd28377; z[60] <= 17'd34314;
+ x[61] <= 17'd15886; y[61] <= 17'd28659; z[61] <= 17'd34886;
+ x[62] <= 17'd15383; y[62] <= 17'd28932; z[62] <= 17'd35458;
+ x[63] <= 17'd14876; y[63] <= 17'd29196; z[63] <= 17'd36030;
+ x[64] <= 17'd14364; y[64] <= 17'd29451; z[64] <= 17'd36602;
+ x[65] <= 17'd13848; y[65] <= 17'd29697; z[65] <= 17'd37174;
+ x[66] <= 17'd13327; y[66] <= 17'd29935; z[66] <= 17'd37746;
+ x[67] <= 17'd12803; y[67] <= 17'd30163; z[67] <= 17'd38317;
+ x[68] <= 17'd12275; y[68] <= 17'd30381; z[68] <= 17'd38889;
+ x[69] <= 17'd11743; y[69] <= 17'd30591; z[69] <= 17'd39461;
+ x[70] <= 17'd11207; y[70] <= 17'd30791; z[70] <= 17'd40033;
+ x[71] <= 17'd10668; y[71] <= 17'd30982; z[71] <= 17'd40605;
+ x[72] <= 17'd10125; y[72] <= 17'd31164; z[72] <= 17'd41177;
+ x[73] <= 17'd9580; y[73] <= 17'd31336; z[73] <= 17'd41749;
+ x[74] <= 17'd9032; y[74] <= 17'd31498; z[74] <= 17'd42321;
+ x[75] <= 17'd8480; y[75] <= 17'd31651; z[75] <= 17'd42893;
+ x[76] <= 17'd7927; y[76] <= 17'd31794; z[76] <= 17'd43465;
+ x[77] <= 17'd7371; y[77] <= 17'd31928; z[77] <= 17'd44037;
+ x[78] <= 17'd6812; y[78] <= 17'd32051; z[78] <= 17'd44608;
+ x[79] <= 17'd6252; y[79] <= 17'd32165; z[79] <= 17'd45180;
+ x[80] <= 17'd5690; y[80] <= 17'd32270; z[80] <= 17'd45752;
+ x[81] <= 17'd5126; y[81] <= 17'd32364; z[81] <= 17'd46324;
+ x[82] <= 17'd4560; y[82] <= 17'd32449; z[82] <= 17'd46896;
+ x[83] <= 17'd3993; y[83] <= 17'd32523; z[83] <= 17'd47468;
+ x[84] <= 17'd3425; y[84] <= 17'd32588; z[84] <= 17'd48040;
+ x[85] <= 17'd2855; y[85] <= 17'd32643; z[85] <= 17'd48612;
+ x[86] <= 17'd2285; y[86] <= 17'd32688; z[86] <= 17'd49184;
+ x[87] <= 17'd1714; y[87] <= 17'd32723; z[87] <= 17'd49756;
+ x[88] <= 17'd1143; y[88] <= 17'd32748; z[88] <= 17'd50328;
+ x[89] <= 17'd571; y[89] <= 17'd32763; z[89] <= 17'd50899;
+ x[90] <= 17'd0; y[90] <= 17'd32768; z[90] <= 17'd51471;
+
+ clock <= 0;
+ init <= 0;
+ reset <= 1;
+ x_i <= 0;
+ y_i <= 0;
+ theta_i <= 0;
+ #1 clock <= 1;
+ #1 clock <= 0;
+ reset <= 0;
+
+ for (j=0;j<=90;j = j+1) begin // test 91 different angles, 0 to 90 degrees
+`ifdef ROTATE // compute sin and cos
+ x_i <= `CORDIC_1;
+ y_i <= 0;
+ theta_i <= z[j];
+`endif
+`ifdef VECTOR // compute the arctan
+ x_i <= x[j];
+ y_i <= y[j];
+ theta_i <= 0;
+`endif
+
+
+`ifdef ITERATE
+ init <= 1; // load the value into the rotator
+ #1 clock <= 1;
+ #1 clock <= 0;
+ init <= 0;
+ for(i=0;i<`ITERATIONS;i = i+1) begin // iterate on the value
+ #1 clock <= 1;
+ #1 clock <= 0;
+ end
+ show_results(j,x_o,y_o,theta_o);
+`endif
+
+
+`ifdef COMBINATORIAL
+ #1; // give a little time to view the waveform...
+ show_results(j,x_o,y_o,theta_o);
+`endif
+
+`ifdef PIPELINE
+ #1 clock <= 1;
+ #1 clock <= 0;
+ if (j >= (`ITERATIONS-2)) begin // wait until the results start popping out
+ show_results((j-(`ITERATIONS-2)),x_o,y_o,theta_o);
+ end
+ if (j == 90) // now flush the pipe
+ for(i=0;i<(`ITERATIONS-2);i = i+1) begin
+ #1 clock <= 1;
+ #1 clock <= 0;
+ show_results((90-`ITERATIONS+3+i),x_o,y_o,theta_o);
+ end
+`endif
+
+
+ end
+ for(i=0;i<16;i=i+1) // dump a few extra clock just for grins
+ #1 clock <= ~clock;
+end
+
+endmodule
Index: verilog_cordic_core/tags
===================================================================
--- verilog_cordic_core/tags (nonexistent)
+++ verilog_cordic_core/tags (revision 4)
verilog_cordic_core/tags
Property changes :
Added: svn:mergeinfo
## -0,0 +0,0 ##