1// 2// Copyright 2011-2012 Ettus Research LLC 3// 4// This program is free software: you can redistribute it and/or modify 5// it under the terms of the GNU General Public License as published by 6// the Free Software Foundation, either version 3 of the License, or 7// (at your option) any later version. 8// 9// This program is distributed in the hope that it will be useful, 10// but WITHOUT ANY WARRANTY; without even the implied warranty of 11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12// GNU General Public License for more details. 13// 14// You should have received a copy of the GNU General Public License 15// along with this program. If not, see <http://www.gnu.org/licenses/>. 16// 17 18//! The USRP digital up-conversion chain 19 20module duc_chain 21 #( 22 parameter BASE = 0, 23 parameter DSPNO = 0, 24 parameter WIDTH = 24 25 ) 26 (input clk, input rst, input clr, 27 input set_stb, input [7:0] set_addr, input [31:0] set_data, 28 input set_stb_user, input [7:0] set_addr_user, input [31:0] set_data_user, 29 30 // To TX frontend 31 output [WIDTH-1:0] tx_fe_i, 32 output [WIDTH-1:0] tx_fe_q, 33 34 // From TX control 35 input [31:0] sample, 36 input run, 37 output strobe, 38 output [31:0] debug 39 ); 40 41 wire duc_enb; 42 wire [17:0] scale_factor; 43 wire [31:0] phase_inc; 44 reg [31:0] phase; 45 wire [7:0] interp_rate; 46 wire [3:0] tx_femux_a, tx_femux_b; 47 wire enable_hb1, enable_hb2; 48 wire rate_change; 49 50 setting_reg #(.my_addr(BASE+0)) sr_0 51 (.clk(clk),.rst(rst),.strobe(set_stb),.addr(set_addr), 52 .in(set_data),.out(phase_inc),.changed()); 53 54 setting_reg #(.my_addr(BASE+1), .width(18)) sr_1 55 (.clk(clk),.rst(rst),.strobe(set_stb),.addr(set_addr), 56 .in(set_data),.out(scale_factor),.changed()); 57 58 setting_reg #(.my_addr(BASE+2), .width(10)) sr_2 59 (.clk(clk),.rst(rst),.strobe(set_stb),.addr(set_addr), 60 .in(set_data),.out({enable_hb1, enable_hb2, interp_rate}),.changed(rate_change)); 61 62 // Strobes are all now delayed by 1 cycle for timing reasons 63 wire strobe_cic_pre, strobe_hb1_pre, strobe_hb2_pre; 64 reg strobe_cic = 1; 65 reg strobe_hb1 = 1; 66 reg strobe_hb2 = 1; 67 68 cic_strober #(.WIDTH(8)) 69 cic_strober(.clock(clk),.reset(rst),.enable(duc_enb & ~rate_change),.rate(interp_rate), 70 .strobe_fast(1),.strobe_slow(strobe_cic_pre) ); 71 cic_strober #(.WIDTH(2)) 72 hb2_strober(.clock(clk),.reset(rst),.enable(duc_enb & ~rate_change),.rate(enable_hb2 ? 2 : 1), 73 .strobe_fast(strobe_cic_pre),.strobe_slow(strobe_hb2_pre) ); 74 cic_strober #(.WIDTH(2)) 75 hb1_strober(.clock(clk),.reset(rst),.enable(duc_enb & ~rate_change),.rate(enable_hb1 ? 2 : 1), 76 .strobe_fast(strobe_hb2_pre),.strobe_slow(strobe_hb1_pre) ); 77 78 always @(posedge clk) strobe_hb1 <= strobe_hb1_pre; 79 always @(posedge clk) strobe_hb2 <= strobe_hb2_pre; 80 always @(posedge clk) strobe_cic <= strobe_cic_pre; 81 82 // NCO 83 always @(posedge clk) 84 if(rst) 85 phase <= 0; 86 else if(~duc_enb) 87 phase <= 0; 88 else 89 phase <= phase + phase_inc; 90 91 wire signed [17:0] da, db; 92 wire signed [35:0] prod_i, prod_q; 93 94 wire [15:0] bb_i; 95 wire [15:0] bb_q; 96 wire [17:0] i_interp, q_interp; 97 98 wire [17:0] hb1_i, hb1_q, hb2_i, hb2_q; 99 100 wire [7:0] cpo = enable_hb2 ? ({interp_rate,1'b0}) : interp_rate; 101 // Note that max CIC rate is 128, which would give an overflow on cpo if enable_hb2 is true, 102 // but the default case inside hb_interp handles this 103 104 hb_interp #(.IWIDTH(18),.OWIDTH(18),.ACCWIDTH(WIDTH)) hb_interp_i 105 (.clk(clk),.rst(rst),.bypass(~enable_hb1),.cpo(cpo),.stb_in(strobe_hb1),.data_in({bb_i, 2'b0}),.stb_out(strobe_hb2),.data_out(hb1_i)); 106 hb_interp #(.IWIDTH(18),.OWIDTH(18),.ACCWIDTH(WIDTH)) hb_interp_q 107 (.clk(clk),.rst(rst),.bypass(~enable_hb1),.cpo(cpo),.stb_in(strobe_hb1),.data_in({bb_q, 2'b0}),.stb_out(strobe_hb2),.data_out(hb1_q)); 108 109 small_hb_int #(.WIDTH(18)) small_hb_interp_i 110 (.clk(clk),.rst(rst),.bypass(~enable_hb2),.stb_in(strobe_hb2),.data_in(hb1_i), 111 .output_rate(interp_rate),.stb_out(strobe_cic),.data_out(hb2_i)); 112 small_hb_int #(.WIDTH(18)) small_hb_interp_q 113 (.clk(clk),.rst(rst),.bypass(~enable_hb2),.stb_in(strobe_hb2),.data_in(hb1_q), 114 .output_rate(interp_rate),.stb_out(strobe_cic),.data_out(hb2_q)); 115 116 cic_interp #(.bw(18),.N(4),.log2_of_max_rate(7)) 117 cic_interp_i(.clock(clk),.reset(rst),.enable(duc_enb & ~rate_change),.rate(interp_rate), 118 .strobe_in(strobe_cic),.strobe_out(1), 119 .signal_in(hb2_i),.signal_out(i_interp)); 120 121 cic_interp #(.bw(18),.N(4),.log2_of_max_rate(7)) 122 cic_interp_q(.clock(clk),.reset(rst),.enable(duc_enb & ~rate_change),.rate(interp_rate), 123 .strobe_in(strobe_cic),.strobe_out(1), 124 .signal_in(hb2_q),.signal_out(q_interp)); 125 126 localparam cwidth = WIDTH; // was 18 127 localparam zwidth = 24; // was 16 128 129 wire [cwidth-1:0] da_c, db_c; 130 131 cordic_z24 #(.bitwidth(cwidth)) 132 cordic(.clock(clk), .reset(rst), .enable(duc_enb), 133 .xi({i_interp,{(cwidth-18){1'b0}}}),.yi({q_interp,{(cwidth-18){1'b0}}}), 134 .zi(phase[31:32-zwidth]), 135 .xo(da_c),.yo(db_c),.zo() ); 136 137 MULT18X18S MULT18X18S_inst 138 (.P(prod_i), // 36-bit multiplier output 139 .A(da_c[cwidth-1:cwidth-18]), // 18-bit multiplier input 140 .B(scale_factor), // 18-bit multiplier input 141 .C(clk), // Clock input 142 .CE(1), // Clock enable input 143 .R(rst) // Synchronous reset input 144 ); 145 146 MULT18X18S MULT18X18S_inst_2 147 (.P(prod_q), // 36-bit multiplier output 148 .A(db_c[cwidth-1:cwidth-18]), // 18-bit multiplier input 149 .B(scale_factor), // 18-bit multiplier input 150 .C(clk), // Clock input 151 .CE(1), // Clock enable input 152 .R(rst) // Synchronous reset input 153 ); 154 155 dsp_tx_glue #(.DSPNO(DSPNO), .WIDTH(WIDTH)) dsp_tx_glue( 156 .clock(clk), .reset(rst), .clear(clr), .enable(run), 157 .set_stb(set_stb_user), .set_addr(set_addr_user), .set_data(set_data_user), 158 .frontend_i(tx_fe_i), .frontend_q(tx_fe_q), 159 .duc_out_i(prod_i[33:34-WIDTH]), .duc_out_q(prod_q[33:34-WIDTH]), 160 .duc_in_sample({bb_i, bb_q}), .duc_in_strobe(strobe_hb1), .duc_in_enable(duc_enb), 161 .bb_sample(sample), .bb_strobe(strobe)); 162 163 assign debug = {strobe_cic, strobe_hb1, strobe_hb2,run}; 164 165endmodule // dsp_core 166