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[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
|