aboutsummaryrefslogtreecommitdiffstats
path: root/fpga/usrp3/lib/rfnoc/utils/context_parser.v
diff options
context:
space:
mode:
Diffstat (limited to 'fpga/usrp3/lib/rfnoc/utils/context_parser.v')
-rw-r--r--fpga/usrp3/lib/rfnoc/utils/context_parser.v230
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