|  | 
 
| 
本帖最后由 STGing 于 2022-9-26 19:15 编辑
x
EDA365欢迎您登录!您需要 登录 才可以下载或查看,没有帐号?注册  , j, q" l6 ^6 f; q: ^: l; k6 G( O" Z$ x/ N5 c- W
 一、前言0 e2 D/ v% k" q6 X( ]& B5 j
 无论是FPGA应用开发还是数字IC设计,时序约束和静态时序分析(STA)都是十分重要的设计环节。在FPGA设计中,可以在综合后和实现后进行STA来查看设计是否能满足时序上的要求。本文阐述基本的时序约束和STA操作流程。& ?& ?. O1 m* c- }9 b0 j
 
 ) S; {/ I2 {9 k  E4 p) v二、时序约束与XDC脚本, k0 i; f5 k2 D
 时序约束的目的就是告诉工具当前的时序状态,以让工具尽量优化时序并给出详细的分析报告。一般在行为仿真后、综合前即创建基本的时序约束。Vivado使用SDC基础上的XDC脚本以文本形式约束。以下讨论如何进行最基本时序约束相关脚本。1 \- {& n) f1 P  T
 1 时序约束首要任务是创建主时钟,主时钟即为时钟引脚进入时钟信号或高速收发器生成时钟。[create_clock]8 j" d* u9 V# l. U' J
 create_clock -name clk_name -period N -waveform {pos_time neg_time} [get_ports port_name] (划线部分可选)  {3 |$ u3 [& I4 G0 b; e! \
 创建两个异步的主时钟:. q: f1 s1 s; y* m7 K8 w# E
 create_clock -name clk_a -period 10 [get_ports clk_a]4 z% n8 \8 `9 h' q+ p6 B
 create_clock -name clk_b -period 15 [get_ports clk_b], T$ ~' P9 v) D5 ^2 B- @. N
 set_clock_groups -asynchronous -group clk_a -group clk_b' N' r3 w8 h% x/ w) ~1 F. g
 当两个主时钟是异步关系,它们生成时钟同样是异步关系:
 : g; `0 ~( X0 {8 Z2 B6 r0 Q$ V) A  set_clock_groups -asynchronous -group [get_clocks clk_a -include_generated_clocks] \2 A" Y* K! g  o5 i
 -group [get_clocks clk_b -include_generated_clocks]
 ) @0 e* S, M6 s! ?  @3 X  差分时钟仅约束P端口:
 * R' w7 I+ T6 f( S6 O, e  create_clock -name clk -period 10 [get_ports clk_p]
 , a( b% N$ t/ E5 Y0 u/ K  高速收发器生成时钟作为主时钟:
 7 v( ?8 r3 z5 c9 K. a  create_clock -name gt0_txclk -period 8  [get_pins GT0/.../TXOUTCLK]* S# b$ {% n( F* L) v  }5 k/ `
 有一种特殊情况无需与具体引脚绑定,即创建虚拟时钟。该约束用于设定输入/输出延迟。需要创建虚拟时钟的场景是输入FPGA的数据由FPGA内部产生时钟采样,如串口通信。" ^6 E+ p1 B3 y$ C# K
 create_clock -name clk_v -period 5
 / r( O3 ^1 t5 K  U9 b& I5 o' `2 创建主时钟后,需要约束生成时钟:[create_generated_clock]
 ( }$ M4 r* ]0 b- t. [6 V  生成时钟分为两种。由PLL MMCM等专用时钟单元生成产生的时钟信号,Vivado会自动产生相关约束。还有一种是自定义生成时钟,一般为逻辑分频得到。
 ; {4 T( K4 P6 r  时钟源是时钟端口:
 7 S4 u5 J* }2 O" i- N9 ?  create_generated_clock -name clk_div -source [get_ports clk] -divide_by 2 [get_pins rega/Q] 意思是在rega单元的Q引脚上的时钟信号clk_div是由clk经过2分频得到的生成时钟。
 ! t' q( N# a+ E2 q/ d  时钟源是引脚:
 ]2 I7 R" G( T, H; m; t: i  create_generated_clock -name clk_div -source [get_pins rega/C] -divide_by 2 [get_pins rega/Q]( t% v8 N, E7 W5 T
 除了使用-divide_by -multiply_by表示主时钟和生成时钟的频率关系,也可以用 -edges实现更精确的表达:
 5 l& ], O, w9 x$ ?9 |) H  create_generated_clock -name clk_div -source [get_pins rega/C] -edges {1 3 5} [get_pins rega/Q]  t- N3 k  R+ o; j: i. Z" w# `  z
 相移关系使用-edge_shift命令描述。
 1 \! x6 `2 V3 G+ s$ f  该约束命令还常用于重命名时钟信号:3 r3 i. `! y: Y
 create_generated_clock -name clk_rename [get_pins clk_gen/.../CLKOUT0]* z) H# o) z' R
 3 创建时钟组:[set_clock_groups]- X- R" {6 j  c8 y# u7 ~
 a. 异步时钟情况:
 1 r1 Q& \: t: R$ P  set_clock_groups -asynchronous -group clk_a -group clk_b  clk_a和clk_b是异步时钟。9 w1 G3 G" _$ k/ P
 b. 物理互斥情况:
 6 H5 r7 ?6 t/ ~+ }# v+ y  create_clock -name clk_a -period 10 [get_ports clk]3 X# H+ G) @5 {+ Q
 create_clock -name clk_b -period 8 [get_ports clk] -add: Y! Q# k  T( A; B
 create_clock -name clk_c -period 5 [get_ports clk] -add
 ' k% O1 d' }) W! w5 F) |: @  set_clock_groups -physically_exclusive -group clk_a -group clk_b -group clk_c3 T3 j" T; g* v& Z( `
 该种情况仅是为了观察clk引脚时钟信号周期依次为10ns 8ns和5ns时,时序是否收敛。因此这三个时钟物理上不同时存在。3 E! o% O" s4 U& A# E. K$ y' t
 c. 逻辑互斥情况:
 2 Q# U" V7 {( V4 m8 Y  set_clock_groups -logically_exclusive\
 ! n! r3 ]3 ?! ]" ?' x* G* f4 q  -group [get_clocks -of [get_pins clk_core/.../CLKOUT0]] -group [get_clocks -of [get_pins clk_core/.../CLKOUT1]]
 % k0 {0 _2 K4 ^8 X2 L- p( @  clkout0和clkout1送入到BUFGMUX中,后续根据sel信号确定选择哪一个作为工作时钟。此时clkout0和clkout1同时存在电路中,但仅有一个会作为后续电路工作时钟,因此逻辑上互斥。* m! E- g& y1 W* x3 U$ S& X7 ~* v
 特殊用法:当asynchronous 的group只有一个,说明改组内时钟是同步的,但与其他所以时钟异步。
 ( z- ?! B" h3 E3 p1 ]% v4 设置伪路径:[set_false_path]6 N  U: s5 n( u' B( N
 设置伪路径后,不再对特殊路径进行时序分析。特殊路径如测试逻辑、添加同步电路后的跨时钟域路径等。在两个时钟域之间应该相互设置为set_false:# Y5 T& R) D/ g6 ~
 set_false_path -from [get_clocks clk_a] -to [get_clocks clk_b]& t' E; \4 }$ b( B
 set_false_path -from [get_clocks clk_b] -to [get_clocks clk_a]: z; L( U+ z3 G
 
 - c& u2 V0 Y' u& s( e
 % n" i0 C5 j1 Z" a' f  [* J  ^
 | 
 |