Timequest Timing Analyzer進行時序分析(二)


四、用TimeQuest對DAC7512控制器進行時序分析

    在對某個對象下時序約束的時候,首先要能正確識別它,TimeQuest會對設計中各組成部分根據屬性進行歸類,我們在下時序約束的時候,可以通過命令查找對應類別的某個對象。

TimeQuest對設計中各組成部分的歸類主要有cells,pins,nets和ports幾種。寄存器,門電路等為cells;設計的輸入輸出端口為ports;寄存器,門電路等的輸入輸出引腳為pins;ports和pins之間的連線為nets。具體可以參照下圖(此圖出自Altera Time Quest的使用說明)。

 

    下面我們按照本文第三部分用TimeQuest做時序分析的基本操作流程所描述的流程對DAC7512控制器進行時序分析。建立和預編譯項目的部分相對簡單,涉及到的也只是QuartusII的一些基本操作,這里我們就不再做具體的敘述。主要介紹如何向項目中添加時序約束和如何進行時序驗證。首先建立一個名稱與項目top層名字一致的sdc文件,然后按照下面的步驟添加時序約束。

 

1. 創建時鍾

    添加時序約束的第一步就是創建時鍾。為了確保STA結果的准確性,必須定義設計中所有的時鍾,並指定時鍾所有相關參數。TimeQuest支持下面的時鍾類型:

a) 基准時鍾(Base clocks)

b) 虛擬時鍾(Virtual clocks)

c) 多頻率時鍾(Multifrequency clocks)

d) 生成時鍾(Generated clocks)

我們在添加時序約束的時候,首先創建時鍾的原因是后面其它的時序約束都要參考相關的時鍾的。

基准時鍾:

    基准時鍾是輸入到FPGA中的原始輸入時鍾。與PLLs輸出的時鍾不同,基准時鍾一般是由片外晶振產生的。定義基准時鍾的原因是其他生成時鍾和時序約束通常都以基准時鍾為參照。很明顯,在DAC7512控制器中,CLK_IN是基准時鍾。我們用下面的命令來創建這個基准時鍾:

 1 create_clock -name CLK_IN -period 40 -waveform {0 20} [get_ports {CLK_IN}] 

    其中,create_clock是創建時鍾的命令,后面是命令的各種選項。其中-name CLK_IN選項給出了時鍾的名字,即CLK_IN。-period 40給出了時鍾的周期,即40ns。-waveform {0 20}給出了時鍾的占空比,即50/50。最后的[get_ports {CLK_IN}] 是嵌套的tcl命令,給出了CLK_IN對應的port,實際上也就是CLK_IN的輸入引腳。

    在sdc文件里添加上述命令后,在quartusII里編譯設計,然后通過tools –> TimeQuest Time Aanlyzer命令打開TimeQuest。在TimeQuest的Tasks窗口,找到Report Clocks,雙擊之,TimeQuest就會在右邊主窗口給出設計中已成功添加的時鍾信息。如下圖所示,可以看到CLK_IN,其類型為基准時鍾,周期為40ns,頻率為25MHz,targets項為CLK_IN,即表示這個時鍾是連接在CLK_IN端口上的。這說明上面create_clock的命令已經在設計中正確創建了時鍾CLK_IN。

實際上對於create_clock命令,我們可以通過quartus II的幫助系統(http://quartushelp.altera.com/current/),查找它的語法。在QuartusII的幫助里,可以查找到:

Syntax

create_clock [-h | -help] [-long_help] [-add] [-name <clock_name>] -period <value> [-waveform <edge_list>] [<targets>]

     另外,幫助系統里有很詳盡的關於該命令的描述,並且給出了各種使用的范例。不僅僅是這一個命令,所有的命令都可以在幫助系統里找到。如果看到一個陌生的命令,或者不知道命令該如何使用,那么最好的辦法就是在幫助系統里查找該命令。

PLL時鍾:

     上面我們創建了基准時鍾。下面我們創建PLL輸出的時鍾。在Altera的FPGA中,PLL電路是通過ALTPLL的IP庫被添加到設計中的。下圖是一個典型的ALTPLL的結構圖。

從圖上可以看到,當我們選定了基准時鍾和PLL的參數以后,PLL的輸出c0和c1的參數就隨之確定了。所以在QuartusII環境下,可以通過一個簡單的命令讓軟件自動生成PLL輸出的時鍾的時序約束。

 

derive_pll_clocks

    這個命令會自動創建PLL輸出的C0和C1的相關時序約束。同樣的,在sdc文件里添加該命令,然后編譯,在TimeQuest里查看時鍾信息。如下圖所示,derive_pll_clocks在系統里添加了兩個時鍾,PLL1|altpll_component|auto_generated|pll1|clk[0]和PLL1|altpll_component|auto_generated|pll1|clk[1]。可以看出,時鍾是按“PLL層次結構+時鍾端口名字”的規則命名的。時鍾的類型為created clock,周期頻率是在PLL里設定好的。duty_cycle為50/50。Clock source為PLL1|altpll_component|auto_generated|pll1|inclk[0],實際上就是我們之前定義的CLK_IN。derive_pll_clocks會自動搜索時域網絡並創建PLL的輸出時鍾。也可以使用create_generated_clock命令。

derive_pll_clocks的命令格式為:derive_pll_clocks  [-create_base_clocks] [-use_tan_name]

選項[[-create_base_clocks]自動為pll生成輸入時鍾,[-use_tan_name],在默認的情況下,時鍾的名字為輸出時鍾的名字。

derive_pll_clocks命令調用create_generated_clock命令以在pll的輸出時鍾上生成衍生時鍾,create_generated_clock的源是pll的輸入時鍾引腳,在調用derive_pll_clocks命令之前或之后,我們必須手動的為pll生成一個作為其輸入時鍾的基礎時鍾,們如果我們未定義這個輸入時鍾,那么報告中就不會有pll的輸出時鍾,分析儀會給出警告:

The master clock for this clock assignment could no be derived.

clock:<name of pll output clock pin name> was not created.

所以使用<-created_base_clocks>選項自動為pll生成輸入時鍾約束。

可以將drive_pll_clocks命令放在你的sdc中,以使得derive_pll_clocks命令能自動的檢測pll的任何變化,當使用derive_pll_clocks命令,將自動對pll進行約束。

用derive_pll_clocks命令創建PLL相關的時鍾很是方便,但不好的地方就是,時鍾的命名太過復雜,我們在添加與此時鍾相關的時序約束時,就必須用這種名字很長的時鍾,容易出錯,且可讀性也差。所以建議還是采用create_generated_clock命令來創建PLL的時鍾 create_generated_clock命令的語法如下,可以從quartusII的幫助系統里找到每個參數的詳細解釋。

 

Syntax

create_generated_clock [-h | -help] [-long_help] [-add] [-divide_by <factor>] [-duty_cycle <percent>] [-edge_shift <shift_list>] [-edges <edge_list>] [-invert] [-master_clock <clock>] [-multiply_by <factor>] [-name <clock_name>] [-offset <time>] [-phase <degrees>] -source <clock_source> [<targets>]

 

 可以用下面的命令來創建PLL的兩個時鍾C0和C1。我們把時鍾命名為CLK25M和CLK50M,source clock為CLK_IN。

 

create_generated_clock -name CLK25M -source CLK_IN -duty_cycle 50.000 -multiply_by 1 -master_clock {CLK_IN} [get_pins {PLL1|altpll_component|auto_generated|pll1|clk[0]}]

create_generated_clock -name CLK50M -source CLK_IN -duty_cycle 50.000 -multiply_by 2 -master_clock {CLK_IN} [get_pins {PLL1|altpll_component|auto_generated|pll1|clk[1]}]

    用這兩個命令創建的時鍾與derive_pll_clocks命令創建的時鍾的本質是一樣的,只是給時鍾定義了不同的名字。當然我們也可以用derive_pll_clocks中對時鍾的命名方式來使用create_generated_clock命令。同樣的,可以按照上面的方法,在TimeQuest里查看創建時鍾的結果,如下圖所示。

注意,derive_pll_clocks,若沒有選擇[-create_base_clocks],此命令不會為驅動pll的input clock ports create base clocks,若選擇此項,就會自動為pll的輸入端口創建基准時鍾。

 

 到此為止,我們創建了PLL的基准時鍾以及PLL輸出的兩個時鍾CLK25M和CLK50M。

DA_SCLK時鍾:

       在TimeQuest的Tasks窗口里,選擇Report Unconstrained Paths命令,TimeQuest會報告出所有需要下約束但實際並沒有約束的情況。在Report里的Unconstrained Path列表下,我們可以查看這個報告。雙擊Clock Status Summary,就可以在主窗口看到所有時鍾的情況。見下圖,很明顯,軟件辨識出DAC7512模塊下的DA_SCLK為時鍾信號,但是我們並沒有對該時鍾添加約束,所以用紅色將這個時鍾顯示了出來。下一步我們就來創建這個時鍾。

DA_SCLK是用CLK50M通過二分頻電路得到的。所以其source clock為CLK50M。但是,我們在使用create_generated_clock命令創建該時鍾的時候,在-source的參數里,卻不能直接使用CLK50M,而必須使用CLK50M所對應的pin,即PLL1|altpll_component|auto_generated|pll1|clk[1]。這主要是因為-source參數只支持pins,ports和registers。DA_SCLK是由CLK50M通過二分頻電路生成的,其代碼如下: 

 1 reg DA_SCLK;
 2 
 3 always @(posedge CLK50M or negedge RESET)
 4 
 5 begin
 6 
 7 if(~RESET)
 8 
 9 DA_SCLK <= 1'b0;
10 
11 else
12 
13 DA_SCLK <= ~DA_SCLK;
14 
15 end
View Code

可以看到,本質上DA_SCLK為一個寄存器的輸出,所以使用get_registers命令獲取DA_SCLK。DA_SCLK是由CLK50M經二分頻電路生成的,所以-divide_by的參數應該是2。綜上所述,用下面的命令創建DA_SCLK:

create_generated_clock -name DA_SCLK -divide_by 2 -source [get_pins {PLL1|altpll_component|auto_generated|pll1|clk[1]}] [get_registers {DAC7512:DAC7512|DA_SCLK} ]

到此為止,DAC7512控制器中所有4個時鍾都創建好了。如下圖所示:

 我們再看TimeQuest中Unconstrained Paths中clock Status Summary,就會發現,所有的時鍾都已經被添加了約束。

    


免責聲明!

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



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