01signal.com

用 Vivado理解 Partial Reconfiguration

这是关于 Partial Reconfiguration或 Dynamic Function eXchange (DFX) 与 Xilinx的 Vivado的四篇系列文章中的第一篇。这篇文章的目的是解释这个主题的主要概念。这为下一篇文章奠定了基础,其中概述了使用 Partial Reconfiguration设置 FPGA 项目的实际步骤。

介绍

Partial reconfiguration 是一种技术,允许在 FPGA的某些部分替换 logic ,而其他部分正常工作。这包括用 bitstream为 FPGA 供电,就像最初的 bitstream 在通电时对其功能进行编程一样。但是, Partial Reconfiguration 的 bitstream 不会导致 FPGA 停止。相反,它适用于特定的 logic elements,并更新控制其行为的内存单元。它是特定 logic blocks的 hot replacement 。

Xilinx的 FPGAs 从 Virtex-4 开始支持此功能(以及 Intel的 FPGAs 从 Series-V开始)。

这篇文章将介绍 Partial Reconfiguration 背后的概念,而不涉及实际的技术细节,为下一篇文章做准备,下一篇文章就是这样做的。因为所有内容都与本主题中的所有内容相关,所以在将其分解为单个操作之前了解整个框架非常重要。

再解释一下?

让我们从没有 Partial Reconfiguration的情况下如何更改 FPGA 的功能开始。假设在 design hierarchy的某处有 instantiation 或 module 。例如,在 Verilog中:

moduleA reconfig_ins
     (
      .clk(clk),
      .this(this_w),
      .that(that_w),
 [ ... ]
      );

或在 VHDL中:

reconfig_ins : moduleA
    port map(
      clk        => clk,
      this       => this_w,
      that       => that_w,
 [ ... ]
      );

显然,在项目中的某个地方有一个称为 moduleA.v 或 moduleA.vhd 的 module ,或者一个称为 moduleA的 IP ,它填充了 instantiation (连同它的 submodules)。所以我们执行项目的 implementation ,得到一个 bitstream 文件,并用它加载 FPGA 。到目前为止,通常的程序。

但是现在,假设我们在上面的代码中写的是 moduleB 而不是 moduleA ,并且对 logic 执行一次 implementation ,得到一个 bitstream 文件。为此, design中必须有一个 moduleB.v 或 moduleB.vhd,或称为 moduleB 的 IP 。

我们现在有两个 bitstream 文件,它们的不同之处在于 instance 内部的 logic ,称为 reconfig_ins 。要在这两个 bitstreams之间切换,我们需要用所需的 bitstream加载整个 FPGA 。这涉及中断 FPGA的操作。

Partial Reconfiguration 是一种允许从一个版本更改到另一个版本而不会出现这种中断的技术: FPGA 保持正常工作,而 reconfig_ins 中的 logic 从 moduleA 变为 moduleB,反之亦然。几乎不用说,这仅靠两个 designs 中的一个 implementation 是不可能的。

moduleA 和 moduleB 统称为 Reconfigurable Modules (RM),就是说它们的 logic 可以借助 Partial Reconfiguration注入到 FPGA 中。

动机

使用 Partial Reconfiguration有几个原因,例如:

偏 bitstream

如果您对 FPGA design有一定的经验,那么您很可能已经习惯了一个简单的例程: 对 design的 source code (和 IPs)进行一些编辑,启动 implementation tools,并检查它是否正常。然后通过 JTAG将 bitstream 加载到 FPGA 中。或者,使用 bitstream的 image 加载 flash device 。

因为这是我们都习惯的,所以很容易将 bitstream 误认为是大量数据,这些数据充满了整个 FPGA ,其中包含有关每个 logic element 应该如何表现的神秘信息。实际上, bitstream 由一系列命令组成,这些命令在 FPGA 加载时按顺序执行。事实上,普通的 bitstream 会为整个 FPGA 加载信息,但它是通过控制过程进度的几个命令完成的。这些命令的一个更重要的方面是它们决定了哪些 logic elements 加载了每条数据。

由于 bitstream 本身说明了哪些 logic elements 受到影响,因此可以制造一个 bitstream ,它只改变一些 logic elements,而使其他 logic elements 保持不变。这是 Partial Reconfiguration的基石。

话虽如此, partial bitstream 必须与 FPGA中已经加载的 logic 兼容。这不仅仅是覆盖错误的 logic elements的问题: 初始 bitstream 与部分 bitstream紧密耦合,特别是因为初始 bitstream 使用在由部分 bitstream更改的区域内的 logic 和 routing resources 。当部分 bitstream 相对于最初的 bitstream正确设置时,这种微妙的舞蹈就会被忽视。如果没有, FPGA 很可能会发疯,包括本应保持不变的功能。

加载部分 bitstream

Partial Configuration bitstream 到 FPGA 的交付可以通过任何允许加载 bitstreams的接口完成,只要该过程可以在 FPGA 运行时完成。这包括 JTAG 接口,因此 Partial Configuration 的 .bit 文件可以像往常一样与 Hardware Manager 一起加载。但更有趣的是,它可以在 FPGA自己的 logic内部使用专用的 Internal Configuration Access Port (ICAP)完成。这个 port 只能用于 Partial Reconfiguration,因为 FPGA的 logic fabric 中加载 bitstream 的部分在整个过程中必须保持完整。

ICAP 只是 FPGA子系统的一个接口,用于加载 bitstreams,并没有说明 bitstream的来源。因此,对 bitstream 数据如何到达 FPGA或存储位置和存储方式没有限制。它只是必须以某种方式可用于为 ICAP提供数据的 FPGA logic 部分。

例如, Xillybus 提供了一种简单的方法,可以通过 PCIe 或 USB 3.x 接口从计算机将 bitstream 文件发送到 ICAP ,如果开发板有这种接口的话。

Static logic

要正确完成 Partial Reconfiguration ,必须尊重相反的部分: static logic。这是 FPGA design 中必须保持不变的部件的总称,因此从最初的 bitstream 加载时就存在。

这个 logic 在两个方面是静态的: 功能方面,这意味着 logic 由 FPGA design 中的部件(HDL 和 IP)组成,这些部件在 FPGA的初始启动时不会中断。第二个同样重要的方面是,此 logic 的放置仅限于 logic fabric 中分配为静态的站点。在这些网站上,不允许以后进行任何操作。

在现实生活中的 design中,仅 static logic 保持不变是不够的,但同样重要的是,当 FPGA 的其他部分发生变化时,它仍能正常运行。由于几乎可以肯定在 static logic 和变化的 logic 之间有 nets 连接,因此确保一切顺利运行是 FPGA designer的责任。本系列的第三篇文章讨论了这一点。

static logic 和 reconfigurable logic的分离

为了使 Partial Reconfiguration 成为可能, static logic 和 reconfigurable logic之间必须严格分开。特别是, FPGA 上的物理 logic elements 必须分开,这样当 FPGA 与 bitstream一起加载时,任何包含 static logic 的站点都不会受到影响。

要了解这需要什么,让我们首先看看我们都习惯了什么。

回想一下,常规 FPGA implementation 进程从 HDL design的 synthesis 开始。请注意, HDL 中的 instantiation 和 modules 并不意味着它们之间有任何分离。反之亦然: synthesizer 将 instantiations 视为 logic 应该如何工作的描述。因此, synthesizer 可以自由地将整个 design 视为一个大而扁平的 logic。跨越 modules 边界的优化不仅是允许的,而且是需要的并且经常发生。例如,如果 module X 中的 register 恰好等同于 module Y中的某些完全不相关的 register ,则删除 registers 中的一个,其余的一个用于两个 modules (除非明确告知 synthesizer 避免这样做)。

一旦 HDL 的 synthesis 完成, synthesized netlist 将与 design的 IPs (如果有)混合。

接下来,将这大块 logic elements 放置在 FPGA的 logic fabric各处,并以实现 timing constraints 和其他目标的方式布线。属于 design 不同部分的 Logic 可以打包到同一个 slice中,也可以打包在 FPGA的相反部分中。即使是 design 中最小的变化也可能导致显着不同的放置。这是混乱但无害的,因为每个 implementation 都是独立的,谁在乎 logic 是如何分散在 FPGA的 logic fabric上的。

回到 Partial Reconfiguration: 如前所述,要使此功能成为可能, static logic 和 reconfigurable logic之间必须有明显的区别。为了确保这一点,使用了一种称为 Hierarchical Design 的技术。这个想法是将整个 design 视为组件的集合,就像 PCB上的物理组件一样。一方面是每个组件(即 instantiated module)都在 logic fabric上分配了一个特定区域。由于每个组件都需要分离,因此单独执行 synthesis 显然是有意义的——就像您单独生产组件一样。

因此,让我们将这个概念与 Partial Reconfiguration联系起来,归结为与 design工作的两个主要区别:

Pblocks

Vivado对 floorplanning unit 的术语是 Pblock,它只是 Vivado内部信息的占位符。有 Tcl 函数可以创建 Pblock,将 logic cells 添加到其中,然后添加 FPGA logic sites的组 (sets)。 Vivado 将此解释为 placement constraint ,它要求添加到 Pblock 的 logic cells 只能放置在分配给它的 sites 中。所以说到底, Pblocks 就像 XDC 文件中的其他 constraints 一样。

Pblocks 通常使用 Vivado的 GUI 定义,方法是打开 synthesized design 或 implemented design,并在 FPGA的图形表示上绘制矩形区域。这将创建一个 Pblock ,其中包括绘制的矩形中的所有 logic elements 。更准确地说,并非所有类型的 logic elements 都包括在内,而仅包括允许用于 floorplanning 的那些(对于该 FPGA 系列)。所以 Vivado 将矩形转换为 logic elements的范围。

通过编辑 XDC 文件手动设置这些范围同样可以。此外,它允许创建一个由多个矩形组成的区域,因此形状可以比一个矩形更复杂。但是 Xilinx的文档 (UG909) 建议尽量保持形状简单以避免 routing的困难。

这是 Kintex-7的 XDC 文件的示例:

create_pblock pblock_pr_block_ins
add_cells_to_pblock [get_pblocks pblock_pr_block_ins] [get_cells -quiet [list pr_block_ins]]
resize_pblock [get_pblocks pblock_pr_block_ins] -add {SLICE_X118Y0:SLICE_X153Y99 SLICE_X118Y250:SLICE_X145Y349 SLICE_X0Y0:SLICE_X117Y349}
resize_pblock [get_pblocks pblock_pr_block_ins] -add {DSP48_X5Y100:DSP48_X5Y139 DSP48_X5Y0:DSP48_X5Y39 DSP48_X0Y0:DSP48_X4Y139}
resize_pblock [get_pblocks pblock_pr_block_ins] -add {RAMB18_X4Y0:RAMB18_X6Y39 RAMB18_X4Y100:RAMB18_X5Y139 RAMB18_X0Y0:RAMB18_X3Y139}
resize_pblock [get_pblocks pblock_pr_block_ins] -add {RAMB36_X4Y0:RAMB36_X6Y19 RAMB36_X4Y50:RAMB36_X5Y69 RAMB36_X0Y0:RAMB36_X3Y69}

下图显示了它在 implemented design中的外观。 reconfigurable partition (命名为 pblock_pr_block_ins,在本例中几乎不包含 logic )以紫色绘制。它的形状被创建为三个矩形的 union (上面每个 resize_pblock 命令中列出的三个范围)。

在此图中,所有 placed logic 均以青色绘制。 logic 绝大多数属于 static region,其局限在小范围内可见一斑。

Example of device view with Pblock partition

请注意,只有 slices、 RAMs 和 DSP48 受 constraints限制。这些是 Partial Reconfiguration 可以使用 series-7 FPGAs控制的唯一 logic 类型。其他一切,实际上除了“纯 logic”之外的任何东西都必须属于 static design。

使用 Ultrascale FPGAs 及更高版本,几乎任何 logic 都可以用 Partial Reconfiguration重新加载。

Pblocks有额外的限制,但这里没有必要重复 UG909 中的第 6-8 章。

无论如何,打开 implemented design是个好主意,无论如何,放大和缩小 FPGA的视图,并观察 logic elements 在 FPGA中的组织方式。特别注意,有相同类型的 logic 列。有时在列中间有几个 logic elements 打破了均匀性(特别是特殊的 logic elements,如 ICAP 块、 PCIe 块等)。

值得一提的是, Pblocks 的话题并非专门针对 Partial Reconfiguration。例如,本节中所说的一切也适用于将 Pblocks 用于 hierarchical design。

更多关于 floorplanning

这里有几个违反直觉的事实: 尽管 floorplanning 的图形表示由在 FPGA的地图上绘制的形状组成,但它仅适用于由其 placement constraints控制的 logic 类型。所以如果 FPGA 的几乎所有 slices 都分配给 Partial Reconfiguration,那么完全被这些 slices 包围的其他 logic elements 的岛屿很可能属于 static logic。例如,如果 ICAP 块本身位于分配给 Partial Reconfiguration的矩形的中间,则没有任何问题。

这并不奇怪,因为 Partial Reconfiguration bitstream 是针对某些 logic elements 而其他的则完好无损。但是 routing呢?如果 ICAP 的块卡在 reconfigurable logic的中间,那线是怎么拉到 static logic的 slices 上的?

这将我们引向第二个违反直觉的事实: static design 的 routing 使用 reconfigurable region内部的资源。这个 routing 在整个 Partial Reconfiguration 过程中保持稳定,否则它不会是 static logic。所以在 reconfigurable region内部, reconfigurable logic 的 routing 发生了变化,但 static logic 的 routing 保持不变。如果说这整个话题有什么神奇之处,那就是这个小事实。这也是为什么使用与 static logic 不兼容的 partial bitstream 可能会完全破坏 FPGA 的原因。

当然,反过来是不正确的: 除了上面 XDC 示例中明确列出的资源外, reconfigurable logic 不使用任何资源。至于 routing 资源,加载 Partial Reconfiguration bitstream 时 static region 中的任何内容都不会改变,因此从这个意义上说, reconfigurable logic 永远不会影响 static region。嗯,这几乎是真的: 如果 reconfigurable region 的形状不是一个普通的矩形, Vivado 可能会让 routing 超出 reconfigurable region 。这只发生在 Ultrascale FPGAs上,目的是改进 routing。

此时应该清楚的是,绘制 floorplanning 的规则并不简单。好消息是 Vivado 产生了相当丰富的 Critical Warnings 以响应违反 floorplanning规则的行为。因此,通过反复试验找到合适的 floorplan 是一种合理的工作方式。

Parent implementations 和 Child implementations

关于 reconfigurable logic的 implementation ,需要注意的是, FPGA 中的每一个 path 都必须达到 timing constraints,并且在加载 reconfigurable logic 之前和之后都必须如此。因此,与 static logic分开的 reconfigurable logic的 implementation 是不可能的。相反,对于每个 reconfigurable module, implementation 总是在整个 FPGA 上执行。 timing constraints (以及其他 constraints)在每个 implementation上强制执行。

为了澄清这一点,让我们从上面返回 moduleA 和 moduleB 的示例。对于此示例, Vivado 执行包含 moduleA 的完整 design 的 implementation ,然后对 moduleB执行相同操作。作为副产品,这两个选项中的每一个都有常规的 bitstream 文件。

值得强调的是: 所有 implementations 都生产完整的 initial bitstream 和 partial bitstream。所有 implementations 都是如此,无论它们是 Parent 还是 Child。因此,当 FPGA 启动时,可以使用这些 initial bitstreams中的任何一个加载它。

为了能够使用 Partial Reconfiguration从 moduleA 迁移到 moduleB , static partition 中的所有内容都必须完全相同。这包括 logic 本身、 placement 和 routing。为了实现这一点, Vivado 在一种情况下(例如,使用 moduleA)执行 implementation 作为 Parent Implementation。然后它为所有其他场景执行 Child Implementations (例如使用 moduleB)。本系列的最后一篇文章详细介绍了这是如何完成的,但长话短说:

Vivado 开始像 Hierarchical Design一样为 moduleA 运行 Parent Implementation 。这意味着 static logic 和 reconfigurable logic 的 synthesis 是分开完成的,并且 floorplanning constraints 将 placements 强制到 FPGA上的不同站点中。除了这两个差异之外,还执行常规 implementation 。特别是,执行 placement 和 routing 是为了在此特定场景下获得最佳结果(即使 floorplanning constraints 和单独的 synthesis 可能会导致次优性能)。

下一步是为 moduleB执行 Child Implementation 。不需要 static design的 synthesis ,因为这已经代表 Parent Implementation完成。所以 synthesis 只在 reconfigurable logic上进行。

implementation 的执行方式与 Parent Implementation相同,但有一个关键区别: 所有 static logic 的 place and route 被强制与 Parent Implementation的结果相同。鉴于此限制, reconfigurable logic 的 place and route 被执行以获得最佳结果。

所以 Parent 和 Child 之间关系的关键是 Child Implementation 从 Parent Implementation 结束的地方开始,但用自己的 logic替换 reconfigurable logic 。然后 Child Implementation 照常继续,但不触及 static logic区域内的任何东西。

因为所有的 Child Implementations 都需要适应 static logic的 placements 和 routes,所以 timing constraints可能比 design的普通 implementation 更难实现。实际上有两个障碍:

在选择应为 Parent Implementation选择哪个 reconfigurable modules 时,应牢记这一点。例如,最难实现 timing constraints 的可能是 module 。或者 module 代表另一个 modules 与 static logic的连接方式。或者可能,反过来: reconfigurable module 实际上根本不包含 logic (“grey box”),以实现 static logic的中性 implementation 。

至于 bitstreams的使用, Vivado对于一个有 Partial Reconfiguration 的项目的 implementation 的范式是,当所有 bitstreams 都是最新的并且相互兼容时, implementation 就结束了。也就是说, implementations的任何一个 initial bitstreams 都可以用来加载 FPGA 的开始。在此之后,任何一个 implementations的 partial bitstreams 都可以加载。

因此,第一个“Generate Bitstream”启动了 Parent Implementation 和所有 Child Implementations。在随后的 compilations 中, Vivado 照常只执行需要更新的 runs 。

Dynamic Function eXchange Wizard

这个可以从 Tools 菜单启动的 Wizard的目的是定义 Parent Implementation 和 Child Implementations,特别是哪个 Implementation 包含哪个 reconfigurable module。

通过查看它在添加 Child Implementation时发出的 Tcl 命令来解释这个 Wizard 是最简单的:

create_reconfig_module -name bpf -partition_def [get_partition_defs pr ]
add_files -norecurse /path/to/pr_block1.v  -of_objects [get_reconfig_modules bpf]
create_pr_configuration -name config_2 -partitions [list pr_block_ins:bpf ]
create_run child_0_impl_1 -parent_run impl_1 -pr_config config_2 -flow {Vivado Implementation 2020}

我将从最后一行到第一行向后遍历这个 Tcl 序列:

所以在最后一行,创建了一个 Child Implementation run 。新的 run 被命名为“child_0_impl_1”,它的 parent run 被选为“impl_1”。同样重要的是,这款新 run 的 configuration 设置为“config_2”。

“config_2”在第三行定义,表示“bpf”是用于名为“pr_block_ins”的 reconfigurable partition 的 reconfigurable module 。 “pr_block_ins”上面已经提到过,那么“bpf”是什么?

在第一行中,创建了一个 reconfig_module 并将其命名为“bpf”——这只是方便说明 logic 功能的任何名称。第二行表示将某个 Verilog 文件添加到此 reconfigurable module。

所以总而言之,这四行创建了一个新的 Child Implementation,并且说创建一个 reconfigurable module需要某个 Verilog 文件的 synthesis 。此外,在 Tcl environment 中创建了两个 objects ,“bpf”和“config_2”。

现在回到 Dynamic Function eXchange Wizard: 它是一个 GUI 工具,代表 design sources、 reconfigurable modules、 configurations 和 implementation runs之间的关系。这只是一种方便的方式来传达信息以生成如上所示的 Tcl 命令。

这个工具可能看起来过于复杂,但那是因为示例很简单。在现实的 design中, reconfig_module 很可能有多个 source files,并且可能分配有 IPs 。因此, GUI 让事情变得更简单。

但为什么需要 configuration (“config_2”)?为什么“bpf”和“pr_block_ins”之间没有用 create_run 命令建立连接?再一次,这是一个合理的问题,因为这篇文章仅限于一个 reconfigurable partition。如果有多个这样的 partitions,则一个 configuration 定义了哪个 partition 得到哪个 reconfigurable module,因此给每个这样的组合命名是有意义的,例如 config_*。

那么如果有多个 partitions,是否需要为每个可能的 reconfigurable modules组合制作一个 implementation 呢?这个问题与本系列文章无关,因此请随意跳到下一节。

回想一下, Vivado的 implementation 是在整个 design上做的,即 static logic 和 reconfigurable logic 合在一起,保证它符合 timing constraints 的整体。因此,如果有多个 partitions,使用 Partial Reconfiguration 的安全方法是使用它们的 partial bitstreams加载所有 partitions ,这样所有 partial bitstreams 都是同一个 implementation run的结果。换言之,所有 partial bitstreams 都是使用相同的 configuration (例如“config_2”)创建的,因此这些 partial bitstreams 的组合是经过工具验证的 implementation 的结果。尤其是这个 implementation ,号称能实现 timing constraints。

然而,如果 reconfigurable modules 没有相互交互(即 reconfigurable modules 的所有 top-level ports 都连接到 static logic,而不是相互连接),我无法弄清楚单独处理每个 partition 会出现什么问题。事实上,如果混合使用来自不同 runs 的 partial bitstreams , Vivado 并没有明确批准整个 FPGA 的 timing 。但是既然所有的 paths 和 static logic 都达到了 timing constraints,而且 static logic 在所有 implementation runs上都是一样的,那还不够好吗?官方文档似乎没有提供有关此问题的信息。

Routing 和 Partition Pins

拼图中还缺少一件: routing 连接 static logic 和 reconfigurable logic。回想一下, Parent Implementation 以针对相关 configuration中包含的 reconfigurable logic 的最佳方式执行 design 的 place and route 。但是 child的 reconfigurable module 需要适配到同一个 reconfigurable partition中,并与 static design连接。 routing 至少有一部分属于 static logic,因此不能改变。

这就是 Partition Pins 的用武之地。从概念上讲,可以将 reconfigurable logic 视为一个物理组件,而将 partition pins 视为连接到 PCB的金属引脚。

但实际上, partition pins 只是 FPGA资源在 routing坐标系中的位置。它们是 static logic的 routing 结束的地方, reconfigurable logic的 routing 继续的地方。它们唯一重要的是 Parent Implementation 和 Child Implementations 就它们的位置达成一致。

建立这些锚点不需要 LUTs 或 flip-flops 等物理资源,它们不会贡献额外的 routing delay。当然,通往和离开 partition pins 的 routing 段创建了 delay,但 partition pins 本身不添加任何 delay。

partition pins 的位置由工具自动选择, Parent implementation 执行时, Child implementations 被迫适应。也就是说, static logic 和 reconfigurable logic 之间的 routing 从 Parent Implementation 所说的地方开始, Child Implementation 只能在 reconfigurable partition内部尽力而为。事实证明,某些 partition pins 被放置在对 Child的 reconfigurable logic不利的位置,这可能会导致实现 timing constraints的困难。

Partition pins 通常在靠近 reconfigurable partition周边的某个地方组合在一起。似乎 Vivado 旨在选择对特定 design不太专业的站点。

但是, partition pins 可以在 reconfigurable partition内部的任何地方找到,如果这是在 Parent Implementation期间实现 timing constraints 所必需的。回想一下, static design 可以使用 reconfigurable partition内部的 routing 资源。因此, static routing的某些部分进入 reconfigurable partition是没有问题的。

为防止 timing constraints 和 partition pins出现问题,如果 reconfigurable module 的 output ports 是 registers并且 inputs 也由 registers 采样是有益的。同样, static logic 最好类似地应用 registers 。事实上,只要有可能并且不会使 design变得复杂,遵循这条规则总是一个好主意。

Greybox

DFX Wizard 的另一件事是 greybox: 在 Edit Configuration 窗口中,可以将 greybox 指定为 reconfigurable module,而不是常规 reconfigurable modules之一。 greybox 是由 Vivado生成的伪造 module 。它适合真正的 reconfigurable module的 ports ,但不是真正的 logic,而是每个 port pin都有一个 LUT 。为 inputs 生成的 LUTs 在另一端没有任何连接, outputs 的 LUTs 生成零值。对于 vector ports,为 vector中的每个 bit 创建一个 LUT 。

在 Parent Implementation中使用 greybox 可能不是一个好主意,因为它使 place and route 进程太容易了。即使 reconfigurable modules 彼此之间有很大的不同,写一个简单的 module 可能会更好,在某种程度上挑战工具。

但是为了创建具有最小 logic的 initial bitstream 文件,只包含 greybox modules 的 child implementation 可能有用。回想一下,所有 implementations 都生产完整的 bitstreams,它们都可以用作 initial bitstream,因为它们都具有完全相同的 static logic。

Clearing Bitstreams (仅限Ultrascale )

这仅与 Ultrascale FPGAs ( Ultrascale+无关)有关。

如上所述,所有 implementations 都创建了两个 bitstreams: 一个 bitstream 用于整个 design,可用于初始加载 FPGA ,包括相关的 reconfigurable module 。第二个 bitstream 用于 Partial Reconfiguration 与相同的 reconfigurable module。

对于 Ultrascale 设备,还有第三个 bitstream,即“clearing bitstream”,它是在每个 implementation上创建的。这个 bitstream 需要在 partial bitstream之前发送到 FPGA 。请注意,发送到 FPGA 的 clearing bitstream 必须与当前在 FPGA内部的 logic 匹配,而不是与即将加载的 bitstream 匹配。因此,需要跟踪 FPGA的当前情况,而其他 FPGA 系列则不需要。

加载 clearing bitstream 会关闭 reconfigurable module,即使它并没有真正改变 logic。此 module 的 output ports 可能会显示任何值,直到新的 partial bitstream 已加载并启动。

根据 UG909的说法,加载错误 reconfigurable module 的 clearing bitstream (即不是与 FPGA中的 logic 匹配的 clearing bitstream )也可能会破坏 static logic ,从而导致 reconfiguration 机制发生故障。

Xilinx的文档似乎对如果在未先加载 clearing bitstream 的情况下加载 partial bitstream 会发生什么情况含糊不清。在 UG909 的第 9 章中,它首先说: “Prior to loading in a partial bitstream for a new Reconfigurable Module, the existing Reconfigurable Module must be cleared”。所以结论是 clearing bitstream 是强制性的。

但在下面几行,同一指南显示“If a clearing bit file is not loaded, initialization routines (GSR) have no effect”。这意味着完全不使用 clearing bitstream 是可以的,如果所有 synchronous elements (原则上是RAMs 和 flip-flops)在未知状态下唤醒是可以的。在我自己跳过 clearing bitstream 的轶事实验中,我没有发现任何问题,但这并不能证明什么。

因此,对于 Ultrascale FPGAs,肯定需要跟踪 FPGA中加载的内容。例如,这可以通过将 output port 添加到 reconfigurable module来完成, reconfigurable module具有一个常数值(一个 ID code),每个 reconfigurable module都不同。这允许 static logic 识别当前加载的 reconfigurable module 。无论如何,像这样的 ID code 都是一个好主意。

Plugin 与 Remote Update 用例

Vivado 采用的这种 parent-child 方法显然是为特定用例设计的,我将其称为 plugin usage: 通过加载当前需要的 reconfigurable module 来降低 FPGA的成本,而不是一直在 FPGA 中拥有所有可能的功能。例如,如果 FPGA 用于实现多个 image filters, Partial Reconfiguration 允许将每个 filter 实现为一个 reconfigurable module,并且只用需要的 filter 重新加载 FPGA 。

Xilinx 使用术语“Dynamic Function eXchange”(DFX)来表示 Partial Configuration,似乎反映了该技术的主要预期用途。

当这是 Partial Reconfiguration的目的时, parent-child 方法效果很好。生成完整的 bitstream files 套件。任何一个 initial bitstreams 都可以用来初始化 FPGA,以后所有的 reconfigurable bitstreams 都可以用于 Partial Reconfiguration。当项目的新版本发布时,由所有 bitfiles组成的整个套件都会被替换。

但是还有另一种使用模式,我将其称为 Remote Update。那时 Partial Reconfiguration 被用作版本升级的手段,可能在遥远的将来。在这种使用场景下, initial bitstream 是在某个时间点发布的,之后无法更改。稍后, partial bitstreams 发布,这些必须与 initial bitstream兼容。这些后来的版本可能会持续数年。

对于 Remote Update, parent-child 方法可能很难按原样使用。即使在没有重复 parent的 Implementation 的情况下运行 Child Implementation 以获得新的 partial bitstream 是可能的,但长时间这样做可能很困难。例如, static logic 的 source code 意外更改会使 parent的 design失效,从而导致 Parent Implementation重复。结果,新的 static logic 与之前的不兼容,因此基于它的 partial bitstream 不能与原来的 initial bitstream一起使用。

因此,如果 Partial Reconfiguration 旨在作为一种随时间连续更新 FPGA design 的方法,则 implementation 过程需要一些操作。该主题将在本系列的最后一篇文章中讨论。

压缩 bitstreams

这与 Partial Reconfiguration没有直接关系,但有时需要一个小的 initial bitstream 文件,特别是为了确保 FPGA的快速启动。在这种情况下, Partial Reconfiguration 成为快速启动后完成启动过程的一种手段。这可以从相同的数据源(例如 SPI flash)或完全不同的数据源(例如 PCIe 接口)完成。

initial bitstream 和 partial bitstreams都允许压缩 bitstream 。

这是要添加到 XDC 文件的行,以便请求压缩的 bitstream:

set_property bitstream.general.compress true [current_design]

理论部分到此结束。下一篇文章展示了配置项目以使用 Partial Reconfiguration的实际步骤。

此页面由英文自动翻译。 如果有不清楚的地方,请参考原始页面
Copyright © 2021-2024. All rights reserved. (6f913017)