|
EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
本帖最后由 STGing 于 2022-9-26 19:15 编辑
' n& p% r6 }$ F" _& |7 _4 j
: {) b; W/ [4 |' ^) Q1 l1 ~一、前言3 B& f2 a) t8 H: n2 }0 a
无论是FPGA应用开发还是数字IC设计,时序约束和静态时序分析(STA)都是十分重要的设计环节。在FPGA设计中,可以在综合后和实现后进行STA来查看设计是否能满足时序上的要求。本文阐述基本的时序约束和STA操作流程。! Y2 |; o6 S1 ]3 l
+ _0 Y. U& H5 c; D* ]- k
二、时序约束与XDC脚本 m2 H5 I9 t1 ^6 N5 x' }0 t [# }
时序约束的目的就是告诉工具当前的时序状态,以让工具尽量优化时序并给出详细的分析报告。一般在行为仿真后、综合前即创建基本的时序约束。Vivado使用SDC基础上的XDC脚本以文本形式约束。以下讨论如何进行最基本时序约束相关脚本。
' n( H. T" D) n1 c1 时序约束首要任务是创建主时钟,主时钟即为时钟引脚进入时钟信号或高速收发器生成时钟。[create_clock]* n. ?& z) c8 c$ Y ~) k' @! v
create_clock -name clk_name -period N -waveform {pos_time neg_time} [get_ports port_name] (划线部分可选)
' S7 R0 u+ M) J* W4 w: { 创建两个异步的主时钟:3 y! \/ `9 v" `7 N2 A+ m9 a6 a6 c- W
create_clock -name clk_a -period 10 [get_ports clk_a]
. Y# c8 D' h2 Z* X create_clock -name clk_b -period 15 [get_ports clk_b]6 [7 v0 X. P7 A: n
set_clock_groups -asynchronous -group clk_a -group clk_b# h& b" U5 _# e! U- }' M
当两个主时钟是异步关系,它们生成时钟同样是异步关系:
% ~' Z9 U5 A9 E( A* T" K3 \" ]; [ set_clock_groups -asynchronous -group [get_clocks clk_a -include_generated_clocks] \
- l$ r* l4 u0 a! M8 N/ K -group [get_clocks clk_b -include_generated_clocks]
0 s5 {& V. ^# ]9 ?! j+ n/ T) K i 差分时钟仅约束P端口:8 [9 d3 U# ^* C% L& K; U- D3 v
create_clock -name clk -period 10 [get_ports clk_p]8 A8 T# c4 u& \6 Q8 D2 j
高速收发器生成时钟作为主时钟:( c [; {3 a& N2 K# ^1 T) ?
create_clock -name gt0_txclk -period 8 [get_pins GT0/.../TXOUTCLK]' }$ n: ]; y+ G$ P- q6 k; a
有一种特殊情况无需与具体引脚绑定,即创建虚拟时钟。该约束用于设定输入/输出延迟。需要创建虚拟时钟的场景是输入FPGA的数据由FPGA内部产生时钟采样,如串口通信。) [8 d0 C* V% u2 b9 ?
create_clock -name clk_v -period 5
4 c6 w& O2 M6 l6 _9 ~ n2 创建主时钟后,需要约束生成时钟:[create_generated_clock]& _% {( y6 W* Y8 t q5 ?
生成时钟分为两种。由PLL MMCM等专用时钟单元生成产生的时钟信号,Vivado会自动产生相关约束。还有一种是自定义生成时钟,一般为逻辑分频得到。
% a% o& j, _9 F( y3 [0 V7 D 时钟源是时钟端口:/ D. p6 o& f3 B; p
create_generated_clock -name clk_div -source [get_ports clk] -divide_by 2 [get_pins rega/Q] 意思是在rega单元的Q引脚上的时钟信号clk_div是由clk经过2分频得到的生成时钟。6 C6 y0 g- f6 w _8 D1 k# W( f; m
时钟源是引脚:9 d/ t8 s& l) ?2 I" ~1 Z
create_generated_clock -name clk_div -source [get_pins rega/C] -divide_by 2 [get_pins rega/Q]
5 p0 z1 v2 k# `( t 除了使用-divide_by -multiply_by表示主时钟和生成时钟的频率关系,也可以用 -edges实现更精确的表达:/ A( p h% v- h. n5 n. ?
create_generated_clock -name clk_div -source [get_pins rega/C] -edges {1 3 5} [get_pins rega/Q]" |4 q3 G- x/ |+ }
相移关系使用-edge_shift命令描述。
; H- L1 _$ ?# D: \! W" K 该约束命令还常用于重命名时钟信号:8 Z6 ]( t* t4 P
create_generated_clock -name clk_rename [get_pins clk_gen/.../CLKOUT0]; r# H2 P# [- _
3 创建时钟组:[set_clock_groups]
8 [( g5 r1 c( `. K a. 异步时钟情况:
" R( [2 n' e& w$ @* | set_clock_groups -asynchronous -group clk_a -group clk_b clk_a和clk_b是异步时钟。) u) w Y# T2 [7 d6 l
b. 物理互斥情况:+ B" _ z% f) ~7 s3 Q+ s
create_clock -name clk_a -period 10 [get_ports clk] E( W: O! X3 ~ Z$ b3 d
create_clock -name clk_b -period 8 [get_ports clk] -add
' Z1 }4 y2 h+ l; }# O0 b create_clock -name clk_c -period 5 [get_ports clk] -add6 L j( V* P M! U
set_clock_groups -physically_exclusive -group clk_a -group clk_b -group clk_c. S; M$ R' e. G- x* {3 C. l
该种情况仅是为了观察clk引脚时钟信号周期依次为10ns 8ns和5ns时,时序是否收敛。因此这三个时钟物理上不同时存在。* ~8 M9 v2 K8 ]' x3 U8 z+ X$ G
c. 逻辑互斥情况:, j5 i* R, n/ Q2 ^# R+ c
set_clock_groups -logically_exclusive\
- C: Q: H9 e5 l0 u9 t -group [get_clocks -of [get_pins clk_core/.../CLKOUT0]] -group [get_clocks -of [get_pins clk_core/.../CLKOUT1]]
; P2 V" I1 [/ m {# P clkout0和clkout1送入到BUFGMUX中,后续根据sel信号确定选择哪一个作为工作时钟。此时clkout0和clkout1同时存在电路中,但仅有一个会作为后续电路工作时钟,因此逻辑上互斥。
# k6 T6 N4 E- j' [ 特殊用法:当asynchronous 的group只有一个,说明改组内时钟是同步的,但与其他所以时钟异步。5 Y: C* i) O% H! ~/ @! c7 Z/ `
4 设置伪路径:[set_false_path]8 b$ ?" w J5 f+ {, Z" k* I
设置伪路径后,不再对特殊路径进行时序分析。特殊路径如测试逻辑、添加同步电路后的跨时钟域路径等。在两个时钟域之间应该相互设置为set_false:& K9 C6 s' z" ?4 [- T2 D) M) p" P
set_false_path -from [get_clocks clk_a] -to [get_clocks clk_b]
! ]$ |, A% L( J" n; y$ G set_false_path -from [get_clocks clk_b] -to [get_clocks clk_a]$ \8 k6 G0 W( G, P
5 Y4 z, y' t2 R& ^
* a) N, I' N) A) O" M: a( W
|
|