ALTERA在LPM(library of parameterized mudules)庫中提供了參數可配置的單時鍾FIFO(SCFIFO)和雙時鍾FIFO(DCFIFO)。FIFO主要應用在需要數據緩沖且數據符合先進先出規律的同步或異步場合。LPM中的FIFO包含以下幾種:
1.SCFIFO:單時鍾FIFO;
2.DCFIFO:雙時鍾FIFO,數據輸入和輸出的寬度相同;
3.DCFIFO_MIXED_WIDTHS:雙時鍾FIFO,輸入輸出數據位寬可以不同。
配置不細說,直接看時序來理解。
1. 同步FIFO驗證時序
IP核設置說明:
開辟空間8bits*8words;almost_full設置為“6”;almost_empty設置為“2”;采用普通同步FIFO模式(the data becomes available before “rdreq” is asserted)。
引腳說明:
- aclr和sclr:
aclr為異步清零,不管何時,只要出現上升沿,立刻清除q中數據,q<=8’bx。emtpy為1;full為0;almost_empty為1(根據參數判斷);almost_full為0。
sclr為同步清零,只有sclr在clock上升沿時為“1”才能執行清除,效果同aclr。 - wrreq和rdreq:讀寫使能,高電平有效,clock上升沿執行讀、寫操作。
- full:當寫入數據量達到最大空間時,clock上升沿寫入最后一個數據同時full拉高;讀取數據時隨clock上升沿觸發同時拉低。
- empty:與full相反。寫入數據同時拉低;讀到最后一個數據同時拉高。
- almost_full:當usedw的數值≥almost_full參數設置值almost_full_value時為1,其余時刻保持0(不管是讀操作還是寫操作,只與數值比較有關)。
- almost_empty:當usedw的數<almost_empty參數設置值almost_empty_value時為1,其余時刻保持0(不管是讀操作還是寫操作,只與數值比較有關)。
- usedw:顯示當前FIFO中已存數據個數,與寫入數據的個數是同步的,即寫第一個數據時就置1,空或滿時值為0(滿是因為寄存器溢出)。
2. 異步FIFO驗證時序
從時序圖上說明DCFIFO的工作情況,雖然網上也有相關的時序圖,但是寫得不是很清晰。
建立一個位寬為8位,深度為4的DCFIFO。wr_clk與系統時鍾同頻,但是相移180°(反向)。rd_clk = 2*wr_clk。先寫滿,再讀空的方式驗證。從時序圖上看,感覺DCFIFO內部存在兩個存儲空間,接下來解釋。
T1時刻,寫使能wr置高。
T2時刻,第一個wr_clk上升沿到來,第一個數據8’h01寫入到FIFO中,此時wr_empty立即拉低,表明此刻FIFO不為空(寫部分)。wr_usedw此時還是為0,與單時鍾FIFO(SCFIFO)不同的是,SCFIFO第一個數據寫入的時候,usedw會為1,說明wr_usedw有1個時鍾周期的滯后(user guide里面說wrreq to wrusedw會滯后2個wr_clk,不太明白這與寫入數據有什么之間的聯系)。寫滿時usedw溢出后變為0。
T3時刻,rd_empty也被拉低,這就有點像“寫”部分的存儲空間的數據copy到了“讀”部分的存儲空間,而延遲時間正好就是T2與T3之間的時間間隔。隨即rdusedw開始從0遞增,但是遞增周期感覺是以wr_clk為基准。
T4時刻,最后一個數據8’h04寫入FIFO,wr_full被拉高,表明FIFO(寫入部分)已經滿了。wr_usedw計數為3。隨后結束寫使能,即wr拉低。
T5時刻,“寫”部分的存儲空間的數據全部copy至“讀”部分的存儲空間,此時rd_full也就被拉高了。
T6時刻,讀使能信號拉高,即rd信號拉高。
T7時刻,讀時鍾信號rd_clk的第一個有效上升沿到來,讀出第一個數據8’h01。此時“讀”存儲空間的滿信號rd_full被拉低,表明“讀”空間不滿。
T8時刻,“寫”存儲空間的滿信號wr_full才被拉低,表明與“讀”存儲空間之間有延遲。
T9時刻,最后一個數據8’h04被讀出,此時“讀”存儲空間的空信號rd_empty立即被拉高,表明已經空了。rdusedw滯后1個rd_clk減為0。
T10時刻,在“讀”存儲空間已經空了之后,經過一定時間的延遲,“寫”存儲空間才知道FIFO已空。注意在T10時刻前后,可能存在wrusedw的不穩定,在wr_empty重新拉高一個周期之后,wrusedw才重新置零。
經過上述時序的“直譯”,發現DCFIFO的讀和寫像是兩個獨立的內部存儲空間,存在一個“copy”或者握手的過程,所以導致雙方的空、滿信號存在一定的延遲。這就需要考慮,在實際項目中要用到DCFIFO時,采用什么信號來判斷,此刻FIFO能否安全的讀寫(也可以將almost相關的信號添加進來)。DCFIFO的優勢在於寫端和讀端時鍾不一樣,安全的邊寫邊讀,但是得注意讀寫時鍾頻率差異,以便控制FIFO深度以及相應的控制信號。
3、遇到問題
在實際設計中,有個模塊控制FIFO寫入數據A,假設全局時鍾global_clk以時序邏輯的方式驅動FIFO的寫使能(fifo_wr)和寫數據(data),而FIFO的時鍾信號就直接賦上global_clk,那么就會得到如圖1所示的時序圖。
寫使能和數據都在global_clk上升沿發生變化。
那么問題就來了,按道理說,FIFO寫入數據是在wr拉高前提下,在fifo_clk上升沿寫入數據。那么是不是這樣設計就不滿足數據的保持時間?
換一種設計,FIFO的寫使能(fifo_wr)和寫數據(data)依然基於global_clk的時序邏輯,但是fifo_clk相對於global_clk有個相移,比如說反相。那么就得到了圖2的時序圖,這樣就滿足設計需求了嗎?
我想請問的是,一般工程設計,怎樣設計FIFO的時序(主要是時鍾吧)是怎樣的呢?