diff options
Diffstat (limited to 'fpga/usrp3/lib/rfnoc/utils/context_parser.v')
-rw-r--r-- | fpga/usrp3/lib/rfnoc/utils/context_parser.v | 230 |
1 files changed, 230 insertions, 0 deletions
diff --git a/fpga/usrp3/lib/rfnoc/utils/context_parser.v b/fpga/usrp3/lib/rfnoc/utils/context_parser.v new file mode 100644 index 000000000..2d0759af7 --- /dev/null +++ b/fpga/usrp3/lib/rfnoc/utils/context_parser.v @@ -0,0 +1,230 @@ +// +// Copyright 2019 Ettus Research, A National Instruments Company +// +// SPDX-License-Identifier: LGPL-3.0-or-later +// +// Module: context_parser +// +// Description: +// +// This module extracts the context information from the AXI-Stream Raw Data +// (Simple Interface) in RFNoC and outputs it as sideband information for an +// AXI-Stream data bus. This includes the timestamp, if present, and packet +// flags (EOB, EOV). +// +// For each payload and context packet that is input, one data packet will be +// output along with the sideband data. +// +// Parameters: +// +// CHDR_W : Width of the CHDR interface (width of context words) +// ITEM_W : Width of each item/sample +// NIPC : Number of items/samples per clock cycle +// + +module context_parser #( + parameter CHDR_W = 64, + parameter ITEM_W = 32, + parameter NIPC = 2 +) ( + input axis_data_clk, + input axis_data_rst, + + // AXI-Stream Raw Data (Simple Interface) input + input wire [(ITEM_W*NIPC)-1:0] s_axis_payload_tdata, + input wire [ NIPC-1:0] s_axis_payload_tkeep, + input wire s_axis_payload_tlast, + input wire s_axis_payload_tvalid, + output wire s_axis_payload_tready, + // + input wire [ CHDR_W-1:0] s_axis_context_tdata, + input wire s_axis_context_tlast, + input wire s_axis_context_tvalid, + output wire s_axis_context_tready, + + // Data stream out (AXI-Stream) + output wire [(ITEM_W*NIPC)-1:0] m_axis_tdata, + output wire [ NIPC-1:0] m_axis_tkeep, + output wire m_axis_tlast, + output wire m_axis_tvalid, + input wire m_axis_tready, + // Sideband information + output wire [ 63:0] m_axis_ttimestamp, + output wire m_axis_thas_time, + output wire [ 15:0] m_axis_tlength, // Payload length, in bytes + output wire m_axis_teov, + output wire m_axis_teob +); + + `include "../core/rfnoc_chdr_utils.vh" + + + // Sideband-FIFO signals + reg sideband_i_tvalid = 1'b0; + wire sideband_i_tready; + wire sideband_o_tvalid; + wire sideband_o_tready; + + // Sideband data for next packet + reg [63:0] timestamp; + reg has_time; + reg [15:0] length; + reg eov; + reg eob; + + + //--------------------------------------------------------------------------- + // Context State Machine + //--------------------------------------------------------------------------- + // + // This state machine parses the context data so that it can be output as + // sideband information on the AXI-Stream output. + // + // This state machine assumes that the context packet is always properly + // formed (i.e., it doesn't explicitly check for and drop malformed packets). + // + //--------------------------------------------------------------------------- + + localparam ST_HEADER = 0; + localparam ST_TIMESTAMP = 1; + localparam ST_METADATA = 2; + + reg [1:0] state = ST_HEADER; + + always @(posedge axis_data_clk) begin + if (axis_data_rst) begin + state <= ST_HEADER; + sideband_i_tvalid <= 1'b0; + end else begin + sideband_i_tvalid <= 1'b0; + + case(state) + ST_HEADER: begin + // Grab header information + eov <= chdr_get_eov(s_axis_context_tdata[63:0]); + eob <= chdr_get_eob(s_axis_context_tdata[63:0]); + has_time <= chdr_get_has_time(s_axis_context_tdata[63:0]); + length <= chdr_calc_payload_length(CHDR_W, s_axis_context_tdata[63:0]); + + if (s_axis_context_tvalid && s_axis_context_tready) begin + if (CHDR_W > 64) begin + // When CHDR_W > 64, the timestamp is a part of the header word + if (chdr_get_has_time(s_axis_context_tdata[63:0])) begin + timestamp <= s_axis_context_tdata[127:64]; + end + + // Load the sideband data into the FIFO + sideband_i_tvalid <= 1'b1; + + // Check if there's more context packet to wait for + if (!s_axis_context_tlast) begin + state <= ST_METADATA; + end + + end else begin + // When CHDR_W == 64, the timestamp comes after the header word + if (s_axis_context_tlast) begin + // Context packet is ending. Load the sideband data into FIFO. + sideband_i_tvalid <= 1'b1; + end else begin + // More context packet to come + if (chdr_get_has_time(s_axis_context_tdata[63:0])) begin + state <= ST_TIMESTAMP; + end else begin + // Load the sideband data into the FIFO + sideband_i_tvalid <= 1'b1; + state <= ST_METADATA; + end + end + end + end + end + + ST_TIMESTAMP: begin + // This state only applies when CHDR_W == 64 + if (s_axis_context_tvalid && s_axis_context_tready) begin + timestamp <= s_axis_context_tdata; + + // Load the sideband data into the FIFO + sideband_i_tvalid <= 1'b1; + + // Check if there's more context packet to wait for + if (s_axis_context_tlast) begin + state <= ST_HEADER; + end else begin + state <= ST_METADATA; + end + end + end + + ST_METADATA: begin + // This module doesn't handle metadata currently, so just ignore it + if (s_axis_context_tvalid && s_axis_context_tready) begin + if (s_axis_context_tlast) begin + state <= ST_HEADER; + end + end + end + + default: state <= ST_HEADER; + endcase + end + end + + + //--------------------------------------------------------------------------- + // Sideband Data FIFO + //--------------------------------------------------------------------------- + // + // Here we buffer the sideband information into a FIFO. The information will + // be output coincident with the corresponding data packet. + // + //--------------------------------------------------------------------------- + + axi_fifo_short #( + .WIDTH (83) + ) sideband_fifo ( + .clk (axis_data_clk), + .reset (axis_data_rst), + .clear (1'b0), + .i_tdata ({length, eob, eov, has_time, timestamp}), + .i_tvalid (sideband_i_tvalid), + .i_tready (sideband_i_tready), + .o_tdata ({m_axis_tlength, m_axis_teob, m_axis_teov, + m_axis_thas_time, m_axis_ttimestamp}), + .o_tvalid (sideband_o_tvalid), + .o_tready (sideband_o_tready), + .space (), + .occupied () + ); + + + //--------------------------------------------------------------------------- + // Payload Transfer Logic + //--------------------------------------------------------------------------- + // + // Here we handle the logic for AXI-Stream flow control. The data and + // sideband information are treated as a single AXI-Stream bus. The sideband + // information is output for the duration of the packet and is popped off of + // the sideband FIFO at the end of each packet. + // + //--------------------------------------------------------------------------- + + // We can only accept context info when there's room in the sideband FIFO. + assign s_axis_context_tready = sideband_i_tready; + + // Allow payload transfer whenever the sideband info is valid + assign s_axis_payload_tready = (m_axis_tready & sideband_o_tvalid); + assign m_axis_tvalid = (s_axis_payload_tvalid & sideband_o_tvalid); + + // Pop off the sideband info at the end of each packet + assign sideband_o_tready = (s_axis_payload_tready & + s_axis_payload_tvalid & + s_axis_payload_tlast); + + // Other AXI-Stream signals pass through untouched + assign m_axis_tdata = s_axis_payload_tdata; + assign m_axis_tkeep = s_axis_payload_tkeep; + assign m_axis_tlast = s_axis_payload_tlast; + +endmodule |