fpga: rfnoc: Add OFDM block

This commit is contained in:
Wade Fife 2024-05-24 14:19:52 -05:00
parent febf79834a
commit 788ff45345
6 changed files with 2696 additions and 0 deletions

View File

@ -0,0 +1,63 @@
#
# Copyright 2024 Ettus Research, a National Instruments Brand
#
# SPDX-License-Identifier: LGPL-3.0-or-later
#
#-------------------------------------------------
# Top-of-Makefile
#-------------------------------------------------
# Define BASE_DIR to point to the "top" dir
BASE_DIR = $(abspath ../../../../top)
# Include viv_sim_preample after defining BASE_DIR
include $(BASE_DIR)/../tools/make/viv_sim_preamble.mak
#-------------------------------------------------
# IP Specific
#-------------------------------------------------
# If simulation contains IP, define the IP_DIR and point
# it to the base level IP directory
LIB_IP_DIR = $(BASE_DIR)/../lib/ip
# Include makefiles and sources for all IP components
# *after* defining the LIB_IP_DIR
include $(LIB_IP_DIR)/xfft_32k_16b/Makefile.inc
include $(LIB_IP_DIR)/xfft_8k_16b/Makefile.inc
include $(LIB_IP_DIR)/xfft_4k_16b/Makefile.inc
DESIGN_SRCS += $(abspath \
$(LIB_IP_XFFT_32K_16B_OUTS) \
$(LIB_IP_XFFT_8K_16B_OUTS) \
$(LIB_IP_XFFT_4K_16B_OUTS) \
)
#-------------------------------------------------
# Design Specific
#-------------------------------------------------
# Include makefiles and sources for the DUT and its
# dependencies.
include $(BASE_DIR)/../lib/rfnoc/core/Makefile.srcs
include $(BASE_DIR)/../lib/rfnoc/utils/Makefile.srcs
include Makefile.srcs
DESIGN_SRCS += $(abspath \
$(RFNOC_CORE_SRCS) \
$(RFNOC_OOT_SRCS) \
$(RFNOC_NI_ORU_IP_XCI_SRCS) \
)
#-------------------------------------------------
# Testbench Specific
#-------------------------------------------------
SIM_TOP = rfnoc_block_ofdm_tb
SIM_SRCS = $(abspath \
rfnoc_block_ofdm_tb.sv \
)
#-------------------------------------------------
# Bottom-of-Makefile
#-------------------------------------------------
# Include all simulator specific makefiles here
# Each should define a unique target to simulate
# e.g. xsim, vsim, etc and a common "clean" target
include $(BASE_DIR)/../tools/make/viv_simulator.mak

View File

@ -0,0 +1,23 @@
#
# Copyright 2023 Ettus Research, a National Instruments Brand
#
# SPDX-License-Identifier: LGPL-3.0-or-later
#
##################################################
# RFNoC Block Sources
##################################################
# Here, list all the files that are necessary to synthesize this block. Don't
# include testbenches!
# Make sure that the source files are nicely detectable by a regex. Best to put
# one on each line.
# The first argument to addprefix is the current path to this Makefile, so the
# path list is always absolute, regardless of from where we're including or
# calling this file. RFNOC_OOT_SRCS needs to be a simply expanded variable
# (not a recursively expanded variable), and we take care of that in the build
# infrastructure.
RFNOC_OOT_SRCS += $(addprefix $(dir $(abspath $(lastword $(MAKEFILE_LIST)))), \
axis_ofdm_cyclic_prefix_removal.v \
noc_shell_ofdm.v \
rfnoc_block_ofdm.sv \
)

View File

@ -0,0 +1,207 @@
//
// Copyright 2023 Ettus Research, a National Instruments Brand
//
// SPDX-License-Identifier: LGPL-3.0-or-later
//
// Module: axis_ofdm_cyclic_prefix_removal
//
// Description:
//
// Removes cyclic prefix from OFDM symbols. Configuration FIFO allows for
// either queuing up multiple configs with an optional loopback mode that
// writes the current config back into the FIFO. This allows the block
// to execute a pattern, for example if CP lengths can change symbol to symbol
// in a repeating pattern.
//
// Note: There is a two clock bubble cycle after every OFDM symbol due to returning to
// the idle state to load the next config, so this block must be clocked at least
// slightly faster the sample rate, i.e. Clock rate > (Fs)*(1 + 2/(CP length + FFT Size)).
//
// Parameters:
//
// WIDTH : Data / Sample AXIS bus width
// MAX_CP_LEN_LOG2 : Log2 of maximum cyclic prefix length
// MAX_FFT_SIZE_LOG2 : Log2 of maximum FFT size
// DEFAULT_CP_LEN : Number of samples in cyclic prefix
// CP_LEN_FIFO_MODE : 0: FIFO without loopback, 1: FIFO with loopback
// CP_LEN_FIFO_SIZE_LOG2 : Log2 depth of the FIFO
// SET_TLAST : Always set tlast at the end of each symbol
//
`default_nettype none
module axis_ofdm_cyclic_prefix_removal #(
parameter WIDTH = 32,
parameter USER_WIDTH = 1,
parameter MAX_CP_LEN_LOG2 = 16,
parameter MAX_FFT_SIZE_LOG2 = 16,
parameter DEFAULT_CP_LEN = 288,
parameter CP_LEN_FIFO_MODE = 0,
parameter CP_LEN_FIFO_SIZE_LOG2 = 5,
parameter SET_TLAST = 1
)(
input wire clk,
input wire reset,
input wire clear_fifo, // Clears cyclic prefix length FIFO, but only when safe to do so
input wire [MAX_FFT_SIZE_LOG2-1:0] fft_size,
input wire [MAX_CP_LEN_LOG2-1:0] m_axis_cp_len_tdata,
input wire m_axis_cp_len_tvalid,
output wire m_axis_cp_len_tready,
output wire [15:0] cp_len_fifo_occupied,
input wire [WIDTH-1:0] s_axis_data_tdata,
input wire [USER_WIDTH-1:0] s_axis_data_tuser,
input wire s_axis_data_tlast,
input wire s_axis_data_tvalid,
output wire s_axis_data_tready,
output wire [WIDTH-1:0] m_axis_data_tdata,
output wire [USER_WIDTH-1:0] m_axis_data_tuser,
output wire m_axis_data_tlast,
output wire m_axis_data_tvalid,
input wire m_axis_data_tready
);
localparam S_IDLE = 3'd0;
localparam S_CONFIG = 3'd1;
localparam S_CYCLIC_PREFIX = 3'd2;
localparam S_OFDM_SYMBOL = 3'd3;
localparam S_CLEAR_FIFO = 3'd4;
reg [2:0] state;
wire [MAX_CP_LEN_LOG2-1:0] cp_len_fifo_in_tdata, cp_len_fifo_out_tdata;
wire cp_len_fifo_in_tvalid, cp_len_fifo_out_tvalid;
wire cp_len_fifo_in_tready, cp_len_fifo_out_tready;
wire clear_config_fifo = (state == S_CLEAR_FIFO);
axi_fifo #(
.WIDTH (MAX_CP_LEN_LOG2),
.SIZE (CP_LEN_FIFO_SIZE_LOG2))
axi_fifo_config_inst (
.clk (clk),
.reset (reset),
.clear (clear_config_fifo),
.i_tdata (cp_len_fifo_in_tdata),
.i_tvalid (cp_len_fifo_in_tvalid),
.i_tready (cp_len_fifo_in_tready),
.o_tdata (cp_len_fifo_out_tdata),
.o_tvalid (cp_len_fifo_out_tvalid),
.o_tready (cp_len_fifo_out_tready),
.space (),
.occupied (cp_len_fifo_occupied)
);
generate
// No config fifo loopback. New configs can be written at any time.
if (CP_LEN_FIFO_MODE == 0) begin
assign cp_len_fifo_in_tdata = m_axis_cp_len_tdata;
assign cp_len_fifo_in_tvalid = (state == S_CLEAR_FIFO) ? 1'b0 : m_axis_cp_len_tvalid;
assign m_axis_cp_len_tready = (state == S_CLEAR_FIFO) ? 1'b0 : cp_len_fifo_in_tready;
assign cp_len_fifo_out_tready = (state == S_CONFIG);
// Config fifo loopback enabled, writes current config back into config fifo in the S_CONFIG state.
// New configs can be written in any state but S_CONFIG & S_CLEAR.
end else begin
assign cp_len_fifo_in_tdata = (state == S_CONFIG) ? cp_len_fifo_out_tdata : m_axis_cp_len_tdata;
assign cp_len_fifo_in_tvalid = (state == S_CONFIG) ? cp_len_fifo_out_tvalid :
(state == S_CLEAR_FIFO) ? 1'b0 :
/* Else */ m_axis_cp_len_tvalid;
assign m_axis_cp_len_tready = (state == S_CONFIG) ? 1'b0 :
(state == S_CLEAR_FIFO) ? 1'b0 :
/* Else */ cp_len_fifo_in_tready;
assign cp_len_fifo_out_tready = (state == S_CONFIG);
end
endgenerate
// CP length should generally not be larger than the FFT size, but this calculation is just in case
// someone tries to use this block in an unusual way
localparam CNT_WIDTH = MAX_FFT_SIZE_LOG2 > MAX_CP_LEN_LOG2 ? MAX_FFT_SIZE_LOG2 : MAX_CP_LEN_LOG2;
reg [MAX_CP_LEN_LOG2-1:0] cp_len_reg = DEFAULT_CP_LEN;
reg [MAX_FFT_SIZE_LOG2-1:0] fft_size_reg = 'd0;
reg [CNT_WIDTH-1:0] cnt = 'd0;
reg clear_fifo_hold = 1'b0;
always @(posedge clk) begin
// Latch FIFO clear
if (clear_fifo) begin
clear_fifo_hold <= 1'b1;
end
// State machine
case (state)
// Wait in idle state until either a configuration FIFO clear is requested
// or
S_IDLE: begin
cnt <= 1;
if (clear_fifo_hold) begin
state <= S_CLEAR_FIFO;
end else if (s_axis_data_tvalid) begin
// Note: Only update cyclic prefix length and fft size if new values are available
if (cp_len_fifo_out_tvalid) begin
cp_len_reg <= cp_len_fifo_out_tdata;
end
fft_size_reg <= fft_size;
state <= S_CONFIG;
end
end
S_CONFIG: begin
if (cp_len_reg > 0) begin
state <= S_CYCLIC_PREFIX;
end else if (fft_size_reg > 0) begin
state <= S_OFDM_SYMBOL;
end else begin
state <= S_IDLE;
end
end
S_CYCLIC_PREFIX : begin
if (s_axis_data_tvalid & s_axis_data_tready) begin
cnt <= cnt + 1;
if (cnt >= cp_len_reg) begin
cnt <= 1;
if (fft_size_reg > 0) begin
state <= S_OFDM_SYMBOL;
end else begin
state <= S_IDLE;
end
end
end
end
S_OFDM_SYMBOL : begin
if (s_axis_data_tvalid & s_axis_data_tready) begin
cnt <= cnt + 1;
if (cnt >= fft_size_reg) begin
cnt <= 1;
state <= S_IDLE;
end
end
end
S_CLEAR_FIFO : begin
clear_fifo_hold <= 1'b0;
cp_len_reg <= DEFAULT_CP_LEN;
state <= S_IDLE;
end
default : state <= S_IDLE;
endcase
if (reset) begin
clear_fifo_hold <= 1'b0;
cp_len_reg <= DEFAULT_CP_LEN;
cnt <= 1;
state <= S_IDLE;
end
end
assign m_axis_data_tdata = s_axis_data_tdata;
assign m_axis_data_tuser = s_axis_data_tuser;
assign m_axis_data_tlast = (SET_TLAST == 0) ? s_axis_data_tlast : (state == S_OFDM_SYMBOL) & (cnt >= fft_size_reg);
assign m_axis_data_tvalid = (state == S_IDLE) ? 1'b0 :
(state == S_CYCLIC_PREFIX) ? 1'b0 :
(state == S_OFDM_SYMBOL) ? s_axis_data_tvalid :
(state == S_CLEAR_FIFO) ? 1'b0 :
/* Else */ 1'b0;
assign s_axis_data_tready = (state == S_IDLE) ? 1'b0 :
(state == S_CYCLIC_PREFIX) ? 1'b1 :
(state == S_OFDM_SYMBOL) ? m_axis_data_tready :
(state == S_CLEAR_FIFO) ? 1'b0 :
/* Else */ 1'b0;
endmodule
`default_nettype wire

View File

@ -0,0 +1,305 @@
//
// Copyright 2024 Ettus Research, a National Instruments Brand
//
// SPDX-License-Identifier: LGPL-3.0-or-later
//
// Module: noc_shell_ofdm
//
// Description:
//
// This is a tool-generated NoC-shell for the OFDM block.
// See the RFNoC specification for more information about NoC shells.
//
// Parameters:
//
// THIS_PORTID : Control crossbar port to which this block is connected
// CHDR_W : AXIS-CHDR data bus width
// MTU : Maximum transmission unit (i.e., maximum packet size in
// CHDR words is 2**MTU).
//
`default_nettype none
module noc_shell_ofdm #(
parameter [9:0] THIS_PORTID = 10'd0,
parameter CHDR_W = 64,
parameter [5:0] MTU = 10,
parameter NUM_PORTS = 2
) (
//---------------------
// Framework Interface
//---------------------
// RFNoC Framework Clocks
input wire rfnoc_chdr_clk,
input wire rfnoc_ctrl_clk,
input wire ce_clk,
// NoC Shell Generated Resets
output wire rfnoc_chdr_rst,
output wire rfnoc_ctrl_rst,
output wire ce_rst,
// RFNoC Backend Interface
input wire [511:0] rfnoc_core_config,
output wire [511:0] rfnoc_core_status,
// AXIS-CHDR Input Ports (from framework)
input wire [(0+NUM_PORTS)*CHDR_W-1:0] s_rfnoc_chdr_tdata,
input wire [(0+NUM_PORTS)-1:0] s_rfnoc_chdr_tlast,
input wire [(0+NUM_PORTS)-1:0] s_rfnoc_chdr_tvalid,
output wire [(0+NUM_PORTS)-1:0] s_rfnoc_chdr_tready,
// AXIS-CHDR Output Ports (to framework)
output wire [(0+NUM_PORTS)*CHDR_W-1:0] m_rfnoc_chdr_tdata,
output wire [(0+NUM_PORTS)-1:0] m_rfnoc_chdr_tlast,
output wire [(0+NUM_PORTS)-1:0] m_rfnoc_chdr_tvalid,
input wire [(0+NUM_PORTS)-1:0] m_rfnoc_chdr_tready,
// AXIS-Ctrl Control Input Port (from framework)
input wire [31:0] s_rfnoc_ctrl_tdata,
input wire s_rfnoc_ctrl_tlast,
input wire s_rfnoc_ctrl_tvalid,
output wire s_rfnoc_ctrl_tready,
// AXIS-Ctrl Control Output Port (to framework)
output wire [31:0] m_rfnoc_ctrl_tdata,
output wire m_rfnoc_ctrl_tlast,
output wire m_rfnoc_ctrl_tvalid,
input wire m_rfnoc_ctrl_tready,
//---------------------
// Client Interface
//---------------------
// CtrlPort Clock and Reset
output wire ctrlport_clk,
output wire ctrlport_rst,
// CtrlPort Master
output wire m_ctrlport_req_wr,
output wire m_ctrlport_req_rd,
output wire [19:0] m_ctrlport_req_addr,
output wire [31:0] m_ctrlport_req_data,
input wire m_ctrlport_resp_ack,
input wire [31:0] m_ctrlport_resp_data,
// AXI-Stream Data Clock and Reset
output wire axis_data_clk,
output wire axis_data_rst,
// Data Stream to User Logic: in
output wire [NUM_PORTS*32*1-1:0] m_in_axis_tdata,
output wire [NUM_PORTS*1-1:0] m_in_axis_tkeep,
output wire [NUM_PORTS-1:0] m_in_axis_tlast,
output wire [NUM_PORTS-1:0] m_in_axis_tvalid,
input wire [NUM_PORTS-1:0] m_in_axis_tready,
output wire [NUM_PORTS*64-1:0] m_in_axis_ttimestamp,
output wire [NUM_PORTS-1:0] m_in_axis_thas_time,
output wire [NUM_PORTS*16-1:0] m_in_axis_tlength,
output wire [NUM_PORTS-1:0] m_in_axis_teov,
output wire [NUM_PORTS-1:0] m_in_axis_teob,
// Data Stream from User Logic: out
input wire [NUM_PORTS*32*1-1:0] s_out_axis_tdata,
input wire [NUM_PORTS*1-1:0] s_out_axis_tkeep,
input wire [NUM_PORTS-1:0] s_out_axis_tlast,
input wire [NUM_PORTS-1:0] s_out_axis_tvalid,
output wire [NUM_PORTS-1:0] s_out_axis_tready,
input wire [NUM_PORTS*64-1:0] s_out_axis_ttimestamp,
input wire [NUM_PORTS-1:0] s_out_axis_thas_time,
input wire [NUM_PORTS*16-1:0] s_out_axis_tlength,
input wire [NUM_PORTS-1:0] s_out_axis_teov,
input wire [NUM_PORTS-1:0] s_out_axis_teob
);
//---------------------------------------------------------------------------
// Backend Interface
//---------------------------------------------------------------------------
wire data_i_flush_en;
wire [31:0] data_i_flush_timeout;
wire [63:0] data_i_flush_active;
wire [63:0] data_i_flush_done;
wire data_o_flush_en;
wire [31:0] data_o_flush_timeout;
wire [63:0] data_o_flush_active;
wire [63:0] data_o_flush_done;
backend_iface #(
.NOC_ID (32'h0FD30000),
.NUM_DATA_I (0+NUM_PORTS),
.NUM_DATA_O (0+NUM_PORTS),
.CTRL_FIFOSIZE ($clog2(32)),
.MTU (MTU)
) backend_iface_i (
.rfnoc_chdr_clk (rfnoc_chdr_clk),
.rfnoc_chdr_rst (rfnoc_chdr_rst),
.rfnoc_ctrl_clk (rfnoc_ctrl_clk),
.rfnoc_ctrl_rst (rfnoc_ctrl_rst),
.rfnoc_core_config (rfnoc_core_config),
.rfnoc_core_status (rfnoc_core_status),
.data_i_flush_en (data_i_flush_en),
.data_i_flush_timeout (data_i_flush_timeout),
.data_i_flush_active (data_i_flush_active),
.data_i_flush_done (data_i_flush_done),
.data_o_flush_en (data_o_flush_en),
.data_o_flush_timeout (data_o_flush_timeout),
.data_o_flush_active (data_o_flush_active),
.data_o_flush_done (data_o_flush_done)
);
//---------------------------------------------------------------------------
// Reset Generation
//---------------------------------------------------------------------------
wire ce_rst_pulse;
pulse_synchronizer #(.MODE ("POSEDGE")) pulse_synchronizer_ce (
.clk_a(rfnoc_chdr_clk), .rst_a(1'b0), .pulse_a (rfnoc_chdr_rst), .busy_a (),
.clk_b(ce_clk), .pulse_b (ce_rst_pulse)
);
pulse_stretch_min #(.LENGTH(32)) pulse_stretch_min_ce (
.clk(ce_clk), .rst(1'b0),
.pulse_in(ce_rst_pulse), .pulse_out(ce_rst)
);
//---------------------------------------------------------------------------
// Control Path
//---------------------------------------------------------------------------
assign ctrlport_clk = ce_clk;
assign ctrlport_rst = ce_rst;
ctrlport_endpoint #(
.THIS_PORTID (THIS_PORTID),
.SYNC_CLKS (0),
.AXIS_CTRL_MST_EN (0),
.AXIS_CTRL_SLV_EN (1),
.SLAVE_FIFO_SIZE ($clog2(32))
) ctrlport_endpoint_i (
.rfnoc_ctrl_clk (rfnoc_ctrl_clk),
.rfnoc_ctrl_rst (rfnoc_ctrl_rst),
.ctrlport_clk (ctrlport_clk),
.ctrlport_rst (ctrlport_rst),
.s_rfnoc_ctrl_tdata (s_rfnoc_ctrl_tdata),
.s_rfnoc_ctrl_tlast (s_rfnoc_ctrl_tlast),
.s_rfnoc_ctrl_tvalid (s_rfnoc_ctrl_tvalid),
.s_rfnoc_ctrl_tready (s_rfnoc_ctrl_tready),
.m_rfnoc_ctrl_tdata (m_rfnoc_ctrl_tdata),
.m_rfnoc_ctrl_tlast (m_rfnoc_ctrl_tlast),
.m_rfnoc_ctrl_tvalid (m_rfnoc_ctrl_tvalid),
.m_rfnoc_ctrl_tready (m_rfnoc_ctrl_tready),
.m_ctrlport_req_wr (m_ctrlport_req_wr),
.m_ctrlport_req_rd (m_ctrlport_req_rd),
.m_ctrlport_req_addr (m_ctrlport_req_addr),
.m_ctrlport_req_data (m_ctrlport_req_data),
.m_ctrlport_req_byte_en (),
.m_ctrlport_req_has_time (),
.m_ctrlport_req_time (),
.m_ctrlport_resp_ack (m_ctrlport_resp_ack),
.m_ctrlport_resp_status (2'b0),
.m_ctrlport_resp_data (m_ctrlport_resp_data),
.s_ctrlport_req_wr (1'b0),
.s_ctrlport_req_rd (1'b0),
.s_ctrlport_req_addr (20'b0),
.s_ctrlport_req_portid (10'b0),
.s_ctrlport_req_rem_epid (16'b0),
.s_ctrlport_req_rem_portid (10'b0),
.s_ctrlport_req_data (32'b0),
.s_ctrlport_req_byte_en (4'hF),
.s_ctrlport_req_has_time (1'b0),
.s_ctrlport_req_time (64'b0),
.s_ctrlport_resp_ack (),
.s_ctrlport_resp_status (),
.s_ctrlport_resp_data ()
);
//---------------------------------------------------------------------------
// Data Path
//---------------------------------------------------------------------------
genvar i;
assign axis_data_clk = ce_clk;
assign axis_data_rst = ce_rst;
//---------------------
// Input Data Paths
//---------------------
for (i = 0; i < NUM_PORTS; i = i + 1) begin: gen_input_in
chdr_to_axis_data #(
.CHDR_W (CHDR_W),
.ITEM_W (32),
.NIPC (1),
.SYNC_CLKS (0),
.INFO_FIFO_SIZE ($clog2(32)),
.PYLD_FIFO_SIZE ($clog2(32))
) chdr_to_axis_data_in_in (
.axis_chdr_clk (rfnoc_chdr_clk),
.axis_chdr_rst (rfnoc_chdr_rst),
.axis_data_clk (axis_data_clk),
.axis_data_rst (axis_data_rst),
.s_axis_chdr_tdata (s_rfnoc_chdr_tdata[((0+i)*CHDR_W)+:CHDR_W]),
.s_axis_chdr_tlast (s_rfnoc_chdr_tlast[0+i]),
.s_axis_chdr_tvalid (s_rfnoc_chdr_tvalid[0+i]),
.s_axis_chdr_tready (s_rfnoc_chdr_tready[0+i]),
.m_axis_tdata (m_in_axis_tdata[(32*1)*i+:(32*1)]),
.m_axis_tkeep (m_in_axis_tkeep[1*i+:1]),
.m_axis_tlast (m_in_axis_tlast[i]),
.m_axis_tvalid (m_in_axis_tvalid[i]),
.m_axis_tready (m_in_axis_tready[i]),
.m_axis_ttimestamp (m_in_axis_ttimestamp[64*i+:64]),
.m_axis_thas_time (m_in_axis_thas_time[i]),
.m_axis_tlength (m_in_axis_tlength[16*i+:16]),
.m_axis_teov (m_in_axis_teov[i]),
.m_axis_teob (m_in_axis_teob[i]),
.flush_en (data_i_flush_en),
.flush_timeout (data_i_flush_timeout),
.flush_active (data_i_flush_active[0+i]),
.flush_done (data_i_flush_done[0+i])
);
end
//---------------------
// Output Data Paths
//---------------------
for (i = 0; i < NUM_PORTS; i = i + 1) begin: gen_output_out
axis_data_to_chdr #(
.CHDR_W (CHDR_W),
.ITEM_W (32),
.NIPC (1),
.SYNC_CLKS (0),
.INFO_FIFO_SIZE ($clog2(32)),
.PYLD_FIFO_SIZE ($clog2(2**MTU)),
.MTU (MTU),
.SIDEBAND_AT_END (1)
) axis_data_to_chdr_out_out (
.axis_chdr_clk (rfnoc_chdr_clk),
.axis_chdr_rst (rfnoc_chdr_rst),
.axis_data_clk (axis_data_clk),
.axis_data_rst (axis_data_rst),
.m_axis_chdr_tdata (m_rfnoc_chdr_tdata[(0+i)*CHDR_W+:CHDR_W]),
.m_axis_chdr_tlast (m_rfnoc_chdr_tlast[0+i]),
.m_axis_chdr_tvalid (m_rfnoc_chdr_tvalid[0+i]),
.m_axis_chdr_tready (m_rfnoc_chdr_tready[0+i]),
.s_axis_tdata (s_out_axis_tdata[(32*1)*i+:(32*1)]),
.s_axis_tkeep (s_out_axis_tkeep[1*i+:1]),
.s_axis_tlast (s_out_axis_tlast[i]),
.s_axis_tvalid (s_out_axis_tvalid[i]),
.s_axis_tready (s_out_axis_tready[i]),
.s_axis_ttimestamp (s_out_axis_ttimestamp[64*i+:64]),
.s_axis_thas_time (s_out_axis_thas_time[i]),
.s_axis_tlength (s_out_axis_tlength[16*i+:16]),
.s_axis_teov (s_out_axis_teov[i]),
.s_axis_teob (s_out_axis_teob[i]),
.flush_en (data_o_flush_en),
.flush_timeout (data_o_flush_timeout),
.flush_active (data_o_flush_active[0+i]),
.flush_done (data_o_flush_done[0+i])
);
end
endmodule // noc_shell_ofdm
`default_nettype wire

View File

@ -0,0 +1,963 @@
//
// Copyright 2024 Ettus Research, a National Instruments Brand
//
// SPDX-License-Identifier: LGPL-3.0-or-later
//
// Module: rfnoc_block_ofdm
//
// Description:
//
// FFT/IFFT plus cyclic prefix insertion/removal.
//
// User Parameters:
//
// THIS_PORTID : Control crossbar port to which this block is connected
// CHDR_W : AXIS-CHDR data bus width
// MTU : Log2 of maximum transmission unit
// NUM_PORTS : Number of channels
// MAX_FFT_SIZE_LOG2 : Log2 of maximum configurable FFT size
// MAX_CP_LEN_LOG2 : Log2 of maximum cyclic prefix length
// MAX_CP_LIST_LEN_INS_LOG2 : Log2 of max length of cyclic prefix insertion list
// MAX_CP_LIST_LEN_REM_LOG2 : Log2 of max length of cyclic prefix removal list
// CP_INSERTION_REPEAT : Enable (1) or disable (0) CP insertion list FIFO loopback
// CP_REMOVAL_REPEAT : Enable (1) or disable (0) CP removal list FIFO loopback
//
`default_nettype none
module rfnoc_block_ofdm #(
logic [9:0] THIS_PORTID = 10'd0,
int CHDR_W = 64,
logic [5:0] MTU = 6'd10,
int NUM_PORTS = 2,
int MAX_FFT_SIZE_LOG2 = 12,
int MAX_CP_LEN_LOG2 = 12,
int MAX_CP_LIST_LEN_INS_LOG2 = 5,
int MAX_CP_LIST_LEN_REM_LOG2 = 5,
int CP_INSERTION_REPEAT = 1,
int CP_REMOVAL_REPEAT = 1
)(
// RFNoC Framework Clocks and Resets
input wire rfnoc_chdr_clk,
input wire rfnoc_ctrl_clk,
input wire ce_clk,
// RFNoC Backend Interface
input wire [511:0] rfnoc_core_config,
output wire [511:0] rfnoc_core_status,
// AXIS-CHDR Input Ports (from framework)
input wire [(0+NUM_PORTS)*CHDR_W-1:0] s_rfnoc_chdr_tdata,
input wire [(0+NUM_PORTS)-1:0] s_rfnoc_chdr_tlast,
input wire [(0+NUM_PORTS)-1:0] s_rfnoc_chdr_tvalid,
output wire [(0+NUM_PORTS)-1:0] s_rfnoc_chdr_tready,
// AXIS-CHDR Output Ports (to framework)
output wire [(0+NUM_PORTS)*CHDR_W-1:0] m_rfnoc_chdr_tdata,
output wire [(0+NUM_PORTS)-1:0] m_rfnoc_chdr_tlast,
output wire [(0+NUM_PORTS)-1:0] m_rfnoc_chdr_tvalid,
input wire [(0+NUM_PORTS)-1:0] m_rfnoc_chdr_tready,
// AXIS-Ctrl Input Port (from framework)
input wire [31:0] s_rfnoc_ctrl_tdata,
input wire s_rfnoc_ctrl_tlast,
input wire s_rfnoc_ctrl_tvalid,
output wire s_rfnoc_ctrl_tready,
// AXIS-Ctrl Output Port (to framework)
output wire [31:0] m_rfnoc_ctrl_tdata,
output wire m_rfnoc_ctrl_tlast,
output wire m_rfnoc_ctrl_tvalid,
input wire m_rfnoc_ctrl_tready
);
//---------------------------------------------------------------------------
// FFT Configuration Interface Constants
//---------------------------------------------------------------------------
localparam int MAX_FFT_SIZE = 2**MAX_FFT_SIZE_LOG2;
localparam int FFT_SCALE_PAD_W =
MAX_FFT_SIZE == 4096 ? 3 :
MAX_FFT_SIZE == 8192 ? 1 :
MAX_FFT_SIZE == 16384 ? 1 :
MAX_FFT_SIZE == 32768 ? 7 :
MAX_FFT_SIZE == 65536 ? 7 : -1;
localparam int FFT_SCALE_W =
MAX_FFT_SIZE == 4096 ? 12 :
MAX_FFT_SIZE == 8192 ? 14 :
MAX_FFT_SIZE == 16384 ? 14 :
MAX_FFT_SIZE == 32768 ? 16 :
MAX_FFT_SIZE == 65536 ? 16 : -1;
localparam int FFT_FWD_INV_W = 1;
localparam int FFT_CP_LEN_PAD_W =
MAX_FFT_SIZE == 4096 ? 4 :
MAX_FFT_SIZE == 8192 ? 3 :
MAX_FFT_SIZE == 16384 ? 2 :
MAX_FFT_SIZE == 32768 ? 1 :
MAX_FFT_SIZE == 65536 ? 0 : -1;
localparam int FFT_CP_LEN_W =
MAX_FFT_SIZE == 4096 ? 12 :
MAX_FFT_SIZE == 8192 ? 13 :
MAX_FFT_SIZE == 16384 ? 14 :
MAX_FFT_SIZE == 32768 ? 15 :
MAX_FFT_SIZE == 65536 ? 16 : -1;
localparam int FFT_NFFT_PAD_W = 3;
localparam int FFT_NFFT_W = 5;
localparam int FFT_CONFIG_W =
FFT_SCALE_PAD_W + FFT_SCALE_W + FFT_FWD_INV_W +
FFT_CP_LEN_PAD_W + FFT_CP_LEN_W +
FFT_NFFT_PAD_W + FFT_NFFT_W;
// Use conservative 1/N scaling by default
localparam [FFT_SCALE_W-1:0] DEFAULT_FFT_SCALING = {FFT_SCALE_W/2{2'b10}};
//---------------------------------------------------------------------------
// Signal Declarations
//---------------------------------------------------------------------------
// Clocks and Resets
wire ctrlport_clk;
wire ctrlport_rst;
wire ctrlport_rst_noc_shell;
wire axis_data_clk;
wire axis_data_rst;
wire axis_data_rst_noc_shell;
// CtrlPort Master
wire m_ctrlport_req_wr;
wire m_ctrlport_req_rd;
wire [19:0] m_ctrlport_req_addr;
wire [31:0] m_ctrlport_req_data;
reg m_ctrlport_resp_ack = 1'b0;
reg [31:0] m_ctrlport_resp_data;
// Data Stream to User Logic: in
wire [NUM_PORTS*32*1-1:0] m_in_axis_tdata;
wire [NUM_PORTS*1-1:0] m_in_axis_tkeep;
wire [NUM_PORTS-1:0] m_in_axis_tlast;
wire [NUM_PORTS-1:0] m_in_axis_tvalid;
wire [NUM_PORTS-1:0] m_in_axis_tready;
wire [NUM_PORTS*64-1:0] m_in_axis_ttimestamp;
wire [NUM_PORTS-1:0] m_in_axis_thas_time;
wire [NUM_PORTS*16-1:0] m_in_axis_tlength;
wire [NUM_PORTS-1:0] m_in_axis_teov;
wire [NUM_PORTS-1:0] m_in_axis_teob;
// Data Stream from User Logic: out
wire [NUM_PORTS*32*1-1:0] s_out_axis_tdata;
wire [NUM_PORTS*1-1:0] s_out_axis_tkeep;
wire [NUM_PORTS-1:0] s_out_axis_tlast;
wire [NUM_PORTS-1:0] s_out_axis_tvalid;
wire [NUM_PORTS-1:0] s_out_axis_tready;
wire [NUM_PORTS*64-1:0] s_out_axis_ttimestamp;
wire [NUM_PORTS-1:0] s_out_axis_thas_time;
wire [NUM_PORTS*16-1:0] s_out_axis_tlength;
wire [NUM_PORTS-1:0] s_out_axis_teov;
wire [NUM_PORTS-1:0] s_out_axis_teob;
//---------------------------------------------------------------------------
// NoC Shell
//---------------------------------------------------------------------------
noc_shell_ofdm #(
.CHDR_W (CHDR_W),
.THIS_PORTID (THIS_PORTID),
.MTU (MTU),
.NUM_PORTS (NUM_PORTS)
) noc_shell_ofdm_i (
//---------------------
// Framework Interface
//---------------------
// Clock Inputs
.rfnoc_chdr_clk (rfnoc_chdr_clk),
.rfnoc_ctrl_clk (rfnoc_ctrl_clk),
.ce_clk (ce_clk),
// Reset Outputs
.rfnoc_chdr_rst (),
.rfnoc_ctrl_rst (),
.ce_rst (),
// RFNoC Backend Interface
.rfnoc_core_config (rfnoc_core_config),
.rfnoc_core_status (rfnoc_core_status),
// CHDR Input Ports (from framework)
.s_rfnoc_chdr_tdata (s_rfnoc_chdr_tdata),
.s_rfnoc_chdr_tlast (s_rfnoc_chdr_tlast),
.s_rfnoc_chdr_tvalid (s_rfnoc_chdr_tvalid),
.s_rfnoc_chdr_tready (s_rfnoc_chdr_tready),
// CHDR Output Ports (to framework)
.m_rfnoc_chdr_tdata (m_rfnoc_chdr_tdata),
.m_rfnoc_chdr_tlast (m_rfnoc_chdr_tlast),
.m_rfnoc_chdr_tvalid (m_rfnoc_chdr_tvalid),
.m_rfnoc_chdr_tready (m_rfnoc_chdr_tready),
// AXIS-Ctrl Input Port (from framework)
.s_rfnoc_ctrl_tdata (s_rfnoc_ctrl_tdata),
.s_rfnoc_ctrl_tlast (s_rfnoc_ctrl_tlast),
.s_rfnoc_ctrl_tvalid (s_rfnoc_ctrl_tvalid),
.s_rfnoc_ctrl_tready (s_rfnoc_ctrl_tready),
// AXIS-Ctrl Output Port (to framework)
.m_rfnoc_ctrl_tdata (m_rfnoc_ctrl_tdata),
.m_rfnoc_ctrl_tlast (m_rfnoc_ctrl_tlast),
.m_rfnoc_ctrl_tvalid (m_rfnoc_ctrl_tvalid),
.m_rfnoc_ctrl_tready (m_rfnoc_ctrl_tready),
//---------------------
// Client Interface
//---------------------
// CtrlPort Clock and Reset
.ctrlport_clk (ctrlport_clk),
.ctrlport_rst (ctrlport_rst_noc_shell),
// CtrlPort Master
.m_ctrlport_req_wr (m_ctrlport_req_wr),
.m_ctrlport_req_rd (m_ctrlport_req_rd),
.m_ctrlport_req_addr (m_ctrlport_req_addr),
.m_ctrlport_req_data (m_ctrlport_req_data),
.m_ctrlport_resp_ack (m_ctrlport_resp_ack),
.m_ctrlport_resp_data (m_ctrlport_resp_data),
// AXI-Stream Clock and Reset
.axis_data_clk (axis_data_clk),
.axis_data_rst (axis_data_rst_noc_shell),
// Data Stream to User Logic: in
.m_in_axis_tdata (m_in_axis_tdata),
.m_in_axis_tkeep (m_in_axis_tkeep),
.m_in_axis_tlast (m_in_axis_tlast),
.m_in_axis_tvalid (m_in_axis_tvalid),
.m_in_axis_tready (m_in_axis_tready),
.m_in_axis_ttimestamp (m_in_axis_ttimestamp),
.m_in_axis_thas_time (m_in_axis_thas_time),
.m_in_axis_tlength (m_in_axis_tlength),
.m_in_axis_teov (m_in_axis_teov),
.m_in_axis_teob (m_in_axis_teob),
// Data Stream from User Logic: out
.s_out_axis_tdata (s_out_axis_tdata),
.s_out_axis_tkeep (s_out_axis_tkeep),
.s_out_axis_tlast (s_out_axis_tlast),
.s_out_axis_tvalid (s_out_axis_tvalid),
.s_out_axis_tready (s_out_axis_tready),
.s_out_axis_ttimestamp (s_out_axis_ttimestamp),
.s_out_axis_thas_time (s_out_axis_thas_time),
.s_out_axis_tlength (s_out_axis_tlength),
.s_out_axis_teov (s_out_axis_teov),
.s_out_axis_teob (s_out_axis_teob)
);
//---------------------------------------------------------------------------
// Control Registers
//---------------------------------------------------------------------------
// FFT Direction
localparam [0:0] FFT_REVERSE = 0;
localparam [0:0] FFT_FORWARD = 1;
localparam FFT_SIZE_WIDTH = MAX_FFT_SIZE_LOG2+1;
localparam CP_LEN_WIDTH = MAX_CP_LEN_LOG2+1;
// TODO: Add compat register
// Register addresses, multiplied by 4 for 32-bit word alignment
localparam REG_USER_RESET_ADDR = 0; // Any write to this reg forces a reset for 16 clock cycles.
localparam REG_FFT_SIZE_LOG2_ADDR = 8; // Log2 of FFT size
localparam REG_FFT_SCALING_ADDR = 9; // FFT scaling word, see Xilinx documentation
localparam REG_FFT_DIRECTION_ADDR = 10; // FFT or IFFT
localparam REG_FFT_COMMIT_ADDR = 11; // Commit the currently configured settings to the FFT IP
localparam REG_CP_INSERTION_CP_LEN_ADDR = 16; // Cyclic Prefix (CP) length (insertion)
localparam REG_CP_INSERTION_CP_LEN_FIFO_LOAD_ADDR = 17; // Any write to this reg will load a length into the cyclic prefix insertion FIFO
localparam REG_CP_INSERTION_CP_LEN_FIFO_CLR_ADDR = 18; // Any write to this reg will clear the cyclic prefix insertion FIFO
localparam REG_CP_INSERTION_CP_LEN_FIFO_OCC_ADDR = 19; // Read only, fullness of cyclic prefix insertion FIFO
localparam REG_CP_REMOVAL_CP_LEN_ADDR = 32; // Cyclic Prefix (CP) length (removal)
localparam REG_CP_REMOVAL_CP_LEN_FIFO_LOAD_ADDR = 33; // Any write to this reg will load a length into the cyclic prefix removal FIFO
localparam REG_CP_REMOVAL_CP_LEN_FIFO_CLR_ADDR = 34; // Any write to this reg will clear the cyclic prefix removal FIFO
localparam REG_CP_REMOVAL_CP_LEN_FIFO_OCC_ADDR = 35; // Read only, fullness of cyclic prefix removal config FIFO
localparam REG_USER_RESET_WIDTH = 1;
localparam REG_FFT_SIZE_LOG2_WIDTH = FFT_NFFT_W;
localparam REG_FFT_SCALING_WIDTH = FFT_SCALE_W;
localparam REG_FFT_DIRECTION_WIDTH = FFT_FWD_INV_W;
localparam REG_CP_INSERTION_CP_LEN_WIDTH = CP_LEN_WIDTH;
localparam REG_CP_REMOVAL_CP_LEN_WIDTH = CP_LEN_WIDTH;
localparam REG_CP_INSERTION_CP_LEN_FIFO_LOAD_WIDTH = 1;
localparam REG_CP_INSERTION_CP_LEN_FIFO_CLR_WIDTH = 1;
localparam REG_CP_INSERTION_CP_LEN_FIFO_OCC_WIDTH = 16;
localparam REG_CP_REMOVAL_CP_LEN_FIFO_LOAD_WIDTH = 1;
localparam REG_CP_REMOVAL_CP_LEN_FIFO_CLR_WIDTH = 1;
localparam REG_CP_REMOVAL_CP_LEN_FIFO_OCC_WIDTH = 16;
localparam DEFAULT_FFT_SIZE_LOG2 = 12; // 2^12 = 4096
localparam DEFAULT_FFT_DIRECTION = FFT_REVERSE; // Set for FFT
localparam DEFAULT_CP_LEN = 0;
reg [REG_USER_RESET_WIDTH-1:0] reg_user_reset = 1'b0;
reg [REG_FFT_SIZE_LOG2_WIDTH-1:0] reg_fft_size_log2 = DEFAULT_FFT_SIZE_LOG2;
reg [REG_FFT_SCALING_WIDTH-1:0] reg_fft_scaling = DEFAULT_FFT_SCALING;
reg [REG_FFT_DIRECTION_WIDTH-1:0] reg_fft_direction = DEFAULT_FFT_DIRECTION;
reg reg_fft_commit = 1'b0;
reg [REG_CP_INSERTION_CP_LEN_WIDTH-1:0] reg_cp_insertion_len = DEFAULT_CP_LEN;
reg [REG_CP_REMOVAL_CP_LEN_WIDTH-1:0] reg_cp_removal_len = DEFAULT_CP_LEN;
reg [REG_CP_INSERTION_CP_LEN_FIFO_LOAD_WIDTH-1:0] reg_cp_insertion_cp_len_fifo_load = 1'b0;
reg [REG_CP_INSERTION_CP_LEN_FIFO_CLR_WIDTH -1:0] reg_cp_insertion_cp_len_fifo_clr = 1'b0;
reg [REG_CP_REMOVAL_CP_LEN_FIFO_LOAD_WIDTH-1:0] reg_cp_removal_cp_len_fifo_load = 1'b0;
reg [REG_CP_REMOVAL_CP_LEN_FIFO_CLR_WIDTH -1:0] reg_cp_removal_cp_len_fifo_clr = 1'b0;
wire [REG_CP_INSERTION_CP_LEN_FIFO_OCC_WIDTH -1:0] reg_cp_insertion_cp_len_fifo_occupied;
wire [REG_CP_REMOVAL_CP_LEN_FIFO_OCC_WIDTH -1:0] reg_cp_removal_cp_len_fifo_occupied;
wire reg_fft_commit_next;
wire [17:0] m_ctrlport_req_addr_aligned = m_ctrlport_req_addr[19:2];
always @(posedge ctrlport_clk) begin
// Default assignment
m_ctrlport_resp_ack <= 0;
// Always clear these regs after being set
reg_user_reset <= 1'b0;
reg_cp_insertion_cp_len_fifo_load <= 1'b0;
reg_cp_insertion_cp_len_fifo_clr <= 1'b0;
reg_cp_removal_cp_len_fifo_load <= 1'b0;
reg_cp_removal_cp_len_fifo_clr <= 1'b0;
reg_fft_commit <= reg_fft_commit_next;
// Read user registers
if (m_ctrlport_req_rd) begin // Read request
m_ctrlport_resp_ack <= 1; // Always immediately ack
m_ctrlport_resp_data <= 0; // Zero out by default
case (m_ctrlport_req_addr_aligned)
REG_USER_RESET_ADDR: m_ctrlport_resp_data <= reg_user_reset;
REG_FFT_SIZE_LOG2_ADDR: m_ctrlport_resp_data <= reg_fft_size_log2;
REG_FFT_SCALING_ADDR: m_ctrlport_resp_data <= reg_fft_scaling;
REG_FFT_DIRECTION_ADDR: m_ctrlport_resp_data <= reg_fft_direction;
REG_CP_INSERTION_CP_LEN_ADDR: m_ctrlport_resp_data <= reg_cp_insertion_len;
REG_CP_REMOVAL_CP_LEN_ADDR: m_ctrlport_resp_data <= reg_cp_removal_len;
REG_CP_INSERTION_CP_LEN_FIFO_LOAD_ADDR: m_ctrlport_resp_data <= reg_cp_insertion_cp_len_fifo_load;
REG_CP_INSERTION_CP_LEN_FIFO_CLR_ADDR: m_ctrlport_resp_data <= reg_cp_insertion_cp_len_fifo_clr;
REG_CP_INSERTION_CP_LEN_FIFO_OCC_ADDR: m_ctrlport_resp_data <= reg_cp_insertion_cp_len_fifo_occupied;
REG_CP_REMOVAL_CP_LEN_FIFO_LOAD_ADDR: m_ctrlport_resp_data <= reg_cp_removal_cp_len_fifo_load;
REG_CP_REMOVAL_CP_LEN_FIFO_CLR_ADDR: m_ctrlport_resp_data <= reg_cp_removal_cp_len_fifo_clr;
REG_CP_REMOVAL_CP_LEN_FIFO_OCC_ADDR: m_ctrlport_resp_data <= reg_cp_removal_cp_len_fifo_occupied;
default: m_ctrlport_resp_data <= 32'h0BAD_C0DE;
endcase
end
// Write user registers
if (m_ctrlport_req_wr) begin // Write request
m_ctrlport_resp_ack <= 1; // Always immediately ack
case (m_ctrlport_req_addr_aligned)
REG_USER_RESET_ADDR: reg_user_reset <= 1'b1; // Strobe, i.e. will be cleared on the next clock cycle
REG_FFT_SIZE_LOG2_ADDR: reg_fft_size_log2 <= m_ctrlport_req_data[REG_FFT_SIZE_LOG2_WIDTH-1:0];
REG_FFT_SCALING_ADDR: reg_fft_scaling <= m_ctrlport_req_data[REG_FFT_SCALING_WIDTH-1:0];
REG_FFT_DIRECTION_ADDR: reg_fft_direction <= m_ctrlport_req_data[REG_FFT_DIRECTION_WIDTH-1:0];
REG_FFT_COMMIT_ADDR: reg_fft_commit <= 1'b1;
REG_CP_INSERTION_CP_LEN_ADDR: reg_cp_insertion_len <= m_ctrlport_req_data[REG_CP_INSERTION_CP_LEN_WIDTH-1:0];
REG_CP_REMOVAL_CP_LEN_ADDR: reg_cp_removal_len <= m_ctrlport_req_data[REG_CP_REMOVAL_CP_LEN_WIDTH-1:0];
REG_CP_INSERTION_CP_LEN_FIFO_LOAD_ADDR: reg_cp_insertion_cp_len_fifo_load <= 1'b1; // Strobe
REG_CP_INSERTION_CP_LEN_FIFO_CLR_ADDR: reg_cp_insertion_cp_len_fifo_clr <= 1'b1; // Strobe
REG_CP_REMOVAL_CP_LEN_FIFO_LOAD_ADDR: reg_cp_removal_cp_len_fifo_load <= 1'b1; // Strobe
REG_CP_REMOVAL_CP_LEN_FIFO_CLR_ADDR: reg_cp_removal_cp_len_fifo_clr <= 1'b1; // Strobe
REG_CP_INSERTION_CP_LEN_FIFO_OCC_ADDR: ; // Read only
endcase
end
if (ctrlport_rst) begin
m_ctrlport_resp_ack <= 1'b0;
reg_user_reset <= 1'b0;
reg_fft_size_log2 <= DEFAULT_FFT_SIZE_LOG2;
reg_fft_scaling <= DEFAULT_FFT_SCALING;
reg_fft_direction <= DEFAULT_FFT_DIRECTION;
reg_fft_commit <= 1'b0;
reg_cp_insertion_len <= DEFAULT_CP_LEN;
reg_cp_removal_len <= DEFAULT_CP_LEN;
reg_cp_insertion_cp_len_fifo_load <= 1'b0;
reg_cp_insertion_cp_len_fifo_clr <= 1'b0;
reg_cp_removal_cp_len_fifo_load <= 1'b0;
reg_cp_removal_cp_len_fifo_clr <= 1'b0;
end
end
//---------------------------------------------------------------------------
// Reset Logic
//---------------------------------------------------------------------------
localparam RESET_PULSE_LEN = 8;
localparam RESET_CNT_WIDTH = $clog2(RESET_PULSE_LEN);
localparam S_RESET_IDLE = 1'd0;
localparam S_RESET_ASSERT = 1'd1;
reg reset_state = S_RESET_ASSERT;
reg [RESET_CNT_WIDTH:0] user_reset_cnt = 'd0;
reg user_reset = 1'b1;
assign axis_data_rst = user_reset | axis_data_rst_noc_shell;
assign ctrlport_rst = user_reset | ctrlport_rst_noc_shell;
always @(posedge axis_data_clk) begin
case (reset_state)
S_RESET_IDLE : begin
user_reset_cnt <= 'd0;
user_reset <= 1'b0;
if (reg_user_reset) begin
user_reset <= 1'b1;
reset_state <= S_RESET_ASSERT;
end
end
S_RESET_ASSERT : begin
user_reset_cnt <= user_reset_cnt + 1;
if (user_reset_cnt == RESET_PULSE_LEN-1) begin
user_reset_cnt <= 'd0;
user_reset <= 1'b0;
reset_state <= S_RESET_IDLE;
end
end
endcase
if (axis_data_rst_noc_shell) begin
user_reset <= 1'b1;
user_reset_cnt <= 'd0;
reset_state <= S_RESET_ASSERT;
end
end
//---------------------------------------------------------------------------
// Packetization
//---------------------------------------------------------------------------
wire [NUM_PORTS*32*1-1:0] m_axis_user_tdata;
wire [NUM_PORTS-1:0] m_axis_user_teob;
wire [NUM_PORTS-1:0] m_axis_user_tlast;
wire [NUM_PORTS-1:0] m_axis_user_tvalid;
wire [NUM_PORTS-1:0] m_axis_user_tready;
wire [NUM_PORTS*32*1-1:0] s_axis_user_tdata;
wire [NUM_PORTS-1:0] s_axis_user_teob;
wire [NUM_PORTS-1:0] s_axis_user_teov;
wire [NUM_PORTS-1:0] s_axis_user_tlast;
wire [NUM_PORTS-1:0] s_axis_user_tvalid;
wire [NUM_PORTS-1:0] s_axis_user_tready;
for (genvar i = 0; i < NUM_PORTS; i = i + 1) begin : gen_packetize
axis_data_if_packetize #(
.WIDTH (32),
.CHDR_W (CHDR_W),
.SIDEBAND_FWD_FIFO_SIZE_LOG2 (1)) // Increase if using many small bursts
axis_data_if_packetize_inst (
.clk (axis_data_clk),
.reset (axis_data_rst),
.spp (12'd0), // Use the input packet size
.s_axis_tdata (m_in_axis_tdata[32*i +: 32]),
.s_axis_tlast (m_in_axis_tlast[i]),
.s_axis_tkeep (m_in_axis_tkeep[i]),
.s_axis_tvalid (m_in_axis_tvalid[i]),
.s_axis_tready (m_in_axis_tready[i]),
.s_axis_ttimestamp (m_in_axis_ttimestamp[64*i +: 64]),
.s_axis_thas_time (m_in_axis_thas_time[i]),
.s_axis_tlength (m_in_axis_tlength[16*i +: 16]),
.s_axis_teov (m_in_axis_teov[i]),
.s_axis_teob (m_in_axis_teob[i]),
.m_axis_tdata (s_out_axis_tdata[32*i +: 32]),
.m_axis_tkeep (s_out_axis_tkeep[i]),
.m_axis_tlast (s_out_axis_tlast[i]),
.m_axis_tvalid (s_out_axis_tvalid[i]),
.m_axis_tready (s_out_axis_tready[i]),
.m_axis_ttimestamp (s_out_axis_ttimestamp[64*i +: 64]),
.m_axis_thas_time (s_out_axis_thas_time[i]),
.m_axis_tlength (s_out_axis_tlength[16*i +: 16]),
.m_axis_teov (s_out_axis_teov[i]),
.m_axis_teob (s_out_axis_teob[i]),
.m_axis_user_tdata (m_axis_user_tdata[i*32 +: 32]),
.m_axis_user_tkeep (), // Unused
.m_axis_user_teob (m_axis_user_teob[i]),
.m_axis_user_teov (), // Unused
.m_axis_user_tlast (m_axis_user_tlast[i]),
.m_axis_user_tvalid (m_axis_user_tvalid[i]),
.m_axis_user_tready (m_axis_user_tready[i]),
.s_axis_user_tdata (s_axis_user_tdata[i*32 +: 32]),
.s_axis_user_tkeep (1'b1), // Keep all samples
.s_axis_user_teob (s_axis_user_teob[i]),
.s_axis_user_teov (s_axis_user_teov[i]),
.s_axis_user_tlast (s_axis_user_tlast[i]),
.s_axis_user_tvalid (s_axis_user_tvalid[i]),
.s_axis_user_tready (s_axis_user_tready[i])
);
end
// Combine input streams into one. This lets us run the FFT instances (one per channel)
// in lock-step by sharing valid/ready signals. Removes the need for multiple instances of
// FFT configuration logic as well.
wire [NUM_PORTS*32-1:0] m_axis_combine_tdata;
wire [NUM_PORTS-1:0] m_axis_combine_teob;
wire m_axis_combine_tlast;
wire m_axis_combine_tvalid;
wire m_axis_combine_tready;
axis_combine #(
.SIZE (NUM_PORTS),
.WIDTH (32),
.USER_WIDTH (1),
.FIFO_SIZE_LOG2 (0))
axis_combine_inst (
.clk (axis_data_clk),
.reset (axis_data_rst),
.s_axis_tdata (m_axis_user_tdata),
.s_axis_tuser (m_axis_user_teob),
.s_axis_tlast (m_axis_user_tlast),
.s_axis_tvalid (m_axis_user_tvalid),
.s_axis_tready (m_axis_user_tready),
.m_axis_tdata (m_axis_combine_tdata),
.m_axis_tuser (m_axis_combine_teob),
.m_axis_tlast (m_axis_combine_tlast),
.m_axis_tvalid (m_axis_combine_tvalid),
.m_axis_tready (m_axis_combine_tready)
);
//---------------------------------------------------------------------------
// FFT
//---------------------------------------------------------------------------
wire [NUM_PORTS*32-1:0] m_axis_cp_removal_tdata;
wire [NUM_PORTS-1:0] m_axis_cp_removal_teob;
wire [NUM_PORTS-1:0] m_axis_cp_removal_teov;
wire m_axis_cp_removal_tlast;
wire m_axis_cp_removal_tvalid;
wire m_axis_cp_removal_tready;
wire [FFT_CONFIG_W-1:0] s_axis_fft_config_tdata;
wire s_axis_fft_config_tvalid;
wire [NUM_PORTS-1:0] s_axis_fft_config_tready;
wire [NUM_PORTS*32-1:0] s_axis_fft_data_tdata;
wire s_axis_fft_data_tlast;
wire s_axis_fft_data_tvalid;
wire [NUM_PORTS-1:0] s_axis_fft_data_tready;
wire [NUM_PORTS*32-1:0] m_axis_fft_data_tdata;
wire [NUM_PORTS-1:0] m_axis_fft_data_tlast;
wire [NUM_PORTS-1:0] m_axis_fft_data_tvalid;
wire m_axis_fft_data_tready;
wire [NUM_PORTS-1:0] event_frame_started;
wire [NUM_PORTS-1:0] event_fft_overflow;
wire [NUM_PORTS-1:0] event_frame_tlast_unexpected;
wire [NUM_PORTS-1:0] event_frame_tlast_missing;
wire [NUM_PORTS*32-1:0] s_axis_split_bus_tdata;
wire [NUM_PORTS-1:0] s_axis_split_bus_teob;
wire [NUM_PORTS-1:0] s_axis_split_bus_teov;
wire s_axis_split_bus_tlast;
wire s_axis_split_bus_tvalid;
wire s_axis_split_bus_tready;
// Change packet length to FFT size
wire [FFT_SIZE_WIDTH-1:0] fft_size = 1 << reg_fft_size_log2[$clog2(FFT_SIZE_WIDTH)-1:0];
// Clear the commit flag after the FFT has been configured
assign reg_fft_commit_next = (s_axis_fft_config_tvalid && s_axis_fft_config_tready) ?
1'b0 : reg_fft_commit;
integer dbg_removal_in_counter = 0, dbg_removal_out_counter = 0;
integer dbg_removal_in_length, dbg_removal_out_length;
reg dbg_removal_in_eop, dbg_removal_out_eop;
always @(posedge axis_data_clk) begin
if (m_axis_combine_tvalid && m_axis_combine_tready) begin
if (m_axis_combine_tlast && m_axis_combine_teob) begin
dbg_removal_in_counter <= 0;
dbg_removal_in_eop <= 1;
dbg_removal_in_length <= dbg_removal_in_counter+1;
end else begin
dbg_removal_in_eop <= 0;
dbg_removal_in_counter <= dbg_removal_in_counter + 1;
end
end
if (m_axis_cp_removal_tvalid && m_axis_cp_removal_tready) begin
if (m_axis_cp_removal_tlast) begin
dbg_removal_out_counter <= 0;
dbg_removal_out_eop <= 1;
dbg_removal_out_length <= dbg_removal_out_counter+1;
end else begin
dbg_removal_out_eop <= 0;
dbg_removal_out_counter <= dbg_removal_out_counter + 1;
end
end
end
// Remove cyclic prefix
// Also sets the packet size (i.e. tlast) to the FFT size
axis_ofdm_cyclic_prefix_removal #(
.WIDTH (NUM_PORTS*32),
.USER_WIDTH (NUM_PORTS),
.MAX_CP_LEN_LOG2 (CP_LEN_WIDTH),
.MAX_FFT_SIZE_LOG2 (FFT_SIZE_WIDTH),
.DEFAULT_CP_LEN (DEFAULT_CP_LEN),
.CP_LEN_FIFO_MODE (CP_REMOVAL_REPEAT),
.CP_LEN_FIFO_SIZE_LOG2 (MAX_CP_LIST_LEN_REM_LOG2),
.SET_TLAST (1))
axis_ofdm_cyclic_prefix_removal_inst (
.clk (axis_data_clk),
.reset (axis_data_rst),
.clear_fifo (reg_cp_removal_cp_len_fifo_clr),
.fft_size (fft_size),
.m_axis_cp_len_tdata (reg_cp_removal_len),
.m_axis_cp_len_tvalid (reg_cp_removal_cp_len_fifo_load),
// No backpressure needed as the block controller checks "cp_len_fifo_occupied"
// before writing to avoid overflowing FIFO
.m_axis_cp_len_tready (),
.cp_len_fifo_occupied (reg_cp_removal_cp_len_fifo_occupied),
.s_axis_data_tdata (m_axis_combine_tdata),
.s_axis_data_tuser (m_axis_combine_teob),
.s_axis_data_tlast (m_axis_combine_tlast),
.s_axis_data_tvalid (m_axis_combine_tvalid),
.s_axis_data_tready (m_axis_combine_tready),
.m_axis_data_tdata (m_axis_cp_removal_tdata),
.m_axis_data_tuser (m_axis_cp_removal_teob),
.m_axis_data_tlast (m_axis_cp_removal_tlast),
.m_axis_data_tvalid (m_axis_cp_removal_tvalid),
.m_axis_data_tready (m_axis_cp_removal_tready)
);
// We can create a teov from tlast because the packet size is the same as the FFT size
assign m_axis_cp_removal_teov = {(NUM_PORTS){m_axis_cp_removal_tlast}};
// Below is a FIFO for a configurable cyclic prefix length list that cycles until
// the FIFO is cleared. This allows the cyclic prefix length to dynamically change
// at runtime on a FFT by FFT basis up to the depth of the FIFO.
// For example:
// - User writes 32, 64, 128 into the FIFO
// - FFT cyclic prefix length will be configured in the following order:
// 32, 64, 128, 32, 64, 128, etc until FIFO is cleared
// Example #2:
// - User writes 32 into FIFO
// - FFT cyclic prefix length will be 32 until FIFO is cleared
//
// If the FIFO does not have any entries, cylic prefix length defaults to
// CP_LEN_DEFAULT (see FFT configuration state machine below).
// User should generally not load or clear the FIFO while streaming, but the logic
// does not prevent it.
//
wire [CP_LEN_WIDTH-1:0] s_axis_cp_len_fifo_tdata;
wire s_axis_cp_len_fifo_tvalid;
wire [CP_LEN_WIDTH-1:0] m_axis_cp_len_fifo_tdata;
wire m_axis_cp_len_fifo_tvalid;
wire m_axis_cp_len_fifo_tready;
wire cp_len_fifo_empty = (reg_cp_insertion_cp_len_fifo_occupied == 0);
axi_fifo #(
.WIDTH (CP_LEN_WIDTH),
.SIZE (MAX_CP_LIST_LEN_INS_LOG2))
axi_fifo_cp_insertion_cp_len_inst (
.clk (axis_data_clk),
.reset (axis_data_rst),
.clear (reg_cp_insertion_cp_len_fifo_clr),
.i_tdata (s_axis_cp_len_fifo_tdata),
.i_tvalid (s_axis_cp_len_fifo_tvalid),
.i_tready (/* No backpressure needed as block controller checks cp_len_fifo_occupied to not overflow FIFO */),
.o_tdata (m_axis_cp_len_fifo_tdata),
.o_tvalid (m_axis_cp_len_fifo_tvalid), // Unused
.o_tready (m_axis_cp_len_fifo_tready),
.space (),
.occupied (reg_cp_insertion_cp_len_fifo_occupied)
);
// FFT IP configuration state machine
// Loads a new configuration at the start of every FFT
localparam S_FFT_CONFIG = 1'd0;
localparam S_FFT_WAIT_FOR_TLAST = 1'd1;
reg fft_config_state = S_FFT_CONFIG;
always @(posedge axis_data_clk) begin
case (fft_config_state)
S_FFT_CONFIG: begin
if (s_axis_fft_data_tvalid & s_axis_fft_data_tready[0]) begin
fft_config_state <= S_FFT_WAIT_FOR_TLAST;
end
end
S_FFT_WAIT_FOR_TLAST: begin
if (s_axis_fft_data_tvalid & s_axis_fft_data_tready[0] & s_axis_fft_data_tlast) begin
fft_config_state <= S_FFT_CONFIG;
end
end
endcase
if (axis_data_rst) begin
fft_config_state <= S_FFT_CONFIG;
end
end
assign s_axis_fft_config_tdata = {
{FFT_SCALE_PAD_W{1'b0}},
reg_fft_scaling,
reg_fft_direction,
{FFT_CP_LEN_PAD_W{1'b0}},
FFT_CP_LEN_W'(cp_len_fifo_empty ? DEFAULT_CP_LEN : m_axis_cp_len_fifo_tdata),
{FFT_NFFT_PAD_W{1'b0}},
reg_fft_size_log2
};
//assign s_axis_fft_config_tdata[47:41] = '0;
//assign s_axis_fft_config_tdata[40:25] = reg_fft_scaling;
//assign s_axis_fft_config_tdata[24] = reg_fft_direction;
//assign s_axis_fft_config_tdata[23] = '0;
//assign s_axis_fft_config_tdata[22:8] = FFT_CP_LEN_W'(cp_len_fifo_empty ? DEFAULT_CP_LEN : m_axis_cp_len_fifo_tdata);
//assign s_axis_fft_config_tdata[7:5] = '0;
//assign s_axis_fft_config_tdata[4:0] = reg_fft_size_log2;
//assign s_axis_fft_config_tvalid = reg_fft_commit;
assign s_axis_fft_config_tvalid = (fft_config_state == S_FFT_CONFIG) ? s_axis_fft_data_tvalid : 1'b0;
// No cyclic prefix fifo loopback. New configs can be written at any time.
if (CP_INSERTION_REPEAT == 0) begin : gen_cp_ins_repeat
assign s_axis_cp_len_fifo_tdata = reg_cp_insertion_len;
assign s_axis_cp_len_fifo_tvalid = reg_cp_insertion_cp_len_fifo_load;
//assign m_axis_cp_len_fifo_tready = s_axis_fft_config_tvalid & s_axis_fft_config_tready[0];
assign m_axis_cp_len_fifo_tready = (fft_config_state == S_FFT_CONFIG) & s_axis_fft_config_tvalid & s_axis_fft_config_tready[0];
// Cyclic prefix fifo fifo loopback enabled, writes current cp length back into fifo in the S_FFT_CONFIG_LOAD state.
// New cp lengths can only be written in the S_FFT_CONFIG_IDLE state.
end else begin : gen_cp_ins_no_repeat
assign s_axis_cp_len_fifo_tdata = reg_cp_insertion_cp_len_fifo_load ? reg_cp_insertion_len : m_axis_cp_len_fifo_tdata;
assign s_axis_cp_len_fifo_tvalid =
(m_axis_cp_len_fifo_tvalid & (s_axis_fft_config_tvalid & s_axis_fft_config_tready[0])) |
reg_cp_insertion_cp_len_fifo_load;
assign m_axis_cp_len_fifo_tready = s_axis_fft_config_tvalid & s_axis_fft_config_tready[0];
end
// Xilinx FFT IP lacks a pass-through tuser signal so this adds one for our EOB signal
axis_sideband_tuser #(
.WIDTH (NUM_PORTS*32),
.USER_WIDTH (2*NUM_PORTS),
.FIFO_SIZE_LOG2 (5),
.PACKET_MODE (2)) // tuser is EOB and static for the entire packet,
// so we can use this more effecient packet mode
axis_sideband_xfft_tuser (
.clk (axis_data_clk),
.reset (axis_data_rst),
// Input bus with a tuser signal
.s_axis_tdata (m_axis_cp_removal_tdata),
.s_axis_tuser ({m_axis_cp_removal_teob, m_axis_cp_removal_teov}),
.s_axis_tlast (m_axis_cp_removal_tlast),
.s_axis_tvalid (m_axis_cp_removal_tvalid),
.s_axis_tready (m_axis_cp_removal_tready),
// To/from our module, i.e. Xilinx FFT, but without the tuser signal.
// This modules keeps track of the tuser signal values internally
// and will automatically add them back to the output stream.
.m_axis_mod_tdata (s_axis_fft_data_tdata),
.m_axis_mod_tlast (s_axis_fft_data_tlast),
.m_axis_mod_tvalid (s_axis_fft_data_tvalid),
.m_axis_mod_tready (s_axis_fft_data_tready[0]),
.s_axis_mod_tdata (m_axis_fft_data_tdata),
.s_axis_mod_tlast (m_axis_fft_data_tlast[0]),
.s_axis_mod_tvalid (m_axis_fft_data_tvalid[0]),
.s_axis_mod_tready (m_axis_fft_data_tready),
// Output bus, i.e. Xilinx FFT output stream, but with the tuser from the input added on
.m_axis_tdata (s_axis_split_bus_tdata),
.m_axis_tuser ({s_axis_split_bus_teob, s_axis_split_bus_teov}),
.m_axis_tlast (s_axis_split_bus_tlast),
.m_axis_tvalid (s_axis_split_bus_tvalid),
.m_axis_tready (s_axis_split_bus_tready)
);
integer dbg_fft_in_counter = 0, dbg_fft_out_counter = 0;
integer dbg_fft_in_length, dbg_fft_out_length;
reg dbg_fft_in_eop, dbg_fft_out_eop;
genvar i;
for (i = 0; i < NUM_PORTS; i = i + 1) begin : gen_fft
always @(posedge axis_data_clk) begin
if (s_axis_fft_data_tvalid && s_axis_fft_data_tready) begin
if (s_axis_fft_data_tlast) begin
dbg_fft_in_counter <= 0;
dbg_fft_in_eop <= 1;
dbg_fft_in_length <= dbg_fft_in_counter+1;
end else begin
dbg_fft_in_eop <= 0;
dbg_fft_in_counter <= dbg_fft_in_counter + 1;
end
end
if (m_axis_fft_data_tvalid[i] && m_axis_fft_data_tready) begin
if (m_axis_fft_data_tlast[i]) begin
dbg_fft_out_counter <= 0;
dbg_fft_out_eop <= 1;
dbg_fft_out_length <= dbg_fft_out_counter+1;
end else begin
dbg_fft_out_eop <= 0;
dbg_fft_out_counter <= dbg_fft_out_counter + 1;
end
end
end
if (MAX_FFT_SIZE == 4096) begin : gen_4k_FFT
xfft_4k_16b xfft_4k_16b_i (
.aclk (axis_data_clk),
.aresetn (~axis_data_rst),
.s_axis_config_tdata (s_axis_fft_config_tdata),
.s_axis_config_tvalid (s_axis_fft_config_tvalid),
.s_axis_config_tready (s_axis_fft_config_tready[i]),
.s_axis_data_tdata ({ s_axis_fft_data_tdata[32*i +: 16], s_axis_fft_data_tdata[32*i+16 +: 16] }),
.s_axis_data_tlast (s_axis_fft_data_tlast),
.s_axis_data_tvalid (s_axis_fft_data_tvalid),
.s_axis_data_tready (s_axis_fft_data_tready[i]),
.m_axis_data_tdata ({ m_axis_fft_data_tdata[32*i +: 16], m_axis_fft_data_tdata[32*i+16 +: 16] }),
.m_axis_data_tuser (),
.m_axis_data_tlast (m_axis_fft_data_tlast[i]),
.m_axis_data_tvalid (m_axis_fft_data_tvalid[i]),
.m_axis_data_tready (m_axis_fft_data_tready),
.m_axis_status_tdata (),
.m_axis_status_tvalid (),
.m_axis_status_tready (1'b1),
.event_frame_started (event_frame_started[i]),
.event_tlast_unexpected (event_frame_tlast_unexpected[i]),
.event_tlast_missing (event_frame_tlast_missing[i]),
.event_fft_overflow (event_fft_overflow[i]),
.event_status_channel_halt (),
.event_data_in_channel_halt (),
.event_data_out_channel_halt ()
);
end else if (MAX_FFT_SIZE == 8192) begin : gen_8k_fft
xfft_8k_16b xfft_8k_16b_i (
.aclk (axis_data_clk),
.aresetn (~axis_data_rst),
.s_axis_config_tdata (s_axis_fft_config_tdata),
.s_axis_config_tvalid (s_axis_fft_config_tvalid),
.s_axis_config_tready (s_axis_fft_config_tready[i]),
.s_axis_data_tdata ({ s_axis_fft_data_tdata[32*i +: 16], s_axis_fft_data_tdata[32*i+16 +: 16] }),
.s_axis_data_tlast (s_axis_fft_data_tlast),
.s_axis_data_tvalid (s_axis_fft_data_tvalid),
.s_axis_data_tready (s_axis_fft_data_tready[i]),
.m_axis_data_tdata ({ m_axis_fft_data_tdata[32*i +: 16], m_axis_fft_data_tdata[32*i+16 +: 16] }),
.m_axis_data_tuser (),
.m_axis_data_tlast (m_axis_fft_data_tlast[i]),
.m_axis_data_tvalid (m_axis_fft_data_tvalid[i]),
.m_axis_data_tready (m_axis_fft_data_tready),
.m_axis_status_tdata (),
.m_axis_status_tvalid (),
.m_axis_status_tready (1'b1),
.event_frame_started (event_frame_started[i]),
.event_tlast_unexpected (event_frame_tlast_unexpected[i]),
.event_tlast_missing (event_frame_tlast_missing[i]),
.event_fft_overflow (event_fft_overflow[i]),
.event_status_channel_halt (),
.event_data_in_channel_halt (),
.event_data_out_channel_halt ()
);
end else if (MAX_FFT_SIZE == 32768) begin : gen_32k_fft
xfft_32k_16b xfft_32k_16b_i (
.aclk (axis_data_clk),
.aresetn (~axis_data_rst),
.s_axis_config_tdata (s_axis_fft_config_tdata),
.s_axis_config_tvalid (s_axis_fft_config_tvalid),
.s_axis_config_tready (s_axis_fft_config_tready[i]),
.s_axis_data_tdata ({ s_axis_fft_data_tdata[32*i +: 16], s_axis_fft_data_tdata[32*i+16 +: 16] }),
.s_axis_data_tlast (s_axis_fft_data_tlast),
.s_axis_data_tvalid (s_axis_fft_data_tvalid),
.s_axis_data_tready (s_axis_fft_data_tready[i]),
.m_axis_data_tdata ({ m_axis_fft_data_tdata[32*i +: 16], m_axis_fft_data_tdata[32*i+16 +: 16] }),
.m_axis_data_tuser (),
.m_axis_data_tlast (m_axis_fft_data_tlast[i]),
.m_axis_data_tvalid (m_axis_fft_data_tvalid[i]),
.m_axis_data_tready (m_axis_fft_data_tready),
.m_axis_status_tdata (),
.m_axis_status_tvalid (),
.m_axis_status_tready (1'b1),
.event_frame_started (event_frame_started[i]),
.event_tlast_unexpected (event_frame_tlast_unexpected[i]),
.event_tlast_missing (event_frame_tlast_missing[i]),
.event_fft_overflow (event_fft_overflow[i]),
.event_status_channel_halt (),
.event_data_in_channel_halt (),
.event_data_out_channel_halt ()
);
end
end
// Split back into multiple streams
axis_split_bus #(
.WIDTH (32),
.USER_WIDTH (2),
.NUM_PORTS (NUM_PORTS))
axis_split_bus_inst (
.clk (axis_data_clk),
.reset (axis_data_rst),
.s_axis_tdata (s_axis_split_bus_tdata),
.s_axis_tuser ({s_axis_split_bus_teob, s_axis_split_bus_teov}),
.s_axis_tlast (s_axis_split_bus_tlast),
.s_axis_tvalid (s_axis_split_bus_tvalid),
.s_axis_tready (s_axis_split_bus_tready),
.m_axis_tdata (s_axis_user_tdata),
.m_axis_tuser ({s_axis_user_teob, s_axis_user_teov}),
.m_axis_tlast (s_axis_user_tlast),
.m_axis_tvalid (s_axis_user_tvalid),
.m_axis_tready (s_axis_user_tready)
);
/*
(* dont_touch = "true", mark_debug = "true"*) reg [NUM_PORTS*32*1-1:0] m_in_axis_tdata_debug;
(* dont_touch = "true", mark_debug = "true"*) reg [NUM_PORTS-1:0] m_in_axis_tlast_debug;
(* dont_touch = "true", mark_debug = "true"*) reg [NUM_PORTS-1:0] m_in_axis_tvalid_debug;
(* dont_touch = "true", mark_debug = "true"*) reg [NUM_PORTS-1:0] m_in_axis_tready_debug;
(* dont_touch = "true", mark_debug = "true"*) reg [NUM_PORTS*32*1-1:0] s_out_axis_tdata_debug;
(* dont_touch = "true", mark_debug = "true"*) reg [NUM_PORTS-1:0] s_out_axis_tlast_debug;
(* dont_touch = "true", mark_debug = "true"*) reg [NUM_PORTS-1:0] s_out_axis_tvalid_debug;
(* dont_touch = "true", mark_debug = "true"*) reg [NUM_PORTS-1:0] s_out_axis_tready_debug;
(* dont_touch = "true", mark_debug = "true"*) reg [32-1:0] m_axis_combine_tdata_debug[0:NUM_PORTS-1];
(* dont_touch = "true", mark_debug = "true"*) reg [NUM_PORTS-1:0] m_axis_combine_teob_debug;
(* dont_touch = "true", mark_debug = "true"*) reg m_axis_combine_tlast_debug;
(* dont_touch = "true", mark_debug = "true"*) reg m_axis_combine_tvalid_debug;
(* dont_touch = "true", mark_debug = "true"*) reg m_axis_combine_tready_debug;
(* dont_touch = "true", mark_debug = "true"*) reg [32-1:0] m_axis_cp_removal_tdata_debug[0:NUM_PORTS-1];
(* dont_touch = "true", mark_debug = "true"*) reg [NUM_PORTS-1:0] m_axis_cp_removal_teob_debug;
(* dont_touch = "true", mark_debug = "true"*) reg m_axis_cp_removal_tlast_debug;
(* dont_touch = "true", mark_debug = "true"*) reg m_axis_cp_removal_tvalid_debug;
(* dont_touch = "true", mark_debug = "true"*) reg m_axis_cp_removal_tready_debug;
(* dont_touch = "true", mark_debug = "true"*) reg [32-1:0] s_axis_fft_data_tdata_debug[0:NUM_PORTS-1];
(* dont_touch = "true", mark_debug = "true"*) reg s_axis_fft_data_tlast_debug;
(* dont_touch = "true", mark_debug = "true"*) reg s_axis_fft_data_tvalid_debug;
(* dont_touch = "true", mark_debug = "true"*) reg [NUM_PORTS-1:0] s_axis_fft_data_tready_debug;
(* dont_touch = "true", mark_debug = "true"*) reg [32-1:0] m_axis_fft_data_tdata_debug[0:NUM_PORTS-1];
(* dont_touch = "true", mark_debug = "true"*) reg [NUM_PORTS-1:0] m_axis_fft_data_tlast_debug;
(* dont_touch = "true", mark_debug = "true"*) reg [NUM_PORTS-1:0] m_axis_fft_data_tvalid_debug;
(* dont_touch = "true", mark_debug = "true"*) reg m_axis_fft_data_tready_debug;
(* dont_touch = "true", mark_debug = "true"*) reg [NUM_PORTS-1:0] event_frame_started_debug;
(* dont_touch = "true", mark_debug = "true"*) reg [NUM_PORTS-1:0] event_fft_overflow_debug;
(* dont_touch = "true", mark_debug = "true"*) reg [NUM_PORTS-1:0] event_frame_tlast_unexpected_debug;
(* dont_touch = "true", mark_debug = "true"*) reg [NUM_PORTS-1:0] event_frame_tlast_missing_debug;
(* dont_touch = "true", mark_debug = "true"*) reg [32-1:0] s_axis_split_bus_tdata_debug[0:NUM_PORTS-1];
(* dont_touch = "true", mark_debug = "true"*) reg [NUM_PORTS-1:0] s_axis_split_bus_teob_debug;
(* dont_touch = "true", mark_debug = "true"*) reg s_axis_split_bus_tlast_debug;
(* dont_touch = "true", mark_debug = "true"*) reg s_axis_split_bus_tvalid_debug;
(* dont_touch = "true", mark_debug = "true"*) reg s_axis_split_bus_tready_debug;
(* dont_touch = "true", mark_debug = "true"*) reg [CP_LEN_WIDTH-1:0] m_axis_cp_len_fifo_tdata_debug;
(* dont_touch = "true", mark_debug = "true"*) reg m_axis_cp_len_fifo_tvalid_debug;
(* dont_touch = "true", mark_debug = "true"*) reg m_axis_cp_len_fifo_tready_debug;
(* dont_touch = "true", mark_debug = "true"*) reg [FFT_SIZE_WIDTH-1:0] fft_size_debug;
(* dont_touch = "true", mark_debug = "true"*) reg [39:0] s_axis_fft_config_tdata_debug;
(* dont_touch = "true", mark_debug = "true"*) reg s_axis_fft_config_tvalid_debug;
(* dont_touch = "true", mark_debug = "true"*) reg [NUM_PORTS-1:0] s_axis_fft_config_tready_debug;
(* dont_touch = "true", mark_debug = "true"*) reg fft_config_state_debug;
always @(posedge axis_data_clk) begin
m_in_axis_tdata_debug <= m_in_axis_tdata;
m_in_axis_tlast_debug <= m_in_axis_tlast;
m_in_axis_tvalid_debug <= m_in_axis_tvalid;
m_in_axis_tready_debug <= m_in_axis_tready;
s_out_axis_tdata_debug <= s_out_axis_tdata;
s_out_axis_tlast_debug <= s_out_axis_tlast;
s_out_axis_tvalid_debug <= s_out_axis_tvalid;
s_out_axis_tready_debug <= s_out_axis_tready;
{m_axis_combine_tdata_debug[1],m_axis_combine_tdata_debug[0]} <= m_axis_combine_tdata;
m_axis_combine_teob_debug <= m_axis_combine_teob;
m_axis_combine_tlast_debug <= m_axis_combine_tlast;
m_axis_combine_tvalid_debug <= m_axis_combine_tvalid;
m_axis_combine_tready_debug <= m_axis_combine_tready;
{m_axis_cp_removal_tdata_debug[1],m_axis_cp_removal_tdata_debug[0]} <= m_axis_cp_removal_tdata;
m_axis_cp_removal_teob_debug <= m_axis_cp_removal_teob;
m_axis_cp_removal_tlast_debug <= m_axis_cp_removal_tlast;
m_axis_cp_removal_tvalid_debug <= m_axis_cp_removal_tvalid;
m_axis_cp_removal_tready_debug <= m_axis_cp_removal_tready;
{s_axis_fft_data_tdata_debug[1],s_axis_fft_data_tdata_debug[0]} <= s_axis_fft_data_tdata;
s_axis_fft_data_tlast_debug <= s_axis_fft_data_tlast;
s_axis_fft_data_tvalid_debug <= s_axis_fft_data_tvalid;
s_axis_fft_data_tready_debug <= s_axis_fft_data_tready;
{m_axis_fft_data_tdata_debug[1],m_axis_fft_data_tdata_debug[0]} <= m_axis_fft_data_tdata;
m_axis_fft_data_tlast_debug <= m_axis_fft_data_tlast;
m_axis_fft_data_tvalid_debug <= m_axis_fft_data_tvalid;
m_axis_fft_data_tready_debug <= m_axis_fft_data_tready;
event_frame_started_debug <= event_frame_started;
event_fft_overflow_debug <= event_fft_overflow;
event_frame_tlast_unexpected_debug <= event_frame_tlast_unexpected;
event_frame_tlast_missing_debug <= event_frame_tlast_missing;
{s_axis_split_bus_tdata_debug[1],s_axis_split_bus_tdata_debug[0]} <= s_axis_split_bus_tdata;
s_axis_split_bus_teob_debug <= s_axis_split_bus_teob;
s_axis_split_bus_tlast_debug <= s_axis_split_bus_tlast;
s_axis_split_bus_tvalid_debug <= s_axis_split_bus_tvalid;
s_axis_split_bus_tready_debug <= s_axis_split_bus_tready;
m_axis_cp_len_fifo_tdata_debug <= m_axis_cp_len_fifo_tdata;
m_axis_cp_len_fifo_tvalid_debug <= m_axis_cp_len_fifo_tvalid;
m_axis_cp_len_fifo_tready_debug <= m_axis_cp_len_fifo_tready;
fft_size_debug <= fft_size;
s_axis_fft_config_tdata_debug <= s_axis_fft_config_tdata;
s_axis_fft_config_tvalid_debug <= s_axis_fft_config_tvalid;
s_axis_fft_config_tready_debug <= s_axis_fft_config_tready;
fft_config_state_debug <= fft_config_state;
end
*/
endmodule : rfnoc_block_ofdm
`default_nettype wire

File diff suppressed because it is too large Load Diff