|
轉(zhuǎn)了一篇?jiǎng)e人寫的,沒看一眼代碼,因?yàn)樽畈幌矚g的就是看別人寫的代碼。今天抽空自己寫了一段小代碼,在ModelSim中仿真了,結(jié)果還是正確的。
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; //讀數(shù)據(jù)指示器
reg [4:0] cnt_wr; //寫數(shù)據(jù)指示器
reg [4:0] cnt_data; //數(shù)據(jù)個(gè)數(shù)指示器
reg [7:0] fiforam[15:0]; //FIFO存儲(chǔ)數(shù)組
reg empty,full,half_full;
always @ (posedge clk or negedge rst)
begin
if(!rst) //異步復(fù)位
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沒有寫滿,則執(zhí)行寫操作
begin
if(cnt_data==5'd16) //FIFO中已經(jīng)有15個(gè)數(shù)據(jù),再寫就滿了
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) //半滿標(biāo)志
half_full<=1'd1;
else
half_full<=1'd0;
empty<=1'd0; //只寫時(shí)空標(biāo)志為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沒有讀空,則執(zhí)行讀操作
begin
if(cnt_data==5'd0) //FIFO中只有1個(gè)數(shù)據(jù),再讀就空了
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; //只寫時(shí)空標(biāo)志為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: //讀寫同時(shí)進(jìn)行
begin
case({full,empty})
2'b00: //既沒有寫滿也沒有讀空的情況
begin
dout<=fiforam[cnt_rd-1];
if(cnt_rd==5'd16) //如果指示器到最后了,則轉(zhuǎn)到開始
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) //如果指示器到最后了,則轉(zhuǎn)到開始
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
|
|