4. 创建与配置设计分区

在上一节完成增量编译规划之后,真正落到 Quartus 工程里的第一步,是把“计划中的模块边界”变成工具能够识别的 Design Partition(设计分区)。Design Partition 是 Quartus 增量编译的基本单位:只有被声明为分区的层次,才会被单独综合、单独布局布线,并在后续编译中保留其网表与布局结果。没有分区,就没有增量;分区划错,增量编译的收益会大打折扣,甚至出现“每次全编译”的假增量现象。

本节围绕四件事展开:如何创建分区、如何指定分区类型、空分区与顶层分区如何处理、以及如何导出分区层次供团队复用。

一、创建 Design Partition 的两种入口

Quartus 中创建分区主要有两条路径,二者等价,只是操作位置不同。

第一条路径在 Project Navigator → Hierarchy 标签页中完成。展开工程层次树,右键点击目标模块实例,选择 Design Partition → Set as Design Partition。此时该实例图标上会出现一个分区标记,表示它已成为独立分区。

第二条路径在 Assignments → Design Partitions Window 中完成。打开该窗口后,可以看到当前工程所有已声明的分区列表,每一行对应一个分区实例,列包括 Partition Name、Hierarchy Path、Type、Netlist Type、Fitter Placement、Routing 等。在这里可以新增、删除、修改分区属性,是分区管理的“总控台”。

需要特别强调:分区必须落在实例(instance)上,而不是模块定义(module)上。同一个模块被多次例化时,每个实例都可以独立成为分区,也可以只让其中一个成为分区。例如一个 fir_filter 模块在顶层被例化两次,分别命名为 u_fir_a 和 u_fir_b,那么可以只把 u_fir_a 设为分区,而 u_fir_b 保持普通逻辑。这一点在规划阶段就要想清楚,否则后期改名会导致分区路径失效。

二、分区类型(Partition Type)的选择

Design Partitions Window 中的 Type 列决定该分区在增量编译中的角色,常见取值如下:

  • Default:普通分区,参与综合与布局布线,可被增量复用。绝大多数功能模块使用此类型。
  • Top:顶层分区,代表整个设计的顶层,通常只有一个,且不可删除。
  • Empty:空分区,用于占位,不包含实际逻辑,常用于预留接口或后续替换。
  • Reconfigurable:用于部分重配置流程,普通增量编译工程一般不使用。

选择类型时遵循一个原则:只有需要独立保留编译结果、且边界稳定的模块才设为 Default 分区。如果一个模块每次编译都会改动,把它设为分区反而增加管理成本,因为每次都要重新综合该分区。通常建议把“接口稳定、内部逻辑可能迭代”的模块设为分区,例如通信协议栈、算法加速核、视频处理流水线等。

三、空分区与顶层分区的处理

空分区(Empty Partition) 是一个特殊但实用的机制。它的作用是:在顶层保留一个分区位置,但该分区内部暂时没有逻辑,或者逻辑由后续版本填充。空分区在编译时会被当作黑盒处理,不参与综合。使用空分区时要注意两点:

  1. 空分区的端口必须与顶层连接一致,否则编译会报端口不匹配错误。
  2. 空分区不能直接参与时序分析,因为它没有内部网表。若需要时序收敛,必须先用真实逻辑填充。

顶层分区(Top Partition) 是 Quartus 自动创建的分区,代表整个设计的顶层。它不能被删除,也不能被设为 Empty。顶层分区的作用是承载所有子分区的连接关系。当子分区被增量复用后,顶层分区仍然需要重新布局布线,因为子分区之间的连线可能变化。因此,顶层分区的稳定性直接影响增量编译的收益:如果顶层端口或子分区之间的连接频繁改动,即使子分区被复用,顶层仍需大量重布线,整体编译时间下降有限。

实践建议:把顶层逻辑尽量做“薄”,只保留子分区例化和少量胶合逻辑。顶层越薄,增量编译时顶层重布线的代价越小,增量收益越明显。

四、分区层次导出与复用

当分区配置完成后,可以把分区层次结构导出为 .qpartition 文件,供其他工程或团队成员复用。操作路径为:Project → Export Design Partition,选择导出路径并命名。导出的文件记录了分区名称、层次路径、类型、网表类型等属性。

导入时使用 Project → Import Design Partition,选择 .qpartition 文件即可。导入后,Quartus 会按照文件中的层次路径在目标工程中查找对应实例,并自动设置分区属性。如果目标工程的层次结构与导出时不一致,导入会失败或部分失败,因此导出前应确保层次命名规范统一。

下面这张图展示了从工程层次到分区配置、再到导出复用的完整关系。图中左侧是层次树中的实例,中间是 Design Partitions Window 中的属性列,右侧是导出文件与复用目标。

Design Partition 创建、配置与导出关系图 Project Navigator 层次树 top (顶层实例) u_dsp_core u_fir_a u_fir_b u_pcie_ep u_empty_slot 右键 → Set as Design Partition Design Partitions Window Partition Type Netlist top Top — u_dsp_core Default Post-Syn u_fir_a Default Post-Fit u_fir_b Default Post-Fit u_pcie_ep Default Post-Fit u_empty_slot Empty — Type 决定分区角色 Netlist 决定复用粒度 Fitter Placement 决定布局复用 导出与复用 Export Design Partition 生成 .qpartition 文件 Import Design Partition 按层次路径匹配实例 团队复用 / 多工程共享 统一分区命名规范 层次不一致 → 导入失败 需先核对实例路径 声明 导出 分区落在实例上;Type 决定角色;Empty 占位;Top 承载连接;.qpartition 实现跨工程复用

五、配置检查与常见问题

分区配置完成后,建议在 Design Partitions Window 中逐项核对以下内容:

检查项正确做法常见错误
分区路径 与层次树中的实例名完全一致 模块改名后未更新分区,导致分区失效
Type 功能模块用 Default,顶层用 Top,占位用 Empty 把顶层误设为 Default,导致顶层被当作普通分区
Netlist Type 需要复用布局时选 Post-Fit 选 Post-Syn 后期望复用布局,实际仍需重新布局
端口一致性 空分区端口与顶层连接匹配 空分区端口缺失,编译报端口不匹配

一个典型的配置片段如下,展示了在 .qsf 文件中分区相关设置的实际写法:

set_global_assignment -name PARTITION_NETLIST_TYPE POST_FIT -section_id u_dsp_core
set_global_assignment -name PARTITION_FITTER_PRESERVATION_LEVEL PLACEMENT_AND_ROUTING -section_id u_dsp_core
set_global_assignment -name PARTITION_TYPE DEFAULT -section_id u_dsp_core
set_global_assignment -name PARTITION_NETLIST_TYPE POST_FIT -section_id u_fir_a
set_global_assignment -name PARTITION_TYPE DEFAULT -section_id u_fir_a
set_global_assignment -name PARTITION_TYPE EMPTY -section_id u_empty_slot

这些设置与 Design Partitions Window 中的列一一对应。理解 .qsf 中的写法,有助于在脚本化流程或版本管理中批量维护分区配置。

注意:分区一旦创建并完成一次完整编译,后续修改分区边界(例如把某个子模块移入或移出分区)会导致该分区及其父分区的网表失效,必须重新综合。因此分区边界应在规划阶段确定,避免频繁调整。