aboutsummaryrefslogtreecommitdiffstats
path: root/fpga/usrp3
diff options
context:
space:
mode:
authorWade Fife <wade.fife@ettus.com>2020-06-25 00:24:25 -0500
committerAaron Rossetto <aaron.rossetto@ni.com>2020-07-30 12:51:41 -0500
commitb0b3849a18e1f2d3cb255a507b01ac5e7a9416a0 (patch)
treeef5f3484533448c3f512bd257372b42e995d02a4 /fpga/usrp3
parentaca52b700282153760ae9331a791ddd41a2f4dd5 (diff)
downloaduhd-b0b3849a18e1f2d3cb255a507b01ac5e7a9416a0.tar.gz
uhd-b0b3849a18e1f2d3cb255a507b01ac5e7a9416a0.tar.bz2
uhd-b0b3849a18e1f2d3cb255a507b01ac5e7a9416a0.zip
fpga: lib: Add axis_packetize module
This module takes an AXI-Stream without TLAST and outputs the same AXI-Stream with TLAST based on the provided packet size input.
Diffstat (limited to 'fpga/usrp3')
-rw-r--r--fpga/usrp3/lib/axi/Makefile.srcs1
-rw-r--r--fpga/usrp3/lib/axi/axis_packetize.v161
2 files changed, 162 insertions, 0 deletions
diff --git a/fpga/usrp3/lib/axi/Makefile.srcs b/fpga/usrp3/lib/axi/Makefile.srcs
index bf8b3dbd2..598af9ef3 100644
--- a/fpga/usrp3/lib/axi/Makefile.srcs
+++ b/fpga/usrp3/lib/axi/Makefile.srcs
@@ -34,4 +34,5 @@ axis_upsizer.v \
axis_downsizer.v \
axis_width_conv.v \
axis_split.v \
+axis_packetize.v \
))
diff --git a/fpga/usrp3/lib/axi/axis_packetize.v b/fpga/usrp3/lib/axi/axis_packetize.v
new file mode 100644
index 000000000..6ee018d9a
--- /dev/null
+++ b/fpga/usrp3/lib/axi/axis_packetize.v
@@ -0,0 +1,161 @@
+//
+// Copyright 2020 Ettus Research, A National Instruments Brand
+//
+// SPDX-License-Identifier: LGPL-3.0-or-later
+//
+// Module: axis_packetize
+//
+// Description:
+//
+// This module takes in an axi_stream without packet boundaries (i.e.,
+// without tlast) and groups the data into packets by adding tlast at the
+// appropriate time. The size of the packet is controlled by the "size"
+// input, which is sampled at the beginning of each packet to be output. The
+// packet_size input indicates the number of i_tdata words to group into a
+// packet. The i_tlength output indicates the length of the packet being
+// output.
+//
+// The gate input causes data transfers to be stopped at the end of the
+// current packet when the gate input is asserted. It is not legal to
+// deassert tvalid once it has been asserted until the next transfer is
+// completed, so this module monitors the state of the AXI-Stream protocol
+// so that no protocol violations occur.
+//
+// Note that the current transfer may still complete after gate has been
+// asserted, so the downstream logic must be able to account for at least
+// one more transfer.
+//
+// Parameters:
+//
+// DATA_W : Width of the tdata signals.
+// SIZE_W : The width of the packet size port. This dictates the
+// maximum packet size.
+// FLUSH : Controls whether or not the input should be stalled or
+// flushed. That is, when FLUSH=0, the input data is stalled
+// whenever the gate is on (i_tready becomes 0). When
+// FLUSH=1, the input data is dropped whenever the gate is on
+// (i_tready becomes 1).
+// DEFAULT_SIZE : The default packet size to use, if it doesn't need to be
+// changed at run time.
+//
+
+
+module axis_packetize #(
+ parameter DATA_W = 32,
+ parameter SIZE_W = 16,
+ parameter FLUSH = 0,
+ parameter DEFAULT_SIZE = 2**SIZE_W-1
+) (
+ input wire clk,
+ input wire rst,
+
+ input wire gate, // Stop or "gate" packet output
+ input wire [SIZE_W-1:0] size, // Size to use for the next packet
+
+ // Input data stream
+ input wire [DATA_W-1:0] i_tdata,
+ input wire i_tvalid,
+ output wire i_tready,
+
+ // Output data stream
+ output wire [DATA_W-1:0] o_tdata,
+ output reg o_tlast,
+ output wire o_tvalid,
+ input wire o_tready,
+ output wire [SIZE_W-1:0] o_tuser // Current packet's size
+);
+
+ reg start_of_packet = 1; // Next sample is start of a packet
+ reg [SIZE_W-1:0] word_count = 0; // Count of output words
+ reg [SIZE_W-1:0] current_size = DEFAULT_SIZE; // Current packet size
+
+ reg gating = 1'b1; // Indicate if output is blocked
+ reg mid_packet = 1'b0; // Indicate if we're in the middle of a packet
+
+ //---------------------------------------------------------------------------
+ // Packet Size Logic
+ //---------------------------------------------------------------------------
+
+ assign o_tuser = current_size;
+
+ always @(posedge clk) begin
+ if (rst) begin
+ start_of_packet <= 1;
+ word_count <= 0;
+ current_size <= DEFAULT_SIZE;
+ o_tlast <= 0;
+ end else begin
+ if (gating) begin
+ // Wait until we're enabled. Setup for the start of the next packet.
+ start_of_packet <= 1;
+ current_size <= size;
+ word_count <= 0;
+ o_tlast <= (size == 1);
+ end else if (o_tvalid && o_tready) begin
+ start_of_packet <= 1'b0;
+ word_count <= word_count + 1;
+ if (o_tlast) begin
+ // This is the last sample, so restart everything for a new packet.
+ o_tlast <= (size == 1);
+ current_size <= size;
+ word_count <= 0;
+ start_of_packet <= 1'b1;
+ end else if (word_count == current_size-2) begin
+ // This is the second to last sample, so we assert tlast for the
+ // last sample.
+ o_tlast <= 1'b1;
+ end
+ end else if (start_of_packet) begin
+ // We're waiting for the start of the next packet. Keep checking the
+ // size input until the next packet starts.
+ current_size <= size;
+ word_count <= 0;
+ o_tlast <= (size == 1);
+ end
+ end
+ end
+
+ //---------------------------------------------------------------------------
+ // Handshake Monitor
+ //---------------------------------------------------------------------------
+
+ // We start out gated to allow a clock cycle for the length to be loaded.
+
+ // Monitor the state of the handshake so we know when it's OK to
+ // enable/disable data transfer.
+ always @(posedge clk) begin
+ if (rst) begin
+ gating = 1'b1;
+ mid_packet = 1'b0;
+ end else begin
+ // Keep track of if we are in the middle of a packet or not. Note that
+ // mid_packet will be 0 for the first transfer of a packet.
+ if (o_tvalid && o_tready) begin
+ if (o_tlast) begin
+ mid_packet = 1'b0;
+ end else begin
+ mid_packet = 1'b1;
+ end
+ end
+
+ if (gating) begin
+ // We can stop gating any time
+ if (!gate) gating <= 0;
+ end else begin
+ // Only start gating between packets or at the end of a packet
+ if ((mid_packet && !o_tvalid) || (o_tvalid && o_tready && o_tlast)) begin
+ gating <= gate;
+ end
+ end
+ end
+ end
+
+ //---------------------------------------------------------------------------
+ // Data Pass-Through
+ //---------------------------------------------------------------------------
+
+ assign o_tdata = i_tdata;
+ assign o_tvalid = i_tvalid && !gating;
+ assign i_tready = FLUSH ? (o_tready || gating) : (o_tready && !gating);
+
+endmodule