在《時(shí)鐘與復(fù)位》一文中已經(jīng)解釋了亞穩(wěn)態(tài)的含義以及亞穩(wěn)態(tài)存在的危害。在單時(shí)鐘系統(tǒng)中,亞穩(wěn)態(tài)出現(xiàn)的概率非常低,采用同步設(shè)計(jì)基本可以規(guī)避風(fēng)險(xiǎn)。但在實(shí)際應(yīng)用中,一個(gè)系統(tǒng)往往包含多個(gè)時(shí)鐘,且許多時(shí)鐘之間沒有固定的相位關(guān)系,即所謂的異步時(shí)鐘域,這就給設(shè)計(jì)帶來(lái)很大的挑戰(zhàn)。
01跨時(shí)鐘域類型
跨時(shí)鐘域傳輸可分為以下幾種情況:
- 同頻零相位差時(shí)鐘
- 同頻恒定相位差時(shí)鐘
- 非同頻時(shí)鐘
- 整數(shù)倍頻時(shí)鐘
- 非整數(shù)倍頻時(shí)鐘
同頻同相時(shí)鐘可視為等效的時(shí)鐘,在不考慮時(shí)鐘抖動(dòng)(Jitter)影響的情況下,兩個(gè)時(shí)鐘域之間的傳輸可視作同步的。而同頻恒定相位差的時(shí)鐘由于時(shí)鐘有效沿之間有一定的相位差,因此對(duì)建立/保持時(shí)間裕量有一定的影響。設(shè)計(jì)時(shí)需要確保組合邏輯的延時(shí)能滿足采樣處的建立/保持時(shí)間要求,一般可通過(guò)在發(fā)射沿或捕獲沿加入適當(dāng)?shù)钠苼?lái)完成時(shí)序的調(diào)整。
而對(duì)于非同頻的時(shí)鐘,二者可以是同步關(guān)系,也可以是異步關(guān)系,這里再次強(qiáng)調(diào)一下同步與異步的界定標(biāo)準(zhǔn):有固定相位關(guān)系的稱為同步時(shí)鐘,沒有固定相位關(guān)系的稱為異步時(shí)鐘。
那么什么叫固定的相位關(guān)系?即兩個(gè)時(shí)鐘的有效沿之間的偏移量始終保持恒定,也即所謂的相位差固定。
非同頻時(shí)鐘之間的關(guān)系可以分為整數(shù)倍頻和非整數(shù)倍頻。整數(shù)倍頻的時(shí)鐘往往是同源時(shí)鐘,相位關(guān)系也往往是固定的。但是存在源時(shí)鐘域和目標(biāo)時(shí)鐘域的快慢關(guān)系。假設(shè)源時(shí)鐘是20MHz,而目標(biāo)時(shí)鐘域只有5MHz,那么就是快時(shí)鐘域到慢時(shí)鐘域的傳輸。
“慢采快”會(huì)導(dǎo)致數(shù)據(jù)丟失的問題,為了避免這個(gè)問題,要求源時(shí)鐘域的數(shù)據(jù)至少保持一個(gè)目標(biāo)時(shí)鐘域的周期的穩(wěn)定狀態(tài)。對(duì)于單比特控制信號(hào)的“快→慢”傳輸,可以采用如圖所示的脈沖同步器來(lái)檢測(cè)快時(shí)鐘域的脈沖信號(hào)。
一旦data1有脈沖拉高,經(jīng)過(guò)mux的反饋,第一級(jí)DFF的輸出就會(huì)反轉(zhuǎn)并鎖住,直到下一個(gè)data1脈沖的到來(lái)才會(huì)再次反轉(zhuǎn)。中間兩級(jí)DFF就是用來(lái)打兩拍消除亞穩(wěn)態(tài)的,最后一級(jí)DFF輸出的異或用來(lái)檢測(cè)同步過(guò)來(lái)的信號(hào)是否發(fā)生反轉(zhuǎn),由于data1每次脈沖都會(huì)導(dǎo)致clk1時(shí)鐘域的輸出發(fā)生反轉(zhuǎn),于是該脈沖信號(hào)就在clk2時(shí)鐘域被記錄下來(lái)并保持一個(gè)周期的穩(wěn)定狀態(tài)。
那么假如源時(shí)鐘比目標(biāo)時(shí)鐘要慢呢?在“快采慢”的情況下,需要注意快時(shí)鐘域觸發(fā)器不要對(duì)慢時(shí)鐘域的輸出信號(hào)進(jìn)行重復(fù)采樣,在慢時(shí)鐘域維持一個(gè)周期的信號(hào)在慢時(shí)鐘域可能維持好幾個(gè)周期,這顯然會(huì)導(dǎo)致邏輯功能的錯(cuò)誤。因此需要確保同步過(guò)來(lái)的信號(hào)在快時(shí)鐘域也只維持一個(gè)周期,因此采樣如圖所示的邊沿(上升沿)同步電路,就能將慢時(shí)鐘域的脈沖同步到快時(shí)鐘域。
(此法只用于慢時(shí)鐘域的單周期脈沖信號(hào)的同步,若源信號(hào)存在維持幾個(gè)周期的高電平,在快時(shí)鐘域也只會(huì)存在一個(gè)周期的脈沖信號(hào),此時(shí)用基本的電平同步電路就可以了)
非整數(shù)倍頻的時(shí)鐘的之間相位關(guān)系總是在變化,這讓時(shí)序分析變得很復(fù)雜,除了亞穩(wěn)態(tài)的問題,還要考慮相位差的變化是否會(huì)導(dǎo)致丟數(shù)據(jù),即便能滿足時(shí)序,數(shù)據(jù)傳輸不連貫的問題也始終存在。
此時(shí),已經(jīng)標(biāo)準(zhǔn)化的技術(shù),如FIFO和握手,解決了絕大多數(shù)情況下的跨時(shí)鐘域數(shù)據(jù)傳輸。
02FIFO
關(guān)于握手機(jī)制,筆者在《解剖AXI(一)—— 從握手開始》一文中已有說(shuō)明,本文不再過(guò)多贅述。在實(shí)際設(shè)計(jì)中,使用握手機(jī)制來(lái)傳輸單比特信號(hào)產(chǎn)生的延遲要遠(yuǎn)大于使用FIFO進(jìn)行傳輸,因此本文重點(diǎn)介紹FIFO傳輸?shù)臋C(jī)制,以及同步FIFO和異步FIFO的架構(gòu)。
FIFO,即First In First Out,先進(jìn)先出的數(shù)據(jù)緩存器??深惐葹榕抨?duì),先進(jìn)隊(duì)伍的先服務(wù),先寫入FIFO的數(shù)據(jù)先讀出。所以FIFO沒有外部地址線,只能靠回滾遞增的內(nèi)部讀寫指針來(lái)指示下一個(gè)要讀/寫的地址。根據(jù)讀寫控制信號(hào)的時(shí)鐘關(guān)系,又可分為同步FIFO和異步FIFO。
2.1 同步FIFO
同步FIFO的寫時(shí)鐘和讀時(shí)鐘為同步時(shí)鐘,一般情況下為同一個(gè)時(shí)鐘。同步FIFO內(nèi)的所有邏輯都是同步邏輯。一個(gè)最簡(jiǎn)單的同步FIFO框圖如下所示。
產(chǎn)生FIFO空滿信號(hào)的方法有兩種:
一是在FIFO內(nèi)部設(shè)置一個(gè)計(jì)數(shù)器來(lái)指示當(dāng)前FIFO內(nèi)部緩存了多少個(gè)數(shù)據(jù),但這會(huì)引入新的寄存器造成額外的資源開銷;
二是通過(guò)拓寬讀寫指針的位數(shù),然后根據(jù)讀寫指針的關(guān)系來(lái)判斷空滿。
當(dāng)讀指針等于寫指針時(shí),標(biāo)明FIFO處于空狀態(tài),如圖所示,假設(shè)FIFO深度為8,那么讀寫地址的位寬取3,讀寫指針在此基礎(chǔ)上拓寬一位:
當(dāng)FIFO內(nèi)有數(shù)據(jù)寫入時(shí),寫指針增加,此時(shí)讀指針的低N-1位不等于寫指針的低N-1位(N為指針拓寬一位之后的位寬),如圖所示:
如果此時(shí)再讀出兩個(gè)數(shù)據(jù),F(xiàn)IFO又將回到空狀態(tài),此時(shí)讀指針與寫指針又相等:
假如此時(shí),一口氣寫入8個(gè)數(shù)據(jù),寫指針+8,變成4'b1010,F(xiàn)IFO處于滿狀態(tài),此時(shí)讀寫指針的最高位不同,但低N-1位相同:
于是可以總結(jié)得到FIFO空滿信號(hào)的生成條件:
- fifo_empty_o:
assign fifo_empty_o = (wr_ptr == rd_ptr);
- fifo_full_o:
assign fifo_full_o = ((wr_ptr[$clog2(DEPTH)] != rd_ptr[$clog2(DEPTH)]) && (wr_addr == rd_addr));
2.2 異步FIFO
同步FIFO可用于在同步時(shí)鐘域傳輸多比特信號(hào),但若要實(shí)現(xiàn)兩個(gè)異步時(shí)鐘域之間的數(shù)據(jù)傳輸,就要使用異步FIFO。
異步FIFO相較于同步FIFO最大的不同在于讀/寫時(shí)鐘域是異步的,也就是說(shuō)讀寫控制信號(hào)是由不同的時(shí)鐘驅(qū)動(dòng)的,這就導(dǎo)致讀指針需要同步到寫時(shí)鐘域,才能判斷FIFO是否滿;寫指針也需要同步到讀時(shí)鐘域,才能判斷FIFO是否空。
異步FIFO的框圖如下:
但是對(duì)于多比特信號(hào)的跨時(shí)鐘域同步,存在一個(gè)嚴(yán)重的問題。如果像同步FIFO那樣使用二進(jìn)制的讀寫指針,指針每次加一都可能使好幾位發(fā)生翻轉(zhuǎn),以三位指針為例,假設(shè)當(dāng)前指針為3'b111下一次操作后指針加1變?yōu)?'b000.
我們已經(jīng)知道,單比特信號(hào)打兩拍同步之后的結(jié)果可能恢復(fù)成0或1的其中一個(gè)穩(wěn)態(tài),假如該單比特信號(hào)是從0→1,最終哪怕同步結(jié)果是0,也不影響整個(gè)電路的功能,只當(dāng)是沒有發(fā)生這次操作,在后續(xù)的運(yùn)行過(guò)程中再把正確信號(hào)同步過(guò)來(lái)也是ok的。
但是對(duì)于多比特信號(hào)而言,多位發(fā)生翻轉(zhuǎn),其中的每一位都可能同步為不同的結(jié)果,也就是說(shuō)3'b111→3'b000可能變成3'b111→3'b010或者3'b111→3'b110、3'b111→3'b001、3'b111→3'b101之類的任意值,這就明顯違背了指針的正常邏輯,破壞了電路的功能。
我們希求的效果是3'b111→3'b000,哪怕同步結(jié)果不是3'b000,也得是3’b111保持不變。因此要求指針遞增每次只變化一位。
剛好,格雷碼的編碼方式就是相鄰兩個(gè)數(shù)值只有一位不同。因此在異步FIFO設(shè)計(jì)中,跨時(shí)鐘域同步讀寫指針之前,要將二進(jìn)制指針先轉(zhuǎn)換成格雷碼編碼的指針,再進(jìn)行同步。
二進(jìn)制和格雷碼的互相轉(zhuǎn)化邏輯,這里不再贅述,只展示Verilog代碼以供參考:
bin2gray:
module bin2gray
#(
parameter WIDTH = 8
)
(
input [WIDTH-1:0] bin,
output [WIDTH-1:0] gray
);
assign gray = bin ^ {1'b0,bin[WIDTH-1:1]};
endmodule
gray2bin:
module gray2bin
#(
parameter WIDTH = 8
)
(
input [WIDTH-1:0] gray,
output [WIDTH-1:0] bin
);
genvar i;
generate
for(i=0;i< WIDTH;i=i+1)begin
assign bin[i] = ^gray[WIDTH-1:i];
end
endgenerate
endmodule
相應(yīng)的,用格雷碼編碼的指針來(lái)判斷異步FIFO的空滿狀態(tài):
- fifo_empty_o:
assign empty = (rd_ptr_gray == wr_ptr_gray_sync_r2);
- fifo_full_o:
assign full = ({~wr_ptr_gray[ADDR_WIDTH:ADDR_WIDTH-1],wr_ptr_gray[ADDR_WIDTH-2:0]} == rd_ptr_gray_sync_r2);
-
fifo
+關(guān)注
關(guān)注
3文章
389瀏覽量
43776 -
時(shí)鐘
+關(guān)注
關(guān)注
11文章
1742瀏覽量
131641 -
時(shí)鐘域
+關(guān)注
關(guān)注
0文章
52瀏覽量
9545 -
異步FIFO
+關(guān)注
關(guān)注
0文章
20瀏覽量
8392 -
同步FIFO
+關(guān)注
關(guān)注
0文章
5瀏覽量
5377
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論