在上面的约束基础上,设计中大部分的时钟已经被约束了。在TimeQuest中,所有的时钟默认都是相关联的,由设计者决定哪些时钟不相关。
所以举例来说,如果在一个周期8ns和10ns的时钟之间有路径,即使这两个时钟是不相关的,TimeQuest仍然会获得时钟之间2ns的setup relationship,并试图满足它。这是TimeQuest中的保守做法,而不像其他工具那样,默认时钟不关联。
由设计者决定哪些时钟不相关。SDC语言有一个强大的命令 se_clock_groups ,来完成这个工作。它的语法如下:
set_clock_groups -asynchronous -group {} -group {} -group {}
注意:
1. 每个group都是互相关联时钟的列表。
2. group对时钟的个数没有限制,即使需要50个group也是可以的。但是如果通过Edit->Inset Constraint 命令添加,那么仅仅支持两个group。但是这仅仅是GUI工具的限制,手动输入SDC命令不受这个约束。
3. TimeQuest默认所有的时钟都在一个大group中。
4. 任何没有在上面命令中出现的时钟,会保持其默认属性——和所有时钟相关。所以如果你忘记了对某个时钟进行指定,那么它将会在所有涉及到它的时域中被分析。
5. A clock cannot be within multiple -groups in a single assignment。
6. 可以有多个set_clock_groups 命令在一个SDC文件中
7. 这个命令通常会很长,所以很难在一行写完,所以记得使用“\”连接符。
8. 针对有着复杂时钟的设计,写这个约束通常会比较复杂。比如说:有两个DDR3核和一个高速收发器可能包含有30或者更多个的时钟。这些例子当中,我们添加上所有我们创建的时钟。既然有前面提到的条件——所有没提到的时钟仍然和所有时钟相关,我们只需要谨慎的将我们了解的时钟合成一组就行。如果载我们未关联的时钟域之间仍然存在failing path,我们就根据报警提示,添加相应的时钟。而在上面的例子当中,一大堆的时钟并不真正的被放入set_clock_groups命令当中,因为他们要么封装在IP核的 .sdc文件中,要么仅仅和相关的时钟域相连。(In this case, a large number of the clocks won't actually be in the set_clock_groups command, since they are either cut in the IP's .sdc file(like the ones generated by the DDR3 cores), or they only connect to clock domains they are related to.)
9. 这里我特意的将 virtual clocks created for I/O analysis排除在约束外。因为他们连接的时钟,仅仅是real paths,所以这里没有必要排除对他们的分析(I generally leave virtual clocks created for I/O analysis out of this constraint. The only clocks they connect to are generally real paths, so there is no need to cut their analysis to other clocks.)。
10. 对于set_clock_groups 命令的选项,要么是 –asynchronous(异步) 要么是 –exclusive(独立的)。- asynchronous 标志意味着各组时钟在组内是触发的,但相互之间是却不能异步传输数据(The asynchronous flag means the clocks are both toggling, but not in a way that can synchronously pass data.)。-exclusive标志意味着时钟不在同一时刻触发,因此是互相独立的。解释这项的一个很好的例子是:一个时钟选择器,有两个时钟连接到输出端。介于一个时间段,只能有一个时钟被触发,因此这两个时钟是-exlucsive的。TimeQuest会无差别的去分析你的设计for either flag。这个选项对于ASIC设计来说是十分有用的,因为它会分析SI issue,诸如 asynchronous时钟之间的cross-talk,却不分析exclusive时钟的之间的cross-talk。If going to Hardcopy, which uses ASIC analysis tools on the back-end, it is recommended to get this right。对于FPGA来说,这些真的不重要。The more conservative value is -asynchronous, since this states the clocks can interfere with each other, and what I use by default。
11. 另一个消除时钟之间timing的方式是:使用set_false_path.命令。如果不想分析sys_clk和dsp_clk之间的时序,可以输入以下命令:
set_false_path -from [get_clocks sys_clk] -to [get_clocks dsp_clk]
set_false_path -from [get_clocks dsp_clk] -to [sys_clk]
当只有少量的时钟信号,这样做是可以的,但是时钟多了以后,约束可读性就会很差。在一个具有多种始终输出的PLL例子中,set_clock_groups命令可以在10行代码内,清晰的显示出时钟相关性,而时钟set_false_path则可能超过50行。
Quick tip for writing set_clock_groups constraint
1. 介于dderive_pll_clock 创建的所有的时钟名字并不被我们全部认知,所以一个快捷创建.sdc文件方式如下:
2. 双击左侧Task窗口的 Report Clocks 命令。这个操作会读取我们的.sdc文件,并报告这些时钟的约束信息。从那个report中,我们可以选中所有我们所知道名字的项目,并点击鼠标右键:
这时候我们已经以Timequest能识别的方式复制了所有的时钟信息,之后,黏贴这些信息到我们的.sdc文件中。
3. 现在我们有了一个所有时钟列表,接下来将他们格式化到set_clock_groups命令中。比如,我可以从下面的空列表开始:
set_clock_groups -asyncrhonous -group { \
} \
-group { \
} \
-group { \
} \
13
-group { \
}
然后黏贴时钟信息到这些组中,适当添减group。
4. 最后,格式化这些命令,增加可读性:
我们注意到,最后一组中,有一个PLL输出信号,而其他的PLL输出则在第二组中。这是因为这里,我设置了该时钟的频率不能和其他时钟相关。必须将它看成一个异步时钟。但是通常情况下,所有PLL的输出都是相关的,因此会在同一group中。 这都由设计者决定。
就这样了,对许多设计来说,约束这些核心很重要,但是在这个快速约束指导中,有一些方面并不能被覆盖到:
1. 添加多周期(Multicycle),降低系统运行频率(见i.e. opening the window.)。比如,一个10ns的时钟会有一个10ns的setup relationship。但是如果数据传输很慢,亦或者寄存器以一个更慢的速度触发,那么设计者就必须设定Multicycle来open window,以满足数据传输的要求。这一操作将会使得setup relationship变成20ns或40ns……同时保持hold relationship为0ns。
2. Multicycle的另一个形式是,设计者希望shift the window。这通常发生在设计者想要时钟产生一个微小的相移。比如,设计者想要从pll中生成一个10ns时钟,第二个时钟也是10ns,但是有着0.5ns的相移,默认情况下setup relationship只有0.5ns 而hold relationship则有-9.5ns。对于满足0.5 ns的setup relationship几乎是不可能的。所以大部分设计者希望数据在下一个周期window之前到达就行了。这里可以通过在main clock 和phase-shift-clock之间添加一个Multicycle解决。这样setup relationship就变成了10.5ns,而hold relationship变成了0.5ns。当设计者生成了有相移的时钟,就应当第一时间想到使用Multicycle。而Multicycle被称作 shifting the window
如果对setup 和hold relationship有困惑的,请查阅章节ebasics of setup and hold,同时也可以参阅下面的章节determining default setup and hold relationships。
3. 添加create_generated_clock命令来ripple clock。Ripple clock的定义是,由寄存器的输出端输出 clk信号,以驱动其他寄存器的时钟输入端,该clk就被称作ripple clock。该时钟并不会穿过寄存器,所以所有的ripple clock都必须有一个 create_generated_clock约束命令。没有被约束的ripple clock会在timequest的”Report Unconstrained Paths“中被显示出来,所以很容易识别。总的来说,ripple clock需要被避免,如果可能,使用clock enable来替代。
4. 对频率选择器的输出端使用create_generated_clock命令。如果没有该约束,所有经过选择器传播的时钟将会被视为相关联的。届时TimeQuest将会分析所有从选择器来的路径(where one clock input feeds the source register and the other clock input feeds the destination, and vice-versa)。尽管有时可以满足时序要求,但这不是设计者想要的。通过添加create_generated_clock命令来约束选择器输出端口,能够将输出端和输入时钟关联起来,以方便设计者正确的对这些时钟进行分组。
文章评论(0条评论)
登录后参与讨论