1// -*- verilog -*-
2//
3//  USRP - Universal Software Radio Peripheral
4//
5//  Copyright (C) 2003, 2007 Matt Ettus
6//
7//  SPDX-License-Identifier: LGPL-3.0-or-later
8//
9
10//
11
12module cordic_z24(clock, reset, enable, xi, yi, zi, xo, yo, zo );
13   parameter bitwidth = 16;
14   parameter stages = 19;
15   localparam zwidth = 24;
16
17   input clock;
18   input reset;
19   input enable;
20   input [bitwidth-1:0] xi, yi;
21   output [bitwidth-1:0] xo, yo;
22   input [zwidth-1:0] zi;
23   output [zwidth-1:0] zo;
24
25   reg [bitwidth+1:0] 	 x0,y0;
26   reg [zwidth-2:0] 	 z0;
27   wire [bitwidth+1:0] 	 x1,x2,x3,x4,x5,x6,x7,x8,x9,x10,x11,x12,x13,x14,x15,x16,x17,x18,x19,x20;
28   wire [bitwidth+1:0] 	 y1,y2,y3,y4,y5,y6,y7,y8,y9,y10,y11,y12,y13,y14,y15,y16,y17,y18,y19,y20;
29   wire [zwidth-2:0] 	 z1,z2,z3,z4,z5,z6,z7,z8,z9,z10,z11,z12,z13,z14,z15,z16,z17,z18,z19,z20;
30
31   wire [bitwidth+1:0] xi_ext = {{2{xi[bitwidth-1]}},xi};
32   wire [bitwidth+1:0] yi_ext = {{2{yi[bitwidth-1]}},yi};
33
34   // Compute consts.  Would be easier if vlog had atan...
35   // see gen_cordic_consts.py
36
37   // constants for 24 bit wide phase
38   localparam 	       c00 = 23'd2097152;
39   localparam 	       c01 = 23'd1238021;
40   localparam 	       c02 = 23'd654136;
41   localparam 	       c03 = 23'd332050;
42   localparam 	       c04 = 23'd166669;
43   localparam 	       c05 = 23'd83416;
44   localparam 	       c06 = 23'd41718;
45   localparam 	       c07 = 23'd20860;
46   localparam 	       c08 = 23'd10430;
47   localparam 	       c09 = 23'd5215;
48   localparam 	       c10 = 23'd2608;
49   localparam 	       c11 = 23'd1304;
50   localparam 	       c12 = 23'd652;
51   localparam 	       c13 = 23'd326;
52   localparam 	       c14 = 23'd163;
53   localparam 	       c15 = 23'd81;
54   localparam 	       c16 = 23'd41;
55   localparam 	       c17 = 23'd20;
56   localparam 	       c18 = 23'd10;
57   localparam 	       c19 = 23'd5;
58   localparam 	       c20 = 23'd3;
59   localparam 	       c21 = 23'd1;
60   localparam 	       c22 = 23'd1;
61   localparam 	       c23 = 23'd0;
62
63   always @(posedge clock)
64     if(reset)
65       begin
66	  x0   <= 0; y0   <= 0;  z0   <= 0;
67       end
68     else// if(enable)
69       begin
70	  z0 <= zi[zwidth-2:0];
71	  case (zi[zwidth-1:zwidth-2])
72	    2'b00, 2'b11 :
73	      begin
74		 x0 <= xi_ext;
75		 y0 <= yi_ext;
76	      end
77	    2'b01, 2'b10 :
78	      begin
79		 x0 <= -xi_ext;
80		 y0 <= -yi_ext;
81	      end
82	  endcase // case(zi[zwidth-1:zwidth-2])
83       end // else: !if(reset)
84
85   // FIXME need to handle variable number of stages
86   // This would be easier if arrays worked better in vlog...
87
88   cordic_stage #(bitwidth+2,zwidth-1,0) cordic_stage0 (clock,reset,enable,x0,y0,z0,c00,x1,y1,z1);
89   cordic_stage #(bitwidth+2,zwidth-1,1) cordic_stage1 (clock,reset,enable,x1,y1,z1,c01,x2,y2,z2);
90   cordic_stage #(bitwidth+2,zwidth-1,2) cordic_stage2 (clock,reset,enable,x2,y2,z2,c02,x3,y3,z3);
91   cordic_stage #(bitwidth+2,zwidth-1,3) cordic_stage3 (clock,reset,enable,x3,y3,z3,c03,x4,y4,z4);
92   cordic_stage #(bitwidth+2,zwidth-1,4) cordic_stage4 (clock,reset,enable,x4,y4,z4,c04,x5,y5,z5);
93   cordic_stage #(bitwidth+2,zwidth-1,5) cordic_stage5 (clock,reset,enable,x5,y5,z5,c05,x6,y6,z6);
94   cordic_stage #(bitwidth+2,zwidth-1,6) cordic_stage6 (clock,reset,enable,x6,y6,z6,c06,x7,y7,z7);
95   cordic_stage #(bitwidth+2,zwidth-1,7) cordic_stage7 (clock,reset,enable,x7,y7,z7,c07,x8,y8,z8);
96   cordic_stage #(bitwidth+2,zwidth-1,8) cordic_stage8 (clock,reset,enable,x8,y8,z8,c08,x9,y9,z9);
97   cordic_stage #(bitwidth+2,zwidth-1,9) cordic_stage9 (clock,reset,enable,x9,y9,z9,c09,x10,y10,z10);
98   cordic_stage #(bitwidth+2,zwidth-1,10) cordic_stage10 (clock,reset,enable,x10,y10,z10,c10,x11,y11,z11);
99   cordic_stage #(bitwidth+2,zwidth-1,11) cordic_stage11 (clock,reset,enable,x11,y11,z11,c11,x12,y12,z12);
100   cordic_stage #(bitwidth+2,zwidth-1,12) cordic_stage12 (clock,reset,enable,x12,y12,z12,c12,x13,y13,z13);
101   cordic_stage #(bitwidth+2,zwidth-1,13) cordic_stage13 (clock,reset,enable,x13,y13,z13,c13,x14,y14,z14);
102   cordic_stage #(bitwidth+2,zwidth-1,14) cordic_stage14 (clock,reset,enable,x14,y14,z14,c14,x15,y15,z15);
103   cordic_stage #(bitwidth+2,zwidth-1,15) cordic_stage15 (clock,reset,enable,x15,y15,z15,c15,x16,y16,z16);
104   cordic_stage #(bitwidth+2,zwidth-1,16) cordic_stage16 (clock,reset,enable,x16,y16,z16,c16,x17,y17,z17);
105   cordic_stage #(bitwidth+2,zwidth-1,17) cordic_stage17 (clock,reset,enable,x17,y17,z17,c17,x18,y18,z18);
106   cordic_stage #(bitwidth+2,zwidth-1,18) cordic_stage18 (clock,reset,enable,x18,y18,z18,c18,x19,y19,z19);
107   cordic_stage #(bitwidth+2,zwidth-1,19) cordic_stage19 (clock,reset,enable,x19,y19,z19,c19,x20,y20,z20);
108
109   assign xo = x20[bitwidth:1];
110   assign yo = y20[bitwidth:1];
111   assign zo = z20;
112
113endmodule // cordic
114
115