導(dǎo)讀:
異步FIFO包含"讀"和"寫“兩個部分,寫操作和讀操作在不同的時鐘域中執(zhí)行,這意味著Write_Clk和Read_Clk的頻率和相位可以完全獨(dú)立。異步FIFO的原理很簡單,寫操作是在寫使能有效時,寫地址指針(Write_Pointer)逐漸遞增,將數(shù)據(jù)寫入存儲器的相應(yīng)位置。讀操作是在讀使能信號有效時,讀地址指(Read_Pointer)逐漸遞增,從存儲器的相應(yīng)位置讀取數(shù)據(jù)。
但異步FIFO有一個難點(diǎn)就是—滿和空的產(chǎn)生。寫操作,我們得判斷FIFO是不是滿了,滿了就不能繼續(xù)往里面寫,不然就會覆蓋還沒取走的數(shù)據(jù)。對于讀操作,我們得判斷FIFO是不是空了,空了就不能接著取,不然舊的數(shù)據(jù)會被取多次。
觸發(fā)異步FIFO的滿和空,是拿讀和寫的Pointer做比較得到的。問題在于:寫操作下的Write_Pointer和讀操作下的Read_Pointer屬于兩個不同的時鐘域信號。兩個不同的時鐘域信號是不能直接做運(yùn)算的,需要同步到同一個時鐘域之后才行,因為有這個CDC同步器的開銷,導(dǎo)致FIFO出現(xiàn) 真 滿空和 假 滿空。
接下來我們一起來看看標(biāo)準(zhǔn)異步FIFO的”真“滿空和“假“滿空如何產(chǎn)生,以及采用格雷碼異步FIFO跟標(biāo)準(zhǔn)FIFO有什么區(qū)別。(這里所謂標(biāo)準(zhǔn)異步FIFO是指不使用特殊編碼方式(如格雷碼)的異步FIFO,即使用常規(guī)的二進(jìn)制地址指針。)
標(biāo)準(zhǔn)異步FIFO
標(biāo)準(zhǔn)異步FIFO結(jié)構(gòu)如上圖,假設(shè)FIFO的深度為8,addr(地址范圍)為0 ~ 7。那么設(shè)計讀寫地址指針都是4bit,即w_ptr[3:0],r_ptr[3:0],其中最高bit是擴(kuò)展位。ptr取值范圍是0 ~15,要比FIFO地址(addr)多一倍。為什么這么設(shè)計呢?因為滿和空本質(zhì)上是讀和寫指向了FIFO的同一個存儲單元,但是“空”是讀指針追上了寫指針,“滿”是寫指針超過了讀指針整整一圈。其中最高位就是用來確定是 “誰追上了誰”
如果兩個ptr低位全等,最高位不等,就是“滿”;
如果兩個Ptr低位全等,最高位相等,就是“空”。
如圖所示,將w_ptr通過CDC同步之后,送到讀時鐘域,得到w_ptr_syn,然后再將它和r_ptr作比較,就可以得到“空”信號,代碼如下:
assign empty = (w_ptr_syn[3:0]== r_ptr[3:0]);
同理,將r_ptr通過CDC同步之后,送到寫時鐘域,得到r_ptr_syn,然后將它和w_ptr作比較,就可以得到滿信號,代碼如下:
assign full = (w_ptr[3] != r_ptr_syn[3]) && (w_ptr[2:0] == r_ptr_syn[2:0]);
大家覺得上面的代碼得到的滿和空是“ 真”滿空嗎?
答案是否定的。因為CDC同步器本身也需要開銷,一般簡單的兩級同步器需要目標(biāo)時鐘域兩個時鐘周期。當(dāng)我們判斷滿信號的時候,我們是在 寫時鐘域 ,用w_ptr和同步過來的r_ptr_syn做比較。r_ptr_syn要比真正的r_ptr要滯后,導(dǎo)致判滿的邏輯并不完全準(zhǔn)確。當(dāng)FIFO接近滿的時候,full信號就會為1,從而阻止對FIFO繼續(xù)寫入(腦補(bǔ):“滿”意味著寫比讀塊,寫指針馬上趕上讀指針一圈,此刻還與滯后同步過來的讀指針比較,是不是快滿還沒滿時就滿足full條件了?)。同理,當(dāng)FIFO接近空,但是實際可能還沒空的時候,empty信號就會為1。
這種假滿空并不會導(dǎo)致FIFO的行為出錯,只會導(dǎo)致FIFO的利用率并非百分百,相當(dāng)于FIFO的深度少了那么一兩層。
那么FIFO能得到真滿空嗎?
答案肯定是可以的。如果我們在寫時鐘域判斷“空”信號,在讀時鐘域判斷“滿”信號呢?(在寫時鐘域,通過滯后的r_ptr_syn都得到了“空”信號,那說明實際的r_ptr必然真的趕上了w_ptr,此刻FIFO絕對空了。在讀時鐘域,通過滯后的w_ptr_syn都得到了“滿”信號,那說明實際的w_ptr必然真的超過了r_ptr一圈,此刻FIFO絕對滿了)。
assign empty_real = (w_ptr[3:0] == r_ptr_syn[3:0]);
assign full_real = (r_ptr[3] != w_ptr_syn[3]) && (r_ptr[2:0] == w_ptr_syn[2:0]);
這個“真”滿空信號,用到的時候并不多。但是理解“真”滿空和“假”滿空,是理解異步FIFO的基礎(chǔ)。
采用格雷碼的異步FIFO
采用格雷碼的異步FIFO判斷“滿”和“空”的原理沒變,跟標(biāo)準(zhǔn)FIFO是一樣的,即在寫時鐘域判斷滿條件,在讀時鐘域判斷空條件:
如果兩個ptr低位全等,最高位不等,就是“滿”;
如果兩個Ptr低位全等,最高位相等,就是“空”。
只不過,地址指針采用的是格雷碼,如寫地址指針:
assign nxt_wptr = (!full && wr_en) ? (wptr +1'b1):wptr;
assign nxt_wptr_gray = (nxt_wptr >>1)^nxt_wptr;
判斷空條件:則在讀時鐘域,讀地址指針格雷碼 與 兩級同步過來后的寫地址指針格雷碼(nxt_wptr_gray)進(jìn)行比較:
always@(posedge rclk or negedge rst_n)
begin
if(!rst_n) begin
wptr_sp1<=6'b0;
wptr_sp2<=6'b0;
end
else begin
wptr_sp1<=nxt_wptr_gray;
wptr_sp2<=wptr_sp1;
end
end
assign empty=(rptr_gray==wptr_sp2);
同理,判斷滿條件:
assign full=(wptr_gray=={~rptr_sp2[3],rptr_sp2[2:0]});
理解到這兒,本質(zhì)上兩種FIFO似乎沒什么區(qū)別,那為什么要用格雷碼編碼呢? 異步FIFO采用格雷碼的主要原因是為了減少在異步時鐘域中地址指針變化時可能出現(xiàn)的不穩(wěn)定性,從而增強(qiáng)異步FIFO的可靠性和穩(wěn)定性 。即使在亞穩(wěn)態(tài)進(jìn)行讀寫指針抽樣也能進(jìn)行正確的空滿狀態(tài)判斷”。
下面兩張圖是采用格雷碼的異步FIFO觸發(fā)滿和空條件的截圖,從圖示可看出,4根標(biāo)紅的格雷碼地址指針 每一周期前后只有1位發(fā)生跳變,如wptr_gray:0010>0110>0111>0101>0100>1100>1101>1111>1110,這就是格雷碼的特性,保證了相鄰的兩個值只有一個位元發(fā)生變化,因此在變化時不會出現(xiàn)多個位同時變化,減少了不穩(wěn)定狀態(tài)的可能性。
滿條件
空條件
為什么2 進(jìn)制指針做空滿判斷存在不穩(wěn)定的可能呢?事實上 2 進(jìn)制讀指針在增減時,經(jīng)常發(fā)生多位突變,比如 6 位地址 111111 會在下一時刻變成 000000 ,在實際電路中,這個變化過程要持續(xù)很長一段時間,會由 111111 經(jīng)歷 6 個狀態(tài)轉(zhuǎn)移到達(dá) 000000 。比如 111111-> 101111 -> 100111 ->100110 -> 100100 -> 000100-> 000000 。由于寫時鐘與讀時鐘不同步,異步的寫時鐘很可能會在狀態(tài)不穩(wěn)定的中間某個狀態(tài)抽樣,這樣就會得到錯誤的讀指針,進(jìn)而做出錯誤的狀態(tài)判斷,導(dǎo)致系統(tǒng)異常。
當(dāng)采用格雷碼只有一個比特發(fā)生改變時,即使在中間狀態(tài)抽樣,其結(jié)果也不外乎兩種:遞增前原指針和遞增后新指針。如果抽樣到遞增后的指針,預(yù)期結(jié)果跟設(shè)計一致。如果抽樣到遞增前的原指針,最壞的情況就是把“不滿”判斷成了“滿”,但是這并不會對邏輯產(chǎn)生影響,只是帶來了寫操作的延遲。
總結(jié)(兩種fifo的主要區(qū)別)
因此,標(biāo)準(zhǔn)范式的FIFO和采用格雷碼的FIFO都存在一定的可能出現(xiàn)假滿空。兩者有一些區(qū)別,主要涉及到地址指針的表示和更新方式。以下是這兩種FIFO的主要區(qū)別:
- 地址指針的表示:
- 標(biāo)準(zhǔn)范式的FIFO:常常使用二進(jìn)制表示的地址指針。這意味著每個存儲單元都有一個唯一的二進(jìn)制地址,用于指示數(shù)據(jù)在FIFO中的位置。
- 采用格雷碼的FIFO:地址指針通常使用格雷碼來表示。格雷碼是一種二進(jìn)制碼,相鄰的兩個值只有一個位元發(fā)生變化。使用格雷碼可以減少地址指針在變化時的不穩(wěn)定性,從而減少在時鐘邊沿時的不穩(wěn)定狀態(tài)。
- 地址指針的更新方式:
- 標(biāo)準(zhǔn)范式的FIFO:地址指針在每個時鐘周期朝一個方向遞增或遞減,用于確定要讀取或?qū)懭氲奈恢?。在寫入?shù)據(jù)時,寫指針增加;在讀取數(shù)據(jù)時,讀指針增加。
- 采用格雷碼的FIFO:格雷碼地址指針的更新方式相對復(fù)雜一些。格雷碼的特性使得在更新時只有一個位發(fā)生變化,這樣可以減少指針變化的不穩(wěn)定性。在讀寫操作時,格雷碼地址指針的更新可能需要一些額外的邏輯。
- 時序穩(wěn)定性:
- 標(biāo)準(zhǔn)范式的FIFO:由于二進(jìn)制地址指針的性質(zhì),通用FIFO在時序上需要額外的同步邏輯,以確保地址指針的穩(wěn)定傳遞。這尤其在不同時鐘域的情況下需要考慮。
- 采用格雷碼的FIFO:格雷碼的特性減少了地址變化的不穩(wěn)定性,因此在一些時序方面可能更容易處理。但格雷碼的使用可能需要更多的邏輯來實現(xiàn)。
選擇使用哪種FIFO設(shè)計取決于具體的應(yīng)用需求和時序約束。格雷碼的FIFO在一些特定情況下可能提供一些優(yōu)勢,但也需要權(quán)衡設(shè)計的復(fù)雜性。
-
fifo
+關(guān)注
關(guān)注
3文章
387瀏覽量
43623 -
信號
+關(guān)注
關(guān)注
11文章
2786瀏覽量
76710 -
時鐘域
+關(guān)注
關(guān)注
0文章
52瀏覽量
9534 -
異步FIFO
+關(guān)注
關(guān)注
0文章
20瀏覽量
8351
發(fā)布評論請先 登錄
相關(guān)推薦
評論