diff --git a/lib/rfnoc/utils/Makefile.srcs b/lib/rfnoc/utils/Makefile.srcs index 11312ee..6aba292 100644 --- a/lib/rfnoc/utils/Makefile.srcs +++ b/lib/rfnoc/utils/Makefile.srcs @@ -30,4 +30,5 @@ ctrlport_to_settings_bus.v \ noc_shell_generic_ctrlport_pyld_chdr.v \ timekeeper.v \ ctrlport_terminator.v \ +chdr_strip_header.sv \ )) diff --git a/lib/rfnoc/utils/chdr_strip_header.sv b/lib/rfnoc/utils/chdr_strip_header.sv new file mode 100644 index 0000000..9eaa271 --- /dev/null +++ b/lib/rfnoc/utils/chdr_strip_header.sv @@ -0,0 +1,155 @@ +// +// Copyright 2022 Ettus Research, a National Instruments Brand +// +// SPDX-License-Identifier: LGPL-3.0-or-later +// +// Module: chdr_strip_header +// +// Description: +// +// Removes the CHDR header depending on the state of strip_en on the first +// word of the packet. +// + +`default_nettype none + + +module chdr_strip_header #( + parameter CHDR_W = 64, + localparam USER_W = 16 +) ( + // Clock and reset + input wire clk, + input wire rst, + + // Strip enable, sampled when the first word of the packet is transferred + input wire strip_en, + + // CHDR input packet + input wire [CHDR_W-1:0] s_chdr_tdata, + input wire s_chdr_tlast, + input wire s_chdr_tvalid, + output logic s_chdr_tready, + + // Output packet (with or without header) + output logic [CHDR_W-1:0] m_tdata, + output logic [USER_W-1:0] m_tuser, + output logic m_tlast, + output logic m_tvalid, + input wire m_tready +); + + `include "../core/rfnoc_chdr_utils.vh" + + enum { + ST_HDR, // CHDR header + ST_STRIP, // Strip header + ST_PASS // Pass packet through + } state; + + localparam COUNT_W = (CHDR_W == 64) ? + 6 : // Max count is timestamp + metadata + 5; // Max count is metadata only (timestamp is in the first word) + + // The number of CHDR words we need to skip to get to the payload, minus one. + logic [COUNT_W-1:0] skip_length; + // Counter to track where we are in the header. + logic [COUNT_W-1:0] skip_count; + + // Total length of the header, including timestamp and metadata, minus 1. + logic [COUNT_W-1:0] hdr_length; + + // Register to hold the new packet length, in bytes + logic [15:0] packet_length; + + //--------------------------------------------------------------------------- + // State Machine Registers + //--------------------------------------------------------------------------- + + always_ff @(posedge clk) begin : sm_reg + case (state) + ST_HDR : begin + skip_count <= 1; + skip_length <= hdr_length; + packet_length <= chdr_get_length(s_chdr_tdata) - (CHDR_W/8); + + if (s_chdr_tvalid && s_chdr_tready) begin + if (hdr_length > 0 && strip_en) begin + state <= ST_STRIP; + end else begin + state <= ST_PASS; + end + end + end + ST_STRIP : begin + if (s_chdr_tvalid && s_chdr_tready) begin + packet_length <= packet_length - (CHDR_W/8); + skip_count <= skip_count + 1; + if (s_chdr_tlast) begin + state <= ST_HDR; + end else if (skip_count == skip_length) begin + state <= ST_PASS; + end + end + end + ST_PASS : begin + if (s_chdr_tvalid && s_chdr_tready && s_chdr_tlast) begin + state <= ST_HDR; + end + end + endcase + + if (rst) begin + state <= ST_HDR; + end + end : sm_reg + + //--------------------------------------------------------------------------- + // State Machine Combinatorial Logic + //--------------------------------------------------------------------------- + + always_comb begin : sm_comb + m_tdata = s_chdr_tdata; + m_tlast = s_chdr_tlast; + + // Calculate the length of the header, including timestamp and metadata, + // minus 1. + if (CHDR_W == 64 && chdr_get_pkt_type(s_chdr_tdata) == CHDR_PKT_TYPE_DATA_TS) begin + hdr_length = chdr_get_num_mdata(s_chdr_tdata) + 1; + end else begin + hdr_length = chdr_get_num_mdata(s_chdr_tdata); + end + + // Drive m_tvalid and s_chdr_tready + case (state) + ST_HDR : begin + m_tuser = chdr_get_length(s_chdr_tdata); + if (strip_en) begin + // Drop header word + m_tvalid = 0; + s_chdr_tready = 1; + end else begin + // Pass header through + m_tvalid = s_chdr_tvalid; + s_chdr_tready = m_tready; + end + end + ST_STRIP : begin + // Drop incoming words + m_tvalid = 0; + m_tuser = 'X; + s_chdr_tready = 1; + end + ST_PASS : begin + // Pass words through + m_tvalid = s_chdr_tvalid; + m_tuser = packet_length; + s_chdr_tready = m_tready; + end + endcase + end : sm_comb + +endmodule : chdr_strip_header + + +`default_nettype wire