入門數字設計的時候,跨時鐘域的數據處理是繞不開的課題,特別是多比特數據跨時鐘域時,都會采用異步FIFO的方法。
異步FIFO中涉及較多的考點這里記錄幾個以供大家參考。
1. 異步FIFO的空滿判斷分別在哪個域?
根據異步FIFO的結構,可以很清楚的分析出,在進行空滿判斷的時候是通過對讀寫指針的比較來判斷空滿的情況。但因為讀寫時鐘域的不同,讀寫指針在跨時鐘域的時候會使用同步器進行同步處理。所以往往寫時鐘域的寫指針較讀指針來說是實時的,因為讀指針實際上是2拍之前的值了,所以會在寫時鐘域來判斷滿的情況。反之在讀時鐘域判斷空的情況。但是判斷空滿會存在延遲即"虛空"和“虛滿”的情況。這樣是否是有問題的呢?這樣雖然會影響FIFO的性能,但是并不會使FIFO的功能出錯,因為滿的時候不會繼續寫入,空的時候不會繼續讀取,不會導致FIFO功能出錯。
異步空滿判斷因為格雷碼的對稱性:
滿:高位不同,次高位不同,低位相同。
空:全相同。
2. 為什么要將二進制轉換成格雷碼來進行讀寫指針的傳遞呢?
這里需要突出的是格雷碼的特性,每次狀態跳變時只有一位變化,在能夠保證bus skew的前提下,即使是在跨時鐘域時,也能避免因多位同時變化而導致的錯誤狀態。因為只有1位跳變的話,即使是發生亞穩態的情況,最差是狀態不變。但如果是多位變化情況就不一定。
3.如果沒有保證格雷碼的時序會出現什么問題呢?
正常情況下的跨時鐘域
格雷碼各bit之間存在較大偏移的情況,bit0_delay > bit1_delay > bit2_delay,且這些bit之間的skew大于clk_wr,出現了010->111多bit位跳變的情況,111->110錯誤跳變的情況。
由上可知當各bit之間的skew較大的時候無法發揮格雷碼的特性且可能會出現錯誤的情況。所以需要在設計的時候保證各bit之間的skew關系。所以為了避免過大的skew,可以對mult-bit設置set_max_delay,將延時限制在有效的范圍內。
查閱網上有些同學說需要保證將限制設置在讀寫時鐘中最快時鐘周期的一半,或者設置成源端時鐘的一半,或者設置成源端時鐘的倍數且bit間的skew明顯小于一個源端時鐘周期。
使用ateris的工具里面建議的是在pre-CTS的時候set_max_delay設置成源端時鐘周期。在Post-CTS的時候需要保證(CLK_A+Delay)Skew < Ttxclk - CLK_B(skew)即保證單個bit的傳輸必須不能超過其他bit。
我們來分析一下這個公式的由來,如果是在pre-CTS階段,時鐘網絡是ideal的不存在CLK_A和CLK_B的skew,Delay小于Ttxclk即可。那為什么不是像網上提到的那樣約束比較嚴格呢?
分情況討論這樣的情況:
1)如果是慢時鐘往快時鐘傳:
下面是慢時鐘周期每個cycle打一個數據,可以看到快時鐘采樣要么是下一個狀態要么是當前狀態。只要每個bit的延遲不超過源時鐘即可。
2)如果是快時鐘往慢時鐘傳:
可以看到慢時鐘域實際上看到的格雷碼跳變是,0000->0001->0110,發生了3個bit同時跳變的情況,但是0110并不是從0001直接跳變而來的,而是在中間周期穩定了一個源端時鐘周期之后跳變的,所以有風險的只有bit2,并且即使恢復成0或者1對FIFO的判斷也沒有影響。所以保證各個狀態之間沒有重疊也不會影響功能,所以設置成源端時鐘周期即可。
還有個博主提到了如下情況:
當快慢時鐘域之間頻率差距過大的時候,會出現慢時鐘域的有效沿采樣的時候,有較多bit發生跳變的情況。
假設慢時鐘域的有效亞穩態窗如上,假設為10%,快時鐘域的狀態至少撐滿一個亞穩態窗。其實這個窗應該就是setup和hold滿足時的區間。
4.如果深度是不是2^n應該如何設置格雷碼的跳變?
同步fifo里,深度任意可配的同步fifo里使用了兩個非飽和的cnt計數器記錄讀寫地址指針,waddr和raddr均比實際地址多一位,最高位用來指示套圈情況。當waddr和raddr的最高位相同時,fifo_cnt = waddr-raddr;當waddr和raddr的最高位相反時,fifo_cnt = DEPTH + waddr[ADDR_WIDTH-1:0] ? - raddr[ADDR_WIDTH-1:0]。最高位作為標志位,當低位計數到DEPTH-1時,高位翻轉。
assign waddr_d_h = (waddr[DP_WD-1:0] == DEPTH-1) ? ~waddr[DP_WD] : waddr[DP_WD];
assign waddr_d_l = (waddr[DP_WD-1:0] == DEPTH-1) ? 0 : waddr[DP_WD-1:0] + 1;
always @(posedge clk or negedge rst_n)beginif(~rst_n) waddr <= 0;else if(wenc) waddr <= {waddr_d_h, waddr_d_l};
end
異步fifo中,如何仍然采用上面的方法就有可能出現非相鄰的跳轉,會出現多bit跳變的情況。
由上圖可以看到格雷碼對稱性的特性。
根據這個特性假設現在的深度為5,那可知當計數到4的時候即格雷碼0110時,下一個狀態應該跳轉到11即格雷碼1110,才能保證只出現單bit的跳轉。
偏移的規律是5的話2^3=8,8-5=3,8+3=11。
parameter DEPTH = 11;
parameter WIDTH = $clog2(DEPTH);//4
parameter DEPTH_TO2 = 2 ^ WIDTH;//16
parameter SHIFT = DEPTH_TO2 - DEPTH;//16-11=5