参考文档:
ug905-vivado-hierarchical-design
Hierarchical Design(HD)允许把一个大的设计分成比较小的模块单独处理,这一过程是通过OOC(out-of-context implement)实现的。
1、 概要
- HD主要有2个用途:
- Module Analysis,当我们想分析某个模块的资源/timing等信息的时候,可以直接对这个模块综合/实现。
- Module Reuse,可以在Top-design中直接使用OOC模块的DCP(包含PR信息)而不用每次重新PR。
- Module Analysis的方法跟正常的流程主要有以下区别:
- 综合的时候需要加上-mode out_of_context选项;
- 如果用vivado之外的工具综合,则在link_design的时候加上-mode out_of_context选项
- 给模块设置HD.PARTITION属性(非必须)
- 给模块设置context约束(非必须)
- 给模块加上PBLOCK约束(必须)
- 设计重用的方法,主要有两点:
- 设置模块的HD.PARTITION属性
- 使用lock_design命令锁定OOC模块的PR结果
2、简介
有以下两种设计场景:
- Bottom-up
模块单独PR的时候很可能对顶层知之甚少,context constraint需要由用户自己写。这些约束指定了模块物理摆放位置,模块IO的布局信息,指定时钟源的位置,还有模块IO的时序路径要求等。 - Top-down
顶层设计很明确,所以可以由顶层驱动OOC模块的PR,OOC模块context约束可以由vivado自动产生。
要实现模块的OOC implementation以下条件需要满足:
- 模块必须要有Pblock约束
- Pblock需要设置CONTAIN_ROUTING属性
- 不同OOC模块的Pblock不能重叠
- Pblock支持嵌套,前提是子pblock必须完全包含在父pblock内
- 所有clock buffer必须要lock,如果OOC模块的时钟由顶层驱动,则需要用HD.CLK_SRC指定顶层时钟buffer的位置
- 如果OOC模块的PR需要重用,那么强烈建议使用HD.PARTPIN_RANGE或HD.PARTPIN_LOCS约束模块IO
使用专用连线的cell
Xilinx推荐把使用专用连线的cell放到OOC模块里面,比如IOLOGIC、IOBUFF、GT等。
这里举个IO buffer的例子,一个OOC模块直接和顶层Port相连,通常建议把IO buffer放到OOC里面,但是如果这个port同时又连到了另一个OOC模块,那就只能把buffer放到顶层,这个时候需要用HD.PARTPIN_LOCS指定这个IO的布线。
3、OOC命令和约束
OOC模块的综合和实现要求工具运行在OOC模式,除此以外流程上和正常没有任何区别。
3.1 OOC命令
3.1.1 synthesis
XST/Synplify都能用,但是这里只介绍vivado。
vivado的综合命令如下:
synth_design -mode out_of_context -flatten_hi9erarchy rebuilt -top <top_module_name> -part <part>
-mode out_of_context 可以阻止工具插入Iobuffer
3.1.2 implementation
实现的步骤没有什么特殊之处,vivado可以支持使用dcp和edf/ngc网表。以下是会用到的一些命令和简单说明(详细说明可以参考xilinx文档)
read_checkpoint <filename.dcp>
这个用于打开DCP文件,DCP是Xilinx定义的压缩文件,里面包含了设计所有的中间信息。
read_edf <netlist_file.edf/ngc>
edf就是纯网表,不包含其他信息,所以约束要另外加。
link_design -mode out_of_context top <top_module_name> -part <part>
这个命令可以把加载到内存里面的网表,dcp等各种东西给他整合起来。
read_bd <block_design.bd>
这个xilinx文档里面没说,block design在生成的时候可以选OOC,所以其实是已经综合过的,这里可以直接读进来。
set_property HD.PARTITION 1 [current_design]
这个命令对于OOC是非必须的,如果OOC的结果后面需要reuse则建议加上这个约束。
之后就是正常的implementation流程。
3.2 约束
3.2.1 ooc only
ooc的约束和顶层的约束有时候会有冲突,以下方法可以让ooc的约束文件只用于ooc流程:
read_xdc -mode out_of_context <file.xdc>
set_property USED_IN {synthesis implementation out_of_context} [get_files file.xdc]
3.2.2 约束介绍
分为3个部分:Timing/pblock/context
3.2.2.1 timing constraints
正常的timing约束都能用在OOC上。
3.2.2.2 pblock constraints
set_property CONTAIN_ROUTING <ture/false> [get_pblocks <block_name>]
是否包含布线,意思是不允许使用pblock之外的布线资源。这个有点没搞明白,如果一条线跨过pblock边界咋办?OOC这个是必须要设为true的。
set_property EXCLUDE_PLACEMENT <true/false> [get_pblocks <block_name>]
是否阻止其他不属于当前pblock的器件摆到pblock里面来。OOC建议设为false。
3.2.2.3 context constraints
Command/property name | Description |
---|---|
HD.CLK_SRC | 当前port在模块之外有时钟buffer,并指定其位置。使用该约束前必须要create_clock |
HD.PARTIN_LOCS | 指定port布线的路径,具体到某个INT tile。不要使用在时钟脚上。不要用在dedicated connection上 |
HD.PARTIN_RANGE | 指定port布线的范围,可以是slice/dsp/block RAM/INT单元 |
set_logic_unconnected | 允许当前port被优化,因为它在顶层是NC的 |
set_logic_one | 允许当前port被优化,因为它在顶层固定为1 |
set_logic_zero | 允许当前port被优化,因为它在顶层固定为0 |
在Module Analysis流程中,接口的nets不会布线。如果想要让工具对这些接口进行routing,需要设置HD.PARTPIN_*约束。
HD.PARTPIN_RANGE可以设置为和PBLOCK一样的范围,如果想要更精确也可以缩小范围,或者用HD.PARTPIN_LOCS直接指定确切位置。
4 顶层重用
4.1 命令
这一步需要工具把Module Analysis生成的DCP读进来。顶层网表中对应模块必须是blackbox。
4.1.1 synthesis
这一步就是把顶层下面的OOC模块设置为成黑盒子再综合。需要注意的是,如果IO buffer是放在OOC模块里的,顶层综合的时候就需要设置这些port不需要引入IO buffer。
4.1.2 implementation
- 设置每个黑盒子模块的HD.PARTITION属性。
- 用read_checkpoint -cell <cell_name> <file> [-strict]命令读入OOC模块
- 用lock_design -level <logical|placement|routing> [<cell>]锁定OOC模块
后面的流程就和正常跑implementation没什么区别了。