時(shí)鐘周期約束
時(shí)鐘周期約束,顧名思義,就是我們對(duì)時(shí)鐘的周期進(jìn)行約束,這個(gè)約束是我們用的最多的約束了,也是最重要的約束。
下面我們講一些Vivado中時(shí)鐘約束指令。
1. Create_clock
在Vivado中使用create_clock來(lái)創(chuàng)建時(shí)鐘周期約束。使用方法為:
create_clock -name-period -waveform { } [get_ports ]
這里的時(shí)鐘必須是主時(shí)鐘primary clock,主時(shí)鐘通常有兩種情形:一種是時(shí)鐘由外部時(shí)鐘源提供,通過(guò)時(shí)鐘引腳進(jìn)入FPGA,該時(shí)鐘引腳綁定的時(shí)鐘為主時(shí)鐘:另一種是高速收發(fā)器(GT)的時(shí)鐘RXOUTCLK或TXOUTCLK。對(duì)于7系列FPGA,需要對(duì)GT的這兩個(gè)時(shí)鐘手工約束:對(duì)于UltraScale FPGA,只需對(duì)GT的輸入時(shí)鐘約束即可,Vivado會(huì)自動(dòng)對(duì)這兩個(gè)時(shí)鐘約束。
如何確定主時(shí)鐘是時(shí)鐘周期約束的關(guān)鍵,除了根據(jù)主時(shí)鐘的兩種情形判斷之外,還可以借助Tcl腳本判斷。
在vivado自帶的example project里面,打開CPU(HDL)的工程,如下圖所示。
把工程的xdc文件中,create_clock的幾項(xiàng)都注釋掉。這里解釋下端口(Port)和管腳(Pin)。get_ports獲取的是FPGA的IO端口,get_pins獲取的是FPGA內(nèi)部子模塊的Pin,具體的我們?cè)诘?4講的Tcl命令中會(huì)講到。
再Open Synthesized Design或者Open Implementation Design,并通過(guò)以下兩種方式查看主時(shí)鐘。
? 方式一
運(yùn)行tcl指令report_clock_networks -name mainclock,顯示結(jié)果如下:
? 方式二
運(yùn)行tcl指令check_timing -override_defaults no_clock,顯示結(jié)果如下:
Vivado中的tcl命令行相當(dāng)好用,有很多的功能,大家可以開始習(xí)慣用起來(lái)了。
對(duì)于高速收發(fā)器的時(shí)鐘,我們也以Vivado中的CPU example工程為例,看下Xilinx官方是怎么約束的。
# Define the clocks for the GTX blocks create_clock -name gt0_txusrclk_i -period 12.8 [get_pins mgtEngine/ROCKETIO_WRAPPER_TILE_i/gt0_ROCKETIO_WRAPPER_TILE_i/gtxe2_i/TXOUTCLK] create_clock -name gt2_txusrclk_i -period 12.8 [get_pins mgtEngine/ROCKETIO_WRAPPER_TILE_i/gt2_ROCKETIO_WRAPPER_TILE_i/gtxe2_i/TXOUTCLK] create_clock -name gt4_txusrclk_i -period 12.8 [get_pins mgtEngine/ROCKETIO_WRAPPER_TILE_i/gt4_ROCKETIO_WRAPPER_TILE_i/gtxe2_i/TXOUTCLK] create_clock -name gt6_txusrclk_i -period 12.8 [get_pins mgtEngine/ROCKETIO_WRAPPER_TILE_i/gt6_ROCKETIO_WRAPPER_TILE_i/gtxe2_i/TXOUTCLK]
當(dāng)系統(tǒng)中有多個(gè)主時(shí)鐘,且這幾個(gè)主時(shí)鐘之間存在確定的相位關(guān)系時(shí),需要用到-waveform參數(shù)。如果有兩個(gè)主時(shí)鐘,如下圖所示。
則時(shí)鐘約束為:
create_clock -name clk0 -period 10.0 -waveform {0 5} [get_ports clk0] create_clock -name clk1 -period 8.0 -waveform {2 8} [get_ports clk1]
約束中的數(shù)字的單位默認(rèn)是ns,若不寫wavefrom參數(shù),則默認(rèn)是占空比為50%且第一個(gè)上升沿出現(xiàn)在0時(shí)刻。使用report_clocks指令可以查看約束是否生效。還是上面的CPU的例子,把約束都還原到最初的狀態(tài)。執(zhí)行report_clocks后,如下所示,我們只列出其中幾項(xiàng)內(nèi)容。
Clock Report Clock Period(ns) Waveform(ns) Attributes Sources sysClk 10.000 {0.000 5.000} P {sysClk} gt0_txusrclk_i 12.800 {0.000 6.400} P {mgtEngine/ROCKETIO_WRAPPER_TILE_i/gt0_ROCKETIO_WRAPPER_TILE_i/gtxe2_i/TXOUTCLK} ... ==================================================== Generated Clocks ==================================================== Generated Clock : clkfbout Master Source : clkgen/mmcm_adv_inst/CLKIN1 Master Clock : sysClk Multiply By : 1 Generated Sources : {clkgen/mmcm_adv_inst/CLKFBOUT} Generated Clock : cpuClk_4 Master Source : clkgen/mmcm_adv_inst/CLKIN1 Master Clock : sysClk Edges : {1 2 3} Edge Shifts(ns) : {0.000 5.000 10.000} Generated Sources : {clkgen/mmcm_adv_inst/CLKOUT0} ...
一般來(lái)講,我們的輸入時(shí)鐘都是差分的,此時(shí)我們只對(duì)P端進(jìn)行約束即可。如果同時(shí)約束了P端和N端,通過(guò)report_clock_interaction命令可以看到提示unsafe。這樣既會(huì)增加內(nèi)存開銷,也會(huì)延長(zhǎng)編譯時(shí)間。
2. create_generated_clock
其使用方法為:
create_generated_clock -name/ -source / -multiply_by / -divide_by / -master_clock /
從名字就能看出來(lái),這個(gè)是約束我們?cè)贔PGA內(nèi)部產(chǎn)生的衍生時(shí)鐘, 所以參數(shù)在中有個(gè)-source,就是指定這個(gè)時(shí)鐘是從哪里來(lái)的,這個(gè)時(shí)鐘叫做master clock,是指上級(jí)時(shí)鐘,區(qū)別于primary clock。
它可以是我們上面講的primary clock,也可以是其他的衍生時(shí)鐘。該命令不是設(shè)定周期或波形,而是描述時(shí)鐘電路如何對(duì)上級(jí)時(shí)鐘進(jìn)行轉(zhuǎn)換。
這種轉(zhuǎn)換可以是下面的關(guān)系:
-簡(jiǎn)單的頻率分頻
-簡(jiǎn)單的頻率倍頻
-頻率倍頻與分頻的組合,獲得一個(gè)非整數(shù)的比例,通常由MMCM或PLL完成
-相移或波形反相
-占空比改變
-上述所有關(guān)系的組合
衍生時(shí)鐘又分兩種情況:
① Vivado自動(dòng)推導(dǎo)的衍生時(shí)鐘
② 用戶自定義的衍生時(shí)鐘
首先來(lái)看第一種,如果使用PLL或者M(jìn)MCM,則Vivado會(huì)自動(dòng)推導(dǎo)出一個(gè)約束。大家可以打開Vivado中有個(gè)叫wavegen的工程,在這個(gè)工程中,輸入時(shí)鐘經(jīng)過(guò)PLL輸出了2個(gè)時(shí)鐘,如下圖所示。
但在xdc文件中,并未對(duì)這2個(gè)輸出時(shí)鐘進(jìn)行約束,只對(duì)輸入的時(shí)鐘進(jìn)行了約束,若我們使用report_clocks指令,則會(huì)看到:
注:有三個(gè)約束是因?yàn)镻LL會(huì)自動(dòng)輸出一個(gè)反饋時(shí)鐘
自動(dòng)推導(dǎo)的好處在于當(dāng)MMCM/PLL/BUFR的配置改變而影響到輸出時(shí)鐘的頻率和相位時(shí),用戶無(wú)需改寫約束,Vivado仍然可以自動(dòng)推導(dǎo)出正確的頻率/相位信息。劣勢(shì)在于,用戶并不清楚自動(dòng)推導(dǎo)出的衍生鐘的名字,當(dāng)設(shè)計(jì)層次改變時(shí),衍生鐘的名字也有可能改變。但由于該衍生時(shí)鐘的約束并非我們自定義的,因此可能會(huì)沒(méi)有關(guān)注到它名字的改變,當(dāng)我們使用者這些衍生時(shí)鐘進(jìn)行別的約束時(shí),就會(huì)出現(xiàn)錯(cuò)誤。
解決辦法是用戶自己手動(dòng)寫出自動(dòng)推導(dǎo)的衍生時(shí)鐘的名字,也僅僅寫出名字即可,其余的不寫。如下所示。
create_generated_clock -name/ -source
這一步很容易會(huì)被提示critical warning,其實(shí)有個(gè)很簡(jiǎn)單的方法,就是name和source都按照vivado中生成的來(lái)。具體我們到后面的例子中會(huì)講到。
3. set_clock_groups
使用方法為:
set_clock_groups -asynchronous -group-group set_clock_groups -physically_exclusive -group -group
這個(gè)約束常用的方法有三種,第一種用法是當(dāng)兩個(gè)主時(shí)鐘是異步關(guān)系時(shí),使用asynchronous來(lái)指定。這個(gè)在我們平時(shí)用的還是比較多的,一般稍微大點(diǎn)的工程,都會(huì)出現(xiàn)至少兩個(gè)主時(shí)鐘,而且這兩個(gè)時(shí)鐘之間并沒(méi)有任何的相位關(guān)系,這時(shí)就要指定:
create_clock -period 10 -name clk1 [get_ports clk1] create_clock -period 8 -name clk2 [get_ports clk2] set_clock_groups -asynchronous -group clk1 -group clk2
第二種用法是當(dāng)我們需要驗(yàn)證同一個(gè)時(shí)鐘端口在不同時(shí)鐘頻率下能否獲得時(shí)序收斂時(shí)使用。比如有兩個(gè)異步主時(shí)鐘clk1和clk2,需要驗(yàn)證在clk2頻率為100MHz,clk1頻率分別為50MHz、100MHz和200MHz下的時(shí)序收斂情況,我們就可以這樣寫。
create_clock -name clk1A -period 20.0 [get_ports clk1] create_clock -name clk1B -period 10.0 [get_ports clk1] -add create_clock -name clk1C -period 5.0 [get_ports clk1] -add create_clock -name clk2 -period 10.0 [get_ports clk2] set_clock_groups -physically_exclusive -group clk1A -group clk1B -group clk1C set_clock_groups -asynchronous -group "clk1A clk1B clk1C" -group clk2
第三種用法就是當(dāng)我們使用BUFGMUX時(shí),會(huì)有兩個(gè)輸入時(shí)鐘,但只會(huì)有一個(gè)時(shí)鐘被使用。比如MMCM輸入100MHz時(shí)鐘,兩個(gè)輸出分別為50MHz和200MHz,這兩個(gè)時(shí)鐘進(jìn)入了BUFGMUX,如下圖所示。
在這種情況下,我們需要設(shè)置的時(shí)序約束如下:
set_clock_groups -logically_exclusive / -group [get_clocks -of [get_pins inst_mmcm/inst/mmcm_adv_inst/CLKOUT0]] / -group [get_clocks -of [get_pins inst_mmcm/inst/mmcm_adv_inst/CLKOUT1]]
4. 創(chuàng)建虛擬時(shí)鐘
虛擬時(shí)鐘通常用于設(shè)定對(duì)輸入和輸出的延遲約束,這個(gè)約束其實(shí)是屬于IO約束中的延遲約束,之所以放到這里來(lái)講,是因?yàn)樘摂M時(shí)鐘的創(chuàng)建,用到了本章節(jié)講的一些理論。虛擬時(shí)鐘和前面講的延遲約束的使用場(chǎng)景不太相同。顧名思義,虛擬時(shí)鐘,就是沒(méi)有與之綁定的物理管腳。
虛擬時(shí)鐘主要用于以下三個(gè)場(chǎng)景:
? 外部IO的參考時(shí)鐘并不是設(shè)計(jì)中的時(shí)鐘
? FPGA I/O路徑參考時(shí)鐘來(lái)源于內(nèi)部衍生時(shí)鐘,但與主時(shí)鐘的頻率關(guān)系并不是整數(shù)倍
? 針對(duì)I/O指定不同的jitter和latency
簡(jiǎn)而言之,之所以要?jiǎng)?chuàng)建虛擬時(shí)鐘,對(duì)于輸入來(lái)說(shuō),是因?yàn)檩斎氲紽PGA數(shù)據(jù)的捕獲時(shí)鐘是FPGA內(nèi)部產(chǎn)生的,與主時(shí)鐘頻率不同;或者PCB上有Clock Buffer導(dǎo)致時(shí)鐘延遲不同。對(duì)于輸出來(lái)說(shuō),下游器件只接收到FPGA發(fā)送過(guò)去的數(shù)據(jù),并沒(méi)有隨路時(shí)鐘,用自己內(nèi)部的時(shí)鐘去捕獲數(shù)據(jù)。
如下圖所示,在FPGA的A和B端口分別有兩個(gè)輸入,其中捕獲A端口的時(shí)鐘是主時(shí)鐘,而捕獲B端口的時(shí)鐘是MMCM輸出的衍生時(shí)鐘,而且該衍生時(shí)鐘與主時(shí)鐘的頻率不是整數(shù)倍關(guān)系。
這種情況下時(shí)序約束如下:
create_clock -name sysclk -period 10 [get_ports clkin] create_clock -name virclk -period 6.4 set_input_delay 2 -clock sysclk [get_ports A] set_input_delay 2 -clock virclk [get_ports B]
可以看到,創(chuàng)建虛擬時(shí)鐘用的也是create_clock約束,但后面并沒(méi)有加get_ports參數(shù),因此被稱為虛擬時(shí)鐘。
再舉個(gè)輸出的例子,我們常用的UART和SPI,當(dāng)FPGA通過(guò)串口向下游器件發(fā)送數(shù)據(jù)時(shí),僅僅發(fā)過(guò)去了uart_tx這個(gè)數(shù)據(jù),下游器件通過(guò)自己內(nèi)部的時(shí)鐘去捕獲uart_tx上的數(shù)據(jù),這就需要通過(guò)虛擬時(shí)鐘來(lái)約束;而當(dāng)FPGA通過(guò)SPI向下游器件發(fā)送數(shù)據(jù)時(shí),會(huì)發(fā)送sclk/sda/csn三個(gè)信號(hào),其中sclk就是sda的隨路時(shí)鐘,下游器件通過(guò)sclk去捕獲sda的數(shù)據(jù),而不是用自己內(nèi)部的時(shí)鐘,這是就不需要虛擬時(shí)鐘,直接使用set_output_delay即可。
注意,虛擬時(shí)鐘必須在約束I/O延遲之前被定義。
5. 最大最小延遲約束
顧名思義,就是設(shè)置路徑的max/min delay,主要應(yīng)用場(chǎng)景有兩個(gè):
? 輸入管腳的信號(hào)經(jīng)過(guò)組合邏輯后直接輸出到管腳
? 異步電路之間的最大最小延遲
設(shè)置方式為:
set_max_delay[-datapath_only] [-from ][-to ][-through ] set_min_delay [-from ] [-to ][-through ]
max/min delay的約束平時(shí)用的相對(duì)少一些,因?yàn)樵诳绠惒綍r(shí)鐘域時(shí),我們往往會(huì)設(shè)置asynchronous或者false_path。對(duì)于異步時(shí)鐘,我們一般都會(huì)通過(guò)設(shè)計(jì)來(lái)保證時(shí)序能夠收斂,而不是通過(guò)時(shí)序約束來(lái)保證。
-
FPGA
+關(guān)注
關(guān)注
1625文章
21620瀏覽量
601238 -
時(shí)序約束
+關(guān)注
關(guān)注
1文章
115瀏覽量
13403 -
Vivado
+關(guān)注
關(guān)注
19文章
804瀏覽量
66224
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論