01signal.com

电子驱魔: 为什么 FPGAs 有时表现得好像被附身了

当事情变得奇怪时

FPGAs 一般而言是非常可靠的组件,但与任何一项技术一样,如果使用不当,它们将不会做得那么好。

不幸的是,可用的 FPGA design 工具在指导我们人类避免犯错误方面毫无帮助,这往往会导致不可靠和不可预测的结果。更具体地说,只有遵循某些 design practices , FPGA 工具才能保证可靠运行,并且有一个基本假设,即我们知道自己在做什么。与 software compilers不同,如果 source code出现错误则拒绝生成 executable code , FPGA 工具只是说: “这是你的 bitstream,喜欢就试试吧,顺便说一下,这里是 200 warnings,如果你明白 warning #143 是什么意思,你也会明白,有一个严重的问题需要修复”。

使用 FPGAs 的人经常会觉得电子设备被某种魔力所控制,没有任何意义。一个问题可能会因为完全不相关的变化而出现和消失,而且看不到任何合理的解释。许多受过良好教育的工程师倾向于采用关于 FPGAs 的荒谬理论,试图为这种奇怪的行为找到一些解释。

这是“Black Magic 模式”: 当明智的人不再相信对他们的问题有合理的解释时,而是寻找基于他们经验的解决方案。当 FPGA 真的很冷时,一切正常吗?好吧,放一个巨大的 heatsink。问题只出现在某些 boards 上而不是其他 boards 上?好的,测试每个 board,并扔掉那些没有的。等等。

它看起来像什么

这是可能影响工程师进入非理性思维模式的部分问题列表。它总是“一切正常,除非......”

这通常伴随着一种信念,即电子设备本身存在缺陷并且不符合其 datasheet。关于一家大公司如何运送有缺陷的组件的阴谋论并不罕见。

所以这不仅仅是一个错误。确实,虫子可以让人发疯,但它们往往具有某种程度的可重复性,而且它们肯定不会因为空气状况而出现和消失。我从未听过软件工程师将错误归咎于 PC 计算机本身(尽管在极少数情况下实际上是这种情况)。相比之下, FPGA design 中的错误肯定会导致硬件级别的故障。从那里指责整个世界的距离很短。

有一个合乎逻辑的解释。真的。

而且触手可及。不一定容易。

在这个领域做了很长一段时间的自由职业者,偶尔会解决这样的情况,当我告诉你的时候相信我: 除了极少数情况外, FPGA 都很好,问题可能出在 bitstream上。

坏消息是, FPGA design通常存在不止一个缺陷,而这些缺陷可能是造成明显问题的原因。因此,可能有很多事情需要解决。有好几次,我被要求修复“几乎可以工作”的 FPGA design,很快我就意识到我面临着一个不切实际的期望,即“这个小问题”会很快得到修复。稳定 design 通常意味着大量工作而没有任何明显的进展。

这样或那样,别无选择。在本页中,我将尝试通过列出电子设备中出现鬼魂的可能原因来恢复理性思维。

当然,最好的办法是从一开始就避免这种情况。遵循我在不同页面上列出的黄金法则是一个好的开始。

为什么事情变得奇怪

嗯,简短的回答是 FPGA design出了点问题。在这种情况下,原则上有两种可能性。相对幸运的可能性是当 FPGA 应该做的事情出现明显且稳定的故障时。这就像一个软件错误: 找到它,修复它,看看修复后它是否有效,完成。

不太幸运的可能性是 FPGA 可以工作,但这主要是一个幸运的巧合。因此,当某些情况发生变化时, FPGA 会突然停止正常工作,然后可能会恢复正常工作。但是为什么会这样呢?

所以重点是: FPGA 是一种电子产品,因此在制造过程中存在误差。更重要的是,当 silicon 的温度发生变化时, transistors 改变状态的速度也会发生变化,信号在 logic fabric上传播的速度也是如此。 supply voltage 的变化也会影响 FPGA内部发生的事情的速度。

因此,如果 FPGA 变热或变冷,相对于 clock,信号可能会稍晚或稍早到达 flip-flop 。仅此一项就可以让这个 flip-flop 错过它应该采样的信号,或者采样 flip-flop 通常会错过的信号。当 die 上相邻(可能不相关)的 logic 变得更少或更多活动时,即使 silicon 的局部加热也会导致这种情况。

同样, FPGAs 也存在制造误差。尽管出厂的所有 FPGAs 都通过了确保它们与其规格兼容的测试,但某些 FPGAs 可能比其他 silicon 更快。这就是为什么一个制造不当的 logic design 可能在一个 FPGA 上工作而在另一个 FPGA 上不能工作的原因。

所有这些随机参数都会影响 logic fabric上的小组件何时改变其状态,而时间上的差异可能会导致完美运行的东西与灾难之间的差异。因此,制造、温度和电压的微小偏差会产生明显的差异。

那么 FPGA 如何可靠呢?正确制作 FPGA design 后, FPGA design 工具可确保一切始终按定义工作。或者更准确地说,一切都适用于任何已通过制造测试并在 datasheet要求范围内使用的 FPGA 。这归结为使环境温度在所需范围内(必要时进行冷却),以及 FPGA引脚上的正确电压。

但是,如果不遵循所需的 FPGA design 实践,这些工具也不能确保正常运行。这意味着不应该产生任何影响的参数变得至关重要,整个 board 停止工作并恢复工作,这取决于根本不重要的事情。奇怪的事情可以变得没有限制。

因此,冒着重复自己的风险,这里有几个例子:

这值得一遍又一遍地重复: 当 FPGA design 正确完成时,这一切都不会发生。或者至少非常罕见。很少有人意识到当 datasheets 被读取和跟踪时电子设备的可靠性,并且 FPGA 也被正确使用。

但我想这个讲道对于那些阅读这个页面的人来说有点太晚了——问题已经存在了。因此,根据我自己的经验,我列出了 FPGA看似闹鬼的一些常见原因。如果您面临这样的问题,很有可能就是其中之一。

原因1: Timing

很大程度上,这些工具是通过实现你给他们的timing constraints来保证 FPGA 的稳定运行的。这是你和工具之间的交易: 只要 FPGA在其允许的温度和电压范围内运行,您就可以准确地表达时序要求,并且这些工具可以确保在您使用的任何 FPGA 上都能实现这些要求。

timing constraints 只是一个包含 reference clock频率的 constraint并不罕见。这可能已经足够好了,但如果您刚刚从其他 design 复制了这一行并且嘿,它有效,那么就有充分的理由进行审查。

实际上,这是关于正确地做 timing 。这不是一项简单的任务,即使对于最有经验的 FPGA designer来说也是如此。这意味着确保 design 中的每一个 signal path 都由 constraint 控制,以确保最终的 flip-flop 始终正确接收信号。除了那些不需要 constraining的 paths 。

所以首先要检查: design 达到 timing constraints了吗?这是非常基本的,但由于大多数 FPGA 工具无论如何都会生成 bitstream , FPGA newbies 可能会犯这个简单的错误。

接下来是回顾 timing constraints。有一个单独的页面讨论这种检查,但长话短说: 你明白 timing constraints 是什么意思吗?它们的含义是否完全符合其应有的含义?如果有选择性 timing constraints ——也就是说,它们覆盖了一些 paths ,特别是 filter conditions ——它们是否确实适用于正确的 paths?

然后,应该仔细阅读 timing report 。再一次,这个单独的页面详细阐述了这个主题。

另一件值得关注的是 crossing clock domains。是否存在不安全地从一个 clock domain 传输到另一个 clock domain 的信号?这可能是由于缺乏对 logic 与每个 clock相关的关注。 clock domain crossings 是否仅使用由 FPGA 工具创建的 FIFOs 完成?如果没有, crossings 是否正确且安全地完成?

原因2: 不合适的 resets

它可能看起来不相关,但如果不能确保 logic的初始状态,它很可能会导致 black magic 行为。

规则很简单: 如果您还没有认真考虑过 resets 和 logic的唤醒功能,那么您可能弄错了。

特别是,考虑这个例子:

always @(posedge clk or negedge resetn)
     if (!resetn)
       the_reg <= 0;
     else
       the_reg <= [ ... ] ;

如果您对 resets 的看法是编写这样的代码,而没有明确考虑停用 @resetn 时会发生什么(即在此示例中更改为高电平),那么您绝对应该查看此页面

无论哪种方式,最好检查它们应该在的位置是否有 resets ,并且它们是否正常工作。这意味着什么将在有关该主题的一系列简短页面中进行讨论。

原因 3: Clocking

clocks 的品质可能是 digital design中最被低估的话题。它通常就像“是的,它从高到低再变回来,让我们将它用作 clock”。

与 FPGA logic 配合使用的 clocks 应该是稳定的,并且具有足够的 jitter 性能。同样重要的是, clock 与 FPGA 的物理连接必须稳定可靠。

所以在这样的声明中,

always @(posedge clk)

任何用作 @clk 的东西都必须非常小心。理想情况下,此 clock 源自专用 clock generator 组件 (oscillator),可确保 clock 稳定且 jitter较低。一般来说,把这个外接的 clock 当做 reference clock 转 PLL使用比较好,而不是直接连接 logic。即使 PLL 不改变 clock的频率也是如此。

这是因为使用 PLL 可以监控 PLL的 lock detector。因此,当 PLL 解锁时,依赖于该 clock 的 logic 可以保持在 reset 状态。如果 reference clock 出现稳定性问题(特别是在 powerup之后不久),这样做会显着降低出现问题的机会。

PLL 可能会被误认为是麻烦制造者,并且会导致显然不必要的 resets ,因为它偶尔会丢失其 lock 。可以通过移除 PLL 并将外部 clock 直接连接到 logic来错误地“修复”,然后一切似乎工作正常。在这种情况下, reference clock很可能存在问题。在这种情况下移除 PLL 并不能解决问题,而是将其推入 logic fabric,可能导致 black magic 情况。

到目前为止,我已经从专用 oscillators讨论了 clocks ,这确实是一个简单的案例。其他来源会变得更糟: 由 processor 或其外围设备之一创建的 Clocks 应谨慎使用(如果有的话)。这样的 clocks 可以被 processor暂时停止,或者偶尔产生非法的 waveforms 。这可能是因为软件写入相关的 hardware registers,可能是不相关任务的一部分。当用 oscilloscope检查 clock 时,这些短暂的事件可能是不可见的,但这些短暂的事件仍然会导致奇怪的故障。

另一个常见的问题来源是source-synchronous clock处理不当。换句话说,当一个外部元件提供一个 clock 信号和一个或多个数据信号时,使数据与 clock同步。通常数据信号可能仅与 clock的 rising edges 一起更改值(或仅在 falling edges上)。

一种常见但相当危险的方法是将 source-synchronous clock 直接连接到 FPGA内部的 application logic。部分问题在于 source-synchronous clock 通常不打算用作连续的 clock,因此可能会暂时停止或使用 spurious pulses。

另一个可能的问题是 source-synchronous 接口通常通过物理连接器连接到 FPGA ,例如当数据源是通过电缆连接到 main board 的相机时。尽管连接器通常是可靠的,但即使由于振动而失去一纳秒的物理接触也足以导致 clock 信号上出现非法 pulse 。当然,这也可能发生在数据信号上,但通常不太重要,特别是当数据源是相机时。但是当这样的 clock 信号直接连接到 application logic 上时,一纳秒的 pulse 绝对可以搅得一团糟。

因此, source-synchronous与 clock 和数据接口的最佳解决方案是将 clock 和 data 都视为常规信号。因此, source-synchronous clock 和数据信号都使用 flip-flops进行采样,使用速度明显更快且稳定且安全的 clock 。优选地,这是通过与 I/O pins相邻的专用 flip-flops 来完成的。

当 source-synchronous clock 从低电平变为高电平时,这反映在采样此信号的 flip-flop 的 output 中的类似变化。因此, source-synchronous clock 的 rising edges 可以与同步 logic进行检测,通过这个 flip-flop 的 output 由低变为高的简单事实。这个 logic 当然是基于更快更稳定的 clock。当这个 logic 检测到这样的 rising edge 时,它会将数据标记为有效。换言之,包含 data inputs 值的 flip-flops 的 outputs 被标记为有效数据。

这种方法与 01-signal sampling 的明显优势在于,无论 clock 信号发生什么情况, FPGA的 logic 都会继续依赖安全的 clock。如果 source-synchronous clock 发疯,则由 logic 检测 edges 做出充分响应。

对于 source-synchronous clock 的相对较低频率(通常高达 200-300 MHz,取决于 FPGA的速度以及是否使用 DDR sampling ),这种技术是可能的。

对于更快的信号源,首选解决方案是将信号源的 clock馈入 PLL,并将 PLL的 output 与 application logic一起使用。如上所述,当 PLL 指示未锁定时,应重置 logic 。出于不同的原因,这也可能是正确的解决方案: 当 01-signal sampling 的频率像刚才建议的那样太高时,确保 sampling 正确的唯一方法是通过 clock的 phase shifting 找到时间。这意味着 logic 会自动调整时序,直到在采样的信号中没有检测到错误。这种技术无论如何都需要使用 PLL 。

原因#4: 违反 RTL design规则

synthesis 的正确 Verilog 代码(或 VHDL)必须遵循一些严格的规则,尤其是 RTL paradigm (Register Transfer Level)。其中,这意味着作为某种内存(例如 flip-flop)的任何 logic element 仅作为 clock edge的结果更改值。唯一的例外是 asynchronous reset,它不能只是任何信号

当 synthesizer 遇到违反这些规则的 Verilog 代码时,它通常会尝试合作并生成可能与模拟显示的行为不同的 logic 。另一种可能性是 synthesis 的结果大部分时间都满足预期的行为,但它可能会随机失败。

例如,为 0 和 14之间的计数器考虑这个错误的 design :

reg [3:0] counter;
wire      reset_cnt;

assign reset_cnt = (counter == 15); // This is so wrong!

always @(posedge clk or posedge reset_cnt)
  if (reset_cnt)
    counter <= 0;
  else
    counter <= counter + 1;

可怕的错误是将 @reset_cnt 用作 asynchronous reset。

但让我们开始解释它是如何在模拟中工作的: @counter 对 @clk的 rising edges 进行计数。但是当 @counter 达到 15值时, @reset_cnt 变为 '1' 并将 @counter 异步复位为零。因此,当使用 @clk对 @counter 进行采样时,它应该显示 0 到 14的值。

在硬件中,这可能不起作用。问题是 @reset_cnt 是 @counter的 combinatorial function 。因此当 @counter 的值从 7 变为 8 时,计算 @reset_cnt 的 logic 可能会短暂地将 @counter 的值视为 15 。这是因为 7 是 binary code中的 0111 ,而 8 编码为 1000。因此,如果 bit 3 与计算 @reset_cnt的 logic 之间的 propagation delay 最短,则该信号可能短暂为 '1' 。因此, @counter 有时会从 0 计数到 14 ,有时会从 0 计数到 7。温度和其他不相关的因素可能会影响观察到的选项之一。

然而,这个例子为什么是错误的解释被大大简化了。这些工具可以以最具创造性的方式免费实现 combinatorial logic ,因此 clock edges之间几乎可以发生任何事情。工具唯一保证的是信号是稳定的,符合 flip-flops 在目的地(setup time 和 hold time)的时序要求。

因此,除非 logic design 严格遵守有关 RTL design的规则,否则肯定会发生奇怪的事情。

原因#5: 温度和 power supplies

这不是造成麻烦的常见原因,而且很容易检查。然而,温度和 power supplies 可能是奇怪问题的根本原因。

很自然,如果 silicon的温度超出允许范围,则无法保证正常工作。最常见的原因是由于散热计划不足而导致的过热,或者风扇与灰尘作斗争。

至于 power supplies,他们可能会因为各种原因生产出故障的 output 。使用 oscilloscope 进行简单检查通常会显示电压是否在指定范围内。但是请注意,电压应始终保持在此范围内。平均电压正确是不够的: switching power supplies 总是产生的噪音和偶尔的 spikes 都不允许超过限制。

请注意,即使不长于 1 μs 的 spike 看起来是无辜的,但在 FPGA内部却有数十到数百个 clock cycles ,因此这是 FPGA 输入错误电压的重要时间段。最好测量靠近 FPGA 的 decoupling capacitors 处的电压,以查看实际到达的电压。还要确保在上限和下限电压下配置 oscilloscope的 trigger ,并确保 oscilloscope 不会对这些做出反应。在 oscilloscope的显示屏上注意到简短的 spikes 并不容易,但 trigger 会捕捉到它们。

有时 power supply 问题是 board design性能不佳的直接结果。许多 power supply modules 都有一个经常被忽视的 minimal current 。如果这个 minimal current 没有从 power supply module中排出,它可能会变得不稳定并产生不符合其规格的电压,或者更糟糕的是,它可能偶尔会出现 oscillations。

另一个常见的错误是将 switching power supply 放在需要 voltage regulator 的地方。特别是有 low-jitter clock oscillators 需要非常干净的 input。如果这样的 oscillator 由嘈杂的 power supply馈送,则此噪声会反射到 clock output上的 jitter 中。如果 Gigabit transceiver 使用此 clock (例如 PCIe、 USB 3.x、 fiber optics 等),这通常会导致 data link不可靠。

同样,当 DDR memories 是 design的一部分时,需要 reference voltage power supply 。 FPGA 和 DDR memories 都使用此电压作为 '0' 和 '1' 之间在这两个组件之间的电线上的电压阈值。如果这个电压是由 switching power supply产生的,那么 voltage supply noise 可能会使 FPGA 和 DDR memories之间无错误地传输数据变得更加困难,甚至不可能。

原因#6: 你在开玩笑吧?

有时, black magic 情况的原因是一个如此大的缺陷,以至于人们想知道一切是如何工作的。例如,当 PCB 上的接线与相关 FPGA pin完全断开,而正确的信号通过 crosstalk 或 parasitic capacitance到达 FPGA 。

这种情况尤其容易发生在 clocks上,因为它们通常在 board各处布线,而且它们是周期性信号这一事实提高了它们到达 FPGA 的机会,足以让它们看起来不错。

所以无论如何,拿一个 oscilloscope 并检查所有 clocks 尽可能靠近 FPGA。如果 clock有 AC coupling capacitor ,这是一个检查的好地方,特别是因为您可能会发现 capacitor 丢失了。

理由 7: 普通的错误

或者更准确地说: design 从未工作过。从来没有人坐下来弄清楚 logic 是如何确保工作的。相反,代码逐渐用 trial and error编写,部分使用模拟,部分使用硬件。当一切看起来正常时,这个过程就完成了,但看看代码,它的工作似乎是一个奇迹: 因为它已经被修补了很多次来修复那个小东西,所以不可能跟踪正在发生的事情,更不用说进行更改了。

我把这个原因放在最后,因为它不是真正的 black magic 行为。这只是一个非常烦人的错误。然而,这是 FPGA 项目卡住的最常见原因。

如果你仍然认为这是 FPGA的错

有时这不是你的错。 FPGA 本身或供应商的软件中可能存在错误。这种情况发生的频率比人们倾向于责怪 FPGA的供应商要少得多,但在极少数情况下,情况确实如此。

因为责备别人的自然诱惑,请帮自己一个忙,不要通过指责 FPGA来结束驱魔会议,除非您拥有以下两者之一,或两者兼而有之:

如果您在没有任何这些的情况下结束并设法以某种方式解决问题,那么您以后很有可能会再次遇到该问题。

我对 FPGA 本身的错误的最佳示例是很久以前,在 Xilinx的 Virtex-4的 hardware FIFO 上。也就是说, FIFO 的 control logic 直接在 silicon 中实现(即不在 logic fabric中)的 dual clock FIFO 。

通过 FIFO 的数据流时不时地卡住。经过一番调查,发现 FIFO 在正常工作一段时间后,同时保持其 empty 信号和 full 信号处于活动状态。这是非法条件,除非 FIFO 被固定在 reset中,但事实并非如此。因此,在完全确定我观察到了正确的信号之后,我结束了这个案例,得出的结论是存在错误

FPGA的 FIFO。我选择了在 logic fabric 中实现的 FIFOs 。

几个月后,我在这些 FIFOs 上发现了一个 errata record ,除非我事先知道问题所在,否则我是不会理解的。但在仔细阅读描述后,我可以得出结论,它证实了我的观察。

这只是一个例子,说明 FPGA的错误必须有多明显才能将问题声明为“不是我的错”。

概括

当 FPGA 似乎违背自然规律时,人们很容易采用偏离常识的解释。尽管如此,寻找一个合理的解释仍然很重要——而且这种解释通常不需要超级大国就可以找到。

然而,寻找原因可能需要对 design进行彻底的审查,这不一定是一件坏事。这样的狩猎可能令人沮丧,但无论如何它都可能对 design的质量做出重大贡献。

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