英文名为Timing Exception,可以认为是时序例外或时序异常(本系列文章 的称法),“例外”或“异常”是指这部分时序的分析与大多数常规时序分析不同。下表给出了Vivado支持的时序异常命令及功能:
命令 | 功能 |
---|---|
set_multicycle_path | 设置路径上从起点到终点传递数据需要的时钟周期数 |
set_false_path | 指示设计中的某条逻辑路径不进行时序分析 |
set_max_delay、set_min_delay | 设置最小与最大路径延迟值,会重写默认的建立与保持约束 |
set_case_analysis | 使用端口或管脚上的逻辑常量或逻辑转换进行时序分析,以限制信号在设计间的传递 |
Vivado不支持即时分析有矛盾的时序异常,需要运行report_exceptions进行完整的分析,报告所有时序异常。多周期路径的情况有很多,比较复杂,单独放在第35篇中讲述。本文介绍其余三种时序异常的相关知识。
某些在拓扑结构上看存在于设计中的路径,但是没有工作或者不需要被计时,便被称作虚假路径。虚假路径在时序分析过程中应该被忽略不计。下面这些情况都属于虚假路径:
举个具体的例子加深对虚假路径的理解,如下图:
两个多路选择器MUX控制两个寄存器间的数据传输,但是两个MUX采用同一个选择信号。仔细分析会发现,无论如何Q端数据都无法传递到D端。虽然结构图上看起来Q和D之间存在一条路径,但是没有起到任何功能,因此应该定义为虚假路径。
为何要在时序分析中移除掉虚假路径?理由如下:
虚假路径由set_false_path命令定义,该命令模板如下:
set_false_path [-setup] [-hold] [-from ] [-to ] [-through ]
几个节点列表选项的含义如下:
下面给出几个定义虚假路径的例子:
#-through的顺序表示路径穿过节点的顺序,因此下面是两条不同的约束
set_false_path -through cell1/pin1 -through cell2/pin2
set_false_path -through cell2/pin2 -through cell1/pin1
#上图中的虚假路径应该用下面这条命令约束
set_false_path -through [get_pins MUX1/a0] -through [get_pins MUX2/a1]
#使用-through而不用-from和-to的好处是可以确保所有通过此节点的路径都会被移除,而不用考虑起点和终点
#移除复位端口到所有寄存器间的时序路径
set_false_path -from [get_port reset] -to [all_registers]
#禁用两个异步时钟域间的时序路径,从CLKA到CLKB
set_false_path -from [get_clocks CLKA] -to [get_clocks CLKB]
#注意,上述命令并没有禁用从CLKB到CLKA的路径,还需要补充如下约束
set_false_path -from [get_clocks CLKB] -to [get_clocks CLKA]
从最后一个例子可知,我们需要双向地禁用时序路径,但是如果设计中有多个异步时钟域,编写起来就非常麻烦。不知道您是否还记得第31篇中讲过的时钟约束方法,这种情况最好其实应该使用set_clock_groups设置不同的异步时钟组。
上面还说到了异步分布式RAM的情况,这里也举一个约束例子。假设一个异步双口分布式RAM,其写操作于RAM时钟同步,但是读操作是异步的,这种情况下应该在写和读时钟间设置一个虚假路径。约束如下:
#在RAM前的写寄存器和RAM后的读寄存器间设置虚假路径
set_false_path -from [get_cells ] -to [get_cells ]
设计中,某些信号在特定模式中为常数值,比如:(1).某些测试信号不会变换,直接连接在VSS或VDD上;(2).某些信号上电后便不再发生变化;(3).如果设计有多种功能模式,某些信号在部分模式下为活跃状态,但在其它模式下为不活跃状态。这些情况便属于“个例分析”。
我们必须告诉静态时序分析引擎,哪些信号为常数值,从而减少分析范围、运行时间和内部占用率,并且不必报告那些不工作的和不相关的路径。通常,设计者使用set_case_analysis命令将信号(管脚和端口)申明为不活跃状态。该命令的语法如下 :
set_case_analysis
参数值value可以是0、1、zero、one、rise、rising、fall或falling。作用对象可以是端口(port)、子单元(英文名为leaf cell)的管脚或层次模块的管脚。下面举两个例子加强对这种时序异常的理解。
第一个例子如下图,clock_sel是一个时钟选择器,通过选择管脚s对两个输入时钟clk_1和clk_2进行选择输出:
如果我们只希望分析一种个例,比如只分析选择clk_2时的情况。通过将 s管脚设置为常数即可只把clk_2传递到输出端口o。约束如下:
set_clock -name -clk_1 -period 10.0 [get_pins clock_sel/I0]
set_clock -name -clk_2 -period 15.0 [get_pins clock_sel/I1]
set_case_analysis 1 {get_pins clock_sel/S}
对某一管脚设置了个例分析,会导致禁用经过该管脚的路径上的时序分析,也不会报告相关信息。第二个例子如下图,BUFG_GT有一个动态时钟分频控制管脚DIV[2:0],由其它逻辑驱动而不是直接连接到VCC/GND:
默认情况下,Vivado会假设输出时钟的最坏可能情况,即1分频(相当于不分频,此时频率最高)。然而如果设计中根本不会出现DIV取1的情况,这就成了过度约束。为了更合理地约束设计,我们可以对DIV[2:0]总线进行个例分析约束,比如可能出现的最差情况为DIV取3,约束如下:
set_case_analysis 0 {get_pins bufg_gt_pclk/DIV[0]}
set_case_analysis 1 {get_pins bufg_gt_pclk/DIV[1]}
set_case_analysis 0 {get_pins bufg_gt_pclk/DIV[2]}
最大延迟约束set_max_delay用于改写路径的默认建立时间(或恢复时间)需求;最小延迟约束set_min_delay用于改写路径的默认保持时间(或移除时间)。两条约束命令的语法模板如下:
set_max_delay [-datapath_only] [-from ] [-to ] [-through ]
set_min_delay [-from ] [-to ] [-through ]
-from、-to和-through和虚假路径中的用法相同。set_max_delay命令中如果添加了-datapath_only,那么计算裕量时便不会考虑时钟斜率。使用最小/最大延迟约束要注意如下三点:
另外在约束最小延迟和最大延迟时,如果-from和-to中的节点选择不合理,会出现路径分割(Path Segmentation)现象。第34篇给出了路径分割的具体实例及说明。
最后再介绍一种时序异常的特例:Timing Arcs,字面翻译为时序弧,之所以没有单独列为一种时序异常,是因为它与其它时序异常有着千丝万缕的关系。其实很多情况下计时器为了处理一些特殊情况会自动禁用某些时序弧,比如:
Vivado提供了set_disable_timing命令,可以人为打断一个单元输入端口到输出端口之间的时序弧。考虑如下应用情况:
当禁用了时序弧后,通过该时序弧的所有时序路径都不会在时序分析中报告。因此使用时要额外小心,避免禁用了必要的时序弧,导致隐藏的时序违背或时序问题使设计在硬件中不能正常工作。set_disable_timing的语法及示例如下:
#语法,-from和-to只能设置为库单元的管脚名称(不是设计管脚名称)
set_disable_timing [-from ] [-to ] [-quiet] [-verbose]
#禁用所有基于LUTRAM的异步FIFO的WCLK到O之间的时序弧
set_disable_timing -from WCLK -to O [get_cells inst_fifo_gen/ gdm.dm/gpr1.dout_i_reg[*]]
#指定对象的所有以O管脚为终点的时序弧都被禁用
set_disable_timing -to O
#指定对象的所有以WCLK管脚为起点的时序弧都被禁用
set_disable_timing -from WCLK
#指定对象内的所有时序弧都被禁用
set_disable_timing
使用report_disable_timing命令可以查看所有自动禁用和手动禁用了的时序弧。注意这个列表可能会非常大,最好加上-file选项保存结果到文件中查看。