aboutsummaryrefslogtreecommitdiffstats
path: root/fpga/usrp3/lib/packet_proc/arm_deframer.v
diff options
context:
space:
mode:
Diffstat (limited to 'fpga/usrp3/lib/packet_proc/arm_deframer.v')
-rw-r--r--fpga/usrp3/lib/packet_proc/arm_deframer.v119
1 files changed, 119 insertions, 0 deletions
diff --git a/fpga/usrp3/lib/packet_proc/arm_deframer.v b/fpga/usrp3/lib/packet_proc/arm_deframer.v
new file mode 100644
index 000000000..c4f77edf7
--- /dev/null
+++ b/fpga/usrp3/lib/packet_proc/arm_deframer.v
@@ -0,0 +1,119 @@
+/////////////////////////////////////////////////////////////////////
+//
+// Copyright 2017 Ettus Research, A National Instruments Company
+//
+// SPDX-License-Identifier: LGPL-3.0-or-later
+//
+// Module: arm_deframer
+// Description:
+// Adds 6 bytes of Zeros at the beginning of every packet. It aligns the
+// 64-bit words of the ethernet packet to be used later for classifying the
+// packets. The module is based on xge64_to_axi64 and has lesser
+// functionality.
+// Note that the block only works for padding 6 bytes.
+//
+/////////////////////////////////////////////////////////////////////
+
+module arm_deframer (
+ // Clocks and Reset
+ input wire clk,
+ input wire reset,
+ input wire clear,
+ // Slave AXI Interface
+ input wire [63:0] s_axis_tdata,
+ input wire [3:0] s_axis_tuser, //used as tkeep here
+ input wire s_axis_tlast,
+ input wire s_axis_tvalid,
+ output reg s_axis_tready,
+ // Master AXI Interface
+ output reg [63:0] m_axis_tdata,
+ output reg [3:0] m_axis_tuser, //used as tkeep here
+ output reg m_axis_tlast,
+ output reg m_axis_tvalid,
+ input wire m_axis_tready
+);
+ // State Machine States
+ localparam START = 2'b00;
+ localparam BODY = 2'b01;
+ localparam EXTRA = 2'b10;
+ localparam PAD_BYTES = 3'b110; //6 bytes
+ wire new_line;
+ wire valid_beat;
+ reg [1:0] state = 2'b00, next_state=2'b00;
+ reg [47:0] holding_reg;
+ reg [2:0] holding_user;
+ // New line will be created by padding 6 bytes if the valid bytes on the
+ // last line are greater than 2 bytes(3 to 7 bytes) or all 8 bytes are valid.
+ assign new_line = (s_axis_tuser[2:0] > 3'b010) || (s_axis_tuser[2:0] == 3'b000);
+ assign valid_beat = s_axis_tvalid & m_axis_tready;
+ always @(posedge clk) begin
+ if (reset | clear) begin
+ state <= START;
+ end else begin
+ state <=next_state;
+ end
+ end
+ // holding last 48 bits from input tdata on every valid_beat.
+ always @(posedge clk)begin
+ if (s_axis_tvalid & s_axis_tready) begin
+ // Register the last 6 bytes of data for one cycle
+ holding_reg <= s_axis_tdata[63:16];
+ // Register the tuser in case there is a new line
+ // tuser should be valid for one extra cycle in that case
+ holding_user <= s_axis_tuser[2:0];
+ end
+ end
+ // Outputs
+ always @(*) begin
+ m_axis_tdata = 64'b0;
+ m_axis_tvalid = 1'b0;
+ m_axis_tlast = 1'b0;
+ m_axis_tuser = 4'b0;
+ s_axis_tready = 1'b1;
+ case (state)
+ START : begin
+ // Pad with 6 bytes of Zeros at the beginning of the packet
+ // Shift the first 2 bytes to the end
+ m_axis_tdata = {s_axis_tdata[15:0], 48'b0};
+ m_axis_tvalid = s_axis_tvalid;
+ m_axis_tlast = s_axis_tlast;
+ m_axis_tuser = 4'b0;
+ s_axis_tready = m_axis_tready;
+ if(valid_beat) next_state = BODY;
+ else next_state = START;
+ end
+ BODY : begin
+ // Shift the remaining packet by 6 bytes.
+ // Here we're using register version of data and tvalid.
+ m_axis_tdata = {s_axis_tdata[15:0], holding_reg};
+ m_axis_tvalid = s_axis_tvalid;
+ m_axis_tlast = new_line? 1'b0: s_axis_tvalid & s_axis_tlast;
+ // Modify the tuser according to the new packet i.e. add 6 to it.
+ m_axis_tuser = (new_line & s_axis_tlast) ? 4'b0: {1'b0, s_axis_tuser[2:0] + PAD_BYTES};
+ s_axis_tready = m_axis_tready;
+ if (valid_beat & s_axis_tlast) next_state = new_line ? EXTRA : START;
+ else next_state = BODY;
+ end
+ EXTRA : begin
+ m_axis_tdata = {16'b0, holding_reg};
+ m_axis_tvalid = 1'b1;
+ m_axis_tlast = 1'b1;
+ // Modify the tuser according to the new shifted packet i.e. add 6 to it.
+ m_axis_tuser = {1'b0, holding_user + PAD_BYTES};
+ // We need to hold off any comming upstream data i.e not ready until
+ // downstream done consuming this data
+ s_axis_tready = 1'b0;
+ if (m_axis_tready) next_state = START;
+ else next_state = EXTRA;
+ end
+ default : begin
+ m_axis_tdata = 64'b0;
+ m_axis_tvalid = 1'b0;
+ m_axis_tlast = 1'b0;
+ m_axis_tuser = 4'b0;
+ s_axis_tready = 1'b1;
+ next_state = START;
+ end
+ endcase
+ end
+endmodule // arm_deframer