Tcl與Design Compiler (十一)——其他的時序約束選項(二)


本文如果有錯,歡迎留言更正;此外,轉載請標明出處 http://www.cnblogs.com/IClearner/  ,作者:IC_learner

前面介紹的設計都不算很復雜,都是使用時鍾的默認行為作為電路的約束,都存在有路徑給你約束,即信號的變化要在一個時鍾周期內完成,並達到穩定值,以滿足寄存器的建立和保持的要求。此外進行可測性設計(design for test)時,為了提高測試的覆蓋率,我們經常使用多路(multiplex,簡稱mux)傳輸電路的控制時鍾,使電路的時鍾信號可以由輸入端直接控制。這些電路約束屬於復雜的約束,除了理論上的講解之外,還會進行實戰,實戰內容主要為圍繞前面的偽路徑和多周期路徑進行的,主要內容如下:

    ·異步設計路徑和邏輯上不存在的路徑的時序約束(時序例外)

    ·多時鍾周期的時序約束

    ·分頻電路和多路時鍾傳輸的時鍾約束

    ·實戰

 

1、異步設計路徑和邏輯上不存在的路徑的時序約束(時序例外)

(1)異步設計的路徑約束

  前面說的都是同步時序電路,下面就用介紹一下異步時序電路的約束吧。異步時序電路的時鍾來自不同的時鍾,模塊之間的時鍾是不同頻或者同頻不同相的關系,一些時鍾在我們的設計里沒有對應的端口,如下圖所示:

               

上圖中,一共用4個時鍾源,有5種不同的時鍾;我們要綜合電路使用的是時鍾CLKC,時鍾源是OSC3,前后模塊的時鍾各不一樣,因此是異步電路。

(在傳統的同步和異步設計分類上,有些由同一個晶振產生的時鍾由於可能沒有固定的相位關系,因此會被認為是異步設計;在那種情況下,我們也可以使用這里的異步約束進行相關的時序約束)

  進行異步電路設計時,設計者要注意會產生亞穩態,導致某些寄存器的輸出為不定態。為了避免產生亞穩態問題,可以考慮在設計中使用雙時鍾、不易到亞穩態的觸發器(double-clocking,metastable-hard Flip-Flops),或使用雙端口(dual-port)的FIFO等等。

  對於穿越異步邊界的任何路徑,我們必須禁止對這些路徑做時序綜合。由於不同時鍾源的時鍾之間相位關系是不確定的,一直在變,對跨時鍾域的路徑作時間約束是毫無意義的。因此我們不要浪費DC的時間,試圖使異步路徑“滿足時序要求”。我們可用set_false_path命令為跨時鍾域的路徑作約束(其實是解除時序路徑的約束)。這也就是異步電路里面的時序約束比較重要的。

  例如對於下面的異步電路:

               

設計之間是異步的,存在垮時鍾域的路徑(如上圖所示),我們就要用set_false_path命令為跨時鍾域的路徑作約束,上圖的異步電路對應的跨時鍾域約束如下所示:

        #Make sure register-register paths meet timing

        create_clock  -period  20  [get_ports CLKA]

        create_clock  -period  10  [get_ports CLKB]

        #Don't optimize logic crossing clock domains

        set_false_path  -from  [get_clocks  CLKA]  -to  [get_clocks  CLKB]

        set_false_path  -from  [get_clocks  CLKB]  -to  [get_clocks  CLKA]

 

如果設計中的所有時鍾都是異步的,可用下面命令為跨時鍾域的路徑做約束:

             

set_false_path命令對路徑作時序約束后,DC做綜合時,將中止對這些路徑做時間的優化。

 

(2)邏輯上不存在的路徑的約束

  set_false_ path命令除了可以用於約束異步電路外,還可以用於約束邏輯上不存在的路徑(logically false paths)。邏輯上不存在的路徑是什么呢,下面通過一個例子說明,對於下面的電路:

           

選擇信號是0的時候,前面的MUX打開的是A1,后面MUX打開的是B2,因此數據的通路就是A1B2(數據從A1流到B2);當選擇信號是1的時候,前面的MUX打開的是B1,后面MUX打開的是A2,因此數據的通路就是B1A2。由此可以看到,選擇信號無論是1還是0,前面的MUX的A1引腳和后面的MUX的A2引腳之間是沒有數據流通的,也就是該邏輯通路並不存在。同樣,前面的MUX的B1引腳和后面的MUX的B2引腳之間的邏輯通路也不存在。因此這兩條數據通路就是邏輯上不存在的路徑,比如從點A1到點A2之間有一條物理上的連接路徑,但是點A1輸入信號並不通過這條路徑傳輸到A2;這種物理上存在連接關系,但是邏輯不存在的路徑稱為邏輯偽路徑,在DC中,偽路徑“false path”稱為時序例外(timing exceptions)。可以用下面的拓撲圖理解:

                   

  我們可以用report_timing_requirements命令報告設計中所有的例外(包括有效的例外和無效的例外)。report_timing_requirements命令加選項"-ignored",將把無效的例外報告出來,例如:

               

上面的報告中,我們可以知道,從引腳{IO_PCI_CLK\pclk}到引腳{IO_SDRAM_CLK\ SDRAM_ CLK}並不存在實際的信號流通,也就是這是一條邏輯偽路徑。引腳{IO_SDRAM_CLK\SDRAM_CLK}不是路徑的終點(根據定義,路徑的終點必須是輸出端口或寄存器的數據輸入引腳);引腳FF1/Q不是路徑的起點(根據定義,時序路徑的起點必須是輸入端口或寄存器的時鍾引腳)。注意:report_timing_requirements命令無”-valid”,選項。該命令的所有選項如下:

               

 

 

  要去掉任何不要的例外,可使用reset_path命令,例如:  dc_shell  >  reset_path   -from   FF1/Q

 

 

2、多時鍾周期的時序約束

(1)關於建立時間

如下圖所示加法器電路,時鍾clk的周期定義為10ns,按設計規格,加法器的延遲約為6個時鍾周期

                         

①默認的的建立時間約束

  默認的時間建立時間約束將指示DC在10ns的時候對C_reg進行建立時間是否滿足的分析;很顯然,默認的時序約束會使寄存器的數據輸入引腳C_reg/D信號變化,不滿足建立(setup)的要求,將產生亞穩態,寄存器C_reg的輸出為不定態。也就是一個時鍾周期的約束不能滿足約束要求。

②修改后的建立時間約束

  對於多時鍾周期的建立時間約束,可以使用下面命令進行修改

      create_clock  -period  10  [get_ports  CLK]

      set_multicycle_path6-setup  -to  [get_pins  C_reg[*]/D]

   (等價於set_multicycle_path-setup  6  -to  [get_pins  C_reg[*]/D] )

  注意這條命令是要知道多時鍾周期的終點寄存器的(注意:這條命令設置了所有的前級寄存器時鍾端口到C_reg寄存器的D端口路徑都是多時鍾周期路徑,而set_multicycle_path6-setup  -from  A_reg/Clk  -to  [get_pins  C_reg[*]/D],則是僅僅現在從A寄存器的時鍾端口C_reg寄存D端口的這一條路徑而已),通過這條命令,就告訴DC將僅僅在第6個上升沿,即60 ns作建立的分析(也就是間隔6個時鍾周期后再做建立時間分析)。這時,加法器的最大允許延遲是:

             

對應的時序關系如下圖所示:

               

 

(2)關於保持時間

①默認的保持時間約束

  對於保持時間的約束,我們是不是默認就OK了呢?在前面的建立時間和保持時間的概念中,我們知道默認的保持分析時間在建立分析的前一周期,(此處應該有鏈接)也就是說,在這個多時鍾周期的加法器中,DC將在50 ns這個時刻分析電路有無違反保持要求,要求加法器的最小延時是(注意這是默認的情況下的所做的時序要求):

                 

默認的保持時間分析對應的時序關系如下所示:

                   

也就是說,經過修改過后的多時鍾周期建立時間約束和默認的保持時間約束就會告訴DC,要DC綜合出一條路徑使其建立時間滿足60 ns的要求,並且同時滿足保持時間50ns的要求

  但是要綜合出這樣一條路徑實際上是沒有必要的,這樣做只會增加電路的復雜度。為什么會這樣呢?這是因為默認保持時間不滿足約束,也就是說,不應該在50ns的時候進行保存時間的檢測,需要修改多時鍾周期保持時間的約束

 

②修改后的保持時間約束

  那在上面什么時候做保持時間分析比較合適呢?我們知道在時間為60 ns的時刻,引起寄存器C_reg的D引腳信號變化的是時鍾CLK在0時刻的觸發沿。此刻(在0ns時),時鍾CLK把寄存器A_reg和B_reg的D引腳信號采樣到它們的輸出端。再通過加法器把信號傳輸到寄存器C_reg的D引腳。由此可見會沖掉C_reg的D端數據只是A_reg和B_reg的D引腳的變化的時候,也就0ns時刻,因此應該對保持時間做出調整,應該在0ns的時候做保持時間的檢測,也就是應該提前5個時鍾周期,從50ns提前到0ns。

  修該后的約束如下所示:

                

對應的時序關系如下所示:

                 

保持時間的分析提前了5個周期,加法器的允許延時為:

                 

  僅僅通過約束告訴DC這是一個多時鍾周期的加法器電路是不夠充分的,一方面是由於后面的觸發器應該經過6個時鍾周期之后才能采到正確的值(但是C_reg不知道什么采到的值是正確的),另一方面是約束僅僅是告訴DC如果這塊電路的延時太大或者太小的時候要報錯;可以這么理解,約束單單保證了時序上這個是一個多時鍾周期的加法器電路,但是這個加法器電路經過延時得到結果后,后面的C_reg采樣的正確性,需要在RTL代碼的設計上保證,需要加上相應的控制信號,保證DC能夠綜合出能夠正確工作的多時鍾周期的加法器。對於前面的加法器,可以需要加上相應的使能信號,因此電路設計如下所示:

                     

 

 

(3)多時鍾路徑和普通路徑同在一個設計中

前面的例子是單純的多時鍾周期設計,當電路里面同時存在多時鍾周期路徑和普通路徑時,如下圖所示:

                     

 

該電路中,要求寄存器間的乘法運算為兩個時鍾周期,加法運算為默認的一個時鍾周期,這時候,可以使用下面命令進行約束:

        create_clock  -period  10  [get_ports  clk];#創建時鍾

        set_multicycle_path  -setup  2  -from  FFA/CP  -through  Multiply/Out  -to FFB/D  ;

        set_multicycle_path  -hold   1  -from  FFA/CP  -through  Multiply/Out  -to FFB/D  ;

注意電路圖中的from、through、to的對象

 

 

3、分頻電路和多路時鍾傳輸的時鍾約束

下面的電路中包含了時鍾分頻電路和多路時鍾傳輸電路:

                     

(1)首先是多路時鍾的傳輸問題

  對於上圖中的電路,其多路時鍾傳輸電路的模型如下所示:

                    

其內部電路的時鍾(Int_Clk)連接到多路輸出電路的輸出,如果我們不告訴DC要用Tst_Clk、Ext_Clk中的哪一個時鍾,DC會自己選擇一個,這就可能出現DC選擇不同的時鍾做建立和保持的分析,因此我們必須指定要用哪個時鍾進行約束和分析。例如對於下面的多路時鍾傳輸電路:

                    

可以使用的下面命令進行約束:

        create_clock   Ext_Clk   -period   10 (=create_clock  -period   10  Ext_Clk )

        create_ clock  Test_Clk  -period  100

        set_dont_touch_network  [get_clocks Ext_Clk]

        set_dont_touch_network  [get_clocks Test_ Clk]

        #Allow DesignTime to use Ext_ Clk  fortiming analysis

        set_disable_timing   CLOCK_GEN/U1  -from  a  -to  y

最后一行的命令(set_disable_timing)去掉了MUX從引腳a到引腳Y的時間弧((timing arc),這時DC認為它們沒有時間關系,也就是,我們只指定使用Ext_ Clk這時鍾進行分析建立時間和保持時間。set_disable_timing命令用起來很靈活,該命令有多個選項。我們可以用該命令使設計中用到的庫單元的時間弧(timing arc)無效set_disable_timing命令使當前設計中的通過指定單元,引腳或端口的時間無效(相當於斷開)。set_false_ path在這里不起作用。我們已經定義了Test_ Clk和Ext_ Clk為時鍾,從引腳a和b到引腳Y是一條理想的時鍾路徑,不受約束,因此set_false_ path命令不起作用。

  除了使用set_disable_timing 這條命令進行多路時鍾傳輸的約束外,還有用模式分析特征(case analysis feature)進行約束,如下所示:

            set_case_analysis   0  [get_pins  U1/sel]

或者

            set_case_analysis   0  [get_ports  sel]

與命令set_disable_timing相比,命令set_case_analysis 會增加DC的運行時間,但使用模式分析命令較簡單。

 

2)接下來是分頻電路

   Design Compiler不能推導出分頻時鍾的波形。時鍾信號可以通過任何的組合電路,但中止於寄存器。DC並不知道寄存器的輸出端為時鍾信號或非時鍾信號。如下圖所示:

                

Int_ClkExt_Clk經過二分頻后從寄存器U2的輸出端口Q輸出的時鍾,但DC並不知道這是你的時鍾信號,需要添加相應的約束,如下所示:

    create_clock   -period  50  [get_ports  Ext_Clk] ;

    create_generated_clock  -name  Int_Clk  -source [get_pins CLOCK_GEN/U2/CP]   -divide_by  2  [get_pins  CLOCK_GEN/U2/Q] ;

    set_clock_latency  -source  1. 5   [get_clocks   Int_Clk] ;

    set_clock_latency   0.5  [get_clocks  Int_Clk] ;

create_generated_clock這條命令會將時鍾源(Ext_Clk)的任何變化自動反映在產生的時鍾(Int_Clk)上。

  做完版圖后的設計已經加入了時鍾樹,連線的寄生參數也被反標(back-annotated)到時鍾樹上。這時候,DC用set_propagated_clock命令和時鍾樹的實際寄生參數自動地計算所有時鍾引腳的延遲。我們不需用set_clock_latency命令為時鍾建模。約束改成:

    create_clock   -period  50  [get_ports  Ext_Clk] ;

    create_generated_clock  -name  Int_Clk  -source [get_pins CLOCK_GEN/U2/CP]   -divide_by  2  [get_pins  CLOCK_GEN/U2/Q] ;

    set_propagated_clock  [list  [all_clocks]  [get_generated_clock  *]]

 

(3)多時鍾發送/接收

  前面分別講了多路時鍾傳輸和分頻的約束,也就把下面電路圖中的陰影部分單獨拿出來進行約束;將下來,將為下面的電路進行多時鍾發送/接收問題(DES_B模塊和DES_A模塊之間存在數據的發送和接收)進行約束:

                     

假設我們使用的Ext_Clk的時鍾,其周期是50ns。模塊B與模塊A的時鍾是有周期關系的,單單看模塊A和模塊B,就是多時鍾同步設計的問題了,對於整個模塊也就是(TOP_LEVEL),可以使用下面的約束:

        create_clock   -period    50   -waveform   {0  25}  Ext_Clk

        create_clock   -period   100   -waveform   {0  50}  Int Clk

        set_clock_latency  -source  1. 5   [get_clocks   Int_Clk] ;

        set_clock_latency   0.5  [get_clocks  Int_Clk] ;

 

 

4、實戰

  這次的實戰和以前的實戰不一樣,這次的實戰不再是從RTL源文件開始,而是從一個被約束過的、綜合過的文件,也就是經過映射后的.ddc文件,通過對編譯后的設計進行合適的約束,使得設計滿足設計要求。

  我們先來看一下我們要進行約束的部分RTL原理圖:

             

這個設計包含了純組合邏輯、時序邏輯、多路選擇器導致的偽路徑。組合和邏輯和時序邏輯具有不同的約束,實驗初始的約束不當,有設計違規;我們需要進行合適的約束,從而消除設計違規。

啟動DC,讀入.ddc設計,進行讀入設計后的檢查

這步驟跟前面的章節類似,不再進行敘述,需要注意的是,因為需要讀入.ddc設計,因此使用的命令是read_ddc

 

查看綜合后原始的違規情況:

               

                    

可以知道有違規情況。

 

③進行合理地約束:

  最初的約束不符合情況,因此在這里我們進行合適的約束(或者說重新進行約束)。

--->約束組合邏輯:

  我們根據下面的原理圖進行約束:

             

 

  ·對於組合邏輯,一方面,組合邏輯的具有6ns的最大延時;另一方面,由於組合邏輯沒有時鍾輸入端口,因此需要創建虛擬時鍾,因此第一步對組合邏輯的約束如下:

      create_clock -name vclk -period 6

      set in_ports [get_ports "coeff* adr_i*"]

      set_input_delay  0 -clock vclk -add_delay $in_ports

      set_output_delay 0 -clock vclk -add_delay [all_outputs]

  ·我們可以查看約束后的虛擬時鍾的路徑情況:

               

可以看到,設計依舊違規了,這是由於多路選擇器的原因,clk和虛擬時鍾vclk進行交疊了;因此我們要在邏輯路徑上設置偽路徑,禁止這些時鍾進行時序分析:

      set_clock_group -name false_grp1 -logically_exclusive -group clk -group vclk

設置完成之后,vclk不違規了。

·組合邏輯並沒有約束完成,虛擬時鍾vclk雖然不違規,但是clk違規了,對於組合邏輯,clk並沒有起到作用,因此還需要禁止clk對組合邏輯的輸入到輸出進行時序分析:

      set_false_path -from [get_clocks clk] -through $in_ports -through [all_outputs] -to [get_clocks clk]

注意,約束使用了兩個“through”選項,把clk到clk的組合路徑,從clk到clk的時序路徑中分離出來;約束完成之后,我們可以查看一下對於組合邏輯的輸入輸出路徑,clk的分析情況:

      report_timing -from $in_ports -to [all_outputs]

結果是通過的。

 

--->約束多周期路徑

  約束完組合路徑,我們就要進行約束時序邏輯路徑了。時序邏輯路徑是由clk控制的,我們先來看一下clk的時序路徑報告:

       report_timing -group clk

得到的結果是違規的,這是因為時序邏輯路徑中存在多周期路徑,在原理圖上,mul_result_reg是多周期路徑,因此需要進行設置多周期路徑約束:

  

  ·建立時間的多周期約束:

        set_multicycle_path  2  -setup  -to  mul_result_reg*/D

也就是設置這條路徑是2個周期的路徑;約束完成之后,我們可以查看是否正確約束:

        report_timing -to mul_result_reg*/D

可以看到,建立時間的約束滿足了,沒有違規

 

  ·保持時間的多周期約束:

我們查看保持時間是否違規:

        report_timing -to mul_result_reg*/D -delay min

可以看到,保持時間是違規的,因此我們要進行保持時間的多周期路徑約束:

        set_multicycle_path 1 -hold -to mul_result_reg*/D

  再次查看之后,我們可以看到,保持時間沒有違規了。

 

  基於上面的原理圖的各個約束都進行了合適的修改,主要是單獨約束組合邏輯、設置虛假路徑和設置(時序邏輯的)多周期路徑這三個方面。

由於這是因為約束不當而引起綜合后的違規,當設置了正當的約束之后,違規就消除了,我們也不必再進行綜合了,實戰步驟到這里就結束了。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM