aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fpga/usrp3/lib/rfnoc/blocks/rfnoc_block_radio/rx_frontend_gen3.v88
-rw-r--r--host/lib/include/uhdlib/usrp/cores/rx_frontend_core_3000.hpp9
-rw-r--r--host/lib/usrp/cores/rx_frontend_core_3000.cpp24
-rw-r--r--host/lib/usrp/x300/x300_radio_control.cpp5
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();