1//
2// Copyright 2012 Ettus Research LLC
3// Copyright 2018 Ettus Research, a National Instruments Company
4// Copyright 2020 Ettus Research, a National Instruments Brand
5//
6// SPDX-License-Identifier: LGPL-3.0-or-later
7//
8// Description: 32 word FIFO with AXI4-Stream interface.
9//
10// NOTE: This module uses the SRLC32E primitive explicitly and as such can
11// only be used with Xilinx technology.
12//
13
14module axi_fifo_short #(
15  parameter WIDTH = 32
16) (
17  input              clk,
18  input              reset,
19  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 reg [5:0] space,
28  output reg [5:0] occupied
29);
30
31  reg  full  = 1'b0, empty = 1'b1;
32  wire write = i_tvalid & i_tready;
33  wire read  = o_tready & o_tvalid;
34
35  assign i_tready = ~full;
36  assign o_tvalid = ~empty;
37
38  reg [4:0] a;
39  genvar i;
40
41  generate
42    for (i=0;i<WIDTH;i=i+1) begin : gen_srlc32e
43      SRLC32E srlc32e(
44        .Q(o_tdata[i]), .Q31(),
45        .A(a),
46        .CE(write),.CLK(clk),.D(i_tdata[i])
47      );
48    end
49  endgenerate
50
51  always @(posedge clk) begin
52    if(reset) begin
53       a <= 0;
54       empty <= 1;
55       full <= 0;
56    end
57    else if(clear) begin
58      a <= 0;
59      empty <= 1;
60      full<= 0;
61    end
62    else if(read & ~write) begin
63      full <= 0;
64      if(a==0)
65        empty <= 1;
66      else
67        a <= a - 1;
68    end
69    else if(write & ~read) begin
70      empty <= 0;
71      if(~empty)
72        a <= a + 1;
73      if(a == 30)
74        full <= 1;
75    end
76  end
77
78  // NOTE: Will fail if you write into a full FIFO or read from an empty one
79
80  always @(posedge clk) begin
81    if(reset)
82      space <= 6'd32;
83    else if(clear)
84      space <= 6'd32;
85    else if(read & ~write)
86      space <= space + 6'd1;
87    else if(write & ~read)
88      space <= space - 6'd1;
89  end
90
91  always @(posedge clk) begin
92    if(reset)
93      occupied <= 6'd0;
94    else if(clear)
95      occupied <= 6'd0;
96    else if(read & ~write)
97      occupied <= occupied - 6'd1;
98    else if(write & ~read)
99      occupied <= occupied + 6'd1;
100  end
101
102endmodule // axi_fifo_short
103