多個bit信號的跨時鐘域僅僅通過簡單的同步器同步時不安全的。
如下圖:
雖然信號都同步到目的時鐘域,可完成的功能卻與設計的初衷不相符。
解決方案之一為對信號進行格雷碼編碼,但此方案只適用于連續變化的信號。另一種方案為增加新的控制信號en,確保傳輸信號穩定時采樣。比如在傳輸信號穩定輸出1、2個clk后再進行采樣。
一、異步FIFO
上面說到的為多bit指示信號傳輸,而數據流的傳輸與指示信號不同在于:數據流大多具有連續性,及背靠背傳輸;數據流要求信號具有較快的傳輸速度。主要的方案是利用FIFO進行傳輸。
異步FIFO結構如下:
?
1、FIFO的參數
- 寬度:一次讀寫操作的數據位
- 深度:可以存儲的N位數據的數目(寬度為N)
- 滿標志:FIFO已滿或將要滿時,由FIFO的狀態電路送出的信號,阻止FIFO寫操作
- 空標志:FIFO已空或將要空時,由FIFO的狀態電路送出的信號,阻止FIFO讀操作
- 讀時鐘:讀操作所遵循的時鐘
- 寫時鐘:寫操作所遵循的時鐘
2、設計空滿標志位電路
正確產生空滿信號是任何FIFO設計的關鍵。其設計原則是:能寫滿而不溢出,能讀空而不多讀。
- 在寫時鐘域下,判斷讀寫指針的關系,生成滿標志
- 在讀時鐘域下,判斷讀寫指針的關系,生成空標志
對于空滿判斷,可看下圖
在判斷空和滿的情況下,都會有讀寫指針相等的情況,可采用以下方法進行區分:
在地址中額外添加一個位,當寫指針增加并越過最后一個地址位時,就將這個額外的位(MSB)加一,其他位回0。讀指針也進行同樣的操作。額外的位作為折回標志位。如果兩個指針的MSB不同,其余位相等,說明讀指針比寫指針少折回了一次,這種情況下,FIFO為滿。而讀寫指針所有位都相等,說明折回次數相等,此時FIFO為空。
解決空滿判斷后,則是讀寫指針同步的問題。二進制的讀寫指針通常位寬超過了1bit,而多比特信號是不可以直接使用兩級同步器的。這時,考慮到FIFO地址是連續變化的,我們使用格雷碼來進行傳輸。格雷碼相鄰兩個數值只有一位發生變化,0和最大數之間也只有一位不同。
而轉換為格雷碼進行傳輸后,如何進行空滿判斷?如下圖:
至于為什么選擇格雷碼進行傳輸,我們來看格雷碼傳輸失效的情況:
格雷碼傳輸失效,只有一位同步出錯,此時地址沒有跳變。如果是寫地址同步失效,用這個錯誤的寫地址在讀時鐘域進行空判斷時不會出錯,最多是讓空標志在FIFO不是真正空的時候產生,而不會產生空讀的情況。格雷碼保證的是同步后的讀寫地址即使在出錯的情況下依然能夠保證FIFO功能的正確性。
?
3、設計FIFO的深度
先從一個例題入手,
假設FIFO的寫時鐘為100MHZ,讀時鐘為80MHZ。在FIFO輸入側,每100個時鐘,寫入80個數據;FIFO讀入測,每個時鐘讀取一個數據。設計合理的FIFO深度,使FIFO不會溢出。
我們需要考慮數據輕載和重載的情況,對緩存能力要求最高的情況為背靠背傳輸,則FIFO深度為160-(160/100)*80=32
我們將問題一般化:
- 寫時鐘頻率WCLK
- 讀時鐘頻率RCLK
- 寫入測每B個時鐘周期有A個數據寫入
- 讀取測每Y個時鐘周期有X個數據讀出
則FIFO的深度為,其中burst_length與寫入測情況有關。