FPGA的跨時鐘域問題
掃描二維碼
隨時隨地手機看文章
這兩天調(diào)試圖像,有一個模塊輸出圖像出現(xiàn)閃屏現(xiàn)象,模塊環(huán)境定義如下:
由于涉及到進出內(nèi)存操作,為了排除進出內(nèi)存問題,先屏蔽掉幀緩存模塊,發(fā)現(xiàn)圖像不閃,因此可以定位幀緩存引入的問題。
再看幀緩存模塊,由于該模塊已經(jīng)過測試,復(fù)用性強穩(wěn)定性高,不會出現(xiàn)大問題,這時對端口信號進行監(jiān)測發(fā)現(xiàn)問題。
輸入控制信號是36MHz,幀緩存模塊內(nèi)部工作時鐘是100MHz,因此需要對輸入控制信號同步到100MHz下。
輸入時序如下:
輸入i_a,i_b(脈沖信號),同時c = i_a && i_b;
因為后面模塊需要同時用到同步后的i_a信號以及c信號,所以需要對i_a,以及c信號同時跨時鐘域,經(jīng)過同步模塊后,抓信號發(fā)現(xiàn)2個信號不再同步了。而每次抓信號看,同步后的i_a與c相差一個周期,而不同的綜合版本,相差的一個周期前后不一致。
這里我就犯了一個很嚴重的錯誤,就是多個信號分別跨時鐘域后進行交匯,存在節(jié)拍上的不確定性。
即對于同樣的同步器,輸入信號a和b經(jīng)過同步以后,o_a與o_b不再保持原有的時序關(guān)系。
因此,為了解決該問題,不再對i_a和i_b分別同步,而是只對i_a進行同步,由o_a生成o_b信號。
這時就到了第二步操作:
assign o_b = o_a && flag;
其中,o_a與flag均為目標時鐘域(100MHz)。此時再抓信號,依然發(fā)現(xiàn)當o_b為1時,存在o_a為0的情況,這從邏輯上是怎么也解釋不通的,而且,兩個信號主要存在差一個周期的情況,因此還是懷疑同步問題。
再看同步代碼,發(fā)現(xiàn)如下設(shè)計:
最普通的做法,對輸入信號進行延展,再用目標時鐘采樣,得到同步后脈沖。
由于是慢時鐘域同步到快時鐘域,所以不存在采樣不到的問題,但這里仍然有個很大的問題,就是同步器的第一級寄存器會由于不滿足建立保持時間而產(chǎn)生亞穩(wěn)態(tài):
一般情況,跨時鐘域信號經(jīng)過第二個寄存器后會趨于穩(wěn)定,因此前面用d1與d2信號做同步輸出信號必然會因亞穩(wěn)態(tài)問題導(dǎo)致輸出也呈亞穩(wěn)態(tài)。
因此簡要修改代碼:
此時再抓信號看,各控制信號正常,再看圖像,也不再閃爍。
跨時鐘域問題很多數(shù)字邏輯設(shè)計的教科書都有講到,對于芯片設(shè)計有專門的CDC檢查,但對于FPGA開發(fā)來說,一般很少使用相關(guān)CDC工具,只能靠開發(fā)者在設(shè)計的時候就考慮全面。
脈沖信號跨時鐘域最常用的就是NDFF方式:
(1)因為輸入sig_in不一定在rx_clk的第一個時鐘沿采樣到,同時考慮到建立保持時間,輸入脈沖的持續(xù)時間必須大于2*Prx_clk;
(2)為了避免綜合工具對同步電路的優(yōu)化造成節(jié)拍上的不確定性以及亞穩(wěn)態(tài),輸入sig_in最好為時序邏輯,而synchronizer內(nèi)部不能有任何組合邏輯;
(3)多個不同信號進行跨時鐘域后進行交匯,則無法保證輸出信號的時序,上面第一個問題就是這個道理;
(4)NDFF的第一級觸發(fā)器輸出信號存在不穩(wěn)定性,即亞穩(wěn)態(tài),一般要經(jīng)過第二級寄存器后信號會趨于穩(wěn)定,因此如果用第一級輸出作為最終輸出,結(jié)果依然會存在亞穩(wěn)態(tài)問題,見上面第二個問題。
跨時鐘域當然還有很多其他方式,同步器只是最簡單最常用的一種,常見的還有握手、FIFO等,也各有注意事項。
對于視頻流來說,數(shù)據(jù)路徑常用FIFO,而控制信號往往采用幀頭信號同步后,重新生成其他控制信號。
以上遇到的問題,也是在設(shè)計中沒有考慮全面導(dǎo)致,以后還需多注意。





