一、FIFO
1.1 定義
FIFO(First in First out)為先進先出隊列,具有存儲功能,可用于不同時鐘域間傳輸數據以及不同的數據寬度進行數據匹配。如其名稱,數據傳輸為單向,從一側進入,再從另一側出來,出來的順序和進入的順序相同。
1.2 實現方式
FIFO可由多種不同的實現方式,可以用塊狀RAM,分布式RAM來實現,也可直接使用IP核,當數據較小時,建議使用分布式RAM實現,數據較大時,用塊狀RAM實現。
1.3 實現原理
FIFO組成包含存儲單元,寫時鐘,讀時鐘,滿標志,空標志,讀寫控制信號,當讀時鐘和寫時鐘都是同一個時鐘時,則為同步FIFO,否則為異步FIFO。
a.首先,在復位操作后,在寫時鐘控制下,如果狀態非滿狀態,數據可寫入到FIFO中。每寫一次數據,寫指針加一,寫滿后將不允許再寫入;
b.當FIFO中數據非空時,在讀時鐘的控制下,數據可從FIFO中讀出。每讀一次數據,讀時鐘加一,位于下一個讀取的位置,在空狀態下,將不能繼續讀數據;
無論是同步FIFO還是異步FIFO,都是以雙口RAM為基礎來實現。
二、代碼實現
代碼為書籍《FPGA應用技術及實踐》中5.3.3 FIFO設計中的代碼,相比原代碼中,對read/write為00時,對count的值變化進行了修改,修改為count<=count更合理,設計為實現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
//讀寫操作下的計數
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
//隊列空狀態判斷
always@(posedge clk)
begin
if(count==2'b00)
empty<=1'b1;
else
empty<=1'b0;
end
//隊列滿狀態判斷
always@(posedge clk)
begin
if(count==max_count)
full<=1'b1;
else
full<=1'b0;
end
endmodule
測試代碼
對于read和write信號,盡量避免在時鐘上升沿時進行狀態變化,如此處write翻轉在201ns,read翻轉在#252,即避免了和時鐘的上升沿同步,也避免了和write翻轉的同步
`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));
//初始狀態賦值
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
三、仿真結果
3.1 復位階段
在起始的50ns內,復位信號rst(紅色標注)為1時,進行復位操作,如黃色定位線所示,輸出data_out為0,empty和full標志為0;
3.2 寫入階段
在110.1ns時開始寫入,時間點不是110ns而是多了0.1ns是由于modelsim默認的開始時刻是0.1ns開始;因為count原先一直處于初始化狀態2'b00,在此時因為寫入進行了empty的邏輯判斷,因為empty為0;
在clk信號中1、2、3、4上升沿位置,即為寫入4個值:6666,7777,8888,9999,寫完后剛好寫滿,因此full標志位在170.1ns處變為1,表示已寫滿無法再寫入。
3.3 讀取階段
在270.1ns時,read/write的值為1/0開始從FIFO中進行數據讀取,在clk信號的1,2,3,4讀取了4個數值,根據data_out可知為6666,7777,8888,9999。讀出順序與寫入順序一致,即先入先出。
3.4 同時讀寫或不讀不寫
在450ns時,read/write都為1,讀寫同時進行,并且empty為1,可知不進行讀操作,count的邏輯。但因full為0,可以進行寫入,此時進行寫入,在4個clk周期寫滿,因此在530.1ns時full標志位為1
在530ns和550ns時,read/write都為0,此時不讀也不寫入,因此輸出狀態不變,一直為9999,
原文鏈接:https://blog.csdn.net/zyp626/article/details/131620099
-
FPGA
+關注
關注
1640文章
21897瀏覽量
611343 -
存儲
+關注
關注
13文章
4457瀏覽量
86836 -
仿真
+關注
關注
51文章
4199瀏覽量
134989 -
fifo
+關注
關注
3文章
396瀏覽量
44426 -
代碼
+關注
關注
30文章
4874瀏覽量
69933
原文標題:FPGA基礎之FIFO實現
文章出處:【微信號:gh_9d70b445f494,微信公眾號:FPGA設計論壇】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
相關推薦
異步FIFO結構及FPGA設計
基于PCI接口芯片外擴FIFO的FPGA實現
高速異步FIFO的設計與實現
基于FPGA的FIFO設計和應用

基于VHDL和FPGA的非對稱同步FIFO設計實現
LabVIEW FPGA模塊實現FIFO深度設定

異步FIFO在FPGA與DSP通信中的運用

基于FPGA的FIFO設計和應用
異步FIFO在FPGA與DSP通信中的應用解析

FPGA的FIFO實現過程
在FPGA上實現自行FIFO設計的方法

如何在Altera FPGA中使用FIFO實現功能設計?

評論