FPGA基礎(chǔ)知識極簡教程(7)詳解亞穩(wěn)態(tài)與跨時鐘域傳輸


寫在前面

這篇文章主要是對過去對于亞穩(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è)計可能無法正常工作。

這是解決高傳播延遲的方法:

  1. 降低時鐘頻率
  2. 將您的邏輯分解為多個階段(流水線)

降低時鐘頻率是最明顯的事情。 如果您能夠較慢地運行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寫成如下的形式:
t _{clk(min)} = t_{su} + t_h + t_p

這是為什么呢?

如果違反建立和保持時間會發(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)是什么呢?
如下圖:

亞穩(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(寄存器時鐘到輸出時間)。


亞穩(wěn)態(tài)發(fā)生

上面所說的是建立時間不足導(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ā)生:

  1. 您正在采樣FPGA外部的信號
  2. 您正在跨時鐘域傳輸數(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)定。

兩級觸發(fā)器同步

當(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),一個用于讀取,一個用于寫入。


參考資料


交個朋友

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容