diff options
Diffstat (limited to 'fpga/usrp3/top/x400/rf/200m')
-rw-r--r-- | fpga/usrp3/top/x400/rf/200m/rf_core_200m.v | 220 | ||||
-rw-r--r-- | fpga/usrp3/top/x400/rf/200m/rf_down_4to2.v | 149 | ||||
-rw-r--r-- | fpga/usrp3/top/x400/rf/200m/rf_up_2to4.v | 149 |
3 files changed, 518 insertions, 0 deletions
diff --git a/fpga/usrp3/top/x400/rf/200m/rf_core_200m.v b/fpga/usrp3/top/x400/rf/200m/rf_core_200m.v new file mode 100644 index 000000000..9a08e7e57 --- /dev/null +++ b/fpga/usrp3/top/x400/rf/200m/rf_core_200m.v @@ -0,0 +1,220 @@ +// +// Copyright 2021 Ettus Research, a National Instruments Brand +// +// SPDX-License-Identifier: LGPL-3.0-or-later +// +// Module: rf_core_200m +// +// Description: +// +// Implementation of rf_core with 200 MHz bandwidth. It presents an interface +// that inputs/outputs 2 samples per cycle. This version is implemented by +// instantiating rf_core_400m and adding up-conversion and down-conversion +// filters. +// + +`default_nettype none + +module rf_core_200m ( + + //--------------------------------------------------------------------------- + // Clocking + //--------------------------------------------------------------------------- + + // Main Clock Inputs + input wire rfdc_clk, + input wire rfdc_clk_2x, + input wire data_clk, + input wire data_clk_2x, + + // AXI4-Lite Config Clock + // This clock is used to synchronize status bits for the RFDC + // registers in the AXI-S clock domain. + input wire s_axi_config_clk, + + //--------------------------------------------------------------------------- + // RFDC Data Interfaces + //--------------------------------------------------------------------------- + // All ports here are in the rfdc_clk domain. + + // ADC + input wire [127:0] adc_data_in_i_tdata_0, + output wire adc_data_in_i_tready_0, + input wire adc_data_in_i_tvalid_0, + input wire [127:0] adc_data_in_q_tdata_0, + output wire adc_data_in_q_tready_0, + input wire adc_data_in_q_tvalid_0, + input wire [127:0] adc_data_in_i_tdata_1, + output wire adc_data_in_i_tready_1, + input wire adc_data_in_i_tvalid_1, + input wire [127:0] adc_data_in_q_tdata_1, + output wire adc_data_in_q_tready_1, + input wire adc_data_in_q_tvalid_1, + + // DAC + output wire [255:0] dac_data_out_tdata_0, + input wire dac_data_out_tready_0, + output wire dac_data_out_tvalid_0, + output wire [255:0] dac_data_out_tdata_1, + input wire dac_data_out_tready_1, + output wire dac_data_out_tvalid_1, + + //--------------------------------------------------------------------------- + // User Data Interface + //--------------------------------------------------------------------------- + // All ports here are in the data_clk domain. + + // ADC + output wire [63:0] adc_data_out_tdata_0, // Packed {Q1,I1,Q0,I0} + output wire adc_data_out_tvalid_0, + output wire [63:0] adc_data_out_tdata_1, // Packed {Q1,I1,Q0,I0} + output wire adc_data_out_tvalid_1, + + // DAC + input wire [63:0] dac_data_in_tdata_0, // Packed {Q1,I1,Q0,I0} with Q in MSBs + output wire dac_data_in_tready_0, + input wire dac_data_in_tvalid_0, + input wire [63:0] dac_data_in_tdata_1, // Packed {Q1,I1,Q0,I0} with Q in MSBs + output wire dac_data_in_tready_1, + input wire dac_data_in_tvalid_1, + + + //--------------------------------------------------------------------------- + // Miscellaneous + //--------------------------------------------------------------------------- + + // Invert I/Q control signals from RFDC to DSP chain. + input wire [3:0] invert_adc_iq_rclk2, + input wire [3:0] invert_dac_iq_rclk2, + + // Control/status vectors from/to RFDC. + // Notice these are all in the s_axi_config_clk domain. + output reg [15:0] dsp_info_sclk, + output wire [15:0] axi_status_sclk, + + // Resets. + input wire adc_data_out_resetn_dclk, + input wire adc_enable_data_rclk, + input wire adc_rfdc_axi_resetn_rclk, + input wire dac_data_in_resetn_dclk, + input wire dac_data_in_resetn_dclk2x, + input wire dac_data_in_resetn_rclk, + input wire fir_resetn_rclk2x, + + // Version (Constant) + output wire [95:0] version_info +); + + `include "../../regmap/rfdc_regs_regmap_utils.vh" + + //--------------------------------------------------------------------------- + // 400 MHz RF Core + //--------------------------------------------------------------------------- + + wire [127:0] adc_400m_tdata_0; + wire adc_400m_tvalid_0; + wire [127:0] adc_400m_tdata_1; + wire adc_400m_tvalid_1; + wire [127:0] dac_400m_tdata_0; + wire dac_400m_tvalid_0; + wire [127:0] dac_400m_tdata_1; + wire dac_400m_tvalid_1; + + wire [ 15:0] dsp_info_sclk_400m; + + rf_core_400m rf_core_400m_i ( + .rfdc_clk (rfdc_clk), + .rfdc_clk_2x (rfdc_clk_2x), + .data_clk (data_clk), + .data_clk_2x (data_clk_2x), + .s_axi_config_clk (s_axi_config_clk), + .adc_data_in_i_tdata_0 (adc_data_in_i_tdata_0), + .adc_data_in_i_tready_0 (adc_data_in_i_tready_0), + .adc_data_in_i_tvalid_0 (adc_data_in_i_tvalid_0), + .adc_data_in_q_tdata_0 (adc_data_in_q_tdata_0), + .adc_data_in_q_tready_0 (adc_data_in_q_tready_0), + .adc_data_in_q_tvalid_0 (adc_data_in_q_tvalid_0), + .adc_data_in_i_tdata_1 (adc_data_in_i_tdata_1), + .adc_data_in_i_tready_1 (adc_data_in_i_tready_1), + .adc_data_in_i_tvalid_1 (adc_data_in_i_tvalid_1), + .adc_data_in_q_tdata_1 (adc_data_in_q_tdata_1), + .adc_data_in_q_tready_1 (adc_data_in_q_tready_1), + .adc_data_in_q_tvalid_1 (adc_data_in_q_tvalid_1), + .dac_data_out_tdata_0 (dac_data_out_tdata_0), + .dac_data_out_tready_0 (dac_data_out_tready_0), + .dac_data_out_tvalid_0 (dac_data_out_tvalid_0), + .dac_data_out_tdata_1 (dac_data_out_tdata_1), + .dac_data_out_tready_1 (dac_data_out_tready_1), + .dac_data_out_tvalid_1 (dac_data_out_tvalid_1), + .adc_data_out_tdata_0 (adc_400m_tdata_0), + .adc_data_out_tvalid_0 (adc_400m_tvalid_0), + .adc_data_out_tdata_1 (adc_400m_tdata_1), + .adc_data_out_tvalid_1 (adc_400m_tvalid_1), + .dac_data_in_tdata_0 (dac_400m_tdata_0), + .dac_data_in_tready_0 (), + .dac_data_in_tvalid_0 (dac_400m_tvalid_0), + .dac_data_in_tdata_1 (dac_400m_tdata_1), + .dac_data_in_tready_1 (), + .dac_data_in_tvalid_1 (dac_400m_tvalid_1), + .invert_adc_iq_rclk2 (invert_adc_iq_rclk2), + .invert_dac_iq_rclk2 (invert_dac_iq_rclk2), + .dsp_info_sclk (dsp_info_sclk_400m), + .axi_status_sclk (axi_status_sclk), + .adc_data_out_resetn_dclk (adc_data_out_resetn_dclk), + .adc_enable_data_rclk (adc_enable_data_rclk), + .adc_rfdc_axi_resetn_rclk (adc_rfdc_axi_resetn_rclk), + .dac_data_in_resetn_dclk (dac_data_in_resetn_dclk), + .dac_data_in_resetn_dclk2x (dac_data_in_resetn_dclk2x), + .dac_data_in_resetn_rclk (dac_data_in_resetn_rclk), + .fir_resetn_rclk2x (fir_resetn_rclk2x), + .version_info (version_info) + ); + + // Change reported bandwidth 200 MHz + always @(*) begin + dsp_info_sclk <= dsp_info_sclk_400m; + dsp_info_sclk[FABRIC_DSP_BW_MSB : FABRIC_DSP_BW] <= FABRIC_DSP_BW_200M; + end + + + //--------------------------------------------------------------------------- + // ADC Down-conversion + //--------------------------------------------------------------------------- + + rf_down_4to2 #( + .NUM_CHANNELS (2) + ) rf_down_4to2_i ( + .clk (data_clk), + .clk_2x (data_clk_2x), + .rst (~adc_data_out_resetn_dclk), + .rst_2x (~adc_data_out_resetn_dclk), // 1x clk reset is safe to use + .i_tdata ({ adc_400m_tdata_1, adc_400m_tdata_0 }), + .i_tvalid ({ adc_400m_tvalid_1, adc_400m_tvalid_0 }), + .o_tdata ({ adc_data_out_tdata_1, adc_data_out_tdata_0 }), + .o_tvalid ({ adc_data_out_tvalid_1, adc_data_out_tvalid_0 }) + ); + + + //--------------------------------------------------------------------------- + // DAC Up-conversion + //--------------------------------------------------------------------------- + + assign dac_data_in_tready_0 = 1'b1; + assign dac_data_in_tready_1 = 1'b1; + + rf_up_2to4 #( + .NUM_CHANNELS (2) + ) rf_up_2to4_i ( + .clk (data_clk), + .clk_2x (data_clk_2x), + .rst (~dac_data_in_resetn_dclk), + .rst_2x (~dac_data_in_resetn_dclk2x), + .i_tdata ({ dac_data_in_tdata_1, dac_data_in_tdata_0 }), + .i_tvalid ({ dac_data_in_tvalid_1, dac_data_in_tvalid_0 }), + .o_tdata ({ dac_400m_tdata_1, dac_400m_tdata_0 }), + .o_tvalid ({ dac_400m_tvalid_1, dac_400m_tvalid_0 }) + ); + +endmodule + +`default_nettype wire diff --git a/fpga/usrp3/top/x400/rf/200m/rf_down_4to2.v b/fpga/usrp3/top/x400/rf/200m/rf_down_4to2.v new file mode 100644 index 000000000..bc1ed177e --- /dev/null +++ b/fpga/usrp3/top/x400/rf/200m/rf_down_4to2.v @@ -0,0 +1,149 @@ +// +// Copyright 2021 Ettus Research, a National Instruments Brand +// +// SPDX-License-Identifier: LGPL-3.0-or-later +// +// Module: rf_down_4to2 +// +// Description: +// +// Implements a down-sampling filter that accepts 4 samples per cycle on the +// input and outputs 2 samples per cycle. A 2x speed clock is used to perform +// the DSP computation, so that less logic can be used to implement the +// half-band filter. +// +// Data Path : In --> Gearbox --> Filter --> Gearbox --> Out +// SPC : 4 2 1 2 +// Clock Rate : 1x 2x 2x 1x +// + +`default_nettype none + +module rf_down_4to2 #( + parameter NUM_CHANNELS = 1 +) ( + input wire clk, + input wire clk_2x, + + // Synchronous resets + input wire rst, + input wire rst_2x, + + // Input - 4 SPC, synchronous to "clk" + input wire [NUM_CHANNELS*128-1:0] i_tdata, + input wire [NUM_CHANNELS* 1-1:0] i_tvalid, + + // Output - 2 SPC, synchronous to "clk" + output wire [NUM_CHANNELS*64-1:0] o_tdata, + output wire [NUM_CHANNELS* 1-1:0] o_tvalid +); + + generate + genvar ch; + for (ch = 0; ch < NUM_CHANNELS; ch = ch + 1) begin : gen_channel + + //----------------------------------------------------------------------- + // Input Gearbox + //----------------------------------------------------------------------- + // + // Convert from 4 SPC on clk to 2 SPC on clk_2x. + // + //----------------------------------------------------------------------- + + wire [63:0] gear_to_filt_tdata; + wire gear_to_filt_tvalid; + + gearbox_2x1 #( + .WORD_W (32), + .IN_WORDS (4), + .OUT_WORDS (2), + .BIG_ENDIAN (0) + ) gearbox_2x1_in ( + .i_clk (clk), + .i_rst (rst), + .i_tdata (i_tdata[ch*128 +: 128]), + .i_tvalid (i_tvalid[ch]), + .o_clk (clk_2x), + .o_rst (rst_2x), + .o_tdata (gear_to_filt_tdata), + .o_tvalid (gear_to_filt_tvalid) + ); + + + //----------------------------------------------------------------------- + // Interpolating Filter + //----------------------------------------------------------------------- + + wire [47:0] filt_to_clip_tdata; + wire filt_to_clip_tvalid; + + hb47_2to1 hb47_2to1_i ( + .aresetn (~rst_2x), + .aclk (clk_2x), + .s_axis_data_tvalid (gear_to_filt_tvalid), + .s_axis_data_tready (), + .s_axis_data_tdata (gear_to_filt_tdata), + .m_axis_data_tvalid (filt_to_clip_tvalid), + .m_axis_data_tuser (), + .m_axis_data_tdata (filt_to_clip_tdata) + ); + + + //----------------------------------------------------------------------- + // Saturation + //----------------------------------------------------------------------- + + wire [31:0] clip_to_gear_tdata; + wire clip_to_gear_tvalid; + + genvar word; + for (word = 0; word < 2; word = word+1) begin : gen_sat + axi_clip #( + .WIDTH_IN (24), + .WIDTH_OUT (16), + .FIFOSIZE (0) + ) axi_clip_i ( + .clk (clk_2x), + .reset (rst_2x), + .i_tdata (filt_to_clip_tdata[word*24 +: 24]), + .i_tlast (1'b0), + .i_tvalid (filt_to_clip_tvalid), + .i_tready (), + .o_tdata (clip_to_gear_tdata[word*16 +: 16]), + .o_tlast (), + .o_tvalid (clip_to_gear_tvalid), + .o_tready (1'b1) + ); + end + + + //----------------------------------------------------------------------- + // Output Gearbox + //----------------------------------------------------------------------- + // + // Convert from 1 SPC on clk_2x to 2 SPC on clk. + // + //----------------------------------------------------------------------- + + gearbox_2x1 #( + .WORD_W (32), + .IN_WORDS (1), + .OUT_WORDS (2), + .BIG_ENDIAN (0) + ) gearbox_2x1_out ( + .i_clk (clk_2x), + .i_rst (rst_2x), + .i_tdata (clip_to_gear_tdata), + .i_tvalid (clip_to_gear_tvalid), + .o_clk (clk), + .o_rst (rst), + .o_tdata (o_tdata[ch*64 +: 64]), + .o_tvalid (o_tvalid[ch]) + ); + + end // for + endgenerate + +endmodule + +`default_nettype wire diff --git a/fpga/usrp3/top/x400/rf/200m/rf_up_2to4.v b/fpga/usrp3/top/x400/rf/200m/rf_up_2to4.v new file mode 100644 index 000000000..0cabf346e --- /dev/null +++ b/fpga/usrp3/top/x400/rf/200m/rf_up_2to4.v @@ -0,0 +1,149 @@ +// +// Copyright 2021 Ettus Research, a National Instruments Brand +// +// SPDX-License-Identifier: LGPL-3.0-or-later +// +// Module: rf_up_2to4 +// +// Description: +// +// Implements an up-sampling filter that accepts 2 samples per cycle on the +// input and outputs 4 samples per cycle. A 2x speed clock is used to perform +// the DSP computation, so that less logic can be used to implement the +// half-band filter. +// +// Data Path : In --> Gearbox --> Filter --> Gearbox --> Out +// SPC : 2 1 2 4 +// Clock Rate : 1x 2x 2x 1x +// + +`default_nettype none + +module rf_up_2to4 #( + parameter NUM_CHANNELS = 1 +) ( + input wire clk, + input wire clk_2x, + + // Synchronous resets + input wire rst, + input wire rst_2x, + + // Input - 2 SPC, synchronous to "clk" + input wire [NUM_CHANNELS*64-1:0] i_tdata, + input wire [NUM_CHANNELS* 1-1:0] i_tvalid, + + // Output - 4 SPC, synchronous to "clk" + output wire [NUM_CHANNELS*128-1:0] o_tdata, + output wire [NUM_CHANNELS* 1-1:0] o_tvalid +); + + generate + genvar ch; + for (ch = 0; ch < NUM_CHANNELS; ch = ch + 1) begin : gen_channel + + //----------------------------------------------------------------------- + // Input Gearbox + //----------------------------------------------------------------------- + // + // Convert from 2 SPC on clk to 1 SPC on clk_2x. + // + //----------------------------------------------------------------------- + + wire [31:0] gear_to_filt_tdata; + wire gear_to_filt_tvalid; + + gearbox_2x1 #( + .WORD_W (32), + .IN_WORDS (2), + .OUT_WORDS (1), + .BIG_ENDIAN (0) + ) gearbox_2x1_in ( + .i_clk (clk), + .i_rst (rst), + .i_tdata (i_tdata[ch*64 +: 64]), + .i_tvalid (i_tvalid[ch]), + .o_clk (clk_2x), + .o_rst (rst_2x), + .o_tdata (gear_to_filt_tdata), + .o_tvalid (gear_to_filt_tvalid) + ); + + + //----------------------------------------------------------------------- + // Interpolating Filter + //----------------------------------------------------------------------- + + wire [95:0] filt_to_clip_tdata; + wire filt_to_clip_tvalid; + + hb47_1to2 hb47_1to2_i ( + .aresetn (~rst_2x), + .aclk (clk_2x), + .s_axis_data_tvalid (gear_to_filt_tvalid), + .s_axis_data_tready (), + .s_axis_data_tdata (gear_to_filt_tdata), + .m_axis_data_tvalid (filt_to_clip_tvalid), + .m_axis_data_tuser (), + .m_axis_data_tdata (filt_to_clip_tdata) + ); + + + //----------------------------------------------------------------------- + // Saturation + //----------------------------------------------------------------------- + + wire [63:0] clip_to_gear_tdata; + wire clip_to_gear_tvalid; + + genvar word; + for (word = 0; word < 4; word = word+1) begin : gen_sat + axi_clip #( + .WIDTH_IN (24), + .WIDTH_OUT (16), + .FIFOSIZE (0) + ) axi_clip_i ( + .clk (clk_2x), + .reset (rst_2x), + .i_tdata (filt_to_clip_tdata[word*24 +: 24]), + .i_tlast (1'b0), + .i_tvalid (filt_to_clip_tvalid), + .i_tready (), + .o_tdata (clip_to_gear_tdata[word*16 +: 16]), + .o_tlast (), + .o_tvalid (clip_to_gear_tvalid), + .o_tready (1'b1) + ); + end + + + //----------------------------------------------------------------------- + // Output Gearbox + //----------------------------------------------------------------------- + // + // Convert from 2 SPC on clk_2x to 4 SPC on clk. + // + //----------------------------------------------------------------------- + + gearbox_2x1 #( + .WORD_W (32), + .IN_WORDS (2), + .OUT_WORDS (4), + .BIG_ENDIAN (0) + ) gearbox_2x1_out ( + .i_clk (clk_2x), + .i_rst (rst_2x), + .i_tdata (clip_to_gear_tdata), + .i_tvalid (clip_to_gear_tvalid), + .o_clk (clk), + .o_rst (rst), + .o_tdata (o_tdata[ch*128 +: 128]), + .o_tvalid (o_tvalid[ch]) + ); + + end // for + endgenerate + +endmodule + +`default_nettype wire |