一、異步FIFO簡介及其原理
FIFO是英文First In First Out 的縮寫,是一種先進先出的數(shù)據(jù)緩存器,它與普通存儲器的區(qū)別是沒有外部讀寫地址線,這樣使用起來非常簡單,但缺點就是只能順序?qū)懭霐?shù)據(jù)。異步FIFO 是指讀寫時鐘不一致,讀寫時鐘是互相獨立的。
1.1 用途
用途1:
跨時鐘域:異步FIFO讀寫分別采用相互異步的不同時鐘。在現(xiàn)代集成電路芯片中,隨著設(shè)計規(guī)模的不斷擴大,一個系統(tǒng)中往往含有數(shù)個時鐘,多時鐘域帶來的一個問題就是,如何設(shè)計異步時鐘之間的接口電路。異步FIFO是這個問題的一種簡便、快捷的解決方案,使用異步FIFO可以在兩個不同時鐘系統(tǒng)之間快速而方便地傳輸實時數(shù)據(jù)。
用途2:
位寬變換:對于不同寬度的數(shù)據(jù)接口也可以用FIFO,例如單片機位8位數(shù)據(jù)輸出,而DSP可能是16位數(shù)據(jù)輸入,在單片機與DSP連接時就可以使用FIFO來達到數(shù)據(jù)匹配的目的。
1.2 結(jié)構(gòu)
由圖可見,異步FIFO的核心部件就是一個 Simple Dual Port RAM ;左右兩邊的長條矩形是地址控制器,負(fù)責(zé)控制地址自增、將二進制地址轉(zhuǎn)為格雷碼以及解格雷碼;下面的兩對D觸發(fā)器 sync_r2w 和 sync_w2r 是同步器,負(fù)責(zé)將寫地址同步至讀時鐘域、將讀地址同步至寫時鐘域。
FIFO的常見參數(shù)
FIFO的寬度:即FIFO一次讀寫操作的數(shù)據(jù)位;
FIFO的深度:指的是FIFO可以存儲多少個N位的數(shù)據(jù)(如果寬度為N)。
滿標(biāo)志:FIFO已滿或?qū)⒁獫M時由FIFO的狀態(tài)電路送出的一個信號,以阻止FIFO的寫操作繼續(xù)向FIFO中寫數(shù)據(jù)而造成溢出(overflow)。
空標(biāo)志:FIFO已空或?qū)⒁諘r由FIFO的狀態(tài)電路送出的一個信號,以阻止FIFO的讀操作繼續(xù)從FIFO中讀出數(shù)據(jù)而造成無效數(shù)據(jù)的讀出(underflow)。
讀時鐘:讀操作所遵循的時鐘,在每個時鐘沿來臨時讀數(shù)據(jù)。
寫時鐘:寫操作所遵循的時鐘,在每個時鐘沿來臨時寫數(shù)據(jù)。
二、 FIFO的“空”/“滿”檢測
FIFO設(shè)計的關(guān)鍵:產(chǎn)生可靠的FIFO讀寫指針和生成FIFO“空”/“滿”狀態(tài)標(biāo)志。
此處切記判斷讀空和寫滿時指針的比較方式時不同的,大華面試時就問到了這個問題,一下把我干糊涂了,直接面試涼了。
如上圖所示的同步模塊synchronize to write clk,其作用是把讀時鐘域的讀指針rd_ptr采集到寫時鐘(wr_clk)域,然后和寫指針wr_ptr進行比較從而產(chǎn)生或撤消寫滿標(biāo)志位wr_full;
同步模塊synchronize to read clk的作用是把寫時鐘域的寫指針wr_ptr采集到讀時鐘域,然后和讀指針rd_ptr進行比較從而產(chǎn)生或撤消讀空標(biāo)志位rd_empty。
2.1、讀寫指針工作原理
讀指針:總是指向下一個將要被寫入的單元,復(fù)位時,指向第一個單元(編號為0)。
寫指針:總是指向當(dāng)前要被讀出的數(shù)據(jù),復(fù)位時,指向第1個單元(編號為0)
FIFO空標(biāo)志位:
(1)系統(tǒng)復(fù)位,讀寫指針全部清零,讀寫指針相等時;
(2)數(shù)據(jù)讀出速率大于寫入速率,讀指針趕上了寫指針,F(xiàn)IFO為空,如圖所示:
FIFO 寫滿標(biāo)志位的產(chǎn)生
(1)讀寫指針指向了同一地址,但寫指針超前整整一圈,F(xiàn)IFO被寫滿;
2.2、 空滿區(qū)分
為了區(qū)分到底是滿狀態(tài)還是空狀態(tài),可以采用以下方法:
在指針中添加一個額外的位,當(dāng)寫指針增加并越過最后一個FIFO地址時,就將未用的最高位(MSB)加1,其他位回0.對讀指針也進行同樣的操作。
此時,對于深度為2^n的FIFO,需要的讀寫指針位寬為(n+1)位。如對于深度為8的FIFO,需要采用4bit的計數(shù)器,0000~1000、1001~1111,MSB作為折回標(biāo)志位,而低3位作為地址指針。
如果兩個指針的MSB不同,其他位相同,說明寫指針比讀指針多折回了一次;如r_addr=0000,而w_addr = 1000,為滿。如果兩個指針的MSB相同,其余位相等,則說明兩個指針折回的次數(shù)相等,說明FIFO為空;
2.3、 二進制FIFO指針的考慮
將一個二進制的計數(shù)值從一個時鐘域同步到另一個時鐘域的時候很容易出現(xiàn)問題,因為采用二進制計數(shù)器時所有位都可能同時變化,在同一個時鐘沿同步多個信號的變化會產(chǎn)生亞穩(wěn)態(tài)問題。而使用格雷碼只有一位變化,因此在兩個時鐘域間同步多個位不會產(chǎn)生問題。所以需要一個二進制到gray碼的轉(zhuǎn)換電路,將地址值轉(zhuǎn)換為相應(yīng)的gray碼,然后將該gray碼同步到另一個時鐘域進行對比,作為空滿狀態(tài)的檢測。
(1)二進制如何轉(zhuǎn)化為格雷碼
二進制數(shù)的最高位保持不變, 后續(xù)位依次與前一位進行異或運算
assign gray_code = (bin_code>>1) ^ bin_code;
(2) 使用gray碼進行對比,如何判斷“空”與“滿”
使用gray碼解決了一個問題,但同時也帶來另一個問題,即在格雷碼域如何判斷空與滿。
對于“空”的判斷依然依據(jù)二者完全相等(包括MSB);
而對于“滿”的判斷,如下圖,由于gray碼除了MSB外,具有鏡像對稱的特點,當(dāng)讀指針指向7,寫指針指向8時,除了MSB,其余位皆相同,不能說它為滿。因此不能單純的只檢測最高位了,在gray碼上判斷為滿必須同時滿足以下3條:
(1)wptr和同步過來的rptr的MSB不相等,因為wptr必須比rptr多折回一次。
(2)wptr與rptr的次高位不相等,如上圖位置7和位置15,轉(zhuǎn)化為二進制對應(yīng)的是0111和1111,MSB不同說明多折回一次,111相同代表同一位置。
(3)剩下的其余位完全相等。
這里直接給出結(jié)論:
判斷讀空時 :將寫時鐘域的寫指針同步到讀時鐘,然后與讀時鐘域的讀指針進行比較,每一位都完全相同才判斷為讀空;
判斷寫滿時:需要 寫時鐘域的格雷碼wgray_next 和 被同步到寫時鐘域的讀指針wr2_rp 高兩位不相同,其余各位完全相同;
1 assign full = (wr_addr_gray == {~(rd_addr_gray_d2[addr_width-:2]),rd_addr_gray_d2[addr_width-2:0]}) ;//高兩位不同
2 assign empty = ( rd_addr_gray == wr_addr_gray_d2 );
三、重要補充
關(guān)于異步FIFO的關(guān)鍵技術(shù),有兩個,一個是格雷碼減小亞穩(wěn)態(tài),另一個是指針信號跨異步時鐘域的傳遞。
我在自己寫異步FIFO的時候也很疑惑,地址指針在同步化的時候,肯定會產(chǎn)生至少兩個周期的延遲,如果是從快時鐘域到慢時鐘域,快時域的地址指針并不能都被慢時域的時鐘捕獲,同步后的指針比起實際的指針延遲會更大。如果以此來產(chǎn)生fifo_empty和fifo_full 信號會非常不準(zhǔn)器。
查找資料和仿真后發(fā)現(xiàn),數(shù)字電路的世界真的很神奇,還有很多的東西需要去學(xué)習(xí)。非常巧妙,FIFO中的一個潛在的條件是write_ptr總是大于或者等于read_ptr;分為兩種情況,寫快讀慢和寫慢讀快。
·
1.在寫時鐘大于讀時鐘時,產(chǎn)生fifo_empty信號,需要將write_ptr同步到讀時鐘域,寫指針會有延時,可能比實際的寫地址要小,如果不滿足fifo_empty的產(chǎn)生條件,沒問題。如果滿足fifo_empty的觸發(fā)條件,說明此時同步后的write_ptr = read_ptr,即實際的write_ptr >= read_ptr,最壞的情況就是write_ptr > read_ptr,像這種FIFO非空而產(chǎn)生空標(biāo)志信號的情況稱為“虛空”,但是也并不影響FIFO的功能。
2.在寫時鐘大于讀時鐘時,產(chǎn)生fifo_full信號,需要將read_ptr同步到寫時鐘域,讀指針會有延時,可能比實際的讀地址要小,如果不滿足fifo_full的產(chǎn)生條件,沒問題。如果滿足fifo_full的觸發(fā)條件,說明此時同步后的read_ptr == write_ptr - fifo_depth,即實際的read_ptr >= read_ptr - fifo_depth,最壞的情況就是read_ptr > read_ptr - fifo_depth,像這種FIFO非滿而產(chǎn)生滿標(biāo)志信號的情況稱為“虛滿”,但是也并不影響FIFO的功能。
寫慢讀快的情況也同上,并沒有大的差異,不再分析。
關(guān)于格雷碼減小亞穩(wěn)態(tài),如果讀寫時鐘差距過大,從快時鐘域同步到慢時鐘域的信號,時鐘捕獲的相鄰兩個數(shù)據(jù)變化并不是只有一個bit位的改變,可能導(dǎo)致格雷碼失去原來的意義。