FIFO總結文檔
- 何為FIFO .?
FIFO(First In First Out ) 先進先出是一個常用於數據緩存的一個數據緩沖器。
fifo主要有WRREQ(寫信號)WRclk(寫時鍾)data(寫數據)wrfull(寫滿標志)wrempty(寫空標志)wrusedw(告知里面還有多少數據)
Rdreq(讀信號)rdclk(讀時鍾)rdfull(讀滿標志)rdempty(讀空標志)rdusedw(告知里面數據個數)
以上所有信號全是高電平有效。
- 為什么要用fifo?
在項目設計中,我們通常需要在兩個模塊之間傳輸數據,如果兩個模塊的數據處理速率相同,那么自然沒有什么問題,直接進行數據之間的對接就可以,可若是兩個模塊的數據處理速度不同呢?如果說數據接收模塊和數據發送模塊的速度不一致的話,必然會導致采集數據出現遺漏的現象,那么又該如何解決這一問題呢?
這里教大家一種比較簡單的方法就是引用FIFO(先進先出)數據緩沖器,所有數據都先經過緩存器去緩存,然后再輸入數據接收模塊。這樣就通過一個數據緩存的方法解決了速度不一致而導致的遺漏數據的問題。
- 如何在quarters和ISE里調用FIFO IP核
先主要說一下quarters里面的調用,在IP核搜索區找到fifo選項,
然后寫入IP核的名字,點擊NEXT就可以進入配置頁面,
在這里可以定義位寬和數據深度,因為同步FIFO用的不多,所以主要說一下異步FIFO,在下方的圖片中可以定義寫空寫滿和讀空讀滿信號以及寫使能和讀使能等等。
其余幾個頁面不需要配置什么直接點擊NEXT就可以。
另外需要注意的是: 讀端口和寫端口的輸出會有幾個時間差,這是由FIFO內部的結構導致的。
- 讀寫控制信號的生成與fifo的應用
系統框架:
三個輸入線和一個輸出線
總共需要三個模塊和一個頂層連線
代碼展示:
寫控制:
module FIFO_wr( input wire wclk, input wire rst_n, input wire wrfull, input wire wrempty, output reg [7:0]wrdata, output reg wrreq ); reg [7:0] state; always @(posedge wclk or negedge rst_n) begin if(!rst_n) begin wrdata<=0; wrreq<=0; state<=0; end else begin case(state) 0:begin if(wrempty) begin wrreq<=1 ; wrdata<=0; state<=1 ; end else state<=0; end 1:begin if(wrfull) begin state<=0; wrreq<=0; wrdata<=0; end else begin wrreq<=1; wrdata<=wrdata+1'b1; end end default: state<=0; endcase end end endmodule
讀控制:
module FIFO_rd( input wire rdclk, input wire rst_n, input wire rdempty, input wire rdfull, output reg rdreq ); reg[2:0]state; always@(posedge rdclk or negedge rst_n) begin if(!rst_n) begin state<=0; rdreq<=0; end else begin case (state) 0:begin if(rdfull) begin state<=1; rdreq<=1; end else state <=0; end 1:begin if(rdempty==0) begin state<=1; rdreq<=1; end else begin rdreq<=0; state<=0; end end default: state<=0; endcase end end endmodule
頂層連線:
module fifo_top( input wire wrclk, input wire rst_n, input wire rdclk, output wire [7:0]rdata ); wire wrfull; wire wrreq; wire [7:0]wrdata; wire wrempty; wire rdfull; wire rdempty; wire rdreq; FIFO_wr U1 ( .wclk(wrclk) , .rst_n(rst_n) , .wrfull(wrfull) , .wrdata(wrdata) , .wrreq(wrreq) , .wrempty(wrempty) ); FIFO_rd U2( .rdclk (rdclk) , .rst_n (rst_n) , .rdempty(rdempty) , .rdreq (rdreq) , .rdfull (rdfull) ); my_fifo U3( .data(wrdata) , .rdclk(rdclk) , .rdreq(rdreq) , .wrclk(wrclk) , .wrreq(wrreq) , .q(rdata) , .rdempty(rdempty) , .rdfull(rdfull) , .wrempty(wrempty) , .wrfull(wrfull) ); endmodule
測試文件:
module fifo_top_tb; reg wrclk; reg rdclk; reg rst_n; wire [7:0] rdata; initial begin wrclk=1; rdclk=1; rst_n=0; #1000 rst_n=1; #100000 $stop; end always #10 wrclk=~wrclk; always #20 rdclk=~rdclk; fifo_top U1( .wrclk (wrclk) , .rst_n (rst_n) , .rdclk (rdclk) , .rdata (rdata) ); endmodule
仿真波形:
可以看到:
當復位結束之前,寫空標志為高電平,當有第一個數據寫進去的時候,寫空標志拉低,當數據寫完的時候,寫滿標志拉高,延時了幾拍后,讀滿標志拉高,當有第一個數據讀出來以后,讀滿標志拉低,當數據讀完后,讀空標志由低變高,延時幾拍后會出現寫空標志,進行下一循環。
由上可以看到當讀和寫的時鍾不一樣的時候也能很方便的達到數據緩存的目的,不至於數據丟失。