Files
b210-k7-fpga/lib/rfnoc/blocks/rfnoc_block_fft/xfft_config_pkg.sv
T
Wade Fife 81f150213f fpga: rfnoc: Add new FFT block
This replaces the legacy RFNoC FFT block with a new one of the same
name that includes a superset of the original features. New features
include cyclic prefix insertion or removal and FFT sizes up to 64k.


Original-commit: 25fffb006755b2e91f0138eb4af3ab9e16b8690c
2024-12-17 22:13:42 +01:00

166 lines
6.2 KiB
Systemverilog

//
// Copyright 2024 Ettus Research, a National Instruments Brand
//
// SPDX-License-Identifier: LGPL-3.0-or-later
//
// Module: xfft_config_pkg
//
// Description:
//
// This package helps helps build and interpret the s_axis_config_tdata bus
// used to configure the Xilinx FFT core. The bus changes depending on the
// parameters of the IP. See the Xilinx Fast Fourier Transform product guide
// (PG109) for details. You can verify the values for a specific
// configuration by clicking the Implementation tab in the Vivado IP
// customization GUI.
//
package xfft_config_pkg;
// Set to 1 if cyclic prefix is enabled on the Xilinx IP. Set to 0 otherwise.
localparam bit CP_ENABLE = 0;
localparam int MAX_W = 256;
// Returns the width of the SCAL_SCH field of the config_tdata bus.
function automatic int fft_scale_w(int max_fft_size_log2);
// max_fft_size_log2 rounded up to the nearest multiple of 2
return ((max_fft_size_log2+1) / 2) * 2;
endfunction
// Returns the FFT scale value needed to get the default 1/N scaling for a
// given FFT size.
function automatic int fft_scale_default(int size_log2);
// Should be [ 10 10 ... 10] if N is a power of 4 (size_log2 is even)
// Should be [ 01 10 ... 10] if N is not a power of 4 (size log2 is odd)
int scale;
for (int i = 0; i < (size_log2+1)/2; i++) begin
scale[i*2 +: 2] = i == size_log2/2 ? 2'b01: 2'b10;
end
return scale;
endfunction
// Returns the width of the FWD_INV field of the config_tdata bus.
function automatic int fft_fwd_inv_w(int max_fft_size_log2);
return 1;
endfunction
// Returns the width of the CP_LEN field of the config_tdata bus.
function automatic int fft_cp_len_w(int max_fft_size_log2);
if (CP_ENABLE) begin
// Always the same as NFFT if present
return max_fft_size_log2;
end else begin
return 0;
end
endfunction
// Returns the width of the NFFT field of the config_tdata bus.
function automatic int fft_nfft_w(int max_fft_size_log2);
return 5;
endfunction
// Returns the LSB position of the SCAL_SCH field of the config_tdata bus.
function automatic int fft_scale_pos(int max_fft_size_log2);
return fft_fwd_inv_pos(max_fft_size_log2) + 1;
endfunction
// Returns the LSB position of the FWD_INV field of the config_tdata bus.
function automatic int fft_fwd_inv_pos(int max_fft_size_log2);
if (CP_ENABLE) begin
if (fft_cp_len_pos(max_fft_size_log2) + fft_cp_len_w(max_fft_size_log2) > 16)
return 24;
else
return 16;
end else begin
return 8;
end
endfunction
// Returns the LSB position of the CP_LEN field of the config_tdata bus.
function automatic int fft_cp_len_pos(int max_fft_size_log2);
return 8;
endfunction
// Returns the LSB position of the NFFT field of the config_tdata bus.
function automatic int fft_nfft_pos(int max_fft_size_log2);
return 0;
endfunction
// Returns the width of the config_tdata bus.
function automatic int fft_config_w(int max_fft_size_log2);
// It's the length needed to hold SCALE_SCH rounded up to the nearest byte
return ((fft_scale_w(max_fft_size_log2) + fft_scale_pos(max_fft_size_log2) + 7) / 8) * 8;
endfunction
// Generates a mask of all ones that is num_bits wide.
function automatic logic [MAX_W-1:0] mask(int num_bits);
logic [MAX_W-1:0] bits;
bits = (1 << num_bits) - 1;
return bits;
endfunction
// Builds the config_tdata value from the provided settings.
function automatic bit [MAX_W-1:0] build_fft_config(
int max_fft_size_log2,
int scale_sch,
bit fwd_inv,
int nfft,
int cp_len = 0
);
bit [MAX_W-1:0] cfg;
assert (max_fft_size_log2 >= 4 && max_fft_size_log2 <= 16) else
$fatal(1, "This FFT size is not yet supported");
assert (!CP_ENABLE || cp_len == 0) else
$fatal(1, "Cyclic prefix must be 0 if not in use");
cfg =
((scale_sch & mask(fft_scale_w (max_fft_size_log2))) << fft_scale_pos (max_fft_size_log2)) |
((fwd_inv & mask(fft_fwd_inv_w(max_fft_size_log2))) << fft_fwd_inv_pos(max_fft_size_log2)) |
((cp_len & mask(fft_cp_len_w (max_fft_size_log2))) << fft_cp_len_pos (max_fft_size_log2)) |
((nfft & mask(fft_nfft_w (max_fft_size_log2))) << fft_nfft_pos (max_fft_size_log2));
return cfg;
endfunction
//synthesis translate_off
// Takes as input the config_tdata bus and prints the settings encoding on it.
function automatic void print_fft_config(int max_fft_size_log2, logic [MAX_W-1:0] cfg);
int scale_sch, fwd_inv, cp_len, nfft;
scale_sch = (cfg >> fft_scale_pos (max_fft_size_log2)) & mask(fft_scale_w (max_fft_size_log2));
fwd_inv = (cfg >> fft_fwd_inv_pos(max_fft_size_log2)) & mask(fft_fwd_inv_w(max_fft_size_log2));
cp_len = (cfg >> fft_cp_len_pos (max_fft_size_log2)) & mask(fft_cp_len_w (max_fft_size_log2));
nfft = (cfg >> fft_nfft_pos (max_fft_size_log2)) & mask(fft_nfft_w (max_fft_size_log2));
$display("SCALE_SCH_0 : 0b%0b", scale_sch);
$display("FWD_INV_0 : %0d", fwd_inv);
if (CP_ENABLE) $display("CP_LEN : %0d", cp_len);
$display("NFFT : %0d", nfft);
endfunction
// The output of this function should match what's shown in the
// Implementation Details tab of the Xilinx Fast Fourier Transform IP
// generation wizard.
function automatic void print_fft_config_fields(int max_fft_size_log2);
$display("SCALE_SCH_0(%0d:%0d) bit%0d",
fft_scale_w(max_fft_size_log2) + fft_scale_pos(max_fft_size_log2) - 1,
fft_scale_pos(max_fft_size_log2), fft_scale_w(max_fft_size_log2));
$display("FWD_INV_0(%0d:%0d) bit%0d",
fft_fwd_inv_w(max_fft_size_log2) + fft_fwd_inv_pos(max_fft_size_log2) - 1,
fft_fwd_inv_pos(max_fft_size_log2), fft_fwd_inv_w(max_fft_size_log2));
if (CP_ENABLE) begin
$display("CP_LEN(%0d:%0d) uint%0d",
fft_cp_len_w(max_fft_size_log2) + fft_cp_len_pos(max_fft_size_log2) - 1,
fft_cp_len_pos(max_fft_size_log2), fft_cp_len_w(max_fft_size_log2));
end
$display("NFFT(%0d:%0d) uint%0d",
fft_nfft_w(max_fft_size_log2) + fft_nfft_pos(max_fft_size_log2) - 1,
fft_nfft_pos(max_fft_size_log2), fft_nfft_w(max_fft_size_log2));
endfunction
//synthesis translate_on
endpackage : xfft_config_pkg