转载自 http://bb2hh.blogbus.com/logs/20373036.html
Author:pythonlong
 
 
一个比较全的例子,不过还有比较多的特殊情况。
 
create_clock -period 100       [get_ports Pclk]
create_clock -period 100/8  -name pclkx8  [get_pins BUF2X2/Y]
 
 
create_clock -period 10  [get_ports Sclk]
create_generated_clock -name clk_div2 -divide_by 2 -source [get_attribute [get_ports Sclk] sources]  [get_pins DIV/clk_div2]
create_generated_clock -name clk_div4 -divide_by 4 -source [get_attribute [get_ports Sclk] sources]   [get_pins DIV/clk_div4]
create_generated_clock -name clk_div8 -divide_by 8  -source [get_attribute [get_ports Sclk] sources]   [get_pins DIV/clk_div8]
 
create_generated_clock -name Sclk1_l -comb -add -source [get_attribute [get_clocks pclkx8] sources] -master_clock pclkx8 [get_pins MUX1/Sclk1]
create_generated_clock -name Sclk1_h -comb -add -source [get_attribute [get_clocks clk_div2] sources] -master_clock clk_div2 [get_pins MUX1/Sclk1]
set_clock_group -logical -group clk_div2 -group pclkx8 
 
create_generated_clock -name Sclk2_l -comb  -add -source [get_attribute [get_clocks clk_div8] sources] -master_clock clk_div8  [get_pins MUX1/Sclk2]
create_generated_clock -name Sclk2_h -comb  -add -source [get_attribute [get_ports Sclk] sources] -master_clock Sclk [get_pins MUX1/Sclk2]
  set_clock_group -logic al -group sclk -group clk_div8
 
对于Sclk1,Sclk2驱动的时钟树的输出port,应该如下设置
set_output_delay -max 3  -clock [get_clocks Sclk1_l] [get_ports xx_out1]
set_output_delay -max 3 -add_delay -clock [get_clocks Sclk1_h] [get_ports xx_out1]
 
set_output_delay -max 3  -clock [get_clocks Sclk2_l] [get_ports xx_out2]
set_output_delay -max 3 -add_delay -clock [get_clocks Sclk2_h] [get_ports xx_out2]
 
对于Pclkx8需要的约束如下:
 
set_input_delay -max 2 -clock [get_clocks Pclk] [get_pins BUF2X2/Y]
 
红色圈圈出的设计要注意的,因为低速Pclkx8作为数据输入,对于Pclkx8又做时钟,又做数据,所以在时钟树前加buffer,然后用buffer的输出pin做create_clock。
同时对时钟作为数据输入的设置false_path 
记住:时钟会向后穿过任何组合逻辑,直到endpoint!
pll是macro,会被astro,或者dc作为black box。对于工具来说信号传输到黑盒子就算终止了,但是内部还要用到黑盒子产生的时钟,所以要create_clock .对于pll输出的clock的input_delay,output_delay约束却要用到外部的Pclk来约束。
 
以上是用dc的新命令来处理。不过用常规来处理也比较不错,不过要在综合以后分析其他没有case的路径。
如下:
create_clock -name SCLK -p 20 [get_ports Sclk]
create_clock -name PCLK -p 8  [get_ports Pclk]
create_generated_clock -name PCLKX8  -multipy_by 8 -source [get_attribute [get_clock] sources]  [get_pins BUF2X2/Z]
create_generated_clock -name SCLK_DIV2 -devide_by  2 -source [get_attribute [get_clock] sources] [get_pins DIV/clk_div2]
create_generated_clock -name SCLK_DIV8 -devide_by  8 -source [get_attribute [get_clock] sources] [get_pins DIV/clk_div8]
set_case_analysis 0 [get_pins MUX2/S0]
set_case_analysis 1 [get_pins MUX1/S0]
set_ideal_network      [get_pins MUX2/Y]
set_dont_touch_network [get_pins MUX2/Y]
set_ideal_network      [get_pins MUX1/Y]
set_dont_touch_network [get_pins MUX1/Y]
上面的约束也不是最好的,如果想进一步精简约束和准确的话,需要仔细分析下时钟域。
如上图所示,pclkx8和sclk以及分频时钟不是同时钟域的。
对于选择时钟,如果输入是同一个时钟域的话,可以在输出端generated出一个最高频率。
如果是异步时钟则不需要set_case_analysis ,2个时钟需要同时分析。
如果选择器不是用MUX来实现,而是用AO或者AOI实现,可能需要在AO,AOI的输出端分别generated这2个时钟。
约束可以写成如下:
create_clock -name SCLK -p 20 [get_ports Sclk]
create_clock -name PCLK -p 8  [get_ports Pclk]
create_generated_clock -name PCLKX8  -multipy_by 8 -source [get_attribute [get_clock] sources]  [get_pins BUF2X2/Z]
create_generated_clock -name SCLK_DIV2 -devide_by  2 -source [get_attribute [get_clock] sources] [get_pins DIV/clk_div2]
create_generated_clock -name MX2_CLK -devide_by  1 -source [get_attribute [get_clock] sources]  [get_pins MX2/Y]
set_ideal_network [get_clocks MX2_CLK]
set_dont_touch_network [get_attribute [get_clocks MX2_CLK] sources]
当然异步时钟之间要设置false path
set_false_path -from [get_clocks PCLKX8] -to [get_clocks  SCLK_DIV2]
set_false_path -from [get_clocks SCLK_DIV2] -to [get_clocks PCLKX8] 
这种约束经济实惠,而且准确,所以推荐。当然例外情况也有可能比如加入dft测试时钟,bist时钟等等,以及mux是用AO,AOI搭建的。