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
|