// 8-bit FIFO with push and pop clocks.  32 bytes deep.
// Author:  Andrew Iverson
// Date: 12-5-99
//
//-----------------------------------------------------

`include "fifo_ram.v"
`include "udcount.v"

module fifo(data_out, empty, full, half_full, pop_en, push_en,
	    data_in, push_clk, pop_clk, n_reset);

  output [7:0] data_out;
  output empty, full, half_full;
  input pop_en, push_en;
  input [7:0] data_in;
  input push_clk, pop_clk, n_reset;

  wire empty, full;
  reg [4:0] push_address, pop_address;

  wire up, down;
  wire merge_clk;
  wire [5:0] fifo_count;
  wire read_en = pop_en;
  wire write_en = push_en;

  fifo_ram my_fifo_ram(.data_out(data_out), .data_in(data_in),
		       .rd_addr(pop_address), .wr_addr(push_address),
		       .write_en(write_en), .write_clk(push_clk));

  udcount my_counter(.count_data(fifo_count), .clk(merge_clk),
		     .up(up), .down(down), .n_reset(n_reset));

  assign half_full = n_reset ? (fifo_count[5:0] >= 6'b010000) : 1'b0;
  assign full = n_reset ? (fifo_count[5:0] == 6'b100000) : 1'b0;
  assign empty = n_reset ? (fifo_count[5:0] == 6'b000000) : 1'b1;

  assign merge_clk = (push_clk ^ pop_clk); 

  assign up = (write_en && !read_en && !full) ? 1'b1 : 1'b0;
  assign down = (!write_en && read_en && !empty) ? 1'b1 : 1'b0;


  always @ (posedge push_clk or negedge n_reset)
  begin
    if (~n_reset)
    begin
      push_address[4:0] <= 5'b00000;
    end
    else
    begin
      if (~full && write_en)
      begin
	push_address[4:0] <= push_address[4:0] + 5'b00001;
      end
    end
  end


  always @ (posedge pop_clk or negedge n_reset)
  begin
    if (~n_reset)
    begin
      pop_address[4:0] <= 5'b00000;
    end
    else
    begin
      if (~empty && read_en)
      begin
	pop_address[4:0] <= pop_address[4:0] + 5'b00001;
      end
    end
  end

endmodule
