// cordic.v
// CORDIC processor
// $Id$
// Larry Doolittle, LBNL
// llc-suite Copyright (c) 2004, The Regents of the University of
// California, through Lawrence Berkeley National Laboratory (subject
// to receipt of any required approvals from the U.S. Dept. of Energy).
// All rights reserved.
// Your use of this software is pursuant to a "BSD-style" open
// source license agreement, the text of which is in license.txt
// (md5sum a1e0e81c78f6eba050b0e96996f49fd5) that should accompany
// this file. If the license agreement is not there, or if you
// have questions about the license, please contact Berkeley Lab's
// Technology Transfer Department at TTD@lbl.gov referring to
// "llc-suite (LBNL Ref CR-1988)"
// Some initial research and design assistance came from Ming Choy.
// This code is has been substantially reengineered from those early
// versions, and may or may not be "derived" from it in the legal sense.
// 16 bit input for x, y
// 17 bit input for phase, including highest order bit (pi)
// (but because of rounding errors, the output is really only accurate
// to about 13 bits)
// still could use some language cleanup
// reference:
// http://www.fpga-guru.com/cordic.htm
`timescale 1ns / 1ns
module addsub(a,b,sum,control);
parameter size=16;
input [size-1:0] a, b;
input control;
output [size-1:0] sum;
assign sum = control ? (a + b) : (a - b);
endmodule
module cstage(xin, yin, zin, ain, xout, yout, zout);
parameter shift=0;
parameter zwidth=16;
parameter width=16;
input [width-1:0] xin, yin;
input [zwidth-1:0] zin, ain;
output [width-1:0] xout, yout;
output [zwidth-1:0] zout;
wire control=zin[zwidth-1];
addsub #( width) ax(xin, {{(shift){yin[width-1]}},yin[width-1:shift]}, xout, control);
addsub #( width) ay(yin, {{(shift){xin[width-1]}},xin[width-1:shift]}, yout, ~control);
addsub #(zwidth) az(zin, ain , zout, control);
endmodule
module cordic(clk, xin, yin, phasein, xout, yout, phaseout);
input clk;
input [15:0] xin, yin;
input [16:0] phasein;
output[15:0] xout, yout;
output[1:0] phaseout;
wire [15:0] xw0, xw1, xw2, xw3, xw4, xw5, xw6, xw7, xw8, xw9, xw10, xw11, xw12, xw13, xw14, xw15;
wire [15:0] yw0, yw1, yw2, yw3, yw4, yw5, yw6, yw7, yw8, yw9, yw10, yw11, yw12, yw13, yw14, yw15;
reg [15:0] x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15;
reg [15:0] y0, y1, y2, y3, y4, y5, y6, y7, y8, y9, y10, y11, y12, y13, y14, y15;
reg [15:0] z0; wire [15:0] zw0;
reg [15:0] z1; wire [15:0] zw1;
reg [14:0] z2; wire [15:0] zw2;
reg [13:0] z3; wire [14:0] zw3;
reg [12:0] z4; wire [13:0] zw4;
reg [11:0] z5; wire [12:0] zw5;
reg [10:0] z6; wire [11:0] zw6;
reg [ 9:0] z7; wire [10:0] zw7;
reg [ 8:0] z8; wire [ 9:0] zw8;
reg [ 7:0] z9; wire [ 8:0] zw9;
reg [ 6:0] z10; wire [ 7:0] zw10;
reg [ 5:0] z11; wire [ 6:0] zw11;
reg [ 4:0] z12; wire [ 5:0] zw12;
reg [ 3:0] z13; wire [ 4:0] zw13;
reg [ 2:0] z14; wire [ 3:0] zw14;
reg [ 1:0] z15; wire [ 2:0] zw15;
// signed 16-bit input angle [-32768 , 32767 ] represents the range [ -pi/2 , pi/2 )
// atan((0.5).^[0:12]')/(2*pi)*8192*4
// floor(atan((0.5).^[0:14]')/(2*pi)*2**(17)+.5)
// keep one high order 0 bit so these are valid signed numbers
wire [15:0] a0 = 16384; // pi/4
wire [15:0] a1 = 9672;
wire [14:0] a2 = 5110;
wire [13:0] a3 = 2594;
wire [12:0] a4 = 1302;
wire [11:0] a5 = 652;
wire [10:0] a6 = 326;
wire [ 9:0] a7 = 163;
wire [ 8:0] a8 = 81;
wire [ 7:0] a9 = 41;
wire [ 6:0] a10 = 20;
wire [ 5:0] a11 = 10;
wire [ 4:0] a12 = 5;
wire [ 3:0] a13 = 3;
wire [ 2:0] a14 = 1;
assign xout = x15;
assign yout = y15;
assign phaseout = z15;
// zero stage: doesn't quite fit the pattern
addsub #(16) ax0 (16'd0, xin, xw0, ~phasein[16]^phasein[15]);
addsub #(16) ay0 (16'd0, yin, yw0, ~phasein[16]^phasein[15]);
assign zw0 = phasein[15:0];
// first stage: can't use cstage because repeat operator of zero is illegal
addsub #(16) ax1 (x0, y0, xw1, z0[15]);
addsub #(16) ay1 (y0, x0, yw1, ~z0[15]);
addsub #(16) az1 (z0, a0, zw1, z0[15]);
cstage #( 1, 16, 16) cs1 (x1, y1, z1, a1, xw2, yw2, zw2);
cstage #( 2, 15, 16) cs2 (x2, y2, z2, a2, xw3, yw3, zw3);
cstage #( 3, 14, 16) cs3 (x3, y3, z3, a3, xw4, yw4, zw4);
cstage #( 4, 13, 16) cs4 (x4, y4, z4, a4, xw5, yw5, zw5);
cstage #( 5, 12, 16) cs5 (x5, y5, z5, a5, xw6, yw6, zw6);
cstage #( 6, 11, 16) cs6 (x6, y6, z6, a6, xw7, yw7, zw7);
cstage #( 7, 10, 16) cs7 (x7, y7, z7, a7, xw8, yw8, zw8);
cstage #( 8, 9, 16) cs8 (x8, y8, z8, a8, xw9, yw9, zw9);
cstage #( 9, 8, 16) cs9 (x9, y9, z9, a9, xw10, yw10, zw10);
cstage #(10, 7, 16) cs10 (x10, y10, z10, a10, xw11, yw11, zw11);
cstage #(11, 6, 16) cs11 (x11, y11, z11, a11, xw12, yw12, zw12);
cstage #(12, 5, 16) cs12 (x12, y12, z12, a12, xw13, yw13, zw13);
cstage #(13, 4, 16) cs13 (x13, y13, z13, a13, xw14, yw14, zw14);
cstage #(14, 3, 16) cs14 (x14, y14, z14, a14, xw15, yw15, zw15);
always @ (posedge clk) begin
x0 <= xw0; y0 <= yw0; z0 <= zw0;
x1 <= xw1; y1 <= yw1; z1 <= zw1;
x2 <= xw2; y2 <= yw2; z2 <= zw2;
x3 <= xw3; y3 <= yw3; z3 <= zw3;
x4 <= xw4; y4 <= yw4; z4 <= zw4;
x5 <= xw5; y5 <= yw5; z5 <= zw5;
x6 <= xw6; y6 <= yw6; z6 <= zw6;
x7 <= xw7; y7 <= yw7; z7 <= zw7;
x8 <= xw8; y8 <= yw8; z8 <= zw8;
x9 <= xw9; y9 <= yw9; z9 <= zw9;
x10 <= xw10; y10 <= yw10; z10 <= zw10;
x11 <= xw11; y11 <= yw11; z11 <= zw11;
x12 <= xw12; y12 <= yw12; z12 <= zw12;
x13 <= xw13; y13 <= yw13; z13 <= zw13;
x14 <= xw14; y14 <= yw14; z14 <= zw14;
x15 <= xw15; y15 <= yw15; z15 <= zw15;
end
endmodule