1//
2// Copyright 2012 Ettus Research, a National Instruments Company
3//
4// SPDX-License-Identifier: LGPL-3.0-or-later
5//
6
7//
8// axi_loopback.v
9//
10// Loopback all data assuming it's in CHDR format, and swap SRC/DST in the SID in the process
11// thus reflecting it back to it's origin...in theory!
12//
13
14module axi_loopback
15 #(
16   parameter WIDTH = 64
17  )
18  (
19   input clk,
20   input reset,
21   // Input AXIS
22   input [WIDTH-1:0] i_tdata,
23   input i_tlast,
24   input i_tvalid,
25   output i_tready,
26   // Output AXIS
27   output [WIDTH-1:0] o_tdata,
28   output o_tlast,
29   output o_tvalid,
30   input o_tready
31   );
32
33   wire [WIDTH-1:0]     fifoin_tdata,fifoout_tdata,dmux_tdata;
34   wire                 fifoin_tlast,dmux_tlast;
35   wire                 fifoin_tvalid,dmux_tvalid;
36   wire                 fifoin_tready,dmux_tready;
37
38   // Since most real endpoints go via Demux4 place one in here to look for bugs.
39   axi_demux4 #(.ACTIVE_CHAN(4'b0001), .WIDTH(WIDTH)) demux
40     (.clk(clk), .reset(reset), .clear(1'b0),
41      .header(), .dest(2'b00),
42      .i_tdata(i_tdata), .i_tlast(i_tlast), .i_tvalid(i_tvalid), .i_tready(i_tready),
43      .o0_tdata(dmux_tdata), .o0_tlast(dmux_tlast), .o0_tvalid(dmux_tvalid), .o0_tready(dmux_tready),
44      .o1_tdata(), .o1_tlast(), .o1_tvalid(), .o1_tready(1'b1),
45      .o2_tdata(), .o2_tlast(), .o2_tvalid(), .o2_tready(1'b1),
46      .o3_tdata(), .o3_tlast(), .o3_tvalid(), .o3_tready(1'b1));
47
48   axi_fifo_short #(.WIDTH(WIDTH+1)) axi_fifo_short1
49     (.clk(clk), .reset(reset), .clear(1'b0),
50      .i_tdata({dmux_tlast,dmux_tdata}), .i_tvalid(dmux_tvalid), .i_tready(dmux_tready),
51      .o_tdata({fifoin_tlast,fifoin_tdata}), .o_tvalid(fifoin_tvalid), .o_tready(fifoin_tready),
52      .space(), .occupied());
53
54   reg header;
55   always @(posedge clk) begin
56     if(reset) begin
57       header <= 1'b1;
58     end else if (header) begin
59       if(fifoin_tvalid & fifoin_tready & ~fifoin_tlast) header <= 1'b0;
60     end else begin
61       if(fifoin_tvalid & fifoin_tready & fifoin_tlast) header <= 1'b1;
62     end
63   end
64
65   assign fifoout_tdata = header ?
66			       {fifoin_tdata[63:32] ,fifoin_tdata[15:0],fifoin_tdata[31:16]} :
67			       fifoin_tdata;
68
69   axi_fifo_short #(.WIDTH(WIDTH+1)) axi_fifo_short2
70     (.clk(clk), .reset(reset), .clear(1'b0),
71      .i_tdata({fifoin_tlast,fifoout_tdata}), .i_tvalid(fifoin_tvalid), .i_tready(fifoin_tready),
72      .o_tdata({o_tlast,o_tdata}), .o_tvalid(o_tvalid), .o_tready(o_tready),
73      .space(), .occupied());
74
75endmodule // axi_loopback
76