module simple_axis_srl_fifo #(
  parameter WIDTH = 8,
  parameter DEPTH = 16
) (
  input  wire                       clk,
  input  wire                       rst,

  input  wire                       din_valid,
  input  wire [WIDTH-1:0]           din,

  output wire                       dout_valid,
  output wire [WIDTH-1:0]           dout,
  input  wire                       dout_ready,

  output wire [$clog2(DEPTH+1)-1:0] count
);

  reg [WIDTH-1:0] data_reg[DEPTH-1:0];
  reg [$clog2(DEPTH+1)-1:0] ptr_reg = 0;
  reg empty_reg = 1'b1, empty_next;

  wire ptr_empty  = ptr_reg == 0;
  wire ptr_empty1 = ptr_reg == 1;
  wire ptr_full   = ptr_reg == DEPTH;
  wire ptr_full1  = ptr_reg == DEPTH-1;

  reg shift;
  reg inc;
  reg dec;

  integer i;

  initial begin
    for (i = 0; i < DEPTH; i = i + 1)
      data_reg[i] <= 0;
  end

  always @* begin
    shift = 1'b0;
    inc = 1'b0;
    dec = 1'b0;
    empty_next = empty_reg;

    if (dout_ready && din_valid) begin
      shift = 1'b1;
      inc = ptr_empty;
      empty_next = 1'b0;
    end else if (dout_ready && dout_valid) begin
      dec = 1'b1;
      empty_next = ptr_empty1;
    end else if (din_valid) begin
      shift = 1'b1;
      inc = 1'b1;
      empty_next = 1'b0;
    end
  end

  always @(posedge clk) begin
    if (inc)
      ptr_reg <= ptr_reg + 1;
    else if (dec)
      ptr_reg <= ptr_reg - 1;
    else
      ptr_reg <= ptr_reg;

    empty_reg <= empty_next;

    if (shift) begin
      data_reg[0] <= din;
      for (i = 0; i < DEPTH-1; i = i + 1)
        data_reg[i+1] <= data_reg[i];
    end

    if (rst) begin
      ptr_reg <= 0;
      empty_reg <= 1'b1;
    end
  end

  assign dout = data_reg[ptr_reg-1];
  assign dout_valid = !empty_reg;
  assign count = ptr_reg;

endmodule