FPGA設計之跨時鐘域的彈性Buffer
\\\插播一條:
自己在今年整理一套單片機單片機相關論文800余篇
論文製作思維導圖
原理圖+源代碼+開題報告+正文+外文資料
想要的同學私信找我。
在前面的文章中我們已經介紹了異步FIFO的設計原理FPGA設計之跨時鐘域(五-異步FIFO)。我們知道為了防止FIFO overflow或者 underflow,異步FIFO有空滿信號。當滿信號有效時會反壓前級邏輯,不讓其繼續寫數據到FIFO內,當空信號有效時,則通知後級邏輯,數據已經全部讀出,不讓其繼續讀取FIFO。如果我們的應用需求是數據必須不斷流入然後流出FIFO呢?這意味著既不能反壓前級也不能通知後級。
彈性Buffer便是應用在這種需求下的一種跨時鐘域的設計方法。本文將從以下幾點介紹彈性Buffer:
·彈性Buffer的應用背景
·彈性Buffer與普通異步FIFO的區別
·彈性Buffer的具體設計
·彈性Buffer有什麼缺點
彈性Buffer的應用背景
在起初的PCI總線設計中,採用的是同步時序結構,即發送端和接收端使用同步時鐘,發送端只需要發送數據,接收端正常採樣即可。這種同步結構要求時鐘到達發送端和接收端的時間精確相同,特別是對總線接口pin-to-pin的skew要求極高。隨著總線頻率的提升,對skew的要求也越來越高,使得時鐘網絡布線越來越困難。
因此,當前的很多高速接口設計,如PCIe,Ethernet都是採用了源同步(source-synchronous)時序結構,即發送端同時發送時鐘和數據,接收端需要從接收到的數據中恢復出數據的採樣時鐘,用該時鐘來採樣收到的數據。這種設計方式雖然避免了上述的問題,但是也帶來了新的問題,即跨時鐘域的問題,因為這種設計結構下一般會有兩個時鐘域,即Recovered Clock Domain和 Local Clock Domain。一般來說,Recovered Clock和 Local Clock之間頻率只有些微的差別,彈性Buffer便是用來解決這種情況下的跨時鐘域數據傳輸問題的。如圖1所示:
圖1 - PCIe器件中使用彈性Buffe做跨時鐘域處理
彈性Buffer與普通異步FIFO的區別
普通的異步FIFO讀寫時鐘不同,隨著數據的不斷寫入或者不斷讀出,最終必然會到達滿或空的狀態,從而停下數據從寫時鐘域向讀時鐘域的流動,直到FIFO不再為滿或空。
對於彈性Buffe來說,讀寫時鐘之間獨有些微的差別,頻次近似。數據會不斷從寫時鐘域流向讀時鐘域的,為了到達這個目標,彈性Buffer會自己丟棄或者插入數據來補償讀寫時鐘之間的頻次/相位差。應用彈性Buffer的總線協議會定義特定的Symbol,假如PCIe協議的Skip或者Ethernet協議的IDLE,這些特殊定義的Symbol就能夠被用來丟棄或者插入而不影響正常的數據傳輸。
彈性Buffer的詳細設計
從上一局部的內容我們能夠看出來,彈性Buffer相比普通異步FIFO主要是增加了丟棄或插入特殊字符的邏輯,同時也沒有滿空信號。
以1G Ethernet協議為例。Ethernet協議要求兩個包之間須要發送特殊字符IDLE,該字符能夠被彈性Buffer用來做時鐘頻次/相位的補償。我們的設計是10bit位寬的數據,採樣時鐘為125M,讀寫時鐘之間允許最高有300ppm的頻次差別。
如何考慮Buffer的深度
以+/-300ppm的容忍程度,頻次範圍則是在124.9625M~125.0375M之間。以最差情況看,假入寫時鐘為124.9625Mhz(8.0024ns),讀時鐘為125.0375Mhz(7.9976ns)。兩者之間時鐘周期的差為0.0048ns,也就是說每 7.9976/0.0048=1666個Cycle會有一次時鐘周期的漂移。
依照Ethernet最長的包長1500bytes計算,一個包會跨越 (1500*8)/10=1200個Cycle。所以一個Ethernet包至多有一次時鐘周期的漂移。假設我們想在每次漂移之後都做時鐘補償,那麼FIFO的深度為4即可,想留一些裕量則能夠考慮更大的深度,如8,16。
如何決定是否丟棄或插入IDLE字符
以FIFO深度為4為例。在FIFO的正常工作模式下,我們會讓FIFO總是處在半滿狀態,即含2個數據。然後我們設置兩個閾值,3和1。當
【文章福利】:小編整理了一些個人覺得比較好的學習書籍、視頻資料共享在群文件裡面,有需要的可以自行添加哦!~點擊綠色通訊軟體搜索airuimcu加入。
FIFO內所含的數據大於等於3時,我們認為寫時鐘過快,則丟棄IDLE字符。當FIFO內所含的數據數目小於等於1時,我們認為讀時鐘過快,需要插入IDLE字符。
那麼什麼時候丟棄或插入呢?當然不能在一個Ethernet包內,因為這樣會導致數據傳輸錯誤。前面我們已經提到在兩個Ethernet包的間隔,協議要求要發送IDLE字符,我們可以在間隔期間看到IDLE字符後選擇丟棄或插入。
綜上,我們設計的彈性Buffer可能會是這樣的一個工作流程:
.FIFO上電後達到半滿狀態
.數據不斷流入FIFO再流出,FIFO一直處於半滿狀態,所存數據個數為2
.一個新的Ethernet數據包來臨,在傳輸這個包期間,FIFO的讀寫時鐘發生了一次漂移,寫時鐘更快。導致FIFO內所存放的數據個數變成了3
.這個Ethernet包傳輸結束,發送端開始發送IDLE字符,我們檢測到IDLE字符後同時檢查FIFO內的數據個數,發現FIFO不是半滿,而是3
.我們認為寫時鐘快了,則丟棄接下來收到的IDLE字符,直到FIFO恢復半滿
彈性Buffer就不需要考慮Overflow或Underflow了麼?
因為我們對彈性Buffer的深度設計是基於讀寫時鐘之間的ppm差計算的,如果能保證讀寫時鐘的ppm差滿足要求,那麼是不用考慮的。
如果無法保證,我們則需要考慮增加Overflow和Underflow的判斷,並報告Error。一旦出現Overflow或Underflow我們認為系統無法正常工作,需要停止運行。
彈性Buffer有什麼缺點
從彈性Buffer的設計可以看出,其主要的缺點是會帶來延遲。為了保證彈性Buffer在正常情況的半滿狀態,我們需要先將數據Buffer在FIFO中。上文中的設計,彈性Buffer會引入至多3個Cycle,至少2個Cycle的延遲。
總結
本篇文章主要介紹了用於跨時鐘域的彈性Buffer的應用背景和設計原理。