目錄
一、FIFO
1.1 定義
1.2 實現(xiàn)方式
1.3 實現(xiàn)原理??
二、代碼實現(xiàn)
三、仿真結(jié)果
3.1 復(fù)位階段
3.2 寫入階段
3.3?讀取階段
3.4?同時讀寫或不讀不寫
四、參考資料
一、FIFO
1.1 定義
????FIFO(First in First out)為先進先出隊列,具有存儲功能,可用于不同時鐘域間傳輸數(shù)據(jù)以及不同的數(shù)據(jù)寬度進行數(shù)據(jù)匹配。如其名稱,數(shù)據(jù)傳輸為單向,從一側(cè)進入,再從另一側(cè)出來,出來的順序和進入的順序相同。
1.2 實現(xiàn)方式
????FIFO可由多種不同的實現(xiàn)方式,可以用塊狀RAM,分布式RAM來實現(xiàn),也可直接使用IP核,當(dāng)數(shù)據(jù)較小時,建議使用分布式RAM實現(xiàn),數(shù)據(jù)較大時,用塊狀RAM實現(xiàn)。
1.3 實現(xiàn)原理??
????FIFO組成包含存儲單元,寫時鐘,讀時鐘,滿標(biāo)志,空標(biāo)志,讀寫控制信號,當(dāng)讀時鐘和寫時鐘都是同一個時鐘時,則為同步FIFO,否則為異步FIFO。
????a.首先,在復(fù)位操作后,在寫時鐘控制下,如果狀態(tài)非滿狀態(tài),數(shù)據(jù)可寫入到FIFO中。每寫一次數(shù)據(jù),寫指針加一,寫滿后將不允許再寫入;
????b.當(dāng)FIFO中數(shù)據(jù)非空時,在讀時鐘的控制下,數(shù)據(jù)可從FIFO中讀出。每讀一次數(shù)據(jù),讀時鐘加一,位于下一個讀取的位置,在空狀態(tài)下,將不能繼續(xù)讀數(shù)據(jù);
????無論是同步FIFO還是異步FIFO,都是以雙口RAM為基礎(chǔ)來實現(xiàn)。
二、代碼實現(xiàn)
?????代碼為書籍《FPGA應(yīng)用技術(shù)及實踐》中5.3.3 FIFO設(shè)計中的代碼,相比原代碼中,對read/write為00時,對count的值變化進行了修改,修改為count<=count更合理,設(shè)計為實現(xiàn)4X16的同步FIFO
module FIFO_V(rst,clk,data_in,data_out,read,write,empty,full );
input rst,clk;
input [15:0] data_in;
output reg [15:0] data_out;
input read,write;
output empty,full;
parameter depth=2,max_count=2'b11;
reg empty,full;
reg [depth-1:0] tail;
reg [depth-1:0] head;
reg [depth-1:0] count;
reg [15:0] fifomem [0:max_count];
//讀空判斷
always@(posedge clk)
begin
if(rst==1)
begin
data_out<=16'h0000;
end
else if(read==1'b1&&empty==1'b0)
begin
data_out<=fifomem[tail];
end
end
//寫滿判斷
always@(posedge clk)
begin
if(rst==1'b0&&write==1'b1&&full==1'b0)
fifomem[head]<=data_in;
end
//寫操作
always@(posedge clk)
begin
if(rst==1)
head<=2'b00;
else
begin
if(write==1'b1&&full==1'b0)
head<=head+1;
end
end
//讀操作
always@(posedge clk)
begin
if(rst==1)
begin
tail<=2'b00;
end
else if(read==1'b1&&empty==1'b0)
begin
tail<=tail+1;
end
end
//讀寫操作下的計數(shù)
always@(posedge clk)
begin
if(rst==1)
begin
count<=2'b00;
end
else
begin
case({read,write})
2'b00:count<=count;
2'b01:if(count!=max_count) count<=count+1;
2'b10:if(count!=2'b00) count<=count-1;
2'b11:count<=count;
endcase
end
end
//隊列空狀態(tài)判斷
always@(posedge clk)
begin
if(count==2'b00)
empty<=1'b1;
else
empty<=1'b0;
end
//隊列滿狀態(tài)判斷
always@(posedge clk)
begin
if(count==max_count)
full<=1'b1;
else
full<=1'b0;
end
endmodule
測試代碼?
對于read和write信號,盡量避免在時鐘上升沿時進行狀態(tài)變化,如此處write翻轉(zhuǎn)在201ns,read翻轉(zhuǎn)在#252,即避免了和時鐘的上升沿同步,也避免了和write翻轉(zhuǎn)的同步
`timescale 1ns / 1ps
module FIFO_tb( );
reg clk,rst,write,read;
reg [15:0] data_in;
wire [15:0] data_out;
wire empty,full;
FIFO_V FIFO_test (.clk(clk),.rst(rst),.data_in(data_in),.write(write),.read(read),.empty(empty),.full(full),.data_out(data_out));
//初始狀態(tài)賦值
initial
begin
clk=0;
rst=1;
data_in=16'h1111;
#51 rst=0;
end
//寫操作
initial
begin
write=1;
#201 write=1;
#30 write=0;
#200 write=1;
#85 write=0;
//#10 write=1;
//#60 write=0;
end
//讀操作
initial
begin
read=0;
#252 read=1;
#200 read=0;
#100 read=1;
end
//輸入信號與時鐘信號生成
always #20 data_in=data_in+16'h1111;
always #10 clk=~clk;
endmodule
三、仿真結(jié)果
3.1 復(fù)位階段
????在起始的50ns內(nèi),復(fù)位信號rst(紅色標(biāo)注)為1時,進行復(fù)位操作,如黃色定位線所示,輸出data_out為0,empty和full標(biāo)志為0;
?
3.2 寫入階段
????在110.1ns時開始寫入,時間點不是110ns而是多了0.1ns是由于modelsim默認(rèn)的開始時刻是0.1ns開始;因為count原先一直處于初始化狀態(tài)2'b00,在此時因為寫入進行了empty的邏輯判斷,因為empty為0;
????在clk信號中1、2、3、4上升沿位置,即為寫入4個值:6666,7777,8888,9999,寫完后剛好寫滿,因此full標(biāo)志位在170.1ns處變?yōu)?,表示已寫滿無法再寫入。
?
3.3?讀取階段
????在270.1ns時,read/write的值為1/0開始從FIFO中進行數(shù)據(jù)讀取,在clk信號的1,2,3,4讀取了4個數(shù)值,根據(jù)data_out可知為6666,7777,8888,9999。讀出順序與寫入順序一致,即先入先出。
3.4?同時讀寫或不讀不寫
????在450ns時,read/write都為1,讀寫同時進行,并且empty為1,可知不進行讀操作,count的邏輯。但因full為0,可以進行寫入,此時進行寫入,在4個clk周期寫滿,因此在530.1ns時full標(biāo)志位為1
?
????在530ns和550ns時,read/write都為0,此時不讀也不寫入,因此輸出狀態(tài)不變,一直為9999,
?
四、參考資料
書籍《FPGA應(yīng)用技術(shù)及實踐》中5.3.3 FIFO設(shè)計章節(jié)文章來源:http://www.zghlxwxcb.cn/news/detail-543324.html
????文章來源地址http://www.zghlxwxcb.cn/news/detail-543324.html
到了這里,關(guān)于Verilog基礎(chǔ)之十四、FIFO實現(xiàn)的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!