Imported Upstream version 3.0
[debian/gnuradio] / usrp / fpga / sdr_lib / duc.v
1 // -*- verilog -*-
2 //
3 //  USRP - Universal Software Radio Peripheral
4 //
5 //  Copyright (C) 2003 Matt Ettus
6 //
7 //  This program is free software; you can redistribute it and/or modify
8 //  it under the terms of the GNU General Public License as published by
9 //  the Free Software Foundation; either version 2 of the License, or
10 //  (at your option) any later version.
11 //
12 //  This program is distributed in the hope that it will be useful,
13 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
14 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 //  GNU General Public License for more details.
16 //
17 //  You should have received a copy of the GNU General Public License
18 //  along with this program; if not, write to the Free Software
19 //  Foundation, Inc., 51 Franklin Street, Boston, MA  02110-1301  USA
20 //
21
22 // DUC block
23
24 module duc(input clock,
25                         input reset,
26                         input enable,
27                         input [3:0] rate1,
28                         input [3:0] rate2,
29                         output strobe,
30                         input [31:0] freq,
31                         input [15:0] i_in,
32                         input [15:0] q_in,
33                         output [15:0] i_out,
34                         output [15:0] q_out
35                         );
36    parameter bw = 16;
37    parameter zw = 16;
38    
39         wire [15:0] i_interp_out, q_interp_out;
40         wire [31:0] phase;
41
42         wire strobe1, strobe2;
43         reg [3:0] strobe_ctr1,strobe_ctr2;
44
45         always @(posedge clock)
46                 if(reset | ~enable)
47                         strobe_ctr2 <= #1 4'd0;
48                 else if(strobe2)
49                         strobe_ctr2 <= #1 4'd0;
50                 else    
51                         strobe_ctr2 <= #1 strobe_ctr2 + 4'd1;
52                                 
53         always @(posedge clock)
54                 if(reset | ~enable)
55                         strobe_ctr1 <= #1 4'd0;
56                 else if(strobe1)
57                         strobe_ctr1 <= #1 4'd0;
58                 else if(strobe2)
59                         strobe_ctr1 <= #1 strobe_ctr1 + 4'd1;
60                                 
61
62         assign strobe2 = enable & ( strobe_ctr2 == rate2 );
63         assign strobe1 = strobe2 & ( strobe_ctr1 == rate1 );
64
65         assign strobe = strobe1;
66
67         function [2:0] log_ceil;
68         input [3:0] val;
69         
70                 log_ceil = val[3] ? 3'd4 : val[2] ? 3'd3 : val[1] ? 3'd2 : 3'd1; 
71         endfunction     
72         
73         wire [2:0] shift1 = log_ceil(rate1);
74         wire [2:0] shift2 = log_ceil(rate2);
75         
76         cordic #(.bitwidth(bw),.zwidth(zw),.stages(16))
77                 cordic(.clock(clock), .reset(reset), .enable(enable),
78                         .xi(i_interp_out), .yi(q_interp_out), .zi(phase[31:32-zw]), 
79                         .xo(i_out), .yo(q_out), .zo()  );
80                 
81         cic_interp_2stage #(.bw(bw),.N(4)) 
82                 interp_i(.clock(clock),.reset(reset),.enable(enable),
83                         .strobe1(strobe1),.strobe2(strobe2),.strobe3(1'b1),.shift1(shift1),.shift2(shift2),
84                         .signal_in(i_in),.signal_out(i_interp_out));
85
86         cic_interp_2stage #(.bw(bw),.N(4)) 
87                 interp_q(.clock(clock),.reset(reset),.enable(enable),
88                         .strobe1(strobe1),.strobe2(strobe2),.strobe3(1'b1),.shift1(shift1),.shift2(shift2),
89                         .signal_in(q_in),.signal_out(q_interp_out));
90         
91         phase_acc #(.resolution(32))
92                 nco (.clk(clock),.reset(reset),.enable(enable),
93                         .freq(freq),.phase(phase));
94                 
95 endmodule