目錄
一、前言
二、設計示例
2.1 設計代碼
2.2 schematic
2.3 no overwriteing
2.4 約束到非時鐘引腳
三、Create_clock應用
3.1 時鐘輸入端口
3.2?7系列高速收發器輸出管腳
3.3?部分原語的輸出管腳
3.4?主時鐘路徑上創建主時鐘
3.5?虛擬時鐘
3.6?差分時鐘的約束
一、前言
? ? ? ?時序約束中,使用Create_clock約束來生成主時鐘,主時鐘可以說是設計的心臟。主時鐘是來自FPGA芯片外部的時鐘,通過時鐘輸入端口或高速收發器GT的輸出引腳進入FPGA內部。對于賽靈思7系列的器件,主時鐘必須手動定義到GT的輸出,對于Ultrascale和Ultrascale+系列的器件,定時器會自動地接入到GT的輸出。
? ? ? ?生成時鐘通常來源于設計內部的時鐘管理單元,如MMCM,PLL等,生成時鐘是與主時鐘(使用create_clock創建的時鐘)相關,其來源來自主時鐘或其他生成時鐘。因此,需先定義主時鐘,再定義生成時鐘。優點是主時鐘變化時生成時鐘會同步進行變化。
二、設計示例
2.1 設計代碼
module create_clock(CLKIN1,CLKIN2,CLKINSEL,CLKFBIN,rst,d,ff_clkout0_a,ff1);
input CLKIN1,CLKIN2,CLKINSEL,CLKFBIN,rst,d;
output reg ff_clkout0_a,ff1;
reg ff_clkout0,ff0;PLLE2_ADV #(.BANDWIDTH("OPTIMIZED"), // OPTIMIZED, HIGH, LOW.CLKFBOUT_MULT(8), // Multiply value for all CLKOUT, (2-64).CLKFBOUT_PHASE(90.0), // Phase offset in degrees of CLKFB, (-360.000-360.000).// CLKIN_PERIOD: Input clock period in nS to ps resolution (i.e. 33.333 is 30 MHz)..CLKIN1_PERIOD(0.0),.CLKIN2_PERIOD(0.0),// CLKOUT0_DIVIDE - CLKOUT5_DIVIDE: Divide amount for CLKOUT (1-128).CLKOUT0_DIVIDE(1),.CLKOUT1_DIVIDE(2),.CLKOUT2_DIVIDE(4),// CLKOUT0_DUTY_CYCLE - CLKOUT5_DUTY_CYCLE: Duty cycle for CLKOUT outputs (0.001-0.999)..CLKOUT0_DUTY_CYCLE(0.4),.CLKOUT1_DUTY_CYCLE(0.5),.CLKOUT2_DUTY_CYCLE(0.5),// CLKOUT0_PHASE - CLKOUT5_PHASE: Phase offset for CLKOUT outputs (-360.000-360.000)..CLKOUT0_PHASE(0.0),.CLKOUT1_PHASE(0.0),.CLKOUT2_PHASE(0.0),.COMPENSATION("EXTERNAL"), // ZHOLD, BUF_IN, EXTERNAL, INTERNAL.DIVCLK_DIVIDE(1), // Master division value (1-56)// REF_JITTER: Reference input jitter in UI (0.000-0.999)..REF_JITTER1(0.0),.REF_JITTER2(0.0),.STARTUP_WAIT("FALSE") // Delay DONE until PLL Locks, ("TRUE"/"FALSE"))PLLE2_ADV_inst (// Clock Outputs: 1-bit (each) output: User configurable clock outputs.CLKOUT0(CLKOUT0), // 1-bit output: CLKOUT0.CLKOUT1(CLKOUT1), // 1-bit output: CLKOUT1.CLKOUT2(CLKOUT2), // 1-bit output: CLKOUT2// Feedback Clocks: 1-bit (each) output: Clock feedback ports.CLKFBOUT(CLKFBOUT), // 1-bit output: Feedback clock// Clock Inputs: 1-bit (each) input: Clock inputs.CLKIN1(CLKIN1), // 1-bit input: Primary clock.CLKIN2(CLKIN2), // 1-bit input: Secondary clock// Control Ports: 1-bit (each) input: PLL control ports.CLKINSEL(CLKINSEL), // 1-bit input: Clock select, High=CLKIN1 Low=CLKIN2.RST(rst), // 1-bit input: Reset// Feedback Clocks: 1-bit (each) input: Clock feedback ports.CLKFBIN(CLKFBIN) // 1-bit input: Feedback clock);// End of PLLE2_ADV_inst instantiationalways@(posedge CLKOUT0,negedge rst)if(!rst)ff_clkout0<=1'b0;else beginff_clkout0<=d;end
always@(posedge CLKOUT0,negedge rst)if(!rst)ff_clkout0_a<=1'b0;else beginff_clkout0_a<=ff_clkout0;end
always@(posedge CLKIN1,negedge rst)if(!rst)ff0<=1'b0;else beginff0<=ff_clkout0;end
always@(posedge CLKIN1,negedge rst)if(!rst)ff1<=1'b0;else beginff1<=ff0;end
endmodule
2.2 schematic
? ?
????生成時鐘與主時鐘關系可以是分頻,倍頻,非整數倍頻率,相移,占空比切換,以及上述關系的組合。
2.3 no overwriteing
在使用Create_clock約束的時候,存在一個設置項Add this clock to the existing clock(no overwriteing),即不要覆蓋已存在的時鐘,通俗理解就是如果約束的位置存在create_clock時,不要覆蓋,勾選則是兩個時鐘共存。以如下約束為例,在端口CLKIN1上約束創建了兩個主時鐘clkin1,clkin1_1,但clkin1_1未勾選no overwriting?
create_clock -period 10.000 -name clkin1 -waveform {0.000 5.000} [get_ports CLKIN1]
create_clock -period 10.000 -name clkin1_1 -waveform {0.000 5.000} [get_ports CLKIN1]
create_clock -period 10.000 -name clkin2 -waveform {0.000 5.000} [get_ports CLKIN2]
create_generated_clock -name clkout0 -source [get_ports CLKIN1] -multiply_by 2 -add -master_clock [get_clocks clkin1] [get_pins PLLE2_ADV_inst/CLKOUT0]
查看Clock summary,只有clkin1_1,因clkin1被覆蓋了所以沒有clkin1
如果clkin1_1勾選no overwriting,約束如下
create_clock -period 10.000 -name clkin1_1 -waveform {0.000 5.000} -add [get_ports CLKIN1]
clock summary中clkin1和clkin1_1同時存在
同時,在時序報告中,會分析clkin1和clkin1_1間的時序結果,即將兩者作為獨立的時鐘
在clock interaction中顯示clkin1和clkin1_1的關系為Timed(unsafe)
2.4 約束到非時鐘引腳
create_clock如果約束到非時鐘引腳上,仍能進行正常時序分析,只是屬于不合理的用法
如下示例,約束到LUT單元ff0_i_1/o上,時鐘名為clk_lut
create_clock -period 10.000 -name clkin2 -waveform {0.000 5.000} [get_ports CLKIN2]
create_clock -period 10.000 -name clkin1 -waveform {0.000 5.000} [get_ports CLKIN1]
create_generated_clock -name clkout0 -source [get_ports CLKIN1] -multiply_by 2 -add -master_clock clkin1 [get_pins PLLE2_ADV_inst/CLKOUT0]
create_clock -period 9.000 -name clk_lut -waveform {0.000 4.500} [get_pins ff0_i_1/O]
ff0_i_1的輸出連接到觸發器ff0_reg上
時序分析報告中存在clk_lut到clkin1的時序路徑
此時路徑的source clock delay為0,data path的起點為ff0_i_1/o
三、Create_clock應用
3.1 時鐘輸入端口
時鐘輸入端口使用create_clock創建主時鐘是最常見的場景,如下圖,在sysclk端口上創建主時鐘,時鐘經過IBUF和BUFG驅動觸發器REGA和REGB
時鐘周期為10ns,占空比為50%的約束示例如下:
create_clock -name SysClk -period 10 -waveform {0 5} [get_ports sysclk]
3.2?7系列高速收發器輸出管腳
第二種場景是設計中存在高速收發器GT,GT的時鐘輸出引腳提供時鐘,如下連接設計
在gt0的TXOUTCLK引腳上創建主時鐘,通過驅動mmcm0來驅動設計中的其他時序單元,
create_clock -name SysClk -period 10 -waveform {0 5} [get_pins gt0/TXOUTCLK]
注意:標題之所以指明7系列器件是因為UltraScale和UltraScale+器件的設計,?AMD?不建議在?GT?的輸出上定義基準時鐘,?因為在定義?REFCLK?輸入時鐘時,?將自動衍生?GT?時鐘。
3.3?部分原語的輸出管腳
如下圖,對于instA,因為沒有輸入IN到輸出OUT的arc,sysclk上的時鐘無法傳播到OUT,此時如果要實現傳播后的效果,可使用create_clock在instA/OUT上創建主時鐘,從而驅動后面的時序單元。
3.4?主時鐘路徑上創建主時鐘
對于在主時鐘驅動的路徑上重新創建主時鐘的做法是不建議的,如下圖,在sysclk上創建了一個主時鐘clk0,在clk0驅動的BUFG1上又創建了一個主時鐘clk1,clk1將會覆蓋傳播到該處的clk0,從而導致時序分析時,REGA和REGB間發起時鐘和捕獲時鐘的時鐘偏斜較大,分析不準,不符合實際情況。
3.5?虛擬時鐘
虛擬時鐘是設計中的一種特殊時鐘,它的生成不需要物理引腳,通常用于FPGA芯片的外部接口時序分析,因為,外部器件的時鐘不會直接連接到FPGA上,所以可以通過虛擬時鐘來模擬外部時鐘與FPGA引腳的關系。
虛擬時鐘通過create_clock約束生成,約束時不指定Source objects,只需設置名稱和波形,下圖示例為創建周期為10ns的虛擬時鐘
create_clock -period 10.000 -name virtual_clcok -waveform {0.000 5.000}
虛擬時鐘通常結合set_input_delay和set_output_delay使用
create_clock -period 10.000 -name virtual_clcok -waveform {0.000 5.000}
set_output_delay -clock [get_clocks virtual_clcok] 1.123 [get_ports ff_clkout0_a]
set_input_delay -clock [get_clocks virtual_clcok] 1.110 [get_ports d]
input_delay的報告如下圖,輸入延時值在data path中體現
3.6?差分時鐘的約束
差分時鐘因為有兩個輸入端口,輸入時鐘的約束怎么約?實際只需要約束差分時鐘輸入端口中的p端口,也就是IBUFGDS的I端口
create_clock -name clk -period 10 [get_ports clk_I]