module sync_fifo #(parameter WIDTH = 8, DEPTH = 4, SHOWAEAD = 1) ( input clk, input rstn, input wren, input rden, input [WIDTH-1:0] din, output [WIDTH-1:0] dout, output full, output empty ); parameter FIFO_MIN = DEPTH > 1 ? 0 : 1; parameter FIFO_MAX = DEPTH > 1 ? DEPTH - 1 : 1; reg [WIDTH-1:0] fifo[FIFO_MAX:FIFO_MIN]; reg [WIDTH-1:0] fifo_out; parameter ADDR = $clog2(DEPTH); reg [ADDR:0] counter; wire [WIDTH-1:0] fifo_head; wire wrreq = wren && !full; wire rdreq = rden && !empty; generate if (DEPTH > 1) assign fifo_head = fifo[counter[ADDR-1:0]]; else assign fifo_head = fifo[1]; endgenerate always @(posedge clk or negedge rstn) begin if (!rstn) begin counter <= 0; end else if (wrreq && !rdreq) begin counter <= counter + 1; end else if (rdreq && !wrreq) begin counter <= counter - 1; end end integer i; always @(posedge clk) begin if (wrreq) begin for (i = FIFO_MIN; i <= FIFO_MAX; i = i + 1) begin if (i == 0) begin fifo[i] <= fifo[FIFO_MAX]; end else if (i == 1) begin fifo[i] <= din; end else begin fifo[i] <= fifo[i - 1]; end end end end always @(posedge clk or negedge rstn) begin if (!rstn) begin fifo_out <= 0; end else if (rdreq) begin fifo_out <= fifo_head; end end assign dout = SHOWAEAD ? fifo_head : fifo_out; assign full = counter[ADDR]; assign empty = counter == 0; endmodule