This adds the NIPC parameter, which configures support for processing multiple items or samples per clock cycle. With this enabled, the FFT block can process at rates higher than 250 MSPS, such as 500 MSPS and beyond. Original-commit: fc76aa940e121fe1f85a3513f6d90df4667338cf
311 lines
11 KiB
Systemverilog
311 lines
11 KiB
Systemverilog
//
|
|
// Copyright 2024 Ettus Research, a National Instruments Brand
|
|
//
|
|
// SPDX-License-Identifier: LGPL-3.0-or-later
|
|
//
|
|
// Module: fft_pipeline_wrapper
|
|
//
|
|
// Description:
|
|
//
|
|
// This module takes a multiple-item-per-cycle data stream and splits the
|
|
// processing of packets across multiple FFT instances, each processing a
|
|
// single item/sample per cycle.
|
|
//
|
|
// See fft_pipeline for documentation of the fft_pipeline parameters and
|
|
// ports. To avoid duplication, it is not repeated here.
|
|
//
|
|
// Parameters:
|
|
//
|
|
// NIPC : Items/samples per cycle on the input/output data port (i_t*, o_t*d)
|
|
//
|
|
|
|
`default_nettype none
|
|
|
|
|
|
module fft_pipeline_wrapper
|
|
import xfft_config_pkg::*;
|
|
#(
|
|
int NIPC = 1,
|
|
|
|
// Parameters for fft_pipeline
|
|
int MAX_FFT_SIZE_LOG2 = 12,
|
|
bit EN_CONFIG_FIFO = 0,
|
|
bit EN_CP_REMOVAL = 1,
|
|
bit EN_CP_INSERTION = 1,
|
|
bit EN_FFT_ORDER = 1,
|
|
bit EN_MAGNITUDE = 1,
|
|
bit EN_MAGNITUDE_SQ = 1,
|
|
bit USE_APPROX_MAG = 1,
|
|
|
|
localparam int FFT_CONFIG_W = fft_config_w(MAX_FFT_SIZE_LOG2),
|
|
localparam int DATA_W = 32,
|
|
localparam int FFT_SIZE_LOG2_W = $clog2(MAX_FFT_SIZE_LOG2+1),
|
|
localparam int CP_LEN_W = MAX_FFT_SIZE_LOG2
|
|
) (
|
|
input wire clk,
|
|
input wire rst,
|
|
|
|
// Global FFT settings
|
|
input wire [ 1:0] fft_order,
|
|
input wire [ 1:0] magnitude,
|
|
input wire [FFT_SIZE_LOG2_W-1:0] fft_size_log2,
|
|
input wire [ FFT_CONFIG_W-1:0] fft_config,
|
|
|
|
// FFT Configuration
|
|
input wire [FFT_CONFIG_W-1:0] fft_config_tdata,
|
|
input wire fft_config_tvalid,
|
|
output wire fft_config_tready,
|
|
|
|
// CP Removal Length
|
|
input wire [CP_LEN_W-1:0] cp_rem_tdata,
|
|
input wire cp_rem_tvalid,
|
|
output wire cp_rem_tready,
|
|
|
|
// CP Insertion Length
|
|
input wire [CP_LEN_W-1:0] cp_ins_tdata,
|
|
input wire cp_ins_tvalid,
|
|
output reg cp_ins_tready,
|
|
|
|
// FFT Event Monitoring
|
|
output wire event_fft_overflow,
|
|
|
|
// Data Input Packets
|
|
input wire [NIPC*DATA_W-1:0] i_tdata,
|
|
input wire i_tlast,
|
|
input wire i_tvalid,
|
|
output wire i_tready,
|
|
|
|
// Data Output Packets
|
|
output wire [NIPC*DATA_W-1:0] o_tdata,
|
|
output wire o_tlast,
|
|
output wire o_tvalid,
|
|
input wire o_tready
|
|
);
|
|
|
|
`include "usrp_utils.svh"
|
|
|
|
if (NIPC == 1) begin : gen_one_spc
|
|
|
|
fft_pipeline #(
|
|
.MAX_FFT_SIZE_LOG2(MAX_FFT_SIZE_LOG2),
|
|
.EN_CONFIG_FIFO (EN_CONFIG_FIFO ),
|
|
.EN_CP_REMOVAL (EN_CP_REMOVAL ),
|
|
.EN_CP_INSERTION (EN_CP_INSERTION ),
|
|
.EN_FFT_ORDER (EN_FFT_ORDER ),
|
|
.EN_MAGNITUDE (EN_MAGNITUDE ),
|
|
.EN_MAGNITUDE_SQ (EN_MAGNITUDE_SQ ),
|
|
.USE_APPROX_MAG (USE_APPROX_MAG )
|
|
) fft_pipeline_i (
|
|
.clk (clk ),
|
|
.rst (rst ),
|
|
.fft_order (fft_order ),
|
|
.magnitude (magnitude ),
|
|
.fft_config (fft_config ),
|
|
.fft_size_log2 (fft_size_log2 ),
|
|
.fft_config_tdata (fft_config_tdata ),
|
|
.fft_config_tvalid (fft_config_tvalid ),
|
|
.fft_config_tready (fft_config_tready ),
|
|
.cp_rem_tdata (cp_rem_tdata ),
|
|
.cp_rem_tvalid (cp_rem_tvalid ),
|
|
.cp_rem_tready (cp_rem_tready ),
|
|
.cp_ins_tdata (cp_ins_tdata ),
|
|
.cp_ins_tvalid (cp_ins_tvalid ),
|
|
.cp_ins_tready (cp_ins_tready ),
|
|
.event_fft_overflow(event_fft_overflow),
|
|
.i_tdata (i_tdata ),
|
|
.i_tlast (i_tlast ),
|
|
.i_tvalid (i_tvalid ),
|
|
.i_tready (i_tready ),
|
|
.o_tdata (o_tdata ),
|
|
.o_tlast (o_tlast ),
|
|
.o_tvalid (o_tvalid ),
|
|
.o_tready (o_tready )
|
|
);
|
|
|
|
end else begin : gen_multi_spc
|
|
|
|
logic [FFT_CONFIG_W-1:0] fft_config_split_tdata [NIPC];
|
|
logic fft_config_split_tvalid[NIPC];
|
|
logic fft_config_split_tready[NIPC];
|
|
|
|
logic [CP_LEN_W-1:0] cp_rem_split_tdata [NIPC];
|
|
logic cp_rem_split_tvalid [NIPC];
|
|
logic cp_rem_split_tready [NIPC];
|
|
|
|
logic [CP_LEN_W-1:0] cp_ins_split_tdata [NIPC];
|
|
logic cp_ins_split_tvalid [NIPC];
|
|
logic cp_ins_split_tready [NIPC];
|
|
|
|
logic [DATA_W-1:0] i_split_tdata [NIPC];
|
|
logic i_split_tlast [NIPC];
|
|
logic i_split_tvalid [NIPC];
|
|
logic i_split_tready [NIPC];
|
|
|
|
logic [DATA_W-1:0] o_split_tdata [NIPC];
|
|
logic o_split_tlast [NIPC];
|
|
logic o_split_tvalid [NIPC];
|
|
logic o_split_tready [NIPC];
|
|
|
|
logic [NIPC-1:0] event_fft_overflow_split;
|
|
|
|
if (EN_CONFIG_FIFO) begin : gen_config_fifo_split
|
|
axis_load_split #(
|
|
.IN_DATA_W (FFT_CONFIG_W),
|
|
.IN_FIFO_SIZE (1 ),
|
|
.OUT_DATA_W (FFT_CONFIG_W),
|
|
.OUT_FIFO_SIZE(1 ),
|
|
.OUT_NUM_PORTS(NIPC )
|
|
) axis_load_split_fft_config (
|
|
.clk (clk ),
|
|
.rst (rst ),
|
|
.i_tdata (fft_config_tdata ),
|
|
.i_tuser ('0 ),
|
|
.i_tlast (1'b1 ),
|
|
.i_tvalid(fft_config_tvalid ),
|
|
.i_tready(fft_config_tready ),
|
|
.o_tdata (fft_config_split_tdata ),
|
|
.o_tuser ( ),
|
|
.o_tlast ( ),
|
|
.o_tvalid(fft_config_split_tvalid),
|
|
.o_tready(fft_config_split_tready)
|
|
);
|
|
end else begin : gen_no_config_fifo_split
|
|
assign fft_config_tready = 1'b1;
|
|
for (genvar idx=0; idx < NIPC; idx++) begin : gen_assign
|
|
assign fft_config_split_tvalid[idx] = 1'b0;
|
|
end
|
|
end
|
|
|
|
axis_load_split #(
|
|
.IN_DATA_W (CP_LEN_W),
|
|
.IN_FIFO_SIZE (1 ),
|
|
.OUT_DATA_W (CP_LEN_W),
|
|
.OUT_FIFO_SIZE(1 ),
|
|
.OUT_NUM_PORTS(NIPC )
|
|
) axis_load_split_cp_rem (
|
|
.clk (clk ),
|
|
.rst (rst ),
|
|
.i_tdata (cp_rem_tdata ),
|
|
.i_tuser ('0 ),
|
|
.i_tlast (1'b1 ),
|
|
.i_tvalid(cp_rem_tvalid ),
|
|
.i_tready(cp_rem_tready ),
|
|
.o_tdata (cp_rem_split_tdata ),
|
|
.o_tuser ( ),
|
|
.o_tlast ( ),
|
|
.o_tvalid(cp_rem_split_tvalid),
|
|
.o_tready(cp_rem_split_tready)
|
|
);
|
|
|
|
axis_load_split #(
|
|
.IN_DATA_W (CP_LEN_W),
|
|
.IN_FIFO_SIZE (1 ),
|
|
.OUT_DATA_W (CP_LEN_W),
|
|
.OUT_FIFO_SIZE(1 ),
|
|
.OUT_NUM_PORTS(NIPC )
|
|
) axis_load_split_cp_ins (
|
|
.clk (clk ),
|
|
.rst (rst ),
|
|
.i_tdata (cp_ins_tdata ),
|
|
.i_tuser ('0 ),
|
|
.i_tlast (1'b1 ),
|
|
.i_tvalid(cp_ins_tvalid ),
|
|
.i_tready(cp_ins_tready ),
|
|
.o_tdata (cp_ins_split_tdata ),
|
|
.o_tuser ( ),
|
|
.o_tlast ( ),
|
|
.o_tvalid(cp_ins_split_tvalid),
|
|
.o_tready(cp_ins_split_tready)
|
|
);
|
|
|
|
axis_load_split #(
|
|
.IN_DATA_W (NIPC*DATA_W ),
|
|
.IN_FIFO_SIZE (1 ),
|
|
.OUT_DATA_W (DATA_W ),
|
|
.OUT_FIFO_SIZE(MAX_FFT_SIZE_LOG2),
|
|
.OUT_NUM_PORTS(NIPC ),
|
|
.USER_W (1 )
|
|
) axis_load_split_data (
|
|
.clk (clk ),
|
|
.rst (rst ),
|
|
.i_tdata (i_tdata ),
|
|
.i_tuser ('0 ),
|
|
.i_tlast (i_tlast ),
|
|
.i_tvalid(i_tvalid ),
|
|
.i_tready(i_tready ),
|
|
.o_tdata (i_split_tdata ),
|
|
.o_tuser ( ),
|
|
.o_tlast (i_split_tlast ),
|
|
.o_tvalid(i_split_tvalid),
|
|
.o_tready(i_split_tready)
|
|
);
|
|
|
|
for (genvar samp_i = 0; samp_i < NIPC; samp_i++) begin : gen_pipelines
|
|
fft_pipeline #(
|
|
.MAX_FFT_SIZE_LOG2(MAX_FFT_SIZE_LOG2),
|
|
.EN_CONFIG_FIFO (EN_CONFIG_FIFO ),
|
|
.EN_CP_REMOVAL (EN_CP_REMOVAL ),
|
|
.EN_CP_INSERTION (EN_CP_INSERTION ),
|
|
.EN_FFT_ORDER (EN_FFT_ORDER ),
|
|
.EN_MAGNITUDE (EN_MAGNITUDE ),
|
|
.EN_MAGNITUDE_SQ (EN_MAGNITUDE_SQ ),
|
|
.USE_APPROX_MAG (USE_APPROX_MAG )
|
|
) fft_pipeline_i (
|
|
.clk (clk ),
|
|
.rst (rst ),
|
|
.fft_order (fft_order ),
|
|
.magnitude (magnitude ),
|
|
.fft_size_log2 (fft_size_log2 ),
|
|
.fft_config (fft_config ),
|
|
.fft_config_tdata (fft_config_split_tdata [samp_i]),
|
|
.fft_config_tvalid (fft_config_split_tvalid [samp_i]),
|
|
.fft_config_tready (fft_config_split_tready [samp_i]),
|
|
.cp_rem_tdata (cp_rem_split_tdata [samp_i]),
|
|
.cp_rem_tvalid (cp_rem_split_tvalid [samp_i]),
|
|
.cp_rem_tready (cp_rem_split_tready [samp_i]),
|
|
.cp_ins_tdata (cp_ins_split_tdata [samp_i]),
|
|
.cp_ins_tvalid (cp_ins_split_tvalid [samp_i]),
|
|
.cp_ins_tready (cp_ins_split_tready [samp_i]),
|
|
.event_fft_overflow(event_fft_overflow_split[samp_i]),
|
|
.i_tdata (i_split_tdata [samp_i]),
|
|
.i_tlast (i_split_tlast [samp_i]),
|
|
.i_tvalid (i_split_tvalid [samp_i]),
|
|
.i_tready (i_split_tready [samp_i]),
|
|
.o_tdata (o_split_tdata [samp_i]),
|
|
.o_tlast (o_split_tlast [samp_i]),
|
|
.o_tvalid (o_split_tvalid [samp_i]),
|
|
.o_tready (o_split_tready [samp_i])
|
|
);
|
|
end
|
|
|
|
axis_load_merge #(
|
|
.IN_DATA_W (DATA_W ),
|
|
.IN_FIFO_SIZE (MAX_FFT_SIZE_LOG2),
|
|
.IN_NUM_PORTS (NIPC ),
|
|
.OUT_DATA_W (NIPC*DATA_W ),
|
|
.OUT_FIFO_SIZE(1 ),
|
|
.USER_W (1 )
|
|
) axis_load_merge_data (
|
|
.clk (clk ),
|
|
.rst (rst ),
|
|
.i_tdata (o_split_tdata ),
|
|
.i_tuser ( ),
|
|
.i_tlast (o_split_tlast ),
|
|
.i_tvalid(o_split_tvalid),
|
|
.i_tready(o_split_tready),
|
|
.o_tdata (o_tdata ),
|
|
.o_tuser ( ),
|
|
.o_tlast (o_tlast ),
|
|
.o_tvalid(o_tvalid ),
|
|
.o_tready(o_tready )
|
|
);
|
|
|
|
assign event_fft_overflow = |event_fft_overflow_split;
|
|
|
|
end
|
|
|
|
endmodule : fft_pipeline_wrapper
|
|
|
|
|
|
`default_nettype wire
|