1//
2// Copyright 2012-2014 Ettus Research LLC
3// Copyright 2018 Ettus Research, a National Instruments Company
4//
5// SPDX-License-Identifier: LGPL-3.0-or-later
6//
7
8// General FIFO block
9//  Size == 0: Uses a single stage flop (axi_fifo_flop).
10//  Size == 1: Uses a two stage flop (axi_fifo_flop2). Best choice for single stage pipelining.
11//             Breaks combinatorial paths on the AXI stream data / control lines at the cost of
12//             additional registers. Maps to SLICELs (i.e. does not use distributed RAM).
13//  Size <= 5: Uses SRL32 to efficient maps a 32 deep FIFO to SLICEMs (axi_fifo_short). Not
14//             recommended for pipelining as most devices have twice as many SLICELs as SLICEMs.
15//  Size  > 5: Uses BRAM fifo (axi_fifo_bram)
16
17module axi_fifo
18  #(parameter WIDTH=32, SIZE=5)
19   (input clk, input reset, input clear,
20    input [WIDTH-1:0] i_tdata,
21    input i_tvalid,
22    output i_tready,
23    output [WIDTH-1:0] o_tdata,
24    output o_tvalid,
25    input o_tready,
26
27    output [15:0] space,
28    output [15:0] occupied);
29
30   generate
31   if(SIZE==0)
32   begin
33      axi_fifo_flop #(.WIDTH(WIDTH)) fifo_flop
34        (.clk(clk), .reset(reset), .clear(clear),
35         .i_tdata(i_tdata), .i_tvalid(i_tvalid), .i_tready(i_tready),
36         .o_tdata(o_tdata), .o_tvalid(o_tvalid), .o_tready(o_tready),
37         .space(space[0]), .occupied(occupied[0]));
38      assign space[15:1] = 15'd0;
39      assign occupied[15:1] = 15'd0;
40   end
41   else if(SIZE==1)
42   begin
43      axi_fifo_flop2 #(.WIDTH(WIDTH)) fifo_flop2
44        (.clk(clk), .reset(reset), .clear(clear),
45         .i_tdata(i_tdata), .i_tvalid(i_tvalid), .i_tready(i_tready),
46         .o_tdata(o_tdata), .o_tvalid(o_tvalid), .o_tready(o_tready),
47         .space(space[1:0]), .occupied(occupied[1:0]));
48      assign space[15:2] = 14'd0;
49      assign occupied[15:2] = 14'd0;
50   end
51   else if(SIZE<=5)
52   begin
53      axi_fifo_short #(.WIDTH(WIDTH)) fifo_short
54        (.clk(clk), .reset(reset), .clear(clear),
55         .i_tdata(i_tdata), .i_tvalid(i_tvalid), .i_tready(i_tready),
56         .o_tdata(o_tdata), .o_tvalid(o_tvalid), .o_tready(o_tready),
57         .space(space[5:0]), .occupied(occupied[5:0]));
58      assign space[15:6] = 10'd0;
59      assign occupied[15:6] = 10'd0;
60   end
61   else
62   begin
63      axi_fifo_bram #(.WIDTH(WIDTH), .SIZE(SIZE)) fifo_bram
64        (.clk(clk), .reset(reset), .clear(clear),
65         .i_tdata(i_tdata), .i_tvalid(i_tvalid), .i_tready(i_tready),
66         .o_tdata(o_tdata), .o_tvalid(o_tvalid), .o_tready(o_tready),
67         .space(space), .occupied(occupied));
68   end
69   endgenerate
70
71endmodule // axi_fifo
72