1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 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[47:0];
// 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 = {48'b0, s_axis_tdata[63:48]};
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 = {holding_reg, s_axis_tdata[63:48]};
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 = {holding_reg, 16'b0};
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
|