stack-machine/fifo.v

73 lines
1.5 KiB
Verilog

module FIFO (CLK_I, RST_I, DAT_I, DAT_O, QUEUE_I, DEQUEUE_I, EMPTY_O, FULL_O);
// entries = 2**QUEUE_SIZE
parameter QUEUE_SIZE = 2;
parameter DATA_WIDTH = 32;
// If true, queue and dequeue can be simultaneous
// on empty and full queues. Otherwise data must
// pass through the queue first, costing one cycle.
parameter WRITE_THROUGH = 0;
input CLK_I, RST_I, QUEUE_I, DEQUEUE_I;
input [DATA_WIDTH-1:0] DAT_I;
output [DATA_WIDTH-1:0] DAT_O;
output EMPTY_O, FULL_O;
reg [QUEUE_SIZE-1:0] HEAD = 0;
reg [QUEUE_SIZE-1:0] TAIL = 0;
wire [QUEUE_SIZE-1:0] NEXT_HEAD = HEAD + 1;
generate
if (WRITE_THROUGH == 0)
begin : force_queue
assign EMPTY_O = (HEAD == TAIL);
assign FULL_O = (NEXT_HEAD == TAIL);
end
else
begin : write_through
assign EMPTY_O = (HEAD == TAIL) & ~QUEUE_I;
assign FULL_O = (NEXT_HEAD == TAIL) & ~DEQUEUE_I;
end
endgenerate
always @(posedge CLK_I)
begin
if (RST_I)
begin
HEAD <= 0;
TAIL <= 0;
end
else
begin
if (QUEUE_I & ~FULL_O)
HEAD <= HEAD + 1;
if (DEQUEUE_I & ~EMPTY_O)
TAIL <= TAIL + 1;
end
end
// synthesis attribute ram_style of QUEUE is distributed;
reg [DATA_WIDTH-1:0] QUEUE[0:(1<<QUEUE_SIZE)-1];
always @(posedge CLK_I)
begin
if (QUEUE_I & ~FULL_O)
QUEUE[HEAD] <= DAT_I;
end
generate
if (WRITE_THROUGH == 0)
begin : force_queue_out
assign DAT_O = QUEUE[TAIL];
end
else
begin : write_through_out
assign DAT_O = (HEAD == TAIL) ? DAT_I : QUEUE[TAIL];
end
endgenerate
endmodule