HyperFlex 架构系列(4):可变延迟模块与自动流水线插入

一、在可变延迟位置做流水线

FPGA 设计中通常存在一些对额外延迟不敏感的位置,例如时钟域边界、主要功能块之间的连接和 false path。在这些位置添加流水线级是最佳实践。但过多添加流水线级也会膨胀面积并增加布线拥塞。

当前版 Quartus Prime 包含了针对延迟不敏感路径的新功能:Hyper-Retimer 可以自动在你标记为 latency-insensitive 的 false path 上添加流水线级,也可以在你指定的寄存器处插入适当数量的流水线级。这些添加的寄存器会被 retime 到设计中的时序关键部分。Hyper-Retimer 添加的流水线级数量会在每次编译或每次设计变更时发生变化。

注意:

  • 如果不指定 latency-insensitive false path 也不使用 auto-pipelining,Hyper-Retimer 的输出网表与你的 RTL 是 cycle-equivalent 的。
  • 如果指定了 latency-insensitive false path 或使用 auto-pipelining,输出网表与 RTL 不再是 cycle-equivalent 的。因此仿真和验证环境必须能适应电路延迟的变化。

1.1 指定延迟不敏感的 False Path

可以指定 latency-insensitive false path 来允许 Hyper-Retimer 在路径上自动添加流水线级。仅在跨时钟域路径上使用这个选项,例如低速配置时钟域与高速数据路径时钟域之间:

set_false_path -latency_insensitive -from [get_clocks {clock_a}] \
  -to [get_clocks {clock_b}]

注意,虽然语法上允许在 from 或 to 中使用寄存器、cell、网线、pin 或 keeper 名称,但 Compiler 会将这种 register-to-register 的 false path 视为 retiming restriction,阻止 Hyper-Retimer 对这些端点做 retiming。在 register-to-register false path 上使用 latency_insensitive 没有收益。

set_false_path 约束的优先级高于所有其他基于路径的 SDC 约束。如果 latency-insensitive false path 所在的时钟域传输包含 FIFO、总线同步器或其他跨域电路,且这些电路上存在 set_max_skew、set_max_delay 或 set_min_delay 等路径约束,那么 clock-to-clock 的 set_false_path 会覆盖这些约束。仅在已从时序分析中实际切断的跨时钟域路径上使用 latency-insensitive false path。

下图上半部分是 RTL,标记了 latency-insensitive false path。下半部分展示了 Hyper-Retimer 在 false path 端点的寄存器另一侧添加流水线级。Hyper-Retimer 可以在 latency-insensitive false path 的源端输入和目的端输出添加寄存器,然后将寄存朝两个时钟域中做 backward 和 forward retiming。

图 36:延迟不敏感 False Path 对电路延迟的影响

Hyper-Retimer 分别分析每个跨时钟域路径的性能,决定自动添加的级数。不同路径可能插入不同数量的流水线级。例如,一条被 latency_insensitive 切断的总线,在 Hyper-Retimer 运行后可能各个比特的延迟不同。因此要确保跨时钟域的数据保持恒定多个时钟周期,使数据在目的端成为确定值。

编译报告不会显示 Hyper-Retimer 在 latency-insensitive false path 上插入的级数。但可以在 Hyper-Retimer 完成后检查时序网表的连接关系来确定。

二、自动流水线插入

自动流水线插入允许 Hyper-Retimer 在你指定的位置插入一定数量的流水线级。你可以为每个寄存器指定最大流水线级数。

1783076869394

Quartus Prime 提供了 hyperpipe_vlat(Variable Latency Module)模板来简化实现。也可以用 QSF 赋值的组合来实现自动流水线插入。

当例化 hyperpipe_vlat 模块且 Enable AutoPipelining(HYPER_RETIMER_ENABLE_ADD_PIPELINING)选项使能时(该选项默认打开),Hyper-Retimer 会在 retiming 过程中在指定寄存器处添加适当数量的额外流水线级,最多不超过你指定的最大值。这个选项位于 Assignments > Settings > Compiler Settings > Advanced Settings (Fitter)。

图 38:最大 10 级流水线的可变延迟模块

例如,如果指定最大 10 级,Hyper-Retimer 可能判断只需要 3 级就能满足时序要求。它只添加实际需要的级数。

1783076863635

可以为不同的 hyperpipe_vlat 实例指定不同的最大流水线级数。

图 40:不同模块的不同最大流水线级数

最大额外流水线级数的有效范围是 1 到 100。

2.1 创建可变延迟模块

hyperpipe_vlat 模块包含单个流水线级。Hyper-Retimer 为同一实例中位宽的所有比特添加相同数量的流水线级。模块参数:

  • WIDTH:总线位宽,默认 1
  • MAX_PIPE:Hyper-Retimer 在该实例上最多可添加的流水线级数,范围 1 至 100,默认 100

图 41:Hyper-Pipelining 可变延迟模块模板

在 Quartus Prime 中创建步骤:

  1. File > New,创建新的 Verilog HDL 或 VHDL 设计文件。
  2. 在新文件中右键,Insert Template。
  3. 选择 Verilog HDL (或 VHDL) > Full Designs > Pipelining > Hyper-Pipelining Variable Latency Module,Enter and Close。
  4. 例化时指定 WIDTH 和 MAX_PIPE 参数的值。
  5. 保存文件。

2.2 例化可变延迟模块

可以使用 Fast Forward 编译来帮助找到适合自动流水线插入的位置。以下位置通常适合:

  • 时钟域边界:当传输的是持续变化的数据时,允许 Fitter 在有利时将这些模块放置得更远。
  • 紧邻复杂组合功能的位置:适用于难以满足时序的功能。
  • 同一时钟域中两个独立功能块之间:允许 Fitter 在有利时将模块放置得更远。

在时钟域边界例化

Fast Forward 编译建议在时钟域边界添加流水线级,这些位置容纳额外延迟通常比较简单。在时钟边界例化可变延迟模块允许 Fitter 在有利时将模块放置得更远。只需在同步器或 FIFO 之前或之后例化 hyperpipe_vlat。例化时不应在 hyperpipe_vlat 与其目标之间有其他寄存器或逻辑。这样 Hyper-Retimer 可以自动插入刚好够用的流水线寄存器来满足时序。在这种情况下 latency-insensitive false path 不合适,因为数据是持续变化的。

紧邻复杂组合功能例化

可以在复杂组合模块之后例化 hyperpipe_vlat(向后 retiming 不需要额外的复位周期来适应初始条件)。你无法控制 hyperpipe_vlat 中的寄存器是向前 retime 到跟随的逻辑,还是向后 retime 到组合模块中。

在独立功能块之间例化

可以在同一时钟域中的两个独立功能块之间例化 hyperpipe_vlat。这样功能块在布局时可以拉开距离,只在块之间添加满足时序所需的最少流水线级数。

不要将可变延迟模块直接放在 partition 边界旁边。需要在模块和 partition 端口之间放置一个寄存器来分隔。如果 hyperpipe_vlat 紧邻 partition 边界,retiming 时不会 auto-pipeline。

图 42:不当的可变延迟模块放置会阻止 Auto-Pipelining

1783076853632

施加 False Path 或例外约束

如果在独立功能块之间例化 hyperpipe_vlat,需要添加 false path 或其他时序例外,允许连接的功能块在布局时浮开。将 false path 或例外施加到 hyperpipe_vlat 模块中的 vlat_r 寄存器上。通过将时序例外放在条件 if 语句内,当时序分析器在 vlat 添加寄存器时以及最终时序签核时,不会使用该例外,确保每个寄存器满足时钟要求。

if { ! [is_post_route] } {
  set_false_path -to my|top|design|hyperpipe_vlat_inst|vlat_r[*]
}

如果没有对应的 false path 或例外约束,hyperpipe_vlat 几乎没有收益。没有 false path 约束时,Hyper-Retimer 在布局布线期间只识别到单个流水线级,额外的流水线级在布局布线完成后才添加。Compiler 倾向于将两个仅由单级流水线连接的功能块放在靠近彼此的位置,除非它们之间的路径被切断。

如果使用 MAX_PIPE 参数限制流水线数量,建议使用 max_delay 或 multicycle 例外替代 set_false_path。set_false_path 可能导致逻辑被放置得过远,使 MAX_PIPE 约束不足。例如当 NUM_PIPES=3 时:

if {![is_post_route]} {
  set_multicycle_path -setup -to my|top|design|hyperpipe_vlat_inst|vlat_r[*] 3
  set_multicycle_path -hold -to my|top|design|hyperpipe_vlat_inst|vlat_r[*] 2
}

施加 -from 或 -to 约束

使用可变延迟模块将 Hyper-Register 向前或向后推入寄存器链:

  • -from 约束:将 vlat_r 放在需要流水线化的组合逻辑之前。
  • -to 约束:将 vlat_r 放在需要流水线化的组合逻辑之后。

图 44:将 vlat_r 放在组合逻辑之前,使用 -from 约束

图 45:将 vlat_r 放在组合逻辑之后,使用 -to 约束

2.3 验证 Auto-Pipelining 选项

Enable Auto-Pipelining(HYPER_RETIMER_ENABLE_ADD_PIPELINING)选项默认打开。在 Assignments > Settings > Compiler Settings > Advanced Settings (Fitter) 中可以验证或修改。关闭它会阻止在 hyperpipe_vlat 实例中进一步添加流水线级。

set_global_assignment -name HYPER_RETIMER_ENABLE_ADD_PIPELINING <ON|OFF>

2.4 不使用可变延迟模块的自动流水线插入

如果不使用 hyperpipe_vlat 模块,对目标寄存器按以下步骤启用 auto-pipeline:

  1. 在 Assignment Editor 中选择 Maximum Additional Pipelining,输入最大流水线数,指定目标寄存器的层级路径:
set_instance_assignment -name HYPER_RETIMER_ADD_PIPELINING \
  <maximum stages> -to <register path>
  1. 指定 preserve pragma 并将目标寄存器的 Netlist Optimizations 设为 Never Allow,防止 auto-pipelining 插入前对总线做任何优化:
set_instance_assignment -name \
  ADV_NETLIST_OPT_ALLOWED NEVER_ALLOW -to <register path>
  1. 创建赋值组使关联的寄存器获得相同数量的额外流水线级。如果不定义组,组名会自动以 add_pipelining_group 为前缀生成:
set_instance_assignment -name \
  HYPER_RETIMER_ADD_PIPELINING_GROUP <group name string> \
  -to <register path>

三、用寄存器替代 Multicycle 例外

设计中常有包含复杂组合逻辑的模块(如 CRC 和其他算术功能),需要多个时钟周期处理。这些模块通常用 multicycle 例外放宽时序要求。HyperFlex 架构 FPGA 设计中可以使用这些模块和约束。

另一种做法是在模块的一个方便位置插入若干寄存器级,Compiler 自动进行平衡。例如要流水线化一个 CRC 功能,不需要识别最优的分解位置和中间项。在它的输入或输出处添加寄存器即可,Compiler 会负责平衡。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值