:可变延迟模块与自动流水线插入)
一、在可变延迟位置做流水线FPGA 设计中通常存在一些对额外延迟不敏感的位置例如时钟域边界、主要功能块之间的连接和 false path。在这些位置添加流水线级是最佳实践。但过多添加流水线级也会膨胀面积并增加布线拥塞。当前版 Quartus Prime 包含了针对延迟不敏感路径的新功能Hyper-Retimer 可以自动在你标记为 latency-insensitive 的 false path 上添加流水线级也可以在你指定的寄存器处插入适当数量的流水线级。这些添加的寄存器会被 retime 到设计中的时序关键部分。Hyper-Retimer 添加的流水线级数量会在每次编译或每次设计变更时发生变化。注意如果不指定 latency-insensitive false path 也不使用 auto-pipeliningHyper-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。Hyper-Retimer 分别分析每个跨时钟域路径的性能决定自动添加的级数。不同路径可能插入不同数量的流水线级。例如一条被 latency_insensitive 切断的总线在 Hyper-Retimer 运行后可能各个比特的延迟不同。因此要确保跨时钟域的数据保持恒定多个时钟周期使数据在目的端成为确定值。编译报告不会显示 Hyper-Retimer 在 latency-insensitive false path 上插入的级数。但可以在 Hyper-Retimer 完成后检查时序网表的连接关系来确定。二、自动流水线插入自动流水线插入允许 Hyper-Retimer 在你指定的位置插入一定数量的流水线级。你可以为每个寄存器指定最大流水线级数。Quartus Prime 提供了 hyperpipe_vlatVariable Latency Module模板来简化实现。也可以用 QSF 赋值的组合来实现自动流水线插入。当例化 hyperpipe_vlat 模块且 Enable AutoPipeliningHYPER_RETIMER_ENABLE_ADD_PIPELINING选项使能时该选项默认打开Hyper-Retimer 会在 retiming 过程中在指定寄存器处添加适当数量的额外流水线级最多不超过你指定的最大值。这个选项位于 Assignments Settings Compiler Settings Advanced Settings (Fitter)。例如如果指定最大 10 级Hyper-Retimer 可能判断只需要 3 级就能满足时序要求。它只添加实际需要的级数。可以为不同的 hyperpipe_vlat 实例指定不同的最大流水线级数。最大额外流水线级数的有效范围是 1 到 100。2.1 创建可变延迟模块hyperpipe_vlat 模块包含单个流水线级。Hyper-Retimer 为同一实例中位宽的所有比特添加相同数量的流水线级。模块参数WIDTH总线位宽默认 1MAX_PIPEHyper-Retimer 在该实例上最多可添加的流水线级数范围 1 至 100默认 100在 Quartus Prime 中创建步骤File New创建新的 Verilog HDL 或 VHDL 设计文件。在新文件中右键Insert Template。选择 Verilog HDL (或 VHDL) Full Designs Pipelining Hyper-Pipelining Variable Latency ModuleEnter and Close。例化时指定 WIDTH 和 MAX_PIPE 参数的值。保存文件。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。施加 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_PIPES3 时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 放在需要流水线化的组合逻辑之后。2.3 验证 Auto-Pipelining 选项Enable Auto-PipeliningHYPER_RETIMER_ENABLE_ADD_PIPELINING选项默认打开。在 Assignments Settings Compiler Settings Advanced Settings (Fitter) 中可以验证或修改。关闭它会阻止在 hyperpipe_vlat 实例中进一步添加流水线级。set_global_assignment -name HYPER_RETIMER_ENABLE_ADD_PIPELINING ON|OFF2.4 不使用可变延迟模块的自动流水线插入如果不使用 hyperpipe_vlat 模块对目标寄存器按以下步骤启用 auto-pipeline在 Assignment Editor 中选择 Maximum Additional Pipelining输入最大流水线数指定目标寄存器的层级路径set_instance_assignment -name HYPER_RETIMER_ADD_PIPELINING \ maximum stages -to register path指定 preserve pragma 并将目标寄存器的 Netlist Optimizations 设为 Never Allow防止 auto-pipelining 插入前对总线做任何优化set_instance_assignment -name \ ADV_NETLIST_OPT_ALLOWED NEVER_ALLOW -to register path创建赋值组使关联的寄存器获得相同数量的额外流水线级。如果不定义组组名会自动以 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 会负责平衡。