fpga: Add X440/FBX support
Co-authored-by: Martin Braun <martin.braun@ettus.com> Co-authored-by: Wade Fife <wade.fife@ni.com> Co-authored-by: Ryan Marlow <ryan@lmarlow.com> Original-commit: 596760a12e4834e47589c12f8a4fd083aa2f7c25
This commit is contained in:
committed by
Aki Tomita
co-authored by
Martin Braun
Wade Fife
Ryan Marlow
parent
a405111ce7
commit
5cadf901c7
@@ -0,0 +1,115 @@
|
||||
//
|
||||
// Copyright 2022 Ettus Research, A National Instruments Brand
|
||||
//
|
||||
// SPDX-License-Identifier: LGPL-3.0-or-later
|
||||
//
|
||||
// Module: adc_iq_repacker
|
||||
//
|
||||
// Description:
|
||||
//
|
||||
// This component repacks IQ from independent vectors into a single
|
||||
// output signal, and implements data swapping when requested.
|
||||
//
|
||||
// The parameters for this component describe the expected amount of
|
||||
// data to be received as well as the data to be generated.
|
||||
//
|
||||
// - SPC = Samples per cycle: amount of samples to be expected
|
||||
// on each I and Q input vector on each "clk" cycle.
|
||||
// - SAMPLE_WIDTH = Amount of bits composing each sample
|
||||
//
|
||||
// This modules incurs in two clk cycles of delay on the data and valid
|
||||
// signals from input to output.
|
||||
//
|
||||
// Example case : SPC = 2, SAMPLE_WIDTH = 16
|
||||
//
|
||||
// adc_x_in size(for I and Q) = 2 x 16 = 32
|
||||
// adc_out size = 2 x 2 x 16 = 64
|
||||
//
|
||||
// _______ _______ _______ ______
|
||||
// clk _| |_______| |_______| |_______|
|
||||
// _ _______________ _______________ _______________ ______
|
||||
// adc_i_in _X_____I1,I0_____X_____I3,I2_____X____32{'X'}____X______
|
||||
// _ _______________ _______________ _______________ ______
|
||||
// adc_q_in _X_____Q1,Q0_____X_____Q3,Q2_____X____32{'X'}____X______
|
||||
// _______________________________
|
||||
// valid_in _| |______________________
|
||||
// _ _______________ _______________ _______________ ______
|
||||
// adc_out _X____64{'X'}____X____64{'X'}____X__Q1,I1,Q0,I0__X__Q3,..
|
||||
// ______________________
|
||||
// valid_out _________________________________|
|
||||
//
|
||||
// When the swap input is high, the order in which Q and I samples
|
||||
// appear on the output vector is inverted
|
||||
//
|
||||
// _______ _______ _______ ______
|
||||
// clk _| |_______| |_______| |_______|
|
||||
// _ _______________ _______________ _______________ ______
|
||||
// adc_i_in _X_____I1,I0_____X_____I3,I2_____X____32{'X'}____X______
|
||||
// _ _______________ _______________ _______________ ______
|
||||
// adc_q_in _X_____Q1,Q0_____X_____Q3,Q2_____X____32{'X'}____X______
|
||||
// _______________________________
|
||||
// valid_in _| |______________________
|
||||
// _ _______________ _______________ _______________ ______
|
||||
// adc_out _X____64{'X'}____X____64{'X'}____X__I1,Q1,I0,Q0__X__I3,..
|
||||
// ______________________
|
||||
// valid_out _________________________________|
|
||||
//
|
||||
// Parameters:
|
||||
// SPC = Samples per cycle
|
||||
// SAMPLE_WIDTH = width of i/q sample inputs. Output will be 2*SAMPLE_WIDTH
|
||||
//
|
||||
|
||||
module adc_iq_repacker #(
|
||||
parameter SPC = 1,
|
||||
parameter SAMPLE_WIDTH = 16
|
||||
)
|
||||
(
|
||||
input wire clk,
|
||||
// Data in
|
||||
input wire [SPC*SAMPLE_WIDTH-1:0] adc_q_in,
|
||||
input wire [SPC*SAMPLE_WIDTH-1:0] adc_i_in,
|
||||
input wire valid_in,
|
||||
// This signal is currently driven in a related clock, and even though it runs at half the rate is should be fine
|
||||
// to handle it in this clock domain(in nature it will also stay high one asserted until the next reset.)
|
||||
input wire enable,
|
||||
// Data is packed [Q,I] (I in LSBs) when swap_iq is '0', and [I,Q] otherwise
|
||||
input wire swap_iq,
|
||||
|
||||
// Data out
|
||||
output reg [SPC*SAMPLE_WIDTH*2-1:0] data_out_tdata,
|
||||
output reg data_out_tvalid
|
||||
);
|
||||
|
||||
localparam IQ_WIDTH = SAMPLE_WIDTH*2;
|
||||
|
||||
reg valid = 1'b0, valid_dly = 1'b0;
|
||||
reg [SPC*SAMPLE_WIDTH-1:0] adc_q_data_in = {SPC*SAMPLE_WIDTH{1'b0}};
|
||||
reg [SPC*SAMPLE_WIDTH-1:0] adc_i_data_in = {SPC*SAMPLE_WIDTH{1'b0}};
|
||||
|
||||
integer sample_num;
|
||||
|
||||
// It is safe to not reset this domain because all of the input signals will be cleared
|
||||
// by a synchronous reset. Safe default values are assigned to all these registers.
|
||||
always @(posedge clk) begin
|
||||
adc_q_data_in <= adc_q_in;
|
||||
adc_i_data_in <= adc_i_in;
|
||||
// Place Q in the MSBs, I in the LSBs by default, unless swapped = 1.
|
||||
for (sample_num=0; sample_num < (SPC); sample_num = sample_num + 1)
|
||||
begin : data_out_gen
|
||||
if (swap_iq) begin
|
||||
data_out_tdata[sample_num*(IQ_WIDTH) +: IQ_WIDTH] <=
|
||||
{adc_i_data_in[sample_num*(SAMPLE_WIDTH) +: SAMPLE_WIDTH],
|
||||
adc_q_data_in[sample_num*(SAMPLE_WIDTH) +: SAMPLE_WIDTH]};
|
||||
end else begin
|
||||
data_out_tdata[sample_num*(IQ_WIDTH) +: IQ_WIDTH] <=
|
||||
{adc_q_data_in[sample_num*(SAMPLE_WIDTH) +: SAMPLE_WIDTH],
|
||||
adc_i_data_in[sample_num*(SAMPLE_WIDTH) +: SAMPLE_WIDTH]};
|
||||
end
|
||||
end
|
||||
// Valid is simply a transferred version of the 1x clock's valid. Delay it one
|
||||
// more cycle to align outputs.
|
||||
valid <= valid_in && enable;
|
||||
data_out_tvalid <= valid;
|
||||
end
|
||||
|
||||
endmodule
|
||||
Reference in New Issue
Block a user