一、前言
我們的都知道FIFO中有兩個特別重要的信號,那就是空滿信號。在異步FIFO中,空滿信號的判斷要比同步FIFO稍微復雜一些,因為它的地址使用的是格雷碼。具體如何判斷空滿可以參考之前的一篇文章:手寫異步FIFO。
看完之后可能你會覺得也沒那么復雜,其實如果只是單純的寫一個異步FIFO,那么會按照文章中介紹的方法進行判斷就夠了。但是這里面還有一些問題需要注意:那就是假空和假滿現象,以及為什么要在寫時鍾域進行判滿操作,在讀時鍾域進行判空操作。
二、假空假滿現象
無論是wclk和rclk誰快誰慢,都可能產生假空假滿現象,但是情況稍有不同,因此下面我們分兩種情況進行討論。需要注意的是,之所以會產生假空假滿現象,主要是因為wptr和rptr的同步問題導致的。因為無論是將wptr同步到rclk時鍾域還是將rptr同步到wclk時鍾域都有一定的延遲。
1、假設wclk比rclk快
- 假滿現象:當wclk比較快時,rptr很快就能同步到wclk時鍾域,在同步過程中認為不會再有讀數據的操作。但是如果同步的這個rptr剛好是FIFO滿之后變化的新值,也即FIFO滿后又有了讀數據操作,此時FIFO已經不滿了;那么由於在rptr同步過來之前的這段時間,wclk時鍾域的rptr的值仍然是上一次同步過來的,也就是符合滿條件的值,此時就會出現假滿現象!
- 假空現象:當rclk比較慢時,在wptr同步到rclk時鍾域之前,可能又會有寫數據的操作。如果同步的這個wptr剛好符合空條件,那么在wptr同步過來之后就會判斷為空。在將wptr同步過來之前的這段時間里,由於又有了寫操作,wptr其實已經變化了,此時FIFO是不空的,此時就出現了假空現象!
2、假設wclk比rclk慢
- 假滿現象:當wclk比較慢時,在rptr同步到wclk時鍾域之前,可能又會有讀數據的操作。如果同步的這個rptr剛好符合FIFO滿條件,那么在rptr同步過來之后就會判斷為滿。在將rptr同步過來之前的這段時間里,由於又有了讀操作,rptr其實已經變化了,此時FIFO是不滿的,此時就出現了假滿現象!
- 假空現象:當rclk比較快時,wptr很快就能同步到rclk時鍾域,在同步過程中認為不會再有寫數據的操作。但是如果同步的這個wptr剛好是FIFO空之后變化的新值,也即FIFO空后又有了寫數據操作,此時FIFO已經不空了;那么由於在wptr同步過來之前的這段時間,rclk時鍾域的wptr的值仍然是上一次同步過來的,也就是符合空條件的值,此時就會出現假空現象!
其實假空假滿都不影響FIFO正常工作,最多只是影響其性能。因為假滿就是提前告訴了寫數據端不要再寫數據了,由於這段時間不能寫數據,所以wptr不變,當過一會rptr同步過來時,再由wptr和rptr判斷的結果就是FIFO不滿了,就又可以寫數據了。而假空也只是告訴讀數據端不要再讀數據了,由於這段時間不能讀數據,所以rptr不變,當過一會wptr同步過來時,再由wptr和rptr判斷的結果就是FIFO不空了,就又可以讀數據了。
有可能你會有疑問,這不是好多情況都沒有討論到嗎?但其實你把其他情況都考慮進去你會發現,都是一些正常狀態,並且最后都會到達假空或者假滿狀態。
三、為什么在wclk時鍾域判斷是否滿,而在rclk時鍾域判斷是否空?
對於這個問題,我們可以按以下的思路去考慮:
1、如果在wclk時鍾域判空:
- 當wclk比較快時,rptr很快就能同步到wclk時鍾域,在同步過程中認為不會再有讀數據的操作。但是由於rptr同步過來仍然是需要時間的,如果被同步的rptr剛好是一個符合空條件的值,那么在同步過來之前這段時間內,rptr仍然是上一個符合非空條件的值。也就是說此時FIFO實際上已經空了,但是還是會報非空,這就會影響FIFO的正常工作了!
- 當wclk比較慢時,在rptr同步到wclk時鍾域之前,可能又會有讀數據的操作。如果同步的這個rptr不符合FIFO空條件,那么在rptr同步過來之后就會判斷為非空。然而在將rptr同步過來之前的這段時間里,由於又有了讀操作,rptr其實已經變化了,此時FIFO有可能是空的。也就是說此時FIFO實際上已經空了,但是還是會報非空,這就會影響FIFO的正常工作了。
2、如果在rclk時鍾域判滿:
- 當rclk比較快時,wptr很快就能同步到rclk時鍾域,在同步過程中認為不會再有寫數據的操作。但是由於wptr同步過來仍然是需要時間的,如果被同步的rptr剛好是一個符合滿條件的值,那么在同步過來之前這段時間內,wptr仍然是上一個符合非滿條件的值。也就是說此時FIFO實際上已經滿了,但是還是會報非滿,這就會影響FIFO的正常工作了!
- 當rclk比較慢時,在wptr同步到rclk時鍾域之前,可能又會有寫數據的操作。如果同步的這個wptr不符合FIFO滿條件,那么在wptr同步過來之后就會判斷為非滿。然而在將wptr同步過來之前的這段時間里,由於又有了寫操作,wptr其實已經變化了,此時FIFO有可能是滿的。也就是說此時FIFO實際上已經滿了,但是還是會報非滿,這就會影響FIFO的正常工作了。
可以看到,當在wclk時鍾域判空或者在rclk時鍾域判滿時,會出現以上幾種影響FIFO正常工作的情況,所以我們是在wclk時鍾域判斷是否滿,而在rclk時鍾域判斷是否空。
四、假設wclk速度比rclk快,那么當raddr+1,再同步到wclk后,如果這期間有了push操作,那會不會使得wptr超過了rptr,造成FIFO overflow呢?
在raddr + 1傳到wclk時鍾域之前,wclk端看到的值還是raddr,它有以下可能情況:
- wptr還沒有趕上rptr,此時FIFO是非滿的,那么如果有push操作是可以正常進行的,並且wptr會加1,等raddr+1同步過來后,仍然是非滿狀態!
- wptr已經趕上了rptr,那么此時full應該是拉高的,就不會允許push操作,所以wptr也不會加1!等raddr+1同步過來后,wptr又落后於rptr了,此時就會是非滿狀態!題目中說由於wclk速度快,在同步raddr+1期間又有了push操作,所以wptr與raddr+1對應的rptr對比得出的空滿狀態才是真的狀態,因此在同步過來之前的這段時間里的滿狀態其實是假滿!但是最多只是可以push但沒有允許push,也即提前告訴了push端不要寫數據了,其實並沒有影響FIFO的正常工作!
通過上述兩種情況就可以看出,wptr是不會超過rptr的。