diff options
Diffstat (limited to 'fpga/usrp2/sdr_lib')
| -rw-r--r-- | fpga/usrp2/sdr_lib/Makefile.srcs | 9 | ||||
| -rw-r--r-- | fpga/usrp2/sdr_lib/cordic_z24.v | 2 | ||||
| -rw-r--r-- | fpga/usrp2/sdr_lib/ddc_chain.v | 190 | ||||
| -rw-r--r-- | fpga/usrp2/sdr_lib/dsp_core_rx.v | 144 | ||||
| -rw-r--r-- | fpga/usrp2/sdr_lib/dsp_core_rx_old.v | 200 | ||||
| -rw-r--r-- | fpga/usrp2/sdr_lib/dsp_core_rx_tb.v | 10 | ||||
| -rw-r--r-- | fpga/usrp2/sdr_lib/dsp_core_rx_udp.v | 200 | ||||
| -rw-r--r-- | fpga/usrp2/sdr_lib/dsp_rx_glue.v | 98 | ||||
| -rw-r--r-- | fpga/usrp2/sdr_lib/dsp_tx_glue.v | 98 | ||||
| -rw-r--r-- | fpga/usrp2/sdr_lib/dspengine_16to8.v | 38 | ||||
| -rw-r--r-- | fpga/usrp2/sdr_lib/dspengine_8to16.v | 203 | ||||
| -rw-r--r-- | fpga/usrp2/sdr_lib/duc_chain.v (renamed from fpga/usrp2/sdr_lib/dsp_core_tx.v) | 74 | ||||
| -rw-r--r-- | fpga/usrp2/sdr_lib/dummy_rx.v | 2 | 
13 files changed, 658 insertions, 610 deletions
diff --git a/fpga/usrp2/sdr_lib/Makefile.srcs b/fpga/usrp2/sdr_lib/Makefile.srcs index 629b92cc8..e6c4c5343 100644 --- a/fpga/usrp2/sdr_lib/Makefile.srcs +++ b/fpga/usrp2/sdr_lib/Makefile.srcs @@ -1,5 +1,5 @@  # -# Copyright 2010 Ettus Research LLC +# Copyright 2010-2012 Ettus Research LLC  #  ################################################## @@ -23,9 +23,10 @@ clip_reg.v \  cordic.v \  cordic_z24.v \  cordic_stage.v \ -dsp_core_rx.v \ -dsp_core_tx.v \ +ddc_chain.v \ +duc_chain.v \  dspengine_16to8.v \ +dspengine_8to16.v \  hb_dec.v \  hb_interp.v \  pipectrl.v \ @@ -39,4 +40,6 @@ sign_extend.v \  small_hb_dec.v \  small_hb_int.v \  tx_frontend.v \ +dsp_tx_glue.v \ +dsp_rx_glue.v \  )) diff --git a/fpga/usrp2/sdr_lib/cordic_z24.v b/fpga/usrp2/sdr_lib/cordic_z24.v index 97b7beaf7..51b074a33 100644 --- a/fpga/usrp2/sdr_lib/cordic_z24.v +++ b/fpga/usrp2/sdr_lib/cordic_z24.v @@ -119,8 +119,6 @@ module cordic_z24(clock, reset, enable, xi, yi, zi, xo, yo, zo );     assign xo = x20[bitwidth:1];       assign yo = y20[bitwidth:1];     assign zo = z20;		   -   //assign xo = x20[bitwidth+1:2];  // CORDIC gain is ~1.6, plus gain from rotating vectors -   //assign yo = y20[bitwidth+1:2];  endmodule // cordic diff --git a/fpga/usrp2/sdr_lib/ddc_chain.v b/fpga/usrp2/sdr_lib/ddc_chain.v new file mode 100644 index 000000000..c32c9f491 --- /dev/null +++ b/fpga/usrp2/sdr_lib/ddc_chain.v @@ -0,0 +1,190 @@ +// +// Copyright 2011-2012 Ettus Research LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program.  If not, see <http://www.gnu.org/licenses/>. +// + +//! The USRP digital down-conversion chain + +module ddc_chain +  #( +    parameter BASE = 0, +    parameter DSPNO = 0, +    parameter WIDTH = 24 +  ) +  (input clk, input rst, input clr, +   input set_stb, input [7:0] set_addr, input [31:0] set_data, +   input set_stb_user, input [7:0] set_addr_user, input [31:0] set_data_user, + +   // From RX frontend +   input [WIDTH-1:0] rx_fe_i, +   input [WIDTH-1:0] rx_fe_q, + +   // To RX control +   output [31:0] sample, +   input run, +   output strobe, +   output [31:0] debug +   ); + +   localparam  cwidth = 25; +   localparam  zwidth = 24; + +   wire ddc_enb; +   wire [31:0] phase_inc; +   reg [31:0]  phase; + +   wire [17:0] scale_factor; +   wire [cwidth-1:0] i_cordic, q_cordic; +   wire [WIDTH-1:0] i_cordic_clip, q_cordic_clip; +   wire [WIDTH-1:0] i_cic, q_cic; +   wire [WIDTH-1:0] i_hb1, q_hb1; +   wire [WIDTH-1:0] i_hb2, q_hb2; +    +   wire        strobe_cic, strobe_hb1, strobe_hb2; +   wire        enable_hb1, enable_hb2; +   wire [7:0]  cic_decim_rate; + +   reg [WIDTH-1:0]  rx_fe_i_mux, rx_fe_q_mux; +   wire        realmode; +   wire        swap_iq; +    +   setting_reg #(.my_addr(BASE+0)) sr_0 +     (.clk(clk),.rst(rst),.strobe(set_stb),.addr(set_addr), +      .in(set_data),.out(phase_inc),.changed()); + +   setting_reg #(.my_addr(BASE+1), .width(18)) sr_1 +     (.clk(clk),.rst(rst),.strobe(set_stb),.addr(set_addr), +      .in(set_data),.out(scale_factor),.changed()); + +   setting_reg #(.my_addr(BASE+2), .width(10)) sr_2 +     (.clk(clk),.rst(rst),.strobe(set_stb),.addr(set_addr), +      .in(set_data),.out({enable_hb1, enable_hb2, cic_decim_rate}),.changed()); + +   setting_reg #(.my_addr(BASE+3), .width(2)) sr_3 +     (.clk(clk),.rst(rst),.strobe(set_stb),.addr(set_addr), +      .in(set_data),.out({realmode,swap_iq}),.changed()); + +   // MUX so we can do realmode signals on either input +    +   always @(posedge clk) +     if(swap_iq) +       begin +	  rx_fe_i_mux <= rx_fe_q; +	  rx_fe_q_mux <= realmode ? 0 : rx_fe_i; +       end +     else +       begin +	  rx_fe_i_mux <= rx_fe_i; +	  rx_fe_q_mux <= realmode ? 0 : rx_fe_q; +       end + +   // NCO +   always @(posedge clk) +     if(rst) +       phase <= 0; +     else if(~ddc_enb) +       phase <= 0; +     else +       phase <= phase + phase_inc; + +   //sign extension of cordic input +   wire [WIDTH-1:0] to_ddc_chain_i, to_ddc_chain_q; +   wire [cwidth-1:0] to_cordic_i, to_cordic_q; +   sign_extend #(.bits_in(WIDTH), .bits_out(cwidth)) sign_extend_cordic_i (.in(to_ddc_chain_i), .out(to_cordic_i)); +   sign_extend #(.bits_in(WIDTH), .bits_out(cwidth)) sign_extend_cordic_q (.in(to_ddc_chain_q), .out(to_cordic_q)); + +   // CORDIC  24-bit I/O +   cordic_z24 #(.bitwidth(cwidth)) +     cordic(.clock(clk), .reset(rst), .enable(ddc_enb), +	    .xi(to_cordic_i),. yi(to_cordic_q), .zi(phase[31:32-zwidth]), +	    .xo(i_cordic),.yo(q_cordic),.zo() ); + +   clip_reg #(.bits_in(cwidth), .bits_out(WIDTH)) clip_i +     (.clk(clk), .in(i_cordic), .strobe_in(1'b1), .out(i_cordic_clip)); +   clip_reg #(.bits_in(cwidth), .bits_out(WIDTH)) clip_q +     (.clk(clk), .in(q_cordic), .strobe_in(1'b1), .out(q_cordic_clip)); + +   // CIC decimator  24 bit I/O +   cic_strober cic_strober(.clock(clk),.reset(rst),.enable(ddc_enb),.rate(cic_decim_rate), +			   .strobe_fast(1),.strobe_slow(strobe_cic) ); + +   cic_decim #(.bw(WIDTH)) +     decim_i (.clock(clk),.reset(rst),.enable(ddc_enb), +	      .rate(cic_decim_rate),.strobe_in(1'b1),.strobe_out(strobe_cic), +	      .signal_in(i_cordic_clip),.signal_out(i_cic)); +    +   cic_decim #(.bw(WIDTH)) +     decim_q (.clock(clk),.reset(rst),.enable(ddc_enb), +	      .rate(cic_decim_rate),.strobe_in(1'b1),.strobe_out(strobe_cic), +	      .signal_in(q_cordic_clip),.signal_out(q_cic)); + +   // First (small) halfband  24 bit I/O +   small_hb_dec #(.WIDTH(WIDTH)) small_hb_i +     (.clk(clk),.rst(rst),.bypass(~enable_hb1),.run(ddc_enb), +      .stb_in(strobe_cic),.data_in(i_cic),.stb_out(strobe_hb1),.data_out(i_hb1)); +    +   small_hb_dec #(.WIDTH(WIDTH)) small_hb_q +     (.clk(clk),.rst(rst),.bypass(~enable_hb1),.run(ddc_enb), +      .stb_in(strobe_cic),.data_in(q_cic),.stb_out(),.data_out(q_hb1)); + +   // Second (large) halfband  24 bit I/O +   wire [8:0]  cpi_hb = enable_hb1 ? {cic_decim_rate,1'b0} : {1'b0,cic_decim_rate}; +   hb_dec #(.WIDTH(WIDTH)) hb_i +     (.clk(clk),.rst(rst),.bypass(~enable_hb2),.run(ddc_enb),.cpi(cpi_hb), +      .stb_in(strobe_hb1),.data_in(i_hb1),.stb_out(strobe_hb2),.data_out(i_hb2)); + +   hb_dec #(.WIDTH(WIDTH)) hb_q +     (.clk(clk),.rst(rst),.bypass(~enable_hb2),.run(ddc_enb),.cpi(cpi_hb), +      .stb_in(strobe_hb1),.data_in(q_hb1),.stb_out(),.data_out(q_hb2)); + +   //scalar operation (gain of 6 bits) +   wire [35:0] prod_i, prod_q; + +   MULT18X18S mult_i +     (.P(prod_i), .A(i_hb2[WIDTH-1:WIDTH-18]), .B(scale_factor), .C(clk), .CE(strobe_hb2), .R(rst) ); +   MULT18X18S mult_q +     (.P(prod_q), .A(q_hb2[WIDTH-1:WIDTH-18]), .B(scale_factor), .C(clk), .CE(strobe_hb2), .R(rst) ); + +   //pipeline for the multiplier (gain of 10 bits) +   reg [WIDTH-1:0] prod_reg_i, prod_reg_q; +   reg strobe_mult; + +   always @(posedge clk) begin +       strobe_mult <= strobe_hb2; +       prod_reg_i <= prod_i[33:34-WIDTH]; +       prod_reg_q <= prod_q[33:34-WIDTH]; +   end + +   // Round final answer to 16 bits +   wire [31:0] ddc_chain_out; +   wire ddc_chain_stb; + +   round_sd #(.WIDTH_IN(WIDTH),.WIDTH_OUT(16)) round_i +     (.clk(clk),.reset(rst), .in(prod_reg_i),.strobe_in(strobe_mult), .out(ddc_chain_out[31:16]), .strobe_out(ddc_chain_stb)); + +   round_sd #(.WIDTH_IN(WIDTH),.WIDTH_OUT(16)) round_q +     (.clk(clk),.reset(rst), .in(prod_reg_q),.strobe_in(strobe_mult), .out(ddc_chain_out[15:0]), .strobe_out()); + +   dsp_rx_glue #(.DSPNO(DSPNO), .WIDTH(WIDTH)) custom( +    .clock(clk), .reset(rst), .clear(clr), .enable(run), +    .set_stb(set_stb_user), .set_addr(set_addr_user), .set_data(set_data_user), +    .frontend_i(rx_fe_i_mux), .frontend_q(rx_fe_q_mux), +    .ddc_in_i(to_ddc_chain_i), .ddc_in_q(to_ddc_chain_q), +    .ddc_out_sample(ddc_chain_out), .ddc_out_strobe(ddc_chain_stb), .ddc_out_enable(ddc_enb), +    .bb_sample(sample), .bb_strobe(strobe)); + +   assign      debug = {enable_hb1, enable_hb2, run, strobe, strobe_cic, strobe_hb1, strobe_hb2}; +    +endmodule // ddc_chain diff --git a/fpga/usrp2/sdr_lib/dsp_core_rx.v b/fpga/usrp2/sdr_lib/dsp_core_rx.v deleted file mode 100644 index d1c7e238a..000000000 --- a/fpga/usrp2/sdr_lib/dsp_core_rx.v +++ /dev/null @@ -1,144 +0,0 @@ -// -// Copyright 2011 Ettus Research LLC -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program.  If not, see <http://www.gnu.org/licenses/>. -// - - -module dsp_core_rx -  #(parameter BASE = 160) -  (input clk, input rst, -   input set_stb, input [7:0] set_addr, input [31:0] set_data, - -   input [23:0] adc_i, input adc_ovf_i, -   input [23:0] adc_q, input adc_ovf_q, -    -   output [31:0] sample, -   input run, -   output strobe, -   output [31:0] debug -   ); - -   wire [31:0] phase_inc; -   reg [31:0]  phase; - -   wire [24:0] i_cordic, q_cordic; -   wire [23:0] i_cordic_clip, q_cordic_clip; -   wire [23:0] i_cic, q_cic; -   wire [23:0] i_hb1, q_hb1; -   wire [23:0] i_hb2, q_hb2; -    -   wire        strobe_cic, strobe_hb1, strobe_hb2; -   wire        enable_hb1, enable_hb2; -   wire [7:0]  cic_decim_rate; - -   reg [23:0]  adc_i_mux, adc_q_mux; -   wire        realmode; -   wire        swap_iq; -    -   setting_reg #(.my_addr(BASE+0)) sr_0 -     (.clk(clk),.rst(rst),.strobe(set_stb),.addr(set_addr), -      .in(set_data),.out(phase_inc),.changed()); -    -   /* -   setting_reg #(.my_addr(BASE+1)) sr_1 -     (.clk(clk),.rst(rst),.strobe(set_stb),.addr(set_addr), -      .in(set_data),.out({scale_i,scale_q}),.changed()); -   */ -    -   setting_reg #(.my_addr(BASE+2), .width(10)) sr_2 -     (.clk(clk),.rst(rst),.strobe(set_stb),.addr(set_addr), -      .in(set_data),.out({enable_hb1, enable_hb2, cic_decim_rate}),.changed()); - -   setting_reg #(.my_addr(BASE+3), .width(2)) sr_3 -     (.clk(clk),.rst(rst),.strobe(set_stb),.addr(set_addr), -      .in(set_data),.out({realmode,swap_iq}),.changed()); - -   // MUX so we can do realmode signals on either input -    -   always @(posedge clk) -     if(swap_iq) -       begin -	  adc_i_mux <= adc_q; -	  adc_q_mux <= realmode ? 24'd0 : adc_i; -       end -     else -       begin -	  adc_i_mux <= adc_i; -	  adc_q_mux <= realmode ? 24'd0 : adc_q; -       end - -   // NCO -   always @(posedge clk) -     if(rst) -       phase <= 0; -     else if(~run) -       phase <= 0; -     else -       phase <= phase + phase_inc; - -   // CORDIC  24-bit I/O -   cordic_z24 #(.bitwidth(25)) -     cordic(.clock(clk), .reset(rst), .enable(run), -	    .xi({adc_i_mux[23],adc_i_mux}),. yi({adc_q_mux[23],adc_q_mux}), .zi(phase[31:8]), -	    .xo(i_cordic),.yo(q_cordic),.zo() ); - -   clip_reg #(.bits_in(25), .bits_out(24)) clip_i -     (.clk(clk), .in(i_cordic), .strobe_in(1'b1), .out(i_cordic_clip)); -   clip_reg #(.bits_in(25), .bits_out(24)) clip_q -     (.clk(clk), .in(q_cordic), .strobe_in(1'b1), .out(q_cordic_clip)); - -   // CIC decimator  24 bit I/O -   cic_strober cic_strober(.clock(clk),.reset(rst),.enable(run),.rate(cic_decim_rate), -			   .strobe_fast(1),.strobe_slow(strobe_cic) ); - -   cic_decim #(.bw(24)) -     decim_i (.clock(clk),.reset(rst),.enable(run), -	      .rate(cic_decim_rate),.strobe_in(1'b1),.strobe_out(strobe_cic), -	      .signal_in(i_cordic_clip),.signal_out(i_cic)); -    -   cic_decim #(.bw(24)) -     decim_q (.clock(clk),.reset(rst),.enable(run), -	      .rate(cic_decim_rate),.strobe_in(1'b1),.strobe_out(strobe_cic), -	      .signal_in(q_cordic_clip),.signal_out(q_cic)); - -   // First (small) halfband  24 bit I/O -   small_hb_dec #(.WIDTH(24)) small_hb_i -     (.clk(clk),.rst(rst),.bypass(~enable_hb1),.run(run), -      .stb_in(strobe_cic),.data_in(i_cic),.stb_out(strobe_hb1),.data_out(i_hb1)); -    -   small_hb_dec #(.WIDTH(24)) small_hb_q -     (.clk(clk),.rst(rst),.bypass(~enable_hb1),.run(run), -      .stb_in(strobe_cic),.data_in(q_cic),.stb_out(),.data_out(q_hb1)); - -   // Second (large) halfband  24 bit I/O -   wire [8:0]  cpi_hb = enable_hb1 ? {cic_decim_rate,1'b0} : {1'b0,cic_decim_rate}; -   hb_dec #(.WIDTH(24)) hb_i -     (.clk(clk),.rst(rst),.bypass(~enable_hb2),.run(run),.cpi(cpi_hb), -      .stb_in(strobe_hb1),.data_in(i_hb1),.stb_out(strobe_hb2),.data_out(i_hb2)); - -   hb_dec #(.WIDTH(24)) hb_q -     (.clk(clk),.rst(rst),.bypass(~enable_hb2),.run(run),.cpi(cpi_hb), -      .stb_in(strobe_hb1),.data_in(q_hb1),.stb_out(),.data_out(q_hb2)); - -   // Round final answer to 16 bits -   round_sd #(.WIDTH_IN(24),.WIDTH_OUT(16)) round_i -     (.clk(clk),.reset(rst), .in(i_hb2),.strobe_in(strobe_hb2), .out(sample[31:16]), .strobe_out(strobe)); - -   round_sd #(.WIDTH_IN(24),.WIDTH_OUT(16)) round_q -     (.clk(clk),.reset(rst), .in(q_hb2),.strobe_in(strobe_hb2), .out(sample[15:0]), .strobe_out()); -    -   assign      debug = {enable_hb1, enable_hb2, run, strobe, strobe_cic, strobe_hb1, strobe_hb2}; -    -endmodule // dsp_core_rx diff --git a/fpga/usrp2/sdr_lib/dsp_core_rx_old.v b/fpga/usrp2/sdr_lib/dsp_core_rx_old.v deleted file mode 100644 index 90d5d839f..000000000 --- a/fpga/usrp2/sdr_lib/dsp_core_rx_old.v +++ /dev/null @@ -1,200 +0,0 @@ -// -// Copyright 2011 Ettus Research LLC -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program.  If not, see <http://www.gnu.org/licenses/>. -// - - -`define DSP_CORE_RX_BASE 160 -module dsp_core_rx_old -  (input clk, input rst, -   input set_stb, input [7:0] set_addr, input [31:0] set_data, - -   input [13:0] adc_a, input adc_ovf_a, -   input [13:0] adc_b, input adc_ovf_b, -    -   input [15:0] io_rx, - -   output [31:0] sample, -   input run, -   output strobe, -   output [31:0] debug -   ); - -   wire [15:0] scale_i, scale_q; -   wire [13:0] adc_a_ofs, adc_b_ofs; -   reg [13:0] adc_i, adc_q; -   wire [31:0] phase_inc; -   reg [31:0]  phase; - -   wire [35:0] prod_i, prod_q; -   wire [23:0] i_cordic, q_cordic; -   wire [23:0] i_cic, q_cic; -   wire [17:0] i_cic_scaled, q_cic_scaled; -   wire [17:0] i_hb1, q_hb1; -   wire [17:0] i_hb2, q_hb2; -   wire [15:0] i_out, q_out; - -   wire        strobe_cic, strobe_hb1, strobe_hb2; -   wire        enable_hb1, enable_hb2; -   wire [7:0]  cic_decim_rate; - -   wire [31:10] UNUSED_1; -   wire [31:4] 	UNUSED_2; -   wire [31:2] 	UNUSED_3; -    -   setting_reg #(.my_addr(`DSP_CORE_RX_BASE+0)) sr_0 -     (.clk(clk),.rst(rst),.strobe(set_stb),.addr(set_addr), -      .in(set_data),.out(phase_inc),.changed()); -    -   setting_reg #(.my_addr(`DSP_CORE_RX_BASE+1)) sr_1 -     (.clk(clk),.rst(rst),.strobe(set_stb),.addr(set_addr), -      .in(set_data),.out({scale_i,scale_q}),.changed()); -    -   setting_reg #(.my_addr(`DSP_CORE_RX_BASE+2)) sr_2 -     (.clk(clk),.rst(rst),.strobe(set_stb),.addr(set_addr), -      .in(set_data),.out({UNUSED_1, enable_hb1, enable_hb2, cic_decim_rate}),.changed()); - -   rx_dcoffset #(.WIDTH(14),.ADDR(`DSP_CORE_RX_BASE+6)) rx_dcoffset_a -     (.clk(clk),.rst(rst),.set_stb(set_stb),.set_addr(set_addr),.set_data(set_data), -      .adc_in(adc_a),.adc_out(adc_a_ofs)); -    -   rx_dcoffset #(.WIDTH(14),.ADDR(`DSP_CORE_RX_BASE+7)) rx_dcoffset_b -     (.clk(clk),.rst(rst),.set_stb(set_stb),.set_addr(set_addr),.set_data(set_data), -      .adc_in(adc_b),.adc_out(adc_b_ofs)); - -   wire [3:0]  muxctrl; -   setting_reg #(.my_addr(`DSP_CORE_RX_BASE+8)) sr_8 -     (.clk(clk),.rst(rst),.strobe(set_stb),.addr(set_addr), -      .in(set_data),.out({UNUSED_2,muxctrl}),.changed()); - -   wire [1:0] gpio_ena; -   setting_reg #(.my_addr(`DSP_CORE_RX_BASE+9)) sr_9 -     (.clk(clk),.rst(rst),.strobe(set_stb),.addr(set_addr), -      .in(set_data),.out({UNUSED_3,gpio_ena}),.changed()); - -   // The TVRX connects to what is called adc_b, thus A and B are -   // swapped throughout the design. -   // -   // In the interest of expediency and keeping the s/w sane, we just remap them here. -   // The I & Q fields are mapped the same: -   // 0 -> "the real A" (as determined by the TVRX) -   // 1 -> "the real B" -   // 2 -> const zero -    -   always @(posedge clk) -     case(muxctrl[1:0])		// The I mapping -       0: adc_i <= adc_b_ofs;	// "the real A" -       1: adc_i <= adc_a_ofs; -       2: adc_i <= 0; -       default: adc_i <= 0; -     endcase // case(muxctrl[1:0]) -           -   always @(posedge clk) -     case(muxctrl[3:2])		// The Q mapping -       0: adc_q <= adc_b_ofs;	// "the real A" -       1: adc_q <= adc_a_ofs; -       2: adc_q <= 0; -       default: adc_q <= 0; -     endcase // case(muxctrl[3:2]) -        -   always @(posedge clk) -     if(rst) -       phase <= 0; -     else if(~run) -       phase <= 0; -     else -       phase <= phase + phase_inc; - -   MULT18X18S mult_i -     (.P(prod_i),    // 36-bit multiplier output -      .A({{4{adc_i[13]}},adc_i} ),    // 18-bit multiplier input -      .B({{2{scale_i[15]}},scale_i}),    // 18-bit multiplier input -      .C(clk),    // Clock input -      .CE(1),  // Clock enable input -      .R(rst)     // Synchronous reset input -      ); - -   MULT18X18S mult_q -     (.P(prod_q),    // 36-bit multiplier output -      .A({{4{adc_q[13]}},adc_q} ),    // 18-bit multiplier input -      .B({{2{scale_q[15]}},scale_q}),    // 18-bit multiplier input -      .C(clk),    // Clock input -      .CE(1),  // Clock enable input -      .R(rst)     // Synchronous reset input -      );  - -    -   cordic_z24 #(.bitwidth(24)) -     cordic(.clock(clk), .reset(rst), .enable(run), -	    .xi(prod_i[23:0]),. yi(prod_q[23:0]), .zi(phase[31:8]), -	    .xo(i_cordic),.yo(q_cordic),.zo() ); - -   cic_strober cic_strober(.clock(clk),.reset(rst),.enable(run),.rate(cic_decim_rate), -			   .strobe_fast(1),.strobe_slow(strobe_cic) ); - -   cic_decim #(.bw(24)) -     decim_i (.clock(clk),.reset(rst),.enable(run), -	      .rate(cic_decim_rate),.strobe_in(1'b1),.strobe_out(strobe_cic), -	      .signal_in(i_cordic),.signal_out(i_cic)); -    -   cic_decim #(.bw(24)) -     decim_q (.clock(clk),.reset(rst),.enable(run), -	      .rate(cic_decim_rate),.strobe_in(1'b1),.strobe_out(strobe_cic), -	      .signal_in(q_cordic),.signal_out(q_cic)); - -   round_reg #(.bits_in(24),.bits_out(18)) round_icic (.clk(clk),.in(i_cic),.out(i_cic_scaled)); -   round_reg #(.bits_in(24),.bits_out(18)) round_qcic (.clk(clk),.in(q_cic),.out(q_cic_scaled)); -   reg 	       strobe_cic_d1; -   always @(posedge clk) strobe_cic_d1 <= strobe_cic; -    -   small_hb_dec #(.WIDTH(18)) small_hb_i -     (.clk(clk),.rst(rst),.bypass(~enable_hb1),.run(run), -      .stb_in(strobe_cic_d1),.data_in(i_cic_scaled),.stb_out(strobe_hb1),.data_out(i_hb1)); -    -   small_hb_dec #(.WIDTH(18)) small_hb_q -     (.clk(clk),.rst(rst),.bypass(~enable_hb1),.run(run), -      .stb_in(strobe_cic_d1),.data_in(q_cic_scaled),.stb_out(),.data_out(q_hb1)); - -   wire [8:0]  cpi_hb = enable_hb1 ? {cic_decim_rate,1'b0} : {1'b0,cic_decim_rate}; -   hb_dec #(.IWIDTH(18), .OWIDTH(18), .CWIDTH(18), .ACCWIDTH(24)) hb_i -     (.clk(clk),.rst(rst),.bypass(~enable_hb2),.run(run),.cpi(cpi_hb), -      .stb_in(strobe_hb1),.data_in(i_hb1),.stb_out(strobe_hb2),.data_out(i_hb2)); - -   hb_dec #(.IWIDTH(18), .OWIDTH(18), .CWIDTH(18), .ACCWIDTH(24)) hb_q -     (.clk(clk),.rst(rst),.bypass(~enable_hb2),.run(run),.cpi(cpi_hb), -      .stb_in(strobe_hb1),.data_in(q_hb1),.stb_out(),.data_out(q_hb2)); - -   round #(.bits_in(18),.bits_out(16)) round_iout (.in(i_hb2),.out(i_out)); -   round #(.bits_in(18),.bits_out(16)) round_qout (.in(q_hb2),.out(q_out)); - -   // Streaming GPIO -   // -   // io_rx[15] => I channel LSB if gpio_ena[0] high -   // io_rx[14] => Q channel LSB if gpio_ena[1] high - -   reg [31:0] sample_reg; -   always @(posedge clk) -     begin -	sample_reg[31:17] <= i_out[15:1]; -	sample_reg[15:1]  <= q_out[15:1]; -	sample_reg[16]    <= gpio_ena[0] ? io_rx[15] : i_out[0];  -	sample_reg[0]     <= gpio_ena[1] ? io_rx[14] : q_out[0]; -     end -    -   assign      sample = sample_reg; -   assign      strobe = strobe_hb2; -   assign      debug = {enable_hb1, enable_hb2, run, strobe, strobe_cic, strobe_cic_d1, strobe_hb1, strobe_hb2}; -    -endmodule // dsp_core_rx diff --git a/fpga/usrp2/sdr_lib/dsp_core_rx_tb.v b/fpga/usrp2/sdr_lib/dsp_core_rx_tb.v index 271db8cef..a221bed44 100644 --- a/fpga/usrp2/sdr_lib/dsp_core_rx_tb.v +++ b/fpga/usrp2/sdr_lib/dsp_core_rx_tb.v @@ -1,6 +1,6 @@  `timescale 1ns/1ns -module dsp_core_rx_tb(); +module ddc_chain_tb();     reg clk, rst; @@ -9,8 +9,8 @@ module dsp_core_rx_tb();     initial clk = 0;     always #5 clk = ~clk; -   initial $dumpfile("dsp_core_rx_tb.vcd"); -   initial $dumpvars(0,dsp_core_rx_tb); +   initial $dumpfile("ddc_chain_tb.vcd"); +   initial $dumpvars(0,ddc_chain_tb);     reg signed [23:0] adc_in;     wire signed [15:0] adc_out_i, adc_out_q; @@ -27,7 +27,7 @@ module dsp_core_rx_tb();     reg [7:0] set_addr;     reg [31:0] set_data; -   dsp_core_rx #(.BASE(0)) dsp_core_rx +   ddc_chain #(.BASE(0)) ddc_chain       (.clk(clk),.rst(rst),        .set_stb(set_stb),.set_addr(set_addr),.set_data(set_data),        .adc_i(adc_in), .adc_ovf_i(0), @@ -70,4 +70,4 @@ module dsp_core_rx_tb();         adc_in <= adc_in + 4;     //adc_in <= (($random % 473) + 23)/4;  */    -endmodule // dsp_core_rx_tb +endmodule // ddc_chain_tb diff --git a/fpga/usrp2/sdr_lib/dsp_core_rx_udp.v b/fpga/usrp2/sdr_lib/dsp_core_rx_udp.v deleted file mode 100644 index 08dab37e6..000000000 --- a/fpga/usrp2/sdr_lib/dsp_core_rx_udp.v +++ /dev/null @@ -1,200 +0,0 @@ -// -// Copyright 2011 Ettus Research LLC -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program.  If not, see <http://www.gnu.org/licenses/>. -// - - -module dsp_core_rx -  #(parameter BASE = 160) -  (input clk, input rst, -   input set_stb, input [7:0] set_addr, input [31:0] set_data, - -   input [13:0] adc_a, input adc_ovf_a, -   input [13:0] adc_b, input adc_ovf_b, -    -   input [15:0] io_rx, - -   output [31:0] sample, -   input run, -   output strobe, -   output [31:0] debug -   ); - -   wire [15:0] scale_i, scale_q; -   wire [13:0] adc_a_ofs, adc_b_ofs; -   reg [13:0] adc_i, adc_q; -   wire [31:0] phase_inc; -   reg [31:0]  phase; - -   wire [35:0] prod_i, prod_q; -   wire [23:0] i_cordic, q_cordic; -   wire [23:0] i_cic, q_cic; -   wire [17:0] i_cic_scaled, q_cic_scaled; -   wire [17:0] i_hb1, q_hb1; -   wire [17:0] i_hb2, q_hb2; -   wire [15:0] i_out, q_out; - -   wire        strobe_cic, strobe_hb1, strobe_hb2; -   wire        enable_hb1, enable_hb2; -   wire [7:0]  cic_decim_rate; - -   wire [31:10] UNUSED_1; -   wire [31:4] 	UNUSED_2; -   wire [31:2] 	UNUSED_3; -    -   setting_reg #(.my_addr(BASE+0)) sr_0 -     (.clk(clk),.rst(rst),.strobe(set_stb),.addr(set_addr), -      .in(set_data),.out(phase_inc),.changed()); -    -   setting_reg #(.my_addr(BASE+1)) sr_1 -     (.clk(clk),.rst(rst),.strobe(set_stb),.addr(set_addr), -      .in(set_data),.out({scale_i,scale_q}),.changed()); -    -   setting_reg #(.my_addr(BASE+2)) sr_2 -     (.clk(clk),.rst(rst),.strobe(set_stb),.addr(set_addr), -      .in(set_data),.out({UNUSED_1, enable_hb1, enable_hb2, cic_decim_rate}),.changed()); - -   rx_dcoffset #(.WIDTH(14),.ADDR(BASE+3)) rx_dcoffset_a -     (.clk(clk),.rst(rst),.set_stb(set_stb),.set_addr(set_addr),.set_data(set_data), -      .adc_in(adc_a),.adc_out(adc_a_ofs)); -    -   rx_dcoffset #(.WIDTH(14),.ADDR(BASE+4)) rx_dcoffset_b -     (.clk(clk),.rst(rst),.set_stb(set_stb),.set_addr(set_addr),.set_data(set_data), -      .adc_in(adc_b),.adc_out(adc_b_ofs)); - -   wire [3:0]  muxctrl; -   setting_reg #(.my_addr(BASE+5)) sr_8 -     (.clk(clk),.rst(rst),.strobe(set_stb),.addr(set_addr), -      .in(set_data),.out({UNUSED_2,muxctrl}),.changed()); - -   wire [1:0] gpio_ena; -   setting_reg #(.my_addr(BASE+6)) sr_9 -     (.clk(clk),.rst(rst),.strobe(set_stb),.addr(set_addr), -      .in(set_data),.out({UNUSED_3,gpio_ena}),.changed()); - -   // The TVRX connects to what is called adc_b, thus A and B are -   // swapped throughout the design. -   // -   // In the interest of expediency and keeping the s/w sane, we just remap them here. -   // The I & Q fields are mapped the same: -   // 0 -> "the real A" (as determined by the TVRX) -   // 1 -> "the real B" -   // 2 -> const zero -    -   always @(posedge clk) -     case(muxctrl[1:0])		// The I mapping -       0: adc_i <= adc_b_ofs;	// "the real A" -       1: adc_i <= adc_a_ofs; -       2: adc_i <= 0; -       default: adc_i <= 0; -     endcase // case(muxctrl[1:0]) -           -   always @(posedge clk) -     case(muxctrl[3:2])		// The Q mapping -       0: adc_q <= adc_b_ofs;	// "the real A" -       1: adc_q <= adc_a_ofs; -       2: adc_q <= 0; -       default: adc_q <= 0; -     endcase // case(muxctrl[3:2]) -        -   always @(posedge clk) -     if(rst) -       phase <= 0; -     else if(~run) -       phase <= 0; -     else -       phase <= phase + phase_inc; - -   MULT18X18S mult_i -     (.P(prod_i),    // 36-bit multiplier output -      .A({{4{adc_i[13]}},adc_i} ),    // 18-bit multiplier input -      .B({{2{scale_i[15]}},scale_i}),    // 18-bit multiplier input -      .C(clk),    // Clock input -      .CE(1),  // Clock enable input -      .R(rst)     // Synchronous reset input -      ); - -   MULT18X18S mult_q -     (.P(prod_q),    // 36-bit multiplier output -      .A({{4{adc_q[13]}},adc_q} ),    // 18-bit multiplier input -      .B({{2{scale_q[15]}},scale_q}),    // 18-bit multiplier input -      .C(clk),    // Clock input -      .CE(1),  // Clock enable input -      .R(rst)     // Synchronous reset input -      );  - -    -   cordic_z24 #(.bitwidth(24)) -     cordic(.clock(clk), .reset(rst), .enable(run), -	    .xi(prod_i[23:0]),. yi(prod_q[23:0]), .zi(phase[31:8]), -	    .xo(i_cordic),.yo(q_cordic),.zo() ); - -   cic_strober cic_strober(.clock(clk),.reset(rst),.enable(run),.rate(cic_decim_rate), -			   .strobe_fast(1),.strobe_slow(strobe_cic) ); - -   cic_decim #(.bw(24)) -     decim_i (.clock(clk),.reset(rst),.enable(run), -	      .rate(cic_decim_rate),.strobe_in(1'b1),.strobe_out(strobe_cic), -	      .signal_in(i_cordic),.signal_out(i_cic)); -    -   cic_decim #(.bw(24)) -     decim_q (.clock(clk),.reset(rst),.enable(run), -	      .rate(cic_decim_rate),.strobe_in(1'b1),.strobe_out(strobe_cic), -	      .signal_in(q_cordic),.signal_out(q_cic)); - -   round_reg #(.bits_in(24),.bits_out(18)) round_icic (.clk(clk),.in(i_cic),.out(i_cic_scaled)); -   round_reg #(.bits_in(24),.bits_out(18)) round_qcic (.clk(clk),.in(q_cic),.out(q_cic_scaled)); -   reg 	       strobe_cic_d1; -   always @(posedge clk) strobe_cic_d1 <= strobe_cic; -    -   small_hb_dec #(.WIDTH(18)) small_hb_i -     (.clk(clk),.rst(rst),.bypass(~enable_hb1),.run(run), -      .stb_in(strobe_cic_d1),.data_in(i_cic_scaled),.stb_out(strobe_hb1),.data_out(i_hb1)); -    -   small_hb_dec #(.WIDTH(18)) small_hb_q -     (.clk(clk),.rst(rst),.bypass(~enable_hb1),.run(run), -      .stb_in(strobe_cic_d1),.data_in(q_cic_scaled),.stb_out(),.data_out(q_hb1)); - -   wire [8:0]  cpi_hb = enable_hb1 ? {cic_decim_rate,1'b0} : {1'b0,cic_decim_rate}; -   hb_dec #(.IWIDTH(18), .OWIDTH(18), .CWIDTH(18), .ACCWIDTH(24)) hb_i -     (.clk(clk),.rst(rst),.bypass(~enable_hb2),.run(run),.cpi(cpi_hb), -      .stb_in(strobe_hb1),.data_in(i_hb1),.stb_out(strobe_hb2),.data_out(i_hb2)); - -   hb_dec #(.IWIDTH(18), .OWIDTH(18), .CWIDTH(18), .ACCWIDTH(24)) hb_q -     (.clk(clk),.rst(rst),.bypass(~enable_hb2),.run(run),.cpi(cpi_hb), -      .stb_in(strobe_hb1),.data_in(q_hb1),.stb_out(),.data_out(q_hb2)); - -   round #(.bits_in(18),.bits_out(16)) round_iout (.in(i_hb2),.out(i_out)); -   round #(.bits_in(18),.bits_out(16)) round_qout (.in(q_hb2),.out(q_out)); - -   // Streaming GPIO -   // -   // io_rx[15] => I channel LSB if gpio_ena[0] high -   // io_rx[14] => Q channel LSB if gpio_ena[1] high - -   reg [31:0] sample_reg; -   always @(posedge clk) -     begin -	sample_reg[31:17] <= i_out[15:1]; -	sample_reg[15:1]  <= q_out[15:1]; -	sample_reg[16]    <= gpio_ena[0] ? io_rx[15] : i_out[0];  -	sample_reg[0]     <= gpio_ena[1] ? io_rx[14] : q_out[0]; -     end -    -   assign      sample = sample_reg; -   assign      strobe = strobe_hb2; -   assign      debug = {enable_hb1, enable_hb2, run, strobe, strobe_cic, strobe_cic_d1, strobe_hb1, strobe_hb2}; -    -endmodule // dsp_core_rx diff --git a/fpga/usrp2/sdr_lib/dsp_rx_glue.v b/fpga/usrp2/sdr_lib/dsp_rx_glue.v new file mode 100644 index 000000000..038a67a29 --- /dev/null +++ b/fpga/usrp2/sdr_lib/dsp_rx_glue.v @@ -0,0 +1,98 @@ +// +// Copyright 2012 Ettus Research LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program.  If not, see <http://www.gnu.org/licenses/>. +// + +//The following module effects the IO of the DDC chain. +//By default, this entire module is a simple pass-through. + +module dsp_rx_glue +#( +    //the dsp unit number: 0, 1, 2... +    parameter DSPNO = 0, + +    //frontend bus width +    parameter WIDTH = 24 +) +( +    //control signals +    input clock, input reset, input clear, input enable, + +    //user settings bus, controlled through user setting regs API +    input set_stb, input [7:0] set_addr, input [31:0] set_data, + +    //full rate inputs directly from the RX frontend +    input [WIDTH-1:0] frontend_i, +    input [WIDTH-1:0] frontend_q, + +    //full rate outputs directly to the DDC chain +    output [WIDTH-1:0] ddc_in_i, +    output [WIDTH-1:0] ddc_in_q, + +    //strobed samples {I16,Q16} from the RX DDC chain +    input [31:0] ddc_out_sample, +    input ddc_out_strobe, //high on valid sample +    output ddc_out_enable, //enables DDC module + +    //strobbed baseband samples {I16,Q16} from this module +    output [31:0] bb_sample, +    output bb_strobe, //high on valid sample + +    //debug output (optional) +    output [31:0] debug +); + +    generate +        if (DSPNO==0) begin +            `ifndef RX_DSP0_MODULE +            assign ddc_in_i = frontend_i; +            assign ddc_in_q = frontend_q; +            assign bb_sample = ddc_out_sample; +            assign bb_strobe = ddc_out_strobe; +            assign ddc_out_enable = enable; +            `else +            `RX_DSP0_MODULE #(.WIDTH(WIDTH)) rx_dsp0_custom +            ( +                .clock(clock), .reset(reset), .clear(clear), .enable(enable), +                .set_stb(set_stb), .set_addr(set_addr), .set_data(set_data), +                .frontend_i(frontend_i), .frontend_q(frontend_q), +                .ddc_in_i(ddc_in_i), .ddc_in_q(ddc_in_q), +                .ddc_out_sample(ddc_out_sample), .ddc_out_strobe(ddc_out_strobe), .ddc_out_enable(ddc_out_enable), +                .bb_sample(bb_sample), .bb_strobe(bb_strobe) +            ); +            `endif +        end +        else begin +            `ifndef RX_DSP1_MODULE +            assign ddc_in_i = frontend_i; +            assign ddc_in_q = frontend_q; +            assign bb_sample = ddc_out_sample; +            assign bb_strobe = ddc_out_strobe; +            assign ddc_out_enable = enable; +            `else +            `RX_DSP1_MODULE #(.WIDTH(WIDTH)) rx_dsp1_custom +            ( +                .clock(clock), .reset(reset), .clear(clear), .enable(enable), +                .set_stb(set_stb), .set_addr(set_addr), .set_data(set_data), +                .frontend_i(frontend_i), .frontend_q(frontend_q), +                .ddc_in_i(ddc_in_i), .ddc_in_q(ddc_in_q), +                .ddc_out_sample(ddc_out_sample), .ddc_out_strobe(ddc_out_strobe), .ddc_out_enable(ddc_out_enable), +                .bb_sample(bb_sample), .bb_strobe(bb_strobe) +            ); +            `endif +        end +    endgenerate + +endmodule //dsp_rx_glue diff --git a/fpga/usrp2/sdr_lib/dsp_tx_glue.v b/fpga/usrp2/sdr_lib/dsp_tx_glue.v new file mode 100644 index 000000000..46f6789ee --- /dev/null +++ b/fpga/usrp2/sdr_lib/dsp_tx_glue.v @@ -0,0 +1,98 @@ +// +// Copyright 2012 Ettus Research LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program.  If not, see <http://www.gnu.org/licenses/>. +// + +//The following module effects the IO of the DUC chain. +//By default, this entire module is a simple pass-through. + +module dsp_tx_glue +#( +    //the dsp unit number: 0, 1, 2... +    parameter DSPNO = 0, + +    //frontend bus width +    parameter WIDTH = 24 +) +( +    //control signals +    input clock, input reset, input clear, input enable, + +    //user settings bus, controlled through user setting regs API +    input set_stb, input [7:0] set_addr, input [31:0] set_data, + +    //full rate outputs directly to the TX frontend +    output [WIDTH-1:0] frontend_i, +    output [WIDTH-1:0] frontend_q, + +    //full rate outputs directly from the DUC chain +    input [WIDTH-1:0] duc_out_i, +    input [WIDTH-1:0] duc_out_q, + +    //strobed samples {I16,Q16} to the TX DUC chain +    output [31:0] duc_in_sample, +    input duc_in_strobe, //this is a backpressure signal +    output duc_in_enable, //enables DUC module + +    //strobbed baseband samples {I16,Q16} to this module +    input [31:0] bb_sample, +    output bb_strobe, //this is a backpressure signal + +    //debug output (optional) +    output [31:0] debug +); + +    generate +        if (DSPNO==0) begin +            `ifndef TX_DSP0_MODULE +            assign frontend_i = duc_out_i; +            assign frontend_q = duc_out_q; +            assign duc_in_sample = bb_sample; +            assign bb_strobe = duc_in_strobe; +            assign duc_in_enable = enable; +            `else +            `TX_DSP0_MODULE #(.WIDTH(WIDTH)) tx_dsp0_custom +            ( +                .clock(clock), .reset(reset), .clear(clear), .enable(enable), +                .set_stb(set_stb), .set_addr(set_addr), .set_data(set_data), +                .frontend_i(frontend_i), .frontend_q(frontend_q), +                .duc_out_i(duc_out_i), .duc_out_q(duc_out_q), +                .duc_in_sample(duc_in_sample), .duc_in_strobe(duc_in_strobe), .duc_in_enable(duc_in_enable), +                .bb_sample(bb_sample), .bb_strobe(bb_strobe) +            ); +            `endif +        end +        else begin +            `ifndef TX_DSP1_MODULE +            assign frontend_i = duc_out_i; +            assign frontend_q = duc_out_q; +            assign duc_in_sample = bb_sample; +            assign bb_strobe = duc_in_strobe; +            assign duc_in_enable = enable; +            `else +            `TX_DSP1_MODULE #(.WIDTH(WIDTH)) tx_dsp1_custom +            ( +                .clock(clock), .reset(reset), .clear(clear), .enable(enable), +                .set_stb(set_stb), .set_addr(set_addr), .set_data(set_data), +                .frontend_i(frontend_i), .frontend_q(frontend_q), +                .duc_out_i(duc_out_i), .duc_out_q(duc_out_q), +                .duc_in_sample(duc_in_sample), .duc_in_strobe(duc_in_strobe), .duc_in_enable(duc_in_enable), +                .bb_sample(bb_sample), .bb_strobe(bb_strobe) +            ); +            `endif +        end +    endgenerate + +endmodule //dsp_tx_glue diff --git a/fpga/usrp2/sdr_lib/dspengine_16to8.v b/fpga/usrp2/sdr_lib/dspengine_16to8.v index 53c5d29da..448c57d35 100644 --- a/fpga/usrp2/sdr_lib/dspengine_16to8.v +++ b/fpga/usrp2/sdr_lib/dspengine_16to8.v @@ -1,5 +1,5 @@ -// Copyright 2011 Ettus Research LLC +// Copyright 2011-2012 Ettus Research LLC  //  // This program is free software: you can redistribute it and/or modify  // it under the terms of the GNU General Public License as published by @@ -32,13 +32,11 @@ module dspengine_16to8      input [35:0] access_dat_i      ); -   wire 	 convert; -   wire [17:0] 	 scale_factor; -    -   setting_reg #(.my_addr(BASE),.width(19)) sr_16to8 +   wire convert; +   setting_reg #(.my_addr(BASE),.width(1)) sr_16to8       (.clk(clk),.rst(reset),.strobe(set_stb),.addr(set_addr), -      .in(set_data),.out({convert,scale_factor}),.changed()); -    +      .in(set_data),.out(convert),.changed()); +     reg [2:0] 	 dsp_state;     localparam DSP_IDLE = 0;     localparam DSP_PARSE_HEADER = 1; @@ -63,7 +61,7 @@ module dspengine_16to8     wire [15:0] 	 scaled_i, scaled_q;     wire [7:0] 	 i8, q8;     reg [7:0] 	 i8_reg, q8_reg; -   wire 	 stb_read, stb_mult, stb_clip, stb_round, val_read, val_mult, val_clip, val_round; +   wire 	 stb_read, stb_clip, val_read, val_clip;     wire 	 stb_out, stb_reg;     reg 		 even; @@ -193,29 +191,21 @@ module dspengine_16to8     wire [15:0] i16 = access_dat_i[31:16];     wire [15:0] q16 = access_dat_i[15:0]; -   pipectrl #(.STAGES(4), .TAGWIDTH(2)) pipectrl  +   pipectrl #(.STAGES(2), .TAGWIDTH(2)) pipectrl       (.clk(clk), .reset(reset),        .src_rdy_i(send_to_pipe), .dst_rdy_o(), // dst_rdy_o will always be 1 since dst_rdy_i is 1, below        .src_rdy_o(stb_out), .dst_rdy_i(1),   // always accept output of chain -      .strobes({stb_round,stb_clip,stb_mult,stb_read}), .valids({val_round,val_clip,val_mult,val_read}), +      .strobes({stb_clip,stb_read}), .valids({val_clip,val_read}),        .tag_i({last,even}), .tag_o({last_o,even_o}));     always @(posedge clk)       if(stb_out & ~even_o)         {i8_reg,q8_reg} <= {i8,q8}; -    -   MULT18X18S mult_i  -     (.P(prod_i), .A(scale_factor), .B({i16,2'b00}), .C(clk), .CE(stb_mult), .R(reset) );  -   clip_reg #(.bits_in(24),.bits_out(16),.STROBED(1)) clip_i  -     (.clk(clk), .in(prod_i[35:12]), .out(scaled_i), .strobe_in(stb_clip), .strobe_out()); -   round_sd #(.WIDTH_IN(16),.WIDTH_OUT(8),.DISABLE_SD(1)) round_i -     (.clk(clk), .reset(reset), .in(scaled_i), .strobe_in(stb_round), .out(i8), .strobe_out()); - -   MULT18X18S mult_q  -     (.P(prod_q), .A(scale_factor), .B({q16,2'b00}), .C(clk), .CE(stb_mult), .R(reset) );  -   clip_reg #(.bits_in(24),.bits_out(16),.STROBED(1)) clip_q  -     (.clk(clk), .in(prod_q[35:12]), .out(scaled_q), .strobe_in(stb_clip), .strobe_out()); -   round_sd #(.WIDTH_IN(16),.WIDTH_OUT(8),.DISABLE_SD(1)) round_q -     (.clk(clk), .reset(reset), .in(scaled_q), .strobe_in(stb_round), .out(q8), .strobe_out()); + +   clip_reg #(.bits_in(16),.bits_out(8),.STROBED(1)) clip_i +     (.clk(clk), .in(i16), .out(i8), .strobe_in(stb_clip), .strobe_out()); + +   clip_reg #(.bits_in(16),.bits_out(8),.STROBED(1)) clip_q +     (.clk(clk), .in(q16), .out(q8), .strobe_in(stb_clip), .strobe_out());  endmodule // dspengine_16to8 diff --git a/fpga/usrp2/sdr_lib/dspengine_8to16.v b/fpga/usrp2/sdr_lib/dspengine_8to16.v new file mode 100644 index 000000000..85187d78d --- /dev/null +++ b/fpga/usrp2/sdr_lib/dspengine_8to16.v @@ -0,0 +1,203 @@ + +// Copyright 2012 Ettus Research LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program.  If not, see <http://www.gnu.org/licenses/>. +// + +module dspengine_8to16 +  #(parameter BASE = 0, +    parameter BUF_SIZE = 9, +    parameter HEADER_OFFSET = 0) +   (input clk, input reset, input clear, +    input set_stb, input [7:0] set_addr, input [31:0] set_data, + +    output access_we, +    output access_stb, +    input access_ok, +    output access_done, +    output access_skip_read, +    output [BUF_SIZE-1:0] access_adr, +    input [BUF_SIZE-1:0] access_len, +    output [35:0] access_dat_o, +    input [35:0] access_dat_i +    ); + +   wire 	 convert; +    +   setting_reg #(.my_addr(BASE),.width(1)) sr_8to16 +     (.clk(clk),.rst(reset),.strobe(set_stb),.addr(set_addr), +      .in(set_data),.out(convert),.changed()); +    +   reg [3:0] 	 dsp_state; +   localparam DSP_IDLE = 0; +   localparam DSP_IDLE_RD = 1; +   localparam DSP_PARSE_HEADER = 2; +   localparam DSP_READ = 3; +   localparam DSP_READ_WAIT = 4; +   localparam DSP_WRITE_1 = 5; +   localparam DSP_WRITE_0 = 6; +   localparam DSP_READ_TRAILER = 7; +   localparam DSP_WRITE_TRAILER = 8; +   localparam DSP_WRITE_HEADER = 9; +   localparam DSP_DONE = 10; +    +   // Parse VITA header +   wire 	 is_if_data = (access_dat_i[31:29] == 3'b000); +   wire 	 has_streamid = access_dat_i[28]; +   wire 	 has_classid = access_dat_i[27]; +   wire 	 has_trailer = access_dat_i[26]; +   // 25:24 reserved, aka SOB/EOB +   wire 	 has_secs = |access_dat_i[23:22]; +   wire 	 has_tics = |access_dat_i[21:20]; +   wire [3:0] 	 hdr_length = 1 + has_streamid + has_classid + has_classid + has_secs + has_tics + has_tics; +   reg [15:0] 	 hdr_length_reg; + 	  +   reg 		 odd; +    +   reg [BUF_SIZE-1:0] read_adr, write_adr; +   reg 		      has_trailer_reg; +    +   reg [31:0] 	      new_header, new_trailer, trailer_mask; +   reg 		      wait_for_trailer; +   reg [15:0] 	      data_in_len; +   wire       	      is_odd = access_dat_i[22] & access_dat_i[10]; +   wire [15:0] 	      data_in_lenx2 = {data_in_len[14:0], 1'b0} - is_odd; + +   reg [7:0] 	      i8_0, q8_0; +   wire [7:0] 	      i8_1 = access_dat_i[31:24]; +   wire [7:0] 	      q8_1 = access_dat_i[23:16]; +   reg 		      skip; +    + +   always @(posedge clk) +     { i8_0, q8_0 } <= access_dat_i[15:0]; +    +   always @(posedge clk) +     if(reset | clear) +       dsp_state <= DSP_IDLE; +     else +       case(dsp_state) +	 DSP_IDLE : +	   begin +	      read_adr <= HEADER_OFFSET; +	      write_adr <= HEADER_OFFSET; +	      if(access_ok) +		dsp_state <= DSP_IDLE_RD; +	   end + +	 DSP_IDLE_RD: //extra idle state for read to become valid +		dsp_state <= DSP_PARSE_HEADER; + +	 DSP_PARSE_HEADER : +	   begin +	      has_trailer_reg <= has_trailer; +	      new_header[31:0] <= access_dat_i[31:0]; +	      hdr_length_reg <= hdr_length; +	      if(~is_if_data | ~convert | ~has_trailer) +		// ~convert is valid (16 bit mode) but both ~trailer and ~is_if_data are both +		// really error conditions on the TX side.  We shouldn't ever see them in the TX chain +		dsp_state <= DSP_WRITE_HEADER;   +	      else +		begin +		   read_adr <= access_dat_i[15:0] + HEADER_OFFSET - 1; // point to trailer +		   dsp_state <= DSP_READ_TRAILER; +		   wait_for_trailer <= 0; +		   data_in_len <= access_dat_i[15:0] - hdr_length - 1 /*trailer*/; +		end +	   end +	  +	 DSP_READ_TRAILER : +	   begin +	      wait_for_trailer <= 1; +	      if(wait_for_trailer) +		dsp_state <= DSP_WRITE_TRAILER; +	      new_trailer <= access_dat_i[31:0]; // Leave trailer unchanged +	      odd <= is_odd; +	      write_adr <= hdr_length_reg + data_in_lenx2 + HEADER_OFFSET; +	   end + +	 DSP_WRITE_TRAILER : +	   begin +	      dsp_state <= DSP_READ; +	      write_adr <= write_adr - 1; +	      read_adr <= read_adr - 1; +	      new_header[15:0] <= write_adr + (1 - HEADER_OFFSET); // length = addr of trailer + 1 +	   end + +	 DSP_READ : +	   begin +	      read_adr <= read_adr - 1; +	      if(odd) +		dsp_state <= DSP_READ_WAIT; +	      else +		dsp_state <= DSP_WRITE_1; +	      odd <= 0; +	   end + +	 DSP_READ_WAIT : +	   dsp_state <= DSP_WRITE_0; +	  +	 DSP_WRITE_1 : +	   begin +	      write_adr <= write_adr - 1; +	      if(write_adr == (hdr_length_reg+HEADER_OFFSET)) +		begin +		   write_adr <= HEADER_OFFSET; +		   dsp_state <= DSP_WRITE_HEADER; +		end +	      dsp_state <= DSP_WRITE_0; +	   end + +	 DSP_WRITE_0 : +	   begin +	      write_adr <= write_adr - 1; +	      if(write_adr == (hdr_length_reg+HEADER_OFFSET)) +		begin +		   write_adr <= HEADER_OFFSET; +		   dsp_state <= DSP_WRITE_HEADER; +		end +	      else +		dsp_state <= DSP_READ; +	   end + +	 DSP_WRITE_HEADER : +	   dsp_state <= DSP_DONE; + +	 DSP_DONE : +	   begin +	      read_adr <= HEADER_OFFSET; +	      write_adr <= HEADER_OFFSET; +	      dsp_state <= DSP_IDLE; +	   end +       endcase // case (dsp_state) + +   assign access_skip_read = 0; +   assign access_done = (dsp_state == DSP_DONE); + +   assign access_stb = 1; + +   assign access_we = (dsp_state == DSP_WRITE_HEADER) |  +		      (dsp_state == DSP_WRITE_TRAILER) | +		      (dsp_state == DSP_WRITE_0) | +		      (dsp_state == DSP_WRITE_1); +    +   assign access_dat_o = (dsp_state == DSP_WRITE_HEADER) ? { 4'h0, new_header } : +			 (dsp_state == DSP_WRITE_TRAILER) ? { 4'h2, new_trailer } : +			 (dsp_state == DSP_WRITE_0) ? { 4'h0, i8_0, 8'd0, q8_0, 8'd0 } : +			 (dsp_state == DSP_WRITE_1) ? { 4'h0, i8_1, 8'd0, q8_1, 8'd0 } : +			 34'h0DEADBEEF; +          +   assign access_adr = access_we ? write_adr : read_adr; +       +endmodule // dspengine_16to8 diff --git a/fpga/usrp2/sdr_lib/dsp_core_tx.v b/fpga/usrp2/sdr_lib/duc_chain.v index 4e0163e0a..bd3402a1f 100644 --- a/fpga/usrp2/sdr_lib/dsp_core_tx.v +++ b/fpga/usrp2/sdr_lib/duc_chain.v @@ -1,5 +1,5 @@  // -// Copyright 2011 Ettus Research LLC +// Copyright 2011-2012 Ettus Research LLC  //  // This program is free software: you can redistribute it and/or modify  // it under the terms of the GNU General Public License as published by @@ -15,26 +15,35 @@  // along with this program.  If not, see <http://www.gnu.org/licenses/>.  // +//! The USRP digital up-conversion chain -module dsp_core_tx -  #(parameter BASE=0) -  (input clk, input rst, +module duc_chain +  #( +    parameter BASE = 0, +    parameter DSPNO = 0, +    parameter WIDTH = 24 +  ) +  (input clk, input rst, input clr,     input set_stb, input [7:0] set_addr, input [31:0] set_data, +   input set_stb_user, input [7:0] set_addr_user, input [31:0] set_data_user, -   output [23:0] tx_i, output [23:0] tx_q, +   // To TX frontend +   output [WIDTH-1:0] tx_fe_i, +   output [WIDTH-1:0] tx_fe_q, -   // To tx_control +   // From TX control     input [31:0] sample,     input run,     output strobe,     output [31:0] debug     ); -   wire [15:0] i, q, scale_i, scale_q; +   wire duc_enb; +   wire [17:0] scale_factor;     wire [31:0] phase_inc;     reg [31:0]  phase;     wire [7:0]  interp_rate; -   wire [3:0]  dacmux_a, dacmux_b; +   wire [3:0]  tx_femux_a, tx_femux_b;     wire        enable_hb1, enable_hb2;     wire        rate_change; @@ -42,9 +51,9 @@ module dsp_core_tx       (.clk(clk),.rst(rst),.strobe(set_stb),.addr(set_addr),        .in(set_data),.out(phase_inc),.changed()); -   setting_reg #(.my_addr(BASE+1)) sr_1 +   setting_reg #(.my_addr(BASE+1), .width(18)) sr_1       (.clk(clk),.rst(rst),.strobe(set_stb),.addr(set_addr), -      .in(set_data),.out({scale_i,scale_q}),.changed()); +      .in(set_data),.out(scale_factor),.changed());     setting_reg #(.my_addr(BASE+2), .width(10)) sr_2       (.clk(clk),.rst(rst),.strobe(set_stb),.addr(set_addr), @@ -57,13 +66,13 @@ module dsp_core_tx     reg 	       strobe_hb2 = 1;     cic_strober #(.WIDTH(8)) -     cic_strober(.clock(clk),.reset(rst),.enable(run & ~rate_change),.rate(interp_rate), +     cic_strober(.clock(clk),.reset(rst),.enable(duc_enb & ~rate_change),.rate(interp_rate),  		 .strobe_fast(1),.strobe_slow(strobe_cic_pre) );     cic_strober #(.WIDTH(2)) -     hb2_strober(.clock(clk),.reset(rst),.enable(run & ~rate_change),.rate(enable_hb2 ? 2 : 1), +     hb2_strober(.clock(clk),.reset(rst),.enable(duc_enb & ~rate_change),.rate(enable_hb2 ? 2 : 1),  		 .strobe_fast(strobe_cic_pre),.strobe_slow(strobe_hb2_pre) );     cic_strober #(.WIDTH(2)) -     hb1_strober(.clock(clk),.reset(rst),.enable(run & ~rate_change),.rate(enable_hb1 ? 2 : 1), +     hb1_strober(.clock(clk),.reset(rst),.enable(duc_enb & ~rate_change),.rate(enable_hb1 ? 2 : 1),  		 .strobe_fast(strobe_hb2_pre),.strobe_slow(strobe_hb1_pre) );     always @(posedge clk) strobe_hb1 <= strobe_hb1_pre; @@ -74,7 +83,7 @@ module dsp_core_tx     always @(posedge clk)       if(rst)         phase <= 0; -     else if(~run) +     else if(~duc_enb)         phase <= 0;       else         phase <= phase + phase_inc; @@ -82,8 +91,8 @@ module dsp_core_tx     wire        signed [17:0] da, db;     wire        signed [35:0] prod_i, prod_q; -   wire [17:0] bb_i = {sample[31:16],2'b0}; -   wire [17:0] bb_q = {sample[15:0],2'b0}; +   wire [15:0] bb_i; +   wire [15:0] bb_q;     wire [17:0] i_interp, q_interp;     wire [17:0] hb1_i, hb1_q, hb2_i, hb2_q; @@ -92,10 +101,10 @@ module dsp_core_tx     // Note that max CIC rate is 128, which would give an overflow on cpo if enable_hb2 is true,     //   but the default case inside hb_interp handles this -   hb_interp #(.IWIDTH(18),.OWIDTH(18),.ACCWIDTH(24)) hb_interp_i -     (.clk(clk),.rst(rst),.bypass(~enable_hb1),.cpo(cpo),.stb_in(strobe_hb1),.data_in(bb_i),.stb_out(strobe_hb2),.data_out(hb1_i)); -   hb_interp #(.IWIDTH(18),.OWIDTH(18),.ACCWIDTH(24)) hb_interp_q -     (.clk(clk),.rst(rst),.bypass(~enable_hb1),.cpo(cpo),.stb_in(strobe_hb1),.data_in(bb_q),.stb_out(strobe_hb2),.data_out(hb1_q)); +   hb_interp #(.IWIDTH(18),.OWIDTH(18),.ACCWIDTH(WIDTH)) hb_interp_i +     (.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)); +   hb_interp #(.IWIDTH(18),.OWIDTH(18),.ACCWIDTH(WIDTH)) hb_interp_q +     (.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));     small_hb_int #(.WIDTH(18)) small_hb_interp_i       (.clk(clk),.rst(rst),.bypass(~enable_hb2),.stb_in(strobe_hb2),.data_in(hb1_i), @@ -105,24 +114,22 @@ module dsp_core_tx        .output_rate(interp_rate),.stb_out(strobe_cic),.data_out(hb2_q));     cic_interp  #(.bw(18),.N(4),.log2_of_max_rate(7)) -     cic_interp_i(.clock(clk),.reset(rst),.enable(run & ~rate_change),.rate(interp_rate), +     cic_interp_i(.clock(clk),.reset(rst),.enable(duc_enb & ~rate_change),.rate(interp_rate),  		  .strobe_in(strobe_cic),.strobe_out(1),  		  .signal_in(hb2_i),.signal_out(i_interp));     cic_interp  #(.bw(18),.N(4),.log2_of_max_rate(7)) -     cic_interp_q(.clock(clk),.reset(rst),.enable(run & ~rate_change),.rate(interp_rate), +     cic_interp_q(.clock(clk),.reset(rst),.enable(duc_enb & ~rate_change),.rate(interp_rate),  		  .strobe_in(strobe_cic),.strobe_out(1),  		  .signal_in(hb2_q),.signal_out(q_interp)); -   assign      strobe = strobe_hb1; - -   localparam  cwidth = 24;  // was 18 +   localparam  cwidth = WIDTH;  // was 18     localparam  zwidth = 24;  // was 16     wire [cwidth-1:0] da_c, db_c;     cordic_z24 #(.bitwidth(cwidth)) -     cordic(.clock(clk), .reset(rst), .enable(run), +     cordic(.clock(clk), .reset(rst), .enable(duc_enb),  	    .xi({i_interp,{(cwidth-18){1'b0}}}),.yi({q_interp,{(cwidth-18){1'b0}}}),  	    .zi(phase[31:32-zwidth]),  	    .xo(da_c),.yo(db_c),.zo() ); @@ -130,7 +137,7 @@ module dsp_core_tx     MULT18X18S MULT18X18S_inst        (.P(prod_i),    // 36-bit multiplier output        .A(da_c[cwidth-1:cwidth-18]),    // 18-bit multiplier input -      .B({{2{scale_i[15]}},scale_i}),    // 18-bit multiplier input +      .B(scale_factor),    // 18-bit multiplier input        .C(clk),    // Clock input        .CE(1),  // Clock enable input        .R(rst)     // Synchronous reset input @@ -139,15 +146,20 @@ module dsp_core_tx     MULT18X18S MULT18X18S_inst_2        (.P(prod_q),    // 36-bit multiplier output        .A(db_c[cwidth-1:cwidth-18]),    // 18-bit multiplier input -      .B({{2{scale_q[15]}},scale_q}),    // 18-bit multiplier input +      .B(scale_factor),    // 18-bit multiplier input        .C(clk),    // Clock input        .CE(1),  // Clock enable input        .R(rst)     // Synchronous reset input        ); -   assign tx_i = prod_i[28:5]; -   assign tx_q = prod_q[28:5]; -    +   dsp_tx_glue #(.DSPNO(DSPNO), .WIDTH(WIDTH)) dsp_tx_glue( +    .clock(clk), .reset(rst), .clear(clr), .enable(run), +    .set_stb(set_stb_user), .set_addr(set_addr_user), .set_data(set_data_user), +    .frontend_i(tx_fe_i), .frontend_q(tx_fe_q), +    .duc_out_i(prod_i[33:34-WIDTH]), .duc_out_q(prod_q[33:34-WIDTH]), +    .duc_in_sample({bb_i, bb_q}), .duc_in_strobe(strobe_hb1), .duc_in_enable(duc_enb), +    .bb_sample(sample), .bb_strobe(strobe)); +     assign      debug = {strobe_cic, strobe_hb1, strobe_hb2,run};  endmodule // dsp_core diff --git a/fpga/usrp2/sdr_lib/dummy_rx.v b/fpga/usrp2/sdr_lib/dummy_rx.v index b22d5f896..42bbe36b2 100644 --- a/fpga/usrp2/sdr_lib/dummy_rx.v +++ b/fpga/usrp2/sdr_lib/dummy_rx.v @@ -76,4 +76,4 @@ module dummy_rx         q_out <= q_out + 1; -endmodule // dsp_core_rx +endmodule // ddc_chain  | 
