介绍
作为 FPGA 设计师需要多种技能,我肯定无法在一页纸上概括。但是有一些与该行业特别相关的一般准则。我试图将它们总结为 FPGA 设计的五个黄金法则。
规则1: 知道你在做什么
这是第一条规则,也是最难遵守的一条。这意味着了解每一行代码、约束(constraint)或配置命令的含义,以及它的含义。它了解逻辑设计的基本理论,以及设计工具如何响应我们提供给它们的东西。
这与反复试验相反,所有高科技开发工具的供应商都通过提供 debuggers、模拟器和大量标榜“很容易”的工具来暗中鼓励这种做法。
通过记下一些东西来开发软件,用 debugger进行测试运行,看看它是如何进行的,修复一些东西并重复,这并不罕见。有时,从 Internet 的示例中找到的代码片段也可能会被复制粘贴到软件中。使用简单的软件,例如开发网站或智能手机应用程序,这种迭代的工作习惯可以相当高效: 小错误并不是那么严重,可以在它们出现时修复,或者常见的态度也是如此。
但是软件越复杂,这种方法导致死锁的速度就越快。而当谈到 FPGA 设计时,迭代开发实践往往会迅速而艰难地反击。 FPGA 设计工具在预防或警告严重错误方面毫无帮助。绝对欢迎您完全搞砸,这些工具不会妨碍您。
规则#2: 保证有效
或者: “它有效”还不够好。
FPGA 是一种电子产品,而不是计算机。如果遵循设计的某些原则,它仍然是可重复和可靠的(参见规则 #1)。如果不是这样,它很可能会出于任何原因或没有明显原因而玩弄肮脏的把戏。
当没有可见的错误时,这并不能证明没有问题——在任何领域都是如此。例如,如果您的水管工完成工作并且管道没有漏水,这并不意味着工作已正确完成。由于水压升高或有人不小心触碰,管道可能会在稍后开始泄漏。
然而,我们都陷入了进行快速测试或更广泛测试的陷阱,并在一切看起来都很好时认为它已经完成。在开发一个简单的网站或什至不是关键应用程序的软件时,这对于漏水的水管来说是相当可接受的。但是对于 FPGAs,这还不够好。
为 FPGA 开发设计意味着保证设计能够正常工作。它迫使设计工具通过使用它们为实现这一确切目标而提供的技术来生产防故障的比特流(bitstream)。
它正在向自己证明,就像数学证明一样,逻辑设计是正确的,而不是试图用“如果发生这种情况,就那样做”的方式来思考。逻辑应该在最奇怪的极端情况下工作,不是因为这些可能性被单独考虑,而是出于同样的原因,正确的数学表达式无论如何都保持正确。
它最终奏效的事实没有理由庆祝。这是正常工作的自然结果。
规则#3: 明智地模拟(或根本不模拟)
FPGA newbies 最常见的抱怨之一是他们的模拟工作完美,因此他们的设计很好,现在其他地方肯定有问题。这当然是胡说八道。
所以首先,让我们摆在桌面上,除非 Verilog 编码风格遵循一些严格的规则,否则模拟和硬件可以做完全不同的事情(当然 VHDL也是如此)。参见规则#1。
但模拟涵盖了有限的时间跨度和场景,即使做得正确。即使使用中型设计,也需要很长时间才能模拟 FPGA 内部发生的情况,比如 100 ms。不仅如此,在硬件上真正运行设计经常会使逻辑暴露于设计师(designer)没有想象到的场景,因此没有模拟。因此,完美通过模拟的设计可能会在硬件上彻底失败,只是因为 FPGA 的运行时间比模拟覆盖的时间长得多,或者发生了意想不到的事情。
更糟糕的是,很难在硬件上找到错误,因为一切都是并行发生的。与软件调试不同的是,很少有一系列事件可以遵循,更不用说执行 single-step的选项了。 FPGA内部当然有跟踪信号的工具,但要弄清楚要跟踪哪些信号以及使用触发器(trigger)收集跟踪数据的条件并不总是那么容易。
因此,尽可能少地使用模拟作为目标。如果您使用模拟来回修复您的设计以“使其正常工作”,那么当您在硬件上尝试它时,您很可能会遇到麻烦。
相反,尝试编写 FPGA 设计从第一次运行就可以完美运行。这需要在编写第一行代码之前进行一些思考,并知道你在做什么(上面的规则 #1)。模拟应该只是确认你做对了,或者可能检测到一些愚蠢的错字。达到这个目标是一个学习和改进的过程,但它是有回报的。最后,模拟变成了浪费时间,因为它永远找不到任何可以修复的东西。
这不仅可以节省时间,而且要在硬件上修复的错误变得更少且更容易发现。
我很清楚 FPGA 设计常见的第一课是“首先我们模拟,然后我们在硬件上运行”,但这对第一课很有好处。
规则#4: Don't push your luck
或者: 坚持完善的编码风格。
Verilog 用于综合(synthesis)时不是一种编程语言。主要区别在于,如果您使用任何编程语言编写语法正确的内容,则编译器(compiler)(或 interpreter)保证完全按照语法含义执行。或者在最坏的情况下,报告一个错误。
另一方面,综合工具(Synthesizers)生成基于有限逻辑单元(logic elements)集的逻辑。因此,很容易在 Verilog 中编写导致逻辑不可靠的代码,甚至是无法在 FPGA上实现的代码。更糟糕的是,如果无法在 FPGA上将 Verilog 代码实现为逻辑,综合工具经常会产生具有不同行为的逻辑。很多时候,综合工具会在不发射 warning的情况下做到这一点。换句话说, FPGA 上的逻辑所做的事情与预期的(即模拟的)行为不同,而在没有 warning的情况下会发生这种情况。
更糟糕的是,综合工具中的错误比编译器中的更常见。创造性的编码风格绝对可以暴露出这样的错误。
当然,上述所有内容也适用于 VHDL 。
因此,避免此类麻烦的唯一方法是采用一种被其他人广泛使用的编码风格。要记住的问题是“如果综合工具被这段代码弄糊涂了,除了我之外,还有多少人会生气?”。如果答案是“很多人”,那么您是安全的。
坚持完善的编码风格还有另一个优势: Portability。不管您喜不喜欢,今天您使用的是一台综合工具,明天您会发现自己使用的是完全不同的 FPGA 和不同的开发工具。
要了解完善的编码风格是什么样的,请查看工具生成的代表工具内置 IPs的 Verilog 代码。代码的不同作者之间存在一些差异,但某些编码模式会比其他模式更常见。那些是模仿的。
几乎不用说,按照 RTL 范式工作。这不仅仅是一种成熟的编码风格,而是 FPGA 工具所期望的。
关于 Verilog 的教科书和教程可能会产生误导,因为它们通常试图做到全面。因此,它们通常涵盖许多语法正确但很少使用的可能性,有时甚至不适合综合。
规则#5: 时间就是一切
逻辑设计不是软件编程。在 Verilog 电线和寄存器(registers)中获得正确的值是不够的,但在正确的时间出现在正确的位置同样重要。此外,时钟处理正确。
这些或多或少是主要主题:
- 考虑数据如何以及何时流经流水线(pipelines)的不同阶段,特别是当流水线可能(完全或部分)停止时。实际上,任何数据流都是如此。
- 确保时序约束(timing constraints)是正确的。特别是,阅读外部组件的数据手册(datasheets)并进行数学计算。本页讨论时序(timing)的检查。
- 注意时钟: 它们从使用的第一刻起就稳定了吗?他们的抖动(jitter)是否足够低以满足他们的目的?
- 跨时钟域(Clock domain crossing): 需要 resynchronization 逻辑吗?如果是这样,它是否保证信号从一 domain 到另一 domain 的无故障传输?更多关于这个here 。
简而言之,与计算机程序不同的是,逻辑设计不仅关乎将要发生什么,还关乎它何时发生。
概括
没有人说 FPGA 设计很容易,这五个规则中没有一个是容易遵循的。他们每个人都需要知识和一定程度的自律。尽管如此,坚持这些规则绝对值得付出努力。这样做可以省去很多挫败感,尤其是在项目的最后阶段,那时一切都可以正常工作。