寫在前面
這篇文章主要是對過去對于亞穩(wěn)態(tài)以及跨時鐘域傳輸問題的一次總結(jié),作為這個系列博文的一次梳理吧。
注:微信公眾號也會更新,歡迎大家關(guān)注,我有了新文章會通過微信公眾號推送通知大家,讓你有選擇的看到我的最新動態(tài)。
- 個人微信公眾號: FPGA LAB
正文
FPGA或ASIC中的傳播延遲
在以前秋招的時候,我常常遇到時序分析的題目,其中全英文的題目中出現(xiàn)過傳播延遲這個單詞,即:Propagation Delay!
當(dāng)然 ,如果你讀慣了中文的表達,例如我們常常遇到這樣的說法,門延遲,布線延遲等等,這時當(dāng)你遇到了Propagation Delay的時候也許會不確定是什么東西,是Tco?還是Tlogic?還是什么?等等,F(xiàn)orget it !這就會影響你分析問題的狀態(tài)!
今天這里給出明確的定義:
Propagation Delay is the amount of time it takes for a signal to travel from a source to a destination.
意思是傳播延遲是信號從源觸發(fā)器到目的觸發(fā)器所需要的時間!這一看不就是邏輯延遲加上布線延遲嗎?
確實如此!
在FPGA或ASIC內(nèi)部,到處都有成千上萬的細線。 當(dāng)您實際將電線的物理長度加在一起時,它們很容易超過一英尺長( 經(jīng)驗法則是,信號可以在一納秒內(nèi)傳輸一英尺的導(dǎo)線。),考慮到芯片有多小,這非常驚人。 此外,您的代碼執(zhí)行的每個邏輯都需要一定的延遲時間。 由于確實存在這些延遲,因此數(shù)字設(shè)計人員需要了解它們?nèi)绾斡绊慒PGA或ASIC。
如下圖為傳播延遲示意圖:
傳播延遲對時序邏輯至關(guān)重要。 我們知道,時序邏輯是由時鐘驅(qū)動的邏輯。 在上圖中,有兩個觸發(fā)器,它們之間通過一些邏輯和布線(電線)連接在一起。第一個觸發(fā)器的輸出傳播到第二個觸發(fā)器的輸入所花費的時間為傳播延遲。 這兩個觸發(fā)器相距越遠,或者中間的組合邏輯越多,則它們之間的傳播延遲就越長。 傳播延遲時間越長,時鐘的運行速度就越慢。
這樣做的原因是兩個觸發(fā)器使用相同的時鐘。 第一個觸發(fā)器在時鐘沿1處驅(qū)動其輸出。第二個觸發(fā)器直到時鐘沿2才看到第一個觸發(fā)器的輸出變化,此時它驅(qū)動其輸出。 如果信號可以在一個時鐘周期內(nèi)安全地從觸發(fā)器1傳輸?shù)接|發(fā)器2,則您的設(shè)計很好! 如果沒有,您將遇到問題。
例如,考慮兩個觸發(fā)器相距10納秒(ns)的情況。 如果您使用的時鐘頻率為50 MHz(周期為20 ns),則將是安全的。 您還有10 ns的空閑時間。 但是,如果使用200 MHz時鐘(周期為5 ns),則設(shè)計將無法進行時序分析,并且無法按預(yù)期方式工作。
FPGA或ASIC工具中任何時序分析器的目的都是告訴您在時序方面是否存在問題。 如果您的設(shè)計太慢而無法以所需的時鐘頻率運行,則會出現(xiàn)時序錯誤,并且您的設(shè)計可能無法正常工作。
這是解決高傳播延遲的方法:
- 降低時鐘頻率
- 將您的邏輯分解為多個階段(流水線)
降低時鐘頻率是最明顯的事情。 如果您能夠較慢地運行FPGA,那么您的時序?qū)纳啤?將您的邏輯分解成多個階段是更可靠的解決方案。 如果在兩個觸發(fā)器之間邏輯較少,則傳播延遲將減小,并且您的設(shè)計將滿足時序要求。(回顧下retiming是不是也需要這么做呢?)
示意圖如下:
在上圖中,兩個觸發(fā)器之間存在大量邏輯。 如此之多,以至于設(shè)計的傳播延遲太大,并且導(dǎo)致時序不滿足。 如果設(shè)計人員在三個觸發(fā)器之間分解邏輯,則邏輯的一半可以在前兩個觸發(fā)器之間完成,邏輯的另一半可以在后兩個觸發(fā)器之間完成。 現(xiàn)在,這些工具將在一個時鐘周期內(nèi)完成所需工作的時間幾乎增加了一倍。 這就是所謂的流水線,對于成為一名優(yōu)秀的數(shù)字設(shè)計師來說非常重要。 當(dāng)你使用流水線的方式設(shè)計電路時,在高時鐘頻率下滿足時序的機會會更大。
建立和保持時間是什么?
建立時間和保持時間,是數(shù)字設(shè)計師最基礎(chǔ)的問題,他是時序分析的核心,或者說時序分析其實就是圍繞著建立時間以及保持時間來分析的,你的設(shè)計滿足建立時間要求以及保持時間要求,就能通過時序檢測,否則就會違例!
下面就詳細講解他們!
我們都知道,傳播延遲是信號在兩個觸發(fā)器之間通過所花費的時間。 當(dāng)信號沿導(dǎo)線傳輸時,它可以從0-> 1或1-> 0改變。 觸發(fā)器的輸入必須穩(wěn)定(不變),以使FPGA設(shè)計正常工作。 在時鐘采樣之前,輸入必須穩(wěn)定一小段時間。 該時間量稱為建立時間。 建立時間是指在時鐘沿之前,輸入到觸發(fā)器穩(wěn)定所需的時間。 保持時間類似于建立時間,但是它在時鐘沿發(fā)生后處理事件。 保持時間是在時鐘沿之后輸入到觸發(fā)器穩(wěn)定所需的最短時間。
如下示意圖:
在圖中,綠色區(qū)域代表tsu或Setup Time。 藍色區(qū)域代表時間或保持時間。 在這些區(qū)域中,觸發(fā)器中的數(shù)據(jù)必須為穩(wěn)定的0或1,否則會發(fā)生不良情況。
建立和保持時間與傳播延遲和時鐘頻率有何關(guān)系?
建立時間,保持時間和傳播延遲都會影響您的FPGA設(shè)計時序。FPGA工具將檢查以確保您的設(shè)計滿足時序要求,這意味著時鐘的運行速度不超過邏輯允許的速度。可以計算出FPGA時鐘所允許的最短時間(其周期,由T表示)。從中可以找到時鐘的頻率,因為頻率是周期的倒數(shù)(F = 1 / T)。
就以下圖為例吧:

假設(shè)Tco表示觸發(fā)器時鐘有效到數(shù)據(jù)輸出的時間;Tpd表示傳播延遲,Tsu表示建立時間,不考慮時鐘偏斜,那么最小時鐘周期為:
Tmin = Tco + Tpd + Tsu;
通常,在您的FPGA設(shè)計中,t su和t h對于觸發(fā)器是固定的,因此,您可以控制的唯一變量是t p或傳播延遲。這種延遲代表了多少東西,你想在一個時鐘周期內(nèi)完成。您嘗試做的事情越多,t p越長,t clk(min)越高,這意味著您將無法盡快對FPGA設(shè)計進行計時。這是FPGA設(shè)計的基本權(quán)衡。您需要權(quán)衡一個時鐘周期內(nèi)可以為時鐘頻率執(zhí)行多少操作。這兩個是相反的關(guān)系……沒有免費的午餐!
思考:參考資料中把最小時鐘周期Tmin寫成如下的形式:
這是為什么呢?
如果違反建立和保持時間會發(fā)生什么?
如果您的設(shè)計違反設(shè)置或保持時間,則不能保證觸發(fā)器輸出穩(wěn)定??赡転榱?,可能為一,可能在中間的某個地方,未知。這稱為亞穩(wěn)態(tài)。FPGA內(nèi)部的亞穩(wěn)定性不是所希望的,它可能導(dǎo)致您的FPGA表現(xiàn)異常。
FPGA設(shè)計人員發(fā)現(xiàn)他們是否違反設(shè)置或保持時間的主要方法是通過布局布線(Place and Route)運行FPGA時。布局布線(Place and Route)是將VHDL或Verilog代碼放入FPGA時發(fā)生的情況。作為此過程的一部分,F(xiàn)PGA工具將帶您進行設(shè)計并進行時序分析。在此時序分析中,您將看到任何時序錯誤,這些錯誤實際上只是違反設(shè)置時間或保持時間。如何解決這些錯誤將在后面給出!
總之,建立時間和保持時間是FPGA設(shè)計人員要理解的重要概念。如果違反這些時間,F(xiàn)PGA將無法達到預(yù)期的效果!
FPGA中的亞穩(wěn)定是什么?
上面也說了,如果設(shè)計放到FPGA中(ASIC一致),違反了建立時間或保持時間,則輸出會處于亞穩(wěn)態(tài)!
那亞穩(wěn)態(tài)是什么呢?
如下圖:
如上圖所示, 紅色區(qū)域代表tsu或Setup Time。 如您所見,在觸發(fā)器建立期間,輸入到觸發(fā)器的數(shù)據(jù)從低到高。如果數(shù)據(jù)在時鐘上升沿的建立時間內(nèi)發(fā)生跳變,則會產(chǎn)生亞穩(wěn)態(tài)輸出,即輸出值在短時間內(nèi)處于不確定態(tài),有可能是1,有可能是0,也可能什么都不是,處于中間態(tài)!之后穩(wěn)定為0或1。但是我們?nèi)匀徊恢垒敵鲆阅姆N狀態(tài)結(jié)束。有時可能是0,有時其他情況會發(fā)生 再次為1.。這不是理想的行為。 您必須始終知道您的FPGA在做什么。
為了更清晰說明,我們參考資料提出一個類似的例子 :
下圖說明了亞穩(wěn)信號。當(dāng)時鐘信號變化時,輸入信號從低電平轉(zhuǎn)換為高電平,這違反了寄存器的tsu(建立時間)要求。數(shù)據(jù)輸出信號示例從低電平開始,然后變?yōu)閬喎€(wěn)態(tài),在高電平和低電平之間徘徊。信號輸出A解析為輸入數(shù)據(jù)的新邏輯1狀態(tài),而輸出B返回數(shù)據(jù)輸入的原始邏輯0狀態(tài)。在這兩種情況下,輸出到定義的1或0狀態(tài)的轉(zhuǎn)換的延遲都超過寄存器的指定tco(寄存器時鐘到輸出時間)。
上面所說的是建立時間不足導(dǎo)致的亞穩(wěn)態(tài),其實導(dǎo)致亞穩(wěn)態(tài)還有可能是保持時間不足!
亞穩(wěn)態(tài)何時會導(dǎo)致設(shè)計失???
如果在下一個寄存器捕獲數(shù)據(jù)之前數(shù)據(jù)輸出信號穩(wěn)定為有效狀態(tài),則亞穩(wěn)信號不會對系統(tǒng)操作產(chǎn)生負面影響。但是,如果亞穩(wěn)態(tài)信號在到達下一個設(shè)計寄存器之前未穩(wěn)定為低電平或高電平狀態(tài),則可能導(dǎo)致系統(tǒng)故障。
同步寄存器
大多數(shù)亞穩(wěn)態(tài)條件以下列兩種方式之一發(fā)生:
- 您正在采樣FPGA外部的信號
- 您正在跨時鐘域傳輸數(shù)據(jù)
這兩種情況都可以用相同的方式解決。 每當(dāng)遇到可能引入亞穩(wěn)定性的情況時,您都可以簡單地“double-flop”您的數(shù)據(jù)(兩級觸發(fā)器采樣)。
在左圖中,第一個觸發(fā)器正在采樣與時鐘異步的信號。 這將在輸出處創(chuàng)建一個亞穩(wěn)態(tài)條件。 如果再次采樣此輸出,則現(xiàn)在可以修復(fù)亞穩(wěn)態(tài)事件。 第二個觸發(fā)器的輸出將保持穩(wěn)定。

當(dāng)然這只是最簡單的處理方式,當(dāng)考慮到跨時鐘域信號處理時,還需具體情況具體分析。
跨時鐘域傳輸
在FPGA內(nèi)部跨越時鐘域是一項常見的任務(wù),但這是許多數(shù)字設(shè)計人員遇到的麻煩。如果數(shù)字設(shè)計人員不了解從一個時鐘域轉(zhuǎn)換到另一個時鐘域所涉及的所有細節(jié),則可能會出現(xiàn)問題。
下面對跨時鐘域處理可能出現(xiàn)的問題進行總結(jié)!
從較慢的時鐘域過渡到較快的時鐘域
最簡單的跨時鐘域傳輸類型是從一個時鐘域到一個更快的時鐘域。在這種類型的傳輸中,您仍然會受到Metastability的影響,但是該文章中描述的解決方案在這種情況下非常有效。您需要做的就是將數(shù)據(jù)“兩級同步”,如下圖所示。

較慢的時鐘是您的源時鐘域,更快的時鐘是您的目標時鐘域。在較快的時鐘域中,第一個觸發(fā)器具有亞穩(wěn)態(tài)輸出。發(fā)生這種情況的原因是,在執(zhí)行此跨時鐘域傳輸操作時,會違反設(shè)置和保持時間,這是造成亞穩(wěn)性的原因。我們可以通過在較快的時鐘域中簡單地重新采樣數(shù)據(jù)或?qū)?shù)據(jù)進行兩次寄存來解決此問題,如上圖所示。第二個觸發(fā)器的輸出將保持穩(wěn)定,現(xiàn)在可以在更快的時鐘域中使用數(shù)據(jù)。
下面的Verilog設(shè)計顯示了當(dāng)從慢速時鐘域過渡到快速時鐘域時,如何尋找信號的上升沿。請注意,用于邊緣檢測的邏輯必須在快速時鐘域中完成。
// Verilog Example:
reg r1_Data, r2_Data, r3_Data, trig_pos=0;
always @(posedge i_Fast_Clock)
begin
// r1_Data is METASTABLE, r2_Data and r3_Data are STABLE
r1_Data <= i_Slow_Data;
r2_Data <= r1_Data;
r3_Data <= r2_Data;
if (r3_Data == 1'b0 && r2_Data == 1'b1)
begin
// Positive Edge Condition
trig_pos <= 1;
end
end
注 :這里說明的是提取采樣信號的上升沿,如果你不需要這樣,就直接兩級同步即可得到非亞穩(wěn)態(tài)的采樣信號。
從較快的時鐘域過渡到較慢的時鐘域
這種情況比前一種情況稍微復(fù)雜一些。在這里,我們正在從快速時鐘域轉(zhuǎn)向較慢的時鐘域。在這種情況下,很容易想到一個示例,其中快速時鐘域中的數(shù)據(jù)可能在慢速時鐘域甚至沒有看到之前就發(fā)生了變化。例如,考慮一個在100 MHz時鐘域中發(fā)生1個時鐘周期的脈沖,您正在嘗試在25 MHz時鐘域中進行采樣。如果僅使用25 MHz時鐘對數(shù)據(jù)進行采樣,則很有可能永遠不會看到此脈沖! 為了將信號從快速時鐘域傳輸?shù)铰贂r鐘域,您必須擴展信號。請參見下圖,以直觀的方式查看。


當(dāng)您將脈沖或數(shù)據(jù)延長足夠長的時間以確保慢時鐘域有機會對其進行采樣時,就會發(fā)生數(shù)據(jù)拉伸。在上面的示例中,您需要擴展數(shù)據(jù)以確保無論何時采樣數(shù)據(jù)都滿足建立和保持時間。為了正確保證滿足建立時間和保持時間,我建議延長脈沖,使它們在慢速時鐘域中至少占用2個時鐘周期。因此,在上面的示例中,您應(yīng)該將100 MHz脈沖擴展到至少8個時鐘周期(您可以隨時增加)。
這種從快時鐘域到慢時鐘域的信號傳輸,其設(shè)計可以參考我之前的博文:談?wù)効鐣r鐘域傳輸問題(CDC)
博文里給出了設(shè)計:
module Sync_Pulse(
input clka,
input clkb,
input rst_n,
input pulse_ina,
output pulse_outb,
output signal_outb
);
//-------------------------------------------------------
reg signal_a;
reg signal_b;
reg signal_b_r;
reg signal_b_rr;
reg signal_a_r;
reg signal_a_rr;
//-------------------------------------------------------
//在clka下,生成展寬信號signal_a
always @(posedge clka or negedge rst_n)begin
if(rst_n == 1'b0)begin
signal_a <= 1'b0;
end
else if(pulse_ina == 1'b1)begin
signal_a <= 1'b1;
end
else if(signal_a_rr == 1'b1)
signal_a <= 1'b0;
else
signal_a <= signal_a;
end
//-------------------------------------------------------
//在clkb下同步signal_a
always @(posedge clkb or negedge rst_n)begin
if(rst_n == 1'b0)begin
signal_b <= 1'b0;
end
else begin
signal_b <= signal_a;
end
end
//-------------------------------------------------------
//在clkb下生成脈沖信號和輸出信號
always @(posedge clkb or negedge rst_n)begin
if(rst_n == 1'b0)begin
signal_b_r <= 'b0;
signal_b_rr <= 'b0;
end
else begin
signal_b_rr <= signal_b_r;
signal_b_r <= signal_b;
end
end
assign pulse_outb = ~signal_b_rr & signal_b_r;
assign signal_outb = signal_b_rr;
//-------------------------------------------------------
//在clka下采集signal_b_rr,生成signal_a_rr用于反饋拉低signal_a
always @(posedge clka or negedge rst_n)begin
if(rst_n == 1'b0)begin
signal_a_r <= 'b0;
signal_a_rr <= 'b0;
end
else begin
signal_a_rr <= signal_a_r;
signal_a_r <= signal_b_rr;
end
end
endmodule
如何理解,可以參照仿真圖或者波形圖:
異步FIFO
上面所說的還都是單比特信號,對于多比特信號,我們可以使用異步FIFO來處理跨時鐘域傳輸問題,至于異步FIFO的設(shè)計,我是真的沒必要在贅余了,見博客:FPGA基礎(chǔ)知識極簡教程(4)從FIFO設(shè)計講起之異步FIFO篇
這是我最新寫的比較好理解的一種設(shè)計版本。
時序錯誤和跨時鐘域
通常,當(dāng)您跨時鐘域時,會遇到計時錯誤。這個是正常的!這是告訴您的情況,您的設(shè)置和保持時間將無法保持,并且您將處于亞穩(wěn)狀態(tài)。如前所述,亞穩(wěn)定是這項工作的常識,因此,只要您了解并可以圍繞它進行設(shè)計,就可以了。
總之,作為FPGA設(shè)計人員,您將遇到跨時鐘域的情況。您需要清楚地了解在這些情況下發(fā)生的常見陷阱。如果跨時鐘域的情況足夠簡單,則可以將數(shù)據(jù)兩級寄存器采樣或執(zhí)行脈沖展寬。在大多數(shù)情況下,您可能需要使用支持兩個時鐘的FIFO(異步FIFO),一個用于讀取,一個用于寫入。
參考資料
交個朋友
個人微信公眾號:FPGA LAB
知乎:李銳博恩