riple

Stay Hungry, Stay Foolish.

维护遗留代码(5)——逆向添加时钟约束

0
阅读(3549)

问题归结到了时序收敛上,该设计存在的一个最主要的问题是缺少完整、正确的时序约束。时序约束的核心是时钟约束。接下来我要做的第一步是确认该设计包含有 多少个时钟,并一一加以约束。

原设计采用了QSF文件作为时钟约束的输入方式。我原本可以从QSF文件得到SDC文件作 为TimeQuest时序分析工具的约束输入,但是由于原设计的时钟约束并不完整,只有寥寥数行,所以我还是要从头做起。
给一个设计增加时钟约束可以正向进行,也可以逆向进行。所谓正向,就是从设计的时钟方案出 发,在HDL编码开始之前就写好时钟约束;所谓逆向,就是在HDL编码完成后,从HDL代码或综合后的网表反推出原设计的时钟方案。由于没 有相关的设计文档,我只能采用逆向的方法。

好在TimeQuest可以针对综合后的网表自动给出FPGA设计包含的所有时钟。这样一来,就省去了我从HDL代码中手工查找、推导时钟信号的麻烦了。
TimeQuest提供了一个用于诊断SDC时序约束是否完整有效的报告功能。在Reports -> Diagnostic -> Report Unconstrained Paths报告下面,有一项Clock Status Summary报告,该项报告就给出了设计中所有起到了时钟作用的信号。其中,在SDC文件中 已经正确约束的时钟信号,采用黑色字体标出,时钟的名称按照SDC约束中指定的 给出;在SDC文件中约束无效的时钟信号,采用红色字体标出,时钟的名称也按照 SDC约束中指定的给出;在SDC文件中没有约束的遗漏的时钟信号,也采用红色字体 标出,时钟的名称按照网表中该时钟起点的网络节点名称给出。

不查不知道,一查吓一跳:报告中给出了近百条“疑似”时钟信号。我按照网表中给出的路径一一进行了确认,这些信号还当真在HDL代码中用作了时钟。由此暴 露出了该设计在时钟规划上的另一个严重问题:大量地使用了生成时钟(Derived Clock),即“行波”时钟(ripple clock)。
针对“行波”时钟,Altera Forum上有专门的文章, 论述了这种时钟方案对时序收敛的负面影响,建议采用时钟使能代替“行波”时钟。说起来容易,做起来难,关于移除ripple clock的恰当的方法,我留在后面的博客中讨论,这里我们继续讨论时钟约束的问题。
走到这一步,摆在我面前的路有两条:硬着头皮把复杂的生成时钟都约束完;或者先把“行波”时钟移除掉,然后针对简单的时钟方案进行约束。乍看起来第二条路 更加省时省力,这也是我最初的想法。但是我最终选择了第一条路,为的是把原设计的时钟方案捋清 晰,在着手修改代码之前对原设计的时序收敛情况进行摸底, 确认是否是“行波”时钟导致了时序收敛困难。事实证明,走第一条路给了我对原设计更深入的认识,也使得给原设计增加时序例外约束后续工作更加稳妥。关 于增加时序例外约束的讨论,也留在后面的博客里。

书接上文。TimeQuest提供的这一诊断功能并不十分完善。TimeQuest虽然能够指出哪些时钟信号没有约束,但是并不能给出这些时钟该如何约 束。对于约束生成时钟这一任务来说,光有生成时钟的网络节点名称是不够的,我还需要得到对应“基”时钟(Base Clock)的网络节点名称,以及生成时钟与“基”时钟的分/倍频关系和相位关系。
虽然TimeQuest进行时序分析的对象是综合后/布局布线后的网表,但是从这些网表中并 不能逆向推导出时序约束所需要的全部信息,这样的信息必须从HDL语言中推导获得才准确。我尝试过用TimeQuest的Locate功 能,可以在Technology Map Viewer中定位时钟信号的网络节点,也可以进一步用Filter功能查找出对应的“基”时钟的网络节点名称。但是Technology Map Viewer对应的是综合后的网表,提供的是FPGA器件底层结构LE的连接信息,并不包含生成时钟与“基”时钟的分/倍频关系和相位关系这样的高层次信 息。尽管RTL Viewer对应的是比LE级更高一级的RTL级的网表,我需要的信息,在RTL这一级别也难以获得。最终,我选择了用ModelSim从行为级来获取这 些信息。
ModelSim可以对HDL语言进行仿真,从而提供HDL语言行为级的信息。有了这一级别的信息,我就可以完成约束生成时钟的工作。具体操作如下:
1. 从TimeQuest中拷贝时钟信号的网络节点名称。
2. 把网络节点名称转换为ModelSim层次化路径名称。zip
3. 在ModelSim的Wave窗口中,添加该时钟信号。
4. 在ModelSim的Dataflow窗口中,定位该生成时钟信号对应的“基”时钟信号。
5. 添加该“基”时钟信号到Wave窗口中。
6. 通过仿真波形,获取生成时钟与“基”时钟的分/倍频关系和相位关系。
采用这样的方法,我逐一获得了原设计中所有时钟信号的生成信息。有了这些信息,再配合SDC提供的强大的约束功能,就可以完成所有时钟信号的约束。
SDC中对生成时钟进行约束的语句是:
create_generated_clock [-add] [-divide_by ] [-multiply_by ] [-duty_cycle ] [-edge_shift ] [-edges ] [-invert] [-master_clock ] [-name ] [-offset

关于如何正确约束第二级生成时钟的方法,Altera的正式文档和Altera Forum上都没有明确的答案;在Synopsys的一篇SNUG讲稿中,提出了另外一种约束格式,这一格式也被上述SDC约束语句支持。至于哪一种方法 更好,我在Altera Forum上提出了相关的问题,但是至今无人答复。从我使用的效果上来看,二者应该是等价的。对于这一问题,我还要花时间研究一下。

Baidu
map