module Fifo #(parameter [7:0]FIFOSIZE=16)
  (
  input clk,                // system clock
  input [7:0]data_push,     // data to be sent (put into fifo_wr)
  input push,               // on pos edge data is written
  input pop,                // on pos edge data is read
  input clear,
  output fifo_full,         // fifo full signal 
  output fifo_empty,        // fifo empty signal 
  output reg [7:0]data_pop  // data to be sent (put into fifo_wr)
  );

  reg [7:0] fifo[0:FIFOSIZE-1];
  reg [7:0] rd_index = 0;
  reg [7:0] wr_index = 0;
  reg poptm1 = 0;
  reg pushtm1 = 0;
  reg datavalid = 0;

  function [7:0] nextIndex (input [7:0] idx);
      nextIndex = (idx  + 8'd1) & (FIFOSIZE - 8'd1);
  endfunction

  always@(posedge clk)  begin
    if (clear) begin
        wr_index <= 0;
        pushtm1 <= 0;
    end else begin 
      if (push && pushtm1==0 && !fifo_full) begin
        fifo[wr_index] <= data_push;
        wr_index <= nextIndex(wr_index);
      end  
      pushtm1 <= push;
    end  
  end  


  always@(posedge clk)  begin
    if (clear) begin
      rd_index <= 0;
      datavalid <= 0;
      poptm1 <= 0;
    end else begin 
      if ((rd_index != wr_index)) begin
          if (pop && poptm1 == 0) begin
            rd_index <= nextIndex(rd_index);
            datavalid <= 0;
          end else  begin
            data_pop <= fifo[rd_index];
            datavalid <= 1;
          end  
          poptm1 <= pop;
      end    
    end  
  end  

  assign fifo_empty = (rd_index == wr_index) || !datavalid;
  assign fifo_full = (nextIndex(wr_index) == rd_index);
	
endmodule
