always @ (posedge clk or negedge rst)
begin
if(!rst) //异步复位
begin
cnt_rd<=5'd0;
cnt_wr<=5'd0;
cnt_data<=5'd0;
full<=1'd0;
empty<=1'd0;
half_full<=1'd0;
end
else
begin
case({rd,wr})
2'b01: //只写操作
begin
if(!full) //FIFO没有写满,则执行写操作
begin
if(cnt_data==5'd16) //FIFO中已经有15个数据,再写就满了
begin
fiforam[cnt_wr-1]<=din;
cnt_data<=cnt_data;
full<=1'd1;
cnt_wr<=4'd0;
end
else
begin
fiforam[cnt_wr-1]<=din;
cnt_data<=cnt_data+5'd1;
full<=1'd0;
if(cnt_wr==5'd16)
cnt_wr<=4'd1;
else
cnt_wr<=cnt_wr+5'd1;
end
empty<=1'd0; //只写时空标志为0
end
else
begin
cnt_rd<=cnt_rd;
cnt_wr<=cnt_wr;
cnt_data<=cnt_data;
full<=full;
empty<=empty;
half_full<=half_full;
end
end
2'b10: //只读操作
begin
if(!empty) //FIFO没有读空,则执行读操作
begin
if(cnt_data==5'd0) //FIFO中只有1个数据,再读就空了
begin
dout<=fiforam[cnt_rd-1];
cnt_data<=cnt_data;
empty<=1'd1;
cnt_rd<=5'd0;
end
else
begin
dout<=fiforam[cnt_rd-1];
cnt_data<=cnt_data-5'd1;
empty<=1'd0;
if(cnt_rd==5'd16)
cnt_rd<=5'd0;
else
cnt_rd<=cnt_rd+5'd1;
end
full<=1'd0; //只写时空标志为0
end
else
begin
cnt_rd<=cnt_rd;
cnt_wr<=cnt_wr;
cnt_data<=cnt_data;
full<=full;
empty<=empty;
half_full<=half_full;
end
end
2'b11: //读写同时进行
begin
case({full,empty})
2'b00: //既没有写满也没有读空的情况
begin
dout<=fiforam[cnt_rd-1];
if(cnt_rd==5'd16) //如果指示器到最后了,则转到开始
cnt_rd<=5'd1;
else
cnt_rd<=cnt_rd+5'd1;
fiforam[cnt_wr-1]<=din;
if(cnt_wr==5'd16)
cnt_wr<=5'd1;
else
cnt_wr<=cnt_wr+5'd1;
end
2'b01: //没有写满,但已读空的情况
begin
dout<=din;
end
2'b10: //写满的情况
begin
dout<=fiforam[cnt_rd-1];
if(cnt_rd==5'd16) //如果指示器到最后了,则转到开始
cnt_rd<=4'd0;
else
cnt_rd<=cnt_rd+4'd1;
fiforam[cnt_wr-1]<=din;
if(cnt_wr==5'd16)
cnt_wr<=4'd0;
else
cnt_wr<=cnt_wr+4'd1;
end
endcase
end
default:
begin
cnt_rd<=cnt_rd;
cnt_wr<=cnt_wr;
cnt_data<=cnt_data;
full<=full;
empty<=empty;
half_full<=half_full;
end
endcase
end
end