File: axi_embed_tlast.v

package info (click to toggle)
uhd 3.9.5-2
  • links: PTS, VCS
  • area: main
  • in suites: stretch
  • size: 107,272 kB
  • ctags: 57,231
  • sloc: cpp: 66,160; ansic: 59,349; python: 13,245; vhdl: 7,651; tcl: 2,668; sh: 1,634; makefile: 1,031; xml: 557; pascal: 230; csh: 94; asm: 20; perl: 11
file content (124 lines) | stat: -rw-r--r-- 3,096 bytes parent folder | download | duplicates (2)
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
//
// 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;

   reg [31:0] checksum;
   generate if (ADD_CHECKSUM == 1) begin
      always @(posedge clk) begin
         if (reset | clear) begin
            checksum <= 0;
         end else if (i_tready && i_tvalid && i_tlast) begin
            checksum <= 0;
         end else if (i_tready && i_tvalid) begin
            checksum <= checksum ^ i_tdata[31:0] ^ i_tdata[63:32];
         end
      end
   end else begin
      always @* 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