diff options
author | Michael West <michael.west@ettus.com> | 2020-03-19 12:29:29 -0700 |
---|---|---|
committer | Aaron Rossetto <aaron.rossetto@ni.com> | 2020-05-12 12:03:31 -0500 |
commit | d0c162bc7a4ac82f6104506b17d7be05e1780336 (patch) | |
tree | 464a4ce1852dcd7ee986dff9a0d1c74267f3ecf5 | |
parent | 12dfb97c8efce40494efb35bdd81d06b6f8b9b62 (diff) | |
download | uhd-d0c162bc7a4ac82f6104506b17d7be05e1780336.tar.gz uhd-d0c162bc7a4ac82f6104506b17d7be05e1780336.tar.bz2 uhd-d0c162bc7a4ac82f6104506b17d7be05e1780336.zip |
TwinRX: Remove decimation from frontend
The decimation in the rx_frontend_gen3 was added to reduce the bandwidth
between the Radio and the DDC due to the limitation in bandwidth over
the crossbar for dynamically connected blocks. The default FPGA image
for the X300 now has a static connection between the Radio and DDC, so
this is no longer necessary.
This change allows the TwinRX receive channels to be time aligned with
channels from other daughterboards so they can be used in the same
streamer.
Signed-off-by: Michael West <michael.west@ettus.com>
4 files changed, 59 insertions, 67 deletions
diff --git a/fpga/usrp3/lib/rfnoc/blocks/rfnoc_block_radio/rx_frontend_gen3.v b/fpga/usrp3/lib/rfnoc/blocks/rfnoc_block_radio/rx_frontend_gen3.v index 54529136b..eaf082ac5 100644 --- a/fpga/usrp3/lib/rfnoc/blocks/rfnoc_block_radio/rx_frontend_gen3.v +++ b/fpga/usrp3/lib/rfnoc/blocks/rfnoc_block_radio/rx_frontend_gen3.v @@ -1,6 +1,7 @@ // // Copyright 2015 Ettus Research LLC // Copyright 2018 Ettus Research, a National Instruments Company +// Copyright 2020 Ettus Research, a National Instruments Brand // // SPDX-License-Identifier: LGPL-3.0-or-later // @@ -27,7 +28,7 @@ module rx_frontend_gen3 #( wire swap_iq; wire invert_i; wire invert_q; - wire realmode_decim; + wire downconvert; wire bypass_all; wire [1:0] iq_map_reserved; wire [17:0] mag_corr, phase_corr; @@ -37,12 +38,10 @@ module rx_frontend_gen3 #( reg [23:0] adc_i_mux, adc_q_mux; reg adc_mux_stb; wire [23:0] adc_i_ofs, adc_q_ofs, adc_i_comp, adc_q_comp; - reg [23:0] adc_i_ofs_dly, adc_q_ofs_dly; wire adc_ofs_stb, adc_comp_stb; reg [1:0] adc_ofs_stb_dly; wire [23:0] adc_i_dsp, adc_q_dsp; wire adc_dsp_stb; - wire [35:0] corr_i, corr_q; wire [15:0] rx_i_out, rx_q_out; /******************************************************** @@ -58,7 +57,9 @@ module rx_frontend_gen3 #( setting_reg #(.my_addr(SR_IQ_MAPPING), .width(8)) sr_mux_sel ( .clk(clk),.rst(reset),.strobe(set_stb),.addr(set_addr), - .in(set_data),.out({bypass_all,iq_map_reserved,realmode_decim,invert_i,invert_q,realmode,swap_iq}),.changed()); + .in(set_data), + .out({bypass_all,iq_map_reserved,downconvert,invert_i,invert_q,realmode,swap_iq}), + .changed()); // Setting reg: 1 bit to set phase direction: default to 0: // direction bit == 0: the phase is increased by pi/2 (counter clockwise) @@ -179,17 +180,9 @@ module rx_frontend_gen3 #( if (BYPASS_REALMODE_DSP == 0) begin wire [24:0] adc_i_dsp_cout, adc_q_dsp_cout; - wire [23:0] adc_i_cclip, adc_q_cclip; - wire [23:0] adc_i_hb, adc_q_hb; - wire [23:0] adc_i_dec, adc_q_dec; + wire [23:0] adc_i_filt, adc_q_filt; wire adc_dsp_cout_stb; - wire adc_cclip_stb; - wire adc_hb_stb; - - wire valid_hbf0; - wire valid_hbf1; - wire valid_dec0; - wire valid_dec1; + wire adc_filt_stb; // 90 degree mixer quarter_rate_downconverter #(.WIDTH(24)) qr_dc_i( @@ -204,28 +197,51 @@ module rx_frontend_gen3 #( 18'd0, -18'd26536, 18'd0, 18'd14632, 18'd0, -18'd9187, 18'd0, 18'd5990, 18'd0, -18'd3900, 18'd0, 18'd2478, 18'd0, -18'd1505, 18'd0, 18'd855, 18'd0, -18'd440, 18'd0, 18'd194, 18'd0, -18'd62}; - axi_fir_filter_dec #( - .WIDTH(24), - .COEFF_WIDTH(18), - .NUM_COEFFS(47), - .COEFFS_VEC(HB_COEFS), - .BLANK_OUTPUT(0) - ) ffd0 ( - .clk(clk), .reset(reset || sync_in), - - .i_tdata({adc_i_dsp_cout, adc_q_dsp_cout}), - .i_tlast(1'b1), - .i_tvalid(adc_dsp_cout_stb), - .i_tready(), - - .o_tdata({adc_i_dec, adc_q_dec}), - .o_tlast(), - .o_tvalid(adc_hb_stb), - .o_tready(1'b1)); - - assign adc_dsp_stb = realmode_decim ? adc_hb_stb : adc_comp_stb; - assign adc_i_dsp = realmode_decim ? adc_i_dec : adc_i_comp; - assign adc_q_dsp = realmode_decim ? adc_q_dec : adc_q_comp; + // FIR filter for real part + axi_fir_filter #(.IN_WIDTH(24), .COEFF_WIDTH(18), .OUT_WIDTH(24), .NUM_COEFFS(47), .COEFFS_VEC(HB_COEFS), + .RELOADABLE_COEFFS(0), .BLANK_OUTPUT(0), .SYMMETRIC_COEFFS(1), .SKIP_ZERO_COEFFS(1), .USE_EMBEDDED_REGS_COEFFS(0) + ) hbfir0( + .clk(clk), + .reset(reset), + .clear(reset), + .s_axis_data_tdata(adc_i_dsp_cout), + .s_axis_data_tlast(1'b1), + .s_axis_data_tvalid(adc_dsp_cout_stb), + .s_axis_data_tready(), + .m_axis_data_tdata(adc_i_filt), + .m_axis_data_tlast(), + .m_axis_data_tvalid(adc_filt_stb), + .m_axis_data_tready(1'b1), + .s_axis_reload_tdata(18'd0), + .s_axis_reload_tvalid(1'b0), + .s_axis_reload_tlast(1'b0), + .s_axis_reload_tready() + ); + + // FIR filter for imag. part + axi_fir_filter #(.IN_WIDTH(24), .COEFF_WIDTH(18), .OUT_WIDTH(24), .NUM_COEFFS(47), .COEFFS_VEC(HB_COEFS), + .RELOADABLE_COEFFS(0), .BLANK_OUTPUT(0), .SYMMETRIC_COEFFS(1), .SKIP_ZERO_COEFFS(1), .USE_EMBEDDED_REGS_COEFFS(0) + ) hbfir1( + .clk(clk), + .reset(reset), + .clear(reset), + .s_axis_data_tdata(adc_q_dsp_cout), + .s_axis_data_tlast(1'b1), + .s_axis_data_tvalid(adc_dsp_cout_stb), + .s_axis_data_tready(), + .m_axis_data_tdata(adc_q_filt), + .m_axis_data_tlast(), + .m_axis_data_tvalid(), + .m_axis_data_tready(1'b1), + .s_axis_reload_tdata(18'd0), + .s_axis_reload_tvalid(1'b0), + .s_axis_reload_tlast(1'b0), + .s_axis_reload_tready() + ); + + assign adc_dsp_stb = downconvert ? adc_filt_stb : adc_comp_stb; + assign adc_i_dsp = downconvert ? adc_i_filt : adc_i_comp; + assign adc_q_dsp = downconvert ? adc_q_filt : adc_q_comp; end else begin assign adc_dsp_stb = adc_comp_stb; diff --git a/host/lib/include/uhdlib/usrp/cores/rx_frontend_core_3000.hpp b/host/lib/include/uhdlib/usrp/cores/rx_frontend_core_3000.hpp index 6b5dafe2a..60c3feb73 100644 --- a/host/lib/include/uhdlib/usrp/cores/rx_frontend_core_3000.hpp +++ b/host/lib/include/uhdlib/usrp/cores/rx_frontend_core_3000.hpp @@ -45,13 +45,4 @@ public: virtual void set_iq_balance(const std::complex<double>& cor) = 0; virtual void populate_subtree(uhd::property_tree::sptr subtree) = 0; - - /*! Return the sampling rate at the output - * - * In real mode, the frontend core will decimate the sampling rate by a - * factor of 2. - * - * \returns RX sampling rate - */ - virtual double get_output_rate(void) = 0; }; diff --git a/host/lib/usrp/cores/rx_frontend_core_3000.cpp b/host/lib/usrp/cores/rx_frontend_core_3000.cpp index 1dc8be745..756f0995d 100644 --- a/host/lib/usrp/cores/rx_frontend_core_3000.cpp +++ b/host/lib/usrp/cores/rx_frontend_core_3000.cpp @@ -23,11 +23,11 @@ using namespace uhd; #define REG_RX_FE_MAPPING (base + reg_offset * 4) #define REG_RX_FE_HET_CORDIC_PHASE (base + reg_offset * 5) -#define FLAG_DSP_RX_MAPPING_SWAP_IQ (1 << 0) -#define FLAG_DSP_RX_MAPPING_REAL_MODE (1 << 1) -#define FLAG_DSP_RX_MAPPING_INVERT_Q (1 << 2) -#define FLAG_DSP_RX_MAPPING_INVERT_I (1 << 3) -#define FLAG_DSP_RX_MAPPING_REAL_DECIM (1 << 4) +#define FLAG_DSP_RX_MAPPING_SWAP_IQ (1 << 0) +#define FLAG_DSP_RX_MAPPING_REAL_MODE (1 << 1) +#define FLAG_DSP_RX_MAPPING_INVERT_Q (1 << 2) +#define FLAG_DSP_RX_MAPPING_INVERT_I (1 << 3) +#define FLAG_DSP_RX_MAPPING_DOWNCONVERT (1 << 4) //#define FLAG_DSP_RX_MAPPING_RESERVED (1 << 5) //#define FLAG_DSP_RX_MAPPING_RESERVED (1 << 6) #define FLAG_DSP_RX_MAPPING_BYPASS_ALL (1 << 7) @@ -102,7 +102,7 @@ public: break; case fe_connection_t::HETERODYNE: mapping_reg_val = FLAG_DSP_RX_MAPPING_REAL_MODE - | FLAG_DSP_RX_MAPPING_REAL_DECIM; + | FLAG_DSP_RX_MAPPING_DOWNCONVERT; break; default: mapping_reg_val = 0; @@ -189,18 +189,6 @@ public: &rx_frontend_core_3000::set_iq_balance, this, std::placeholders::_1)); } - double get_output_rate() - { - switch (_fe_conn.get_sampling_mode()) { - case fe_connection_t::REAL: - return _adc_rate; - case fe_connection_t::HETERODYNE: - return _adc_rate / 2; - default: - return _adc_rate; - } - } - private: int32_t _i_dc_off, _q_dc_off; double _adc_rate; diff --git a/host/lib/usrp/x300/x300_radio_control.cpp b/host/lib/usrp/x300/x300_radio_control.cpp index c4cea2f8e..7c15554af 100644 --- a/host/lib/usrp/x300/x300_radio_control.cpp +++ b/host/lib/usrp/x300/x300_radio_control.cpp @@ -1582,10 +1582,7 @@ private: tx_chan++; } UHD_ASSERT_THROW(rx_chan or tx_chan); - const double actual_rate = rx_chan ? _rx_fe_map.at(0).core->get_output_rate() - : get_rate(); - RFNOC_LOG_DEBUG("Actual sample rate: " << (actual_rate / 1e6) << " Msps."); - radio_control_impl::set_rate(actual_rate); + RFNOC_LOG_DEBUG("Actual sample rate: " << (get_rate() / 1e6) << " Msps."); // Initialize the daughterboards now that frontend cores and connections exist _db_manager->initialize_dboards(); |