fpga: x400: Add support for X410 motherboard FPGA

Co-authored-by: Andrew Moch <Andrew.Moch@ni.com>
Co-authored-by: Daniel Jepson <daniel.jepson@ni.com>
Co-authored-by: Javier Valenzuela <javier.valenzuela@ni.com>
Co-authored-by: Joerg Hofrichter <joerg.hofrichter@ni.com>
Co-authored-by: Kumaran Subramoniam <kumaran.subramoniam@ni.com>
Co-authored-by: Max Köhler <max.koehler@ni.com>
Co-authored-by: Michael Auchter <michael.auchter@ni.com>
Co-authored-by: Paul Butler <paul.butler@ni.com>
Co-authored-by: Wade Fife <wade.fife@ettus.com>
Co-authored-by: Hector Rubio <hrubio@ni.com>


Original-commit: 6d3765605262016a80f71e36357f749ea35cbe5a
This commit is contained in:
Wade Fife
2021-06-10 11:56:58 -05:00
committed by Aaron Rossetto
co-authored by Andrew Moch Daniel Jepson Javier Valenzuela Joerg Hofrichter Kumaran Subramoniam Max Köhler Michael Auchter Paul Butler Hector Rubio
parent bfef20ea45
commit 61782b02d7
205 changed files with 299634 additions and 0 deletions
+220
View File
@@ -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
+149
View File
@@ -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
+149
View File
@@ -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