首先是看了PARADIGM WORKS的一篇名為《Crossing the Abyss——Asynchronous Signals in a Synchronous World》的paper吧應該是
其實之前華老師很大篇幅的論文都是翻譯的這篇文章里面的內容 國內的博客也有很多說的堂而皇之的話是翻譯這篇文章的
說的都是一些很實在的跨時鍾域的基本知識 感覺看過之后有種醍醐灌頂之感
首先就是基本的同步器就是兩個DFF,這兩個DFF在版圖的時候一定要被放的非常近,以保證非常小的clock skew,再有就是第一個DFF對毛刺非常敏感 所以從原時鍾域同步到新時鍾域的時候 原時鍾域的DFF與這個第一級的同步DFF中間不允許有任何的組合邏輯 因為組合邏輯非常容易產生毛刺 對這個第一級采樣DFF影響非常之大 如果出現了一個glitch在這個DFF的sample window內 那么一個錯誤的值就將直接影響后面電路的工作
接下來簡單的總結一下簡單的單bit同步器分為level synchronizer/edge-detect synchronizer/pulse synchronizer
於是就有了下面這張表
重點是什么呢,以前只知道同步就是用dff打兩拍 但是其實還是有限制的 用的最多的應該就是level的和edge-detect了,level的要求待同步信號要在欲同步域內至少保持兩個時鍾周期的不變化,其實這里我想說的是,最小值應該是小於這個safest period的(就是兩個cycle),我覺得最小值應該是一個欲同步時鍾域的setup time 加上hold time再加上一個欲同步時鍾域的時鍾周期 這個是最小值,稍微想一下worst case 就不難理解了,就能保證這個原時鍾域的一個level可以被正確的采到新的時鍾域,同樣的對edge-detect也有着這樣的問題 不知道對不對 但是paper里面說edge-detect同步器的前級電路最小維持不變時間為一個新時鍾域的cycle加上一個hold time我不是很理解。
下面pulse synchronizer的要求就是要輸入的pulse間隔至少要為兩個新時鍾域的cycle。其實快時鍾到慢時鍾用的時候非常方便 但是慢時鍾到快時鍾的時候我覺得不如用edge-detect來做同步 就可以把需要的時間變短 使得同步效率更高
,其實pulse synchronizer 的電路非常簡單 就是下面這幾行代碼
always @(posedge f_clk or negedge f_rst_n) begin if(~f_rst_n) f_tog <= 1'b0 ; else if(f_pulse) f_tog <= ~f_tog ; end always @(posedge s_clk or negedge s_rst_n) begin if(~s_rst_n) s_syn <= 3'b0 ; else s_syn <= {s_syn[1:0], f_tog} ; end assign s_pulse = s_syn[2] ^ s_syn[1];
f_pulse 是快時鍾域內的一個pulse信號,s_pulse是同步到慢時鍾域內的一個pulse信號
簡單的一個同步器其實里面學問還是蠻多的,接着這paper就講了一些關於握手和fifo的老生常談的東西 包括全握手,部分握手之類的東西 全握手還是比較好理解的 我覺得部分握手不夠robust 用的地方還是看需求吧基本上 如果有條件 仔細考慮可能部分握手可以達到效率高 同時也很robust的地步
至此就總結這篇paper至此 還真是不錯的作品 致謝作者