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
120
121
122
123
124
125
126
127
128
129
130
131
132
|
//
// Copyright 2019 Ettus Research, A National Instruments Company
//
// SPDX-License-Identifier: LGPL-3.0-or-later
//
// Module: chdr_pad_packet
// Description:
// This module pads extra data on the AXI-Stream bus
// to the requested packet size. This module is for
// creating len-sized packets, for DMA engines that
// do not support partial transfers.
//
// Parameters:
// - CHDR_W: Width of the CHDR tdata bus in bits
//
// Signals:
// - s_axis_* : Input AXI-Stream CHDR bus
// - m_axis_* : Output AXI-Stream CHDR bus
// - len : Requested number of CHDR_W lines in the packet (must be > 1)
`default_nettype none
module chdr_pad_packet #(
parameter CHDR_W = 256
)(
input wire clk,
input wire rst,
input wire [15:0] len,
input wire [CHDR_W-1:0] s_axis_tdata,
input wire s_axis_tlast,
input wire s_axis_tvalid,
output reg s_axis_tready,
output wire [CHDR_W-1:0] m_axis_tdata,
output reg m_axis_tlast,
output reg m_axis_tvalid,
input wire m_axis_tready
);
localparam [1:0] ST_HEADER = 2'd0;
localparam [1:0] ST_BODY = 2'd1;
localparam [1:0] ST_PAD = 2'd2;
localparam [1:0] ST_DROP = 2'd3;
reg [1:0] state;
reg [15:0] lines_left;
always @(posedge clk) begin
if (rst || (len <= 16'd1)) begin
state <= ST_HEADER;
end else begin
case(state)
ST_HEADER: begin
lines_left <= len - 16'd1;
if (s_axis_tvalid && m_axis_tready) begin
if (!s_axis_tlast) begin
// Packet is more than one line and length not reached
state <= ST_BODY;
end else begin
// Packet is only one line and length not reached
state <= ST_PAD;
end
end
end
ST_BODY: begin
if (s_axis_tvalid && m_axis_tready) begin
lines_left <= lines_left - 16'd1;
if (s_axis_tlast && (lines_left == 16'd1)) begin
// End of input and reached length
state <= ST_HEADER;
end else if (s_axis_tlast && (lines_left != 16'd1)) begin
// End of input, but length not reached
state <= ST_PAD;
end else if (!s_axis_tlast && (lines_left == 16'd1)) begin
// Reached length, but input continues...
state <= ST_DROP;
end
end
end
ST_PAD: begin
if (m_axis_tready) begin
lines_left <= lines_left - 16'd1;
if (lines_left == 16'd1) begin
state <= ST_HEADER;
end
end
end
ST_DROP: begin
if (s_axis_tvalid && s_axis_tlast) begin
state <= ST_HEADER;
end
end
default: begin
// We should never get here
state <= ST_HEADER;
end
endcase
end
end
assign m_axis_tdata = s_axis_tdata;
always @(*) begin
case(state)
ST_HEADER: begin
if (len <= 16'd1) begin
s_axis_tready <= 1'b0;
m_axis_tvalid <= 1'b0;
end else begin
s_axis_tready <= m_axis_tready;
m_axis_tvalid <= s_axis_tvalid;
end
m_axis_tlast <= 1'b0;
end
ST_BODY: begin
s_axis_tready <= m_axis_tready;
m_axis_tvalid <= s_axis_tvalid;
m_axis_tlast <= (lines_left == 16'd1);
end
ST_PAD: begin
s_axis_tready <= 1'b0;
m_axis_tvalid <= 1'b1;
m_axis_tlast <= (lines_left == 16'd1);
end
ST_DROP: begin
s_axis_tready <= 1'b1;
m_axis_tvalid <= 1'b0;
m_axis_tlast <= 1'b0;
end
endcase
end
endmodule // chdr_pad_packet
`default_nettype wire
|