module fifo #( parameter SIZE = 16, parameter WIDTH = 8 )( input wire clk, input wire wr_en, input wire[WIDTH-1:0] wr_data, input wire rd_en, output reg[WIDTH-1:0] rd_data, output wire full, output wire empty ); localparam LOGSIZE = $clog2(SIZE); reg [WIDTH-1:0] fifo[0:SIZE-1]; reg [LOGSIZE-1:0] wr_ptr; reg [LOGSIZE-1:0] rd_ptr; reg [LOGSIZE:0] count; assign full = (count == SIZE); assign empty = (count == 0); initial begin wr_ptr = 0; rd_ptr = 0; count = 0; end always @(posedge clk) begin // IN rd_data <= fifo[rd_ptr]; if (wr_en && !full && rd_en && !empty) begin fifo[wr_ptr] <= wr_data; wr_ptr <= (wr_ptr == SIZE - 1) ? 0 : (wr_ptr + 1) ; rd_ptr <= (rd_ptr == SIZE - 1) ? 0 : (rd_ptr + 1) ; end else if (wr_en && !full) begin fifo[wr_ptr] <= wr_data; wr_ptr <= (wr_ptr == SIZE - 1) ? 0 : (wr_ptr + 1) ; count <= count + 1; end else if (rd_en && !empty) begin // OUT rd_ptr <= (rd_ptr == SIZE - 1) ? 0 : (rd_ptr + 1) ; count <= count - 1; end end endmodule