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 2014 Ettus Research LLC
// Copyright 2018 Ettus Research, a National Instruments Company
//
// SPDX-License-Identifier: LGPL-3.0-or-later
//
//
// AXI stream neds N+1 bits to transmit packets of N bits so that the LAST bit can be represented.
// LAST occurs relatively infrequently and can be synthesized by using an in-band ESC code to generate
// a multi-word sequence to encode it (and the escape character when it appears as data input).
//
// 0x1234567887654321 with last becomes
// 0xDEADBEEFFEEDCAFE 0x0000000000000001 0x1234567887654321
//
// 0xDEADBEEFFEEDCAFE with last becomes
// 0xDEADBEEFFEEDCAFE 0x0000000000000001 0xDEADBEEFFEEDCAFE
//
// 0xDEADBEEFFEEDCAFE without last becomes
// 0xDEADBEEFFEEDCAFE 0x0000000000000000 0xDEADBEEFFEEDCAFE
//
module axi_embed_tlast #(
parameter WIDTH=64,
parameter ADD_CHECKSUM=0
) (
input clk,
input reset,
input clear,
//
input [WIDTH-1:0] i_tdata,
input i_tlast,
input i_tvalid,
output i_tready,
//
output reg [WIDTH-1:0] o_tdata,
output o_tvalid,
input o_tready
);
localparam PASS = 0;
localparam ZERO = 1;
localparam ONE = 2;
localparam ESCAPE = 3;
localparam IDLE = 0;
localparam LAST = 1;
localparam ESC = 2;
localparam FINISH = 3;
reg [1:0] state, next_state;
reg [1:0] select;
wire [31:0] checksum;
generate if (ADD_CHECKSUM == 1) begin
reg [31:0] checksum_reg;
always @(posedge clk) begin
if (reset | clear) begin
checksum_reg <= 0;
end else if (i_tready && i_tvalid && i_tlast) begin
checksum_reg <= 0;
end else if (i_tready && i_tvalid) begin
checksum_reg <= checksum_reg ^ i_tdata[31:0] ^ i_tdata[63:32];
end
end
assign checksum = checksum_reg;
end else begin
assign checksum = 32'h0;
end endgenerate
always @(posedge clk)
if (reset | clear) begin
state <= IDLE;
end else begin if (o_tready)
state <= next_state;
end
always @(*) begin
case(state)
IDLE: begin
if (i_tlast && i_tvalid) begin
next_state = LAST;
select = ESCAPE;
end else if ((i_tdata == 64'hDEADBEEFFEEDCAFE) && i_tvalid) begin
next_state = ESC;
select = ESCAPE;
end else begin
next_state = IDLE;
select = PASS;
end
end // case: IDLE
LAST: begin
select = ONE;
next_state = FINISH;
end
ESC: begin
select = ZERO;
next_state = FINISH;
end
FINISH: begin
select = PASS;
if (i_tvalid)
next_state = IDLE;
else
next_state = FINISH;
end
endcase // case(state)
end // always @ (*)
//
// Muxes
//
always @*
begin
case(select)
PASS: o_tdata = i_tdata;
ZERO: o_tdata = 0;
ONE: o_tdata = {checksum[31:0],32'h1};
ESCAPE: o_tdata = 64'hDEADBEEFFEEDCAFE;
endcase // case(select)
end
assign o_tvalid = (select == PASS) ? i_tvalid : 1'b1;
assign i_tready = (select == PASS) ? o_tready : 1'b0;
endmodule // axi_embed_tlast
|