blob: 8c526f9355539ea534406c59ee12bc0414d3be72 [file] [log] [blame]
module fifo #( //p0 is not in the fifo
parameter FIFO_DATA_WIDTH = 5,
parameter FIFO_SIZE = 32,
parameter FIFO_SIZE_WIDTH = 5
) (
input clk,
input reset,
input wr_en,
input rd_en,
input [FIFO_DATA_WIDTH-1:0] wdata,
output reg [FIFO_DATA_WIDTH-1:0] rdata,
output reg fifo_full,
output reg fifo_empty,
output reg [FIFO_SIZE_WIDTH-1:0] fifo_num
);
wire wr_cnt_flag;
wire rd_cnt_flag;
wire cnt_cmp_greater;
wire cnt_cmp_equal;
wire [FIFO_SIZE_WIDTH-1:0] rd_line;
wire [FIFO_SIZE_WIDTH-1:0] wr_line;
wire wr_line_end;
wire rd_line_end;
wire fifo_turn_arroud; //to show wr and rd both count over a fifo queue size
reg fifo_recount; //to record wr count over a fifo queue size
reg [FIFO_DATA_WIDTH-1:0] fifo_queue[FIFO_SIZE-1:0];
integer i;
/* verilator lint_off WIDTH */
//write fifo
always @(posedge clk) begin
if (reset) begin
for (i = 0; i < FIFO_SIZE ; i = i + 1) begin
fifo_queue[i] <= i + 1;
end
end else if (wr_cnt_flag) begin
fifo_queue[wr_line] <= wdata;
end
end
//read fifo
always @(*) begin
rdata = fifo_queue[rd_line];
end
//fifo number calculate
always @(*) begin
if (cnt_cmp_greater) begin
fifo_num = wr_line - rd_line;
end else if (cnt_cmp_equal) begin
if (fifo_recount) begin
fifo_num = FIFO_SIZE;
end else begin
fifo_num = 0;
end
end else begin
fifo_num = FIFO_SIZE + wr_line - rd_line;
end
end
assign cnt_cmp_greater = wr_line > rd_line;
assign cnt_cmp_equal = wr_line == rd_line;
always @(*) begin
fifo_full = fifo_num == FIFO_SIZE;
end
always @(*) begin
fifo_empty = fifo_num == 0;
end
//fifo recount
always @(posedge clk) begin
if (reset) begin
fifo_recount <= 1;
end else if (wr_line_end) begin
fifo_recount <= 1;
end else if (fifo_turn_arroud) begin
fifo_recount <= 0;
end
end
assign fifo_turn_arroud = fifo_recount & rd_line_end;
//write counter
counter #(
.CNT_SIZE(FIFO_SIZE),
.CNT_SIZE_WIDTH(FIFO_SIZE_WIDTH)
) wr_cnt(
.clk(clk),
.reset(reset),
.cnt_add_flag(wr_cnt_flag),
.cnt(wr_line),
.cnt_end(wr_line_end)
);
assign wr_cnt_flag = wr_en & !fifo_full;
//read counter
counter #(
.CNT_SIZE(FIFO_SIZE),
.CNT_SIZE_WIDTH(FIFO_SIZE_WIDTH)
) rd_cnt(
.clk(clk),
.reset(reset),
.cnt_add_flag(rd_cnt_flag),
.cnt(rd_line),
.cnt_end(rd_line_end)
);
assign rd_cnt_flag = rd_en & !fifo_empty;
/* verilator lint_on WIDTH */
endmodule