创建设计的第一步是设计分割,设计分割的依据是数据流。设计分割的结果是将设计划分为特定的功能单元,从而使得不同的设计者并行工作,同时每个功能单元可封装为相对独立的IP,实现设计复用。
设计分割时需要考虑的一个重要因素是定义设计层次(Design Hierarchy)。定义设计层次则需要兼顾以下因素:
从时序收敛的角度看,定义设计层次时尽可能从以下几个方面着手,可减少时序收敛的迭代次数。
尽可能将I/O单元放置在顶层
I/O单元分两类:
第一类:简单的单端口I/O(例如IBUF、OBUF、OBUFT和IOBUF)和单速率(SDR, single data-rate)寄存器。对于这类I/O单元,综合工具可根据RTL代码推断出来。
第二类:需要通过原语(primitive)实例化的I/O单元(例如双端口I/O:IBUFDS,OBUFDS)和双速率(DDR, double data-rate)寄存器(例如:IDDR, ODDR,ISERDES和OSERDES)
尽可能将时钟单元放在顶层
时钟单元是指时钟生成模块(例如MMCM,PLL)。将其放置在顶层可便于其他模块共享时钟,从而减少时钟资源(除MMCM和PLL之外还包括BUFG等)的利用率,这对于提高系统性能、降低系统功耗也是有益的。
尽可能使逻辑边界上的数据路径是寄存器输入/寄存器输出
对于包含关键路径的层次边界,要使其输出为寄存器输出,这样可将该路径封装于特定的模块或边界之内。同时,对位于层次边界上的路径的输入也尽可能做到寄存器输入。毕竟,相比于路径分散至多个模块而言,位于单一模块内的时序路径更易分析和修复。对于未寄存的数据路径所在的层次,综合时应将层次优化设置为rebuilt或full,以使优化可以穿越层次。这可通过综合属性KEEP_HIERARCHY实现。对位于边界的数据路径寄存还可获得一个好处:调试时易于跟踪。
下图是一个很好的例子,解释了什么是好的设计层次。可以看到模块的输入输出都做了寄存处理;时钟模块放置在设计的顶层。同时,对顶层的输入输出寄存器使用了综合属性SHREG_EXTRACT,并将其值设置为“no”。目的是保证这些寄存器不会被综合为基于LUT的移位寄存器。毕竟,设计顶层的寄存器可以使用SLICE里的Flip-flop实现,也可以使用IOB中的寄存器实现。这可根据时序需求进行选择。
====================
///回复“年+月”6位数字,可查看yyyy年mm月好文
例如:回复 201805 可查看2018年5月内容///