1//
2// Copyright 2019 Ettus Research, a National Instruments Brand
3//
4// SPDX-License-Identifier: LGPL-3.0-or-later
5//
6// Module: axi_extract_tlast_tkeep
7//
8// Description:
9//
10//   This module extracts the TLAST and TKEEP values that were embedded by the
11//   axi_embed_tlast_tkeep module. See axi_embed_tlast_tkeep for a description
12//   of how the data is encoded.
13//
14//   Here are some extraction examples for DATA_W = 64.
15//
16//     0x1234567887654321 becomes
17//     0x1234567887654321 (no changes)
18//
19//     0xDEADBEEF00000001 0x1234567887654321 becomes
20//     0x1234567887654321 with TLAST=1 and TKEEP=0
21//
22//     0xDEADBEEF00000005 0x1234567887654321 becomes
23//     0x1234567887654321 with TLAST=1 and TKEEP=2
24//
25//     0xDEADBEEF00000000 0xDEADBEEFFEEDCAFE
26//     0xDEADBEEFFEEDCAFE without TLAST=0 and TKEEP=0 becomes
27//
28//     0xDEADBEEF00000002 0xDEADBEEFFEEDCAFE
29//     0xDEADBEEFFEEDCAFE with TLAST=0 and TKEEP=1 becomes
30//
31
32module axi_extract_tlast_tkeep #(
33   parameter DATA_W = 64,
34   parameter KEEP_W = DATA_W  /8
35) (
36   input clk,
37   input rst,
38
39   // Input AXI-Stream
40   input      [DATA_W-1:0] i_tdata,
41   input                   i_tvalid,
42   output reg              i_tready,
43
44   // Output AXI-Stream
45   output reg [DATA_W-1:0] o_tdata,
46   output reg [KEEP_W-1:0] o_tkeep,
47   output reg              o_tlast,
48   output reg              o_tvalid,
49   input                   o_tready
50);
51
52  localparam                  ESC_WORD_W = 32;
53  localparam [ESC_WORD_W-1:0] ESC_WORD   = 'hDEADBEEF;
54
55
56  //---------------------------------------------------------------------------
57  // TKEEP and TLAST Holding Register
58  //---------------------------------------------------------------------------
59
60  reg              save_flags;
61  reg              tlast_saved;
62  reg [KEEP_W-1:0] tkeep_saved;
63
64  always @(posedge clk) begin
65    if (save_flags) begin
66      // Save the TLAST and TKEEP values embedded in the escape word
67      tlast_saved <= i_tdata[0];
68      tkeep_saved <= i_tdata[1 +: KEEP_W];
69    end
70  end
71
72
73  //--------------------------------------------------------------------------
74  // State Machine
75  //--------------------------------------------------------------------------
76
77  localparam ST_IDLE = 0;
78  localparam ST_DATA = 1;
79
80  reg [0:0] state = ST_IDLE;
81  reg [0:0] next_state;
82
83  always @(posedge clk) begin
84    if (rst) begin
85      state <= ST_IDLE;
86    end else begin
87      state <= next_state;
88    end
89  end
90
91  always @(*) begin
92    // Default assignments (pass through)
93    o_tdata    = i_tdata;
94    o_tlast    = 1'b0;
95    o_tkeep    = {KEEP_W{1'b1}};
96    save_flags = 1'b0;
97    next_state = state;
98    o_tvalid   = i_tvalid;
99    i_tready   = o_tready;
100
101    case(state)
102      //
103      // Search for escape code. If found don't pass data downstream but
104      // transition to next state. Otherwise, pass data downstream.
105      //
106      ST_IDLE: begin
107        if ((i_tdata[DATA_W-1 -: ESC_WORD_W] == ESC_WORD) && i_tvalid) begin
108          save_flags = 1'b1;
109          next_state = ST_DATA;
110          o_tvalid   = 1'b0;
111          i_tready   = 1'b1;
112        end
113      end
114
115      //
116      // Output data word with the saved TLAST and TKEEP values
117      //
118      ST_DATA: begin
119        o_tlast = tlast_saved;
120        o_tkeep = tkeep_saved;
121        if (i_tvalid & o_tready) begin
122          next_state = ST_IDLE;
123        end
124      end
125    endcase
126  end
127
128endmodule
129