零、前言
關於同步FIFO如何設計請參考之前的一篇文章:手寫同步FIFO。
關於異步FIFO如何設計請參考之前的一篇文章:手寫異步FIFO。
一、如何設計depth不是2的冪次的異步FIFO?
如果FIFO的深度不是2的冪次,那么格雷碼其實是不連續的,也即在最大值跳變到最小值時不止一個bit發生了變化。當然你也可以設計一個深度略大的,並且是2的冪次的FIFO,但是這樣其實是浪費資源的。
例如我們需要一個深度為5的FIFO,此時我們可以設計一個深度為8的FIFO,但是這樣會浪費資源。那么我們應該怎么辦呢?
其實我們可以換一個思路,通過觀察下表不難發現,格雷碼具有對稱性。0-15這16個格雷碼,如果前后去掉相同個數的格雷碼,那么剩余的格雷碼仍然符合相鄰兩個數只有1 bit的跳變,也包括最后一個到第一個的跳變。
例如,如果要設計深度為5的FIFO,由於需要5*2 = 10個格雷碼,所以可以前后各去掉三個數,也就是保留3-12這十個格雷碼。可以看到,最大的數12和最小的數3也是只有1 bit的跳變。
所以我們可以這樣編碼:addr==0的時候,gray code不從4’b0000開始,而是從4’b0010開始;gray code最大為4’b1010。不過此時需要注意的是:
- 我們在由addr得到格雷碼時不能直接轉換,而是要使用addr + 3進行轉換;同理由格雷碼轉換回addr時,也不要忘記減去3。
- 使用這種編碼時,FIFO的滿判斷邏輯就不是簡單的高兩位相反,低位相同了。比如depth=5, rd_ptr=4’b0010, wr_ptr=4’b1010,表示5個entry已經滿了,但此時並不能通過之前的條件去判斷。具體如何判斷,需要根據depth的大小尋找規律!
根據這個思路,我們就可以設計任意深度的FIFO,而相鄰地址的跳變始終都保持為1 bit。
二、如何設計一個depth=1的異步FIFO?
由於該FIFO只有一個entry,所以之前設計中用到的很多東西我們都不再需要了,例如地址指針wptr/rptr,地址也只需要1bit就夠了,既然是1bit那么也沒必要使用格雷碼了。
判斷空滿的邏輯也變得很簡單,只要push一次數據full信號就拉高,只要pop一次數據,empty信號就拉高。
三、FIFO深度的設置怎么才合理?設置大了和設置小了會有什么影響?
請參考這篇文章:FIFO深度計算。
FIFO的深度設置大了會浪費資源,設置小了會丟失數據。