算子类型与同步#
关键术语
VisualApplets 使用不同的形状来标记每个算子,以显示其类型。圆形图标表示 O 型算子。方形图标表示 M 型或 P 型算子。M 型和 P 型均使用方形图标,因此无法仅凭形状进行区分。请查看产品内置帮助或算子参考以了解其类型。主要区别在于:M 型算子可以阻塞其输入;而 P 型算子不会主动阻塞。
阻塞意味着生成的 FPGA 级在准备好接受更多数据之前可以暂停其输入。您无法使用普通算子连接两个独立的相机流,因为它们的时序不同。请使用带有缓冲区的同步算子来同步数据流。
识别算子类型#
VisualApplets 将算子分为三大类。您可以通过设计窗格中的模块图标形状来识别其类型。产品内置帮助和算子参考记录了每个算子的类型。
| 键入 | 形状 | 主要行为 |
|---|---|---|
| O 型 | 圆形:![]() |
|
| M 型 | 方形: ![]() |
|
| P 型 | 方形: ![]() |
|
每个源算子(例如相机模块)都是一个 M 型算子。每个最终目的地(例如 DmaToPC)都是一个 M 型算子。
O 型算子#
O 型算子执行简单的处理步骤。它们遵循以下规则:
- 输出上的像素数量等于输入上的像素数量。
- 输入和输出之间存在恒定数量时钟周期的延迟。必须在时序同步期间补偿此计时延迟。
- 您可以不受限制地将它们串联或并联组合。拆分和合并 O 型管线不需要任何额外的同步。
- 它们本身无法阻塞数据流,但它们会向下游模块传递阻塞条件。
信息
Basler 建议您在算法适用时优先选择 O 型算子。与 M 型算子相比,它们通常使用更少的 FPGA 资源。
M 型算子#
M 型算子执行更复杂的处理。它们遵循以下规则:
- 它们可以更改输入和输出之间的像素数量。
- 它们可以延迟输出。
- 当它们未准备好接受更多数据时,它们可以阻塞输入。
- 连接它们时必须遵守 link 规则。
- 合并源自不同 M 型源的数据流只能通过使用带有异步输入的专用算子(例如
SYNC或SourceSelector)。
相机算子和缓冲区算子始终是 M 类型算子。许多滤波器和同步算子也属于 M 类型算子。
P 型算子#
P 型算子类似于 M 型算子。主要区别在于它们不会主动阻塞输入。此外,它们不会降低链路带宽,也不会生成超过其接收量的数据。它们可用于不可停止的源。
关键术语
流可持续不断地传输,属于 non-stoppable 流。non-stoppable 源无法通过生成的 FPGA 设计的流控制逻辑暂停。典型的例子是持续发送像素的 camera。相比之下,stoppable 流在下一个 operator 尚未准备好时可以暂停。camera 与下游处理之间的 buffer 通常可以将 non-stoppable 流转换为 stoppable 流。
有关 stoppable 和 non-stoppable 数据流的详细信息,请参见 Stoppable and Non-Stoppable Data Streams 教程主题。
除非 Operator Reference 中另有说明,否则相同的 link 规则适用于 P-type 和 M-type operator。然而,与 M-type operator 不同,P-type operator 可与 non-stoppable 源一起使用。
同步和异步输入#
带有多个输入的 M-type operator 接受 synchronous 输入、asynchronous 输入或两者皆可。某些 operator 提供多组 synchronous 输入,这些输入之间可能是 asynchronous 的。产品内置帮助和 Operator Reference 记录了每个 port 所需的输入类型。
同步输入#
许多 operator 要求在其所有输入端口或一部分输入端口上提供同步输入。同步意味着这些输入端的数据流是对齐的:协议、传入像素的数量以及数据的时序必须完全匹配。
当所有输入均源自专通过 O 类型算子网络路由的公共 M 类型源时,可以保证同步行为。只要没有引入其他源(即 M 类型算子),这些输入就可以通过任意数量的 O 类型算子进行连接。
属于同一同步组的所有输入始终共享单个 M 类型源。
一个典型的例子是 RemoveImage 包含来自同一 LineBuffer:

异步输入#
只有少数算子支持异步输入。异步意味着这些输入上的数据流未对齐:时序、协议和传入像素的数量可能会有所不同。异步输入之间可能不同的特定 Property 取决于算子。异步输入还可以通过各自源的 O 类型算子网络进行连接。只能将异步输入用于明确支持它们的算子。这些算子将异步数据流转换为同步数据流。
支持异步图像输入的算子包括:
SYNCInsertLineInsertImageSourceSelector.
FrameBufferRandomRead 和 FrameBufferMultiRoiDyn 也接受异步图像链路,但其坐标输入必须仍然是同步的。
无法使用普通的多输入算子合并两个独立的 M 类型源。为此,您需要一个支持异步输入的算子:

同步规则#
在 O 类型网络中,无论网络复杂度如何,所有 O 类型模块都必须源自同一 M 类型或 P 类型模块。来自此源的链路可以通过其他 O 类型模块或 O 类型子网。
拆分和合并 O 类型流水线非常直接,不需要额外的同步。

当网络中引入 M 类型或 P 类型算子时,它将成为一个新的数据源。如果在下游合并源自不同源的分支,则合并需要同步,即必须添加具有异步输入的算子,例如 SYNC, InsertLine, InsertImage或 SourceSelector。这些分支无法连接到标准的多输入算子。
VisualApplets 会在设计窗格中用 purple links 突出显示 synchronization violations:

此 O-type network rule 确保了 synchronous 输入:属于同一 synchronous 输入组的所有分支必须源自单一的 M-type 或 P-type 源,并且只能通过 O-type operator。
O 类型网络规则不适用于使用 Image Protocol = VALT_SIGNAL。有关更多信息,请参见 信号链路的不同规则 (见《用户手册》)。
合并独立源#
当两个或多个独立源提供一个处理路径时,您必须同步 timing 和 image dimensions。
- Timing synchronization 用于对齐像素到达各个分支的时间。
- Image dimension synchronization 用于对齐宽度、高度和图像协议。
通常使用以下算子来执行同步: SYNC。在某些情况下,还有其他几种同步选项。
定时同步不正确可能会导致死锁、带宽不足或数据丢失。
信息
为避免死锁,当源以不同速度运行或某个分支增加了延迟时,请在 ImageFifo 或 ImageBuffer算子之前放置一个内存算子,例如 SYNC 。必须对内存元素进行适当的尺寸调整:您需要了解预期的延迟,以便选择足够的缓冲区大小。
死锁无法通过 VisualApplets 中的仿真进行可靠检测,只会出现在硬件中。要检测死锁,请监视 FillLevel 算子的 ImageFifo operator 或其他 buffer operator 在 frame grabber 上,例如在 microDisplay X中。保持在 100% 的 FIFO 通常表明死锁的根源。您无法在 VisualApplets 设计窗格中观察到该 Fill 级别。
有关死锁的更多详细信息,请参见 Troubleshooting: Deadlock
合并异步流时,请确保行速率、帧速率和像素速率相匹配。如果一台相机的运行速度比另一台快,缓冲区就会持续填充,直到溢出并丢失数据。当您需要以相同速率从多台相机进行长时间采集时,请使用触发系统。
使用 SYNC 算子进行同步#
即: SYNC 算子可同步所有输入链路上的时序和图像尺寸。输入数量在实例化算子时即已固定。所有输出都是同步的。下游的 O 型算子随后可以处理合并后的流。
即: SYNC 算子的作用类似于所有输入的阀门。它会等待,直到每个输入上都存在有效的像素。然后,它会同时在所有输出上转发像素。
当输入图像的大小不同时, SYNC 对其进行对齐。根据参数设置,它会扩展较小的图像或裁剪较大的图像。请参见 Operator Reference SYNC 中的 operator 说明和 使用 SyncToMin 和 SyncToMax 参数值 小节了解 SyncToMin 和 SyncToMax 行为。
信息
使用 SYNC 仅当相机是同步触发时,才在设计中靠近相机的位置使用算子。否则缓冲区可能会迅速充满。
典型的双相机路径如下所示:

缓冲区可吸收相机之间的时序偏移。如果没有缓冲区且没有 SYNC,设计将面临死锁或 DRC 警告的风险。
有关逐步叠加和拼接的演练,请参见 User Manual 中的 Synchronization of Asynchronous Image Pipelines。
使用 SyncToMin 和 SyncToMax 参数值#
如果源包含 不同大小的图像,请使用 SyncMode 算子的 SYNC 算子来对齐它们的尺寸。您可以在以下值之间进行选择: SyncToMin 和 SyncToMax.
同步功能确保所有输出图像大小相同。 SYNC 算子支持两种模式:
-
SyncToMin:通过裁剪较大的图像,将所有图像对齐到最小的图像尺寸。
-
SyncToMax:通过扩展较小的图像,将所有图像对齐到最大图像尺寸。在SyncToMax模式下,任何额外的区域都用虚拟零像素进行填充(显示为黑色)。
在仿真中,情况如下:
SyncToMin:裁剪幅面较大的图像。

SyncToMax:使用虚拟像素填充幅面较小的图像。

使用 InsertLine 和 InsertImage 算子进行同步#
InsertLine 通过插入来自多个源的行来组合图像。当两个源按顺序提供行时,可将其用于基于行的拼接。
当相机同步触发时,您可以使用较小的 ImageFifo 算子,而不是 LineBuffer 算子。这减少了资源占用。

信息
InsertLine 和 InsertImage 通常与 CONST 算子结合使用。在此背景下, CONST 指定图像或行是否包含在输出流中。数据总是会被处理,但 CONST 决定了它是出现在输出流中还是在内部被丢弃(即发送到内部垃圾路径)。
InsertImage 通过插入来自多个源的图像来组合图像序列。可将其用于将来自两个相机的图像复用到一个输出序列中。

这两个算子均接受异步输入。如果在不可停止的源上使用这些算子,请在其前方放置足够大小的缓冲区以避免死锁。另请参见算子参考手册中的 InsertLine 和算子参考手册中的 InsertImage。
使用 SourceSelector 算子进行同步#
SourceSelector 在多个图像源(例如两个相机)之间进行选择。它在异步源之间切换,同时保持输入图像的完整性。
只有选定的输入会被转发到输出;所有其他输入都会被丢弃。如果在某个输入仍在传输图像时发生切换,则会先完成传输,然后新的源才会处于活动状态。
使用 SelectSource 用于在运行时控制活动源的参数。
算子会在切换到另一个输入之前完成当前帧。当相机提供输入时,设置 InfiniteSource 更改为 ENABLED 。当输入来自带缓冲的、可停止的流时, DISABLED 将其设置为

Basler 建议您使用 IF 或 CASE 而不是 SourceSelector ,当所有输入均来自同一 M 型模块时。这些算子使用的资源更少。例如,请参见以下带有 CASE 算子输出链路上的 Bit Width:

另请参见算子参考手册中的 SourceSelector。
避免同步#
由于用于同步和缓冲的算子会消耗大量的 FPGA 资源,因此应尽可能避免同步。在许多情况下,可以通过应用替代设计技术来实现这一点。这些技术可能包括在所需的 M 型算子之前合并数据,并在之后拆分数据。以下屏幕截图显示了两个类似工作流的实现,一次使用 MergePixel 和 ADD,另一次使用 SYNC:
![]()
故障排除:死锁#
最常见且最难排查的同步错误之一是死锁。
当两个源直接同步时(例如使用 SYNC 算子且没有任何缓冲),就会发生死锁。在这种情况下,每个源都在等待对方:A 等待 B,B 等待 A。结果就是无法传输任何数据。
下图显示了下层路径上的一个分支模块,它接收到了停止信号,因此其输入端不再接收数据。结果,上层路径也停止接收数据,整个流水线随之停滞:

死锁在仿真中通常不可见,系统在仿真中可能表现为正常运行。然而,在硬件上,它们通常会导致没有输出。在这种情况下,硬件 applet 会冻结,停止向 PC 传输数据,并最终导致 DMA 超时。
信息
死锁很难检测,因为它们通常在仿真中不可见。若要识别可能的死锁,请使用诸如 microDisplay X 等运行时工具在硬件中监控 FIFO Fill 级别。保持在 100% 容量的 FIFO 表示可能存在死锁或瓶颈。
死锁的典型原因:
- 缺少缓冲区
- 不正确的同步
如何解决死锁:
要修复死锁,请插入基于 FIFO 的缓冲,例如 ImageBuffer 或 ImageFifo算子之前放置一个内存算子,例如 SYNC 算子。这允许一个源稍微超前运行,并防止相互等待的条件:

使用 DRC 验证您的设计#
在连接合并的分支后,运行分析 → 设计规则检查 1 级。1 级会报告同步违规并用紫色标记受影响的连线。
设计规则检查 2 级会运行扩展检查并估算 FPGA 资源。在生成之前,请修复 1 级中的形式错误。
阅读 DRC 日志以及高亮显示的模块和连线。有关完整的工作流程,请参阅从空设计到运行中的 Applet 教程主题。
相关主题#
- 用户手册中的连线规则 — O 型网络规则和信号连线
- 可停止和不可停止的数据流教程主题 — 无限源和流控制
- Memory 元素 教程主题 — 前端缓冲区
SYNC - 流水线概念教程主题 — 阻塞和反压
- 基础与示例中的异步图像流水线的同步
- 从空白设计到运行 Applet教程主题 — DRC、仿真和生成
- 参数化教程主题 — 汇聚点的连线属性


