轉了一篇別人寫的,沒看一眼代碼,因為最不喜歡的就是看別人寫的代碼。今天抽空自己寫了一段小代碼,在ModelSim中仿真了,結果還是正確的。
module chipfifo(clk,rst,wr,din,rd,dout,full,empty,half_full);
input clk,rst;
input wr,rd;
input [7:0] din;
output [7:0] dout;
output full,empty,half_full;
reg [7:0] dout;
reg [4:0] cnt_rd; //讀數據指示器
reg [4:0] cnt_wr; //寫數據指示器
reg [4:0] cnt_data; //數據個數指示器
reg [7:0] fiforam[15:0]; //FIFO存儲數組
reg empty,full,half_full;
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
if(cnt_wr==5'd8) //半滿標志
half_full<=1'd1;
else
half_full<=1'd0;
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
endmodule
|