1. 程式人生 > 其它 >FPGA-跨時鐘域問題

FPGA-跨時鐘域問題

這兩天除錯影象,有一個模組輸出影象出現閃屏現象,模組環境定義如下:

由於涉及到進出記憶體操作,為了排除進出記憶體問題,先遮蔽掉幀快取模組,發現影象不閃,因此可以定位幀快取引入的問題。

再看幀快取模組,由於該模組已經過測試,複用性強穩定性高,不會出現大問題,這時對埠訊號進行監測發現問題。

輸入控制訊號是36MHz,幀快取模組內部工作時鐘是100MHz,因此需要對輸入控制訊號同步到100MHz下。

輸入時序如下:

輸入i_a,i_b(脈衝訊號),同時c = i_a && i_b;

因為後面模組需要同時用到同步後的i_a訊號以及c訊號,所以需要對i_a,以及c訊號同時跨時鐘域,經過同步模組後,抓訊號發現2個訊號不再同步了。而每次抓訊號看,同步後的i_a與c相差一個週期,而不同的綜合版本,相差的一個週期前後不一致。

這裡我就犯了一個很嚴重的錯誤,就是多個訊號分別跨時鐘域後進行交匯,存在節拍上的不確定性。

即對於同樣的同步器,輸入訊號a和b經過同步以後,o_a與o_b不再保持原有的時序關係。

因此,為了解決該問題,不再對i_a和i_b分別同步,而是隻對i_a進行同步,由o_a生成o_b訊號。

這時就到了第二步操作:

assign o_b = o_a && flag;

其中,o_a與flag均為目標時鐘域(100MHz)。此時再抓訊號,依然發現當o_b為1時,存在o_a為0的情況,這從邏輯上是怎麼也解釋不通的,而且,兩個訊號主要存在差一個週期的情況,因此還是懷疑同步問題。

再看同步程式碼,發現如下設計:

最普通的做法,對輸入訊號進行延展,再用目標時鐘取樣,得到同步後脈衝。

由於是慢時鐘域同步到快時鐘域,所以不存在取樣不到的問題,但這裡仍然有個很大的問題,就是同步器的第一級暫存器會由於不滿足建立保持時間而產生亞穩態

一般情況,跨時鐘域訊號經過第二個暫存器後會趨於穩定,因此前面用d1與d2訊號做同步輸出訊號必然會因亞穩態問題導致輸出也呈亞穩態。

因此簡要修改程式碼:

此時再抓訊號看,各控制訊號正常,再看影象,也不再閃爍。

跨時鐘域問題很多數字邏輯設計的教科書都有講到,對於晶片設計有專門的CDC檢查,但對於FPGA開發來說,一般很少使用相關CDC工具,只能靠開發者在設計的時候就考慮全面。

脈衝訊號跨時鐘域最常用的就是NDFF方式:

(1)因為輸入sig_in不一定在rx_clk的第一個時鐘沿取樣到,同時考慮到建立保持時間,輸入脈衝的持續時間必須大於2*Prx_clk;

(2)為了避免綜合工具對同步電路的優化造成節拍上的不確定性以及亞穩態,輸入sig_in最好為時序邏輯,而synchronizer內部不能有任何組合邏輯

(3)多個不同訊號進行跨時鐘域後進行交匯,則無法保證輸出訊號的時序,上面第一個問題就是這個道理;

(4)NDFF的第一級觸發器輸出訊號存在不穩定性,即亞穩態,一般要經過第二級暫存器後訊號會趨於穩定,因此如果用第一級輸出作為最終輸出,結果依然會存在亞穩態問題,見上面第二個問題。

跨時鐘域當然還有很多其他方式,同步器只是最簡單最常用的一種,常見的還有握手、FIFO等,也各有注意事項。

對於視訊流來說,資料路徑常用FIFO,而控制訊號往往採用幀頭訊號同步後,重新生成其他控制訊號。

以上遇到的問題,也是在設計中沒有考慮全面導致,以後還需多注意。