blob: d1b93e5f0773eb15eff14cc8bd9a1cb1b06e277a [file] [log] [blame]
module fifo_tmp #(
parameter FIFO_DATA_WIDTH = 5,
parameter FIFO_SIZE = 32,
parameter FIFO_SIZE_WIDTH = 5
) (
input clk,
input reset,
input flush,
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];
/* verilator lint_off WIDTH*/
integer i;
//write fifo
always @(posedge clk) begin
if (reset) begin
for (i = 0; i < FIFO_SIZE; i = i + 1) begin
fifo_queue[i] <= 0;
end
end else if (flush) begin
for (i = 0; i < FIFO_SIZE; i = i + 1) begin
fifo_queue[i] <= 0;
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 <= 0;
end else if (flush) begin
fifo_recount <= 0;
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_tmp #(
.CNT_SIZE(FIFO_SIZE),
.CNT_SIZE_WIDTH(FIFO_SIZE_WIDTH)
) wr_cnt(
.clk(clk),
.reset(reset),
.flush(flush),
.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_tmp #(
.CNT_SIZE(FIFO_SIZE),
.CNT_SIZE_WIDTH(FIFO_SIZE_WIDTH)
) rd_cnt(
.clk(clk),
.reset(reset),
.flush(flush),
.cnt_add_flag(rd_cnt_flag),
.cnt(rd_line),
.cnt_end(rd_line_end)
);
assign rd_cnt_flag = rd_en & !fifo_empty;
endmodule