软件开发
OA系统

扫一扫微信二维码

学数字设计的软件工程师该了解的时钟知识

发布时间2018年07月23日标签:数字,设计,软件,软件工程,工程,工程师,了解,时钟 53
本文由 计算机软件开发 - 听风 翻译,艾凌风 校稿。未经允许,禁止转载!
英文出处:zipcpu。迎接加入翻译组。

假如你有软件工程师背景,想找一份数字设计工程师的工作,那么你必要做的第一件事就是尽可能早的学习时钟概念。对许多从软件工程师转来的初级硬件设计工程师来说,时钟概念都是一件恼人的事情。假如没偶然钟,他们就可以将 HDL(Hardware Description Language,硬件描述语言)转换为一种编程语言,如 $display,if 和 for 循环,如同其他的任何编程语言一样。 然而,这些初级设计师所忽视的时钟,通常是数字设计中最基础的部分。

没有什么时候会比在审查初级 HDL 设计工程师第一次设计的产品的时候,所发现的题目更多。如今,我已经和几位在我参与的论坛上发表过题目的人交谈过了。而当我深入了解后,发现他们正在做的是什么时,我为他们感到很难堪。

以我碰到的一个门生为例北京发光字制作,他不理解为什么网络上没有人正视他的高级加密标准 (AES) 的HDL实现。此处,为了不让他由于名字或项目而难堪,我临时将他称之为门生。(不,我不是教授。)这个“门生”创建了一个 Verilog 设计,进行不止一轮的 AES 加密,但每一轮都是组合逻辑,且两者之间没偶然钟。 我不记得他是在做 AES-128、AES-192 照旧 AES-256,但 AES 必要进行 10 到 14 轮计算。 我记得,他的加密引擎在模仿器中运行完善,然而它只使用一个时钟来加密或解密他的数据。 他为本身的工作感到自大,但不晓畅为什么那些看过这个项目的人都对他说,他的思考体例像一个软件工程师,而不是一个硬件设计师。

事实上,我如今有机会给像这个“门生”一样的 HDL 新手软件工程师诠释迷惑。 他们中的很多人对待 HDL 语言,就像对象另一种软件编程语言一样。 在编程之前,他们去探求任何软件编程语言的基础知识:如何声明变量,如何创建一个 if 语句或 case 语句,如何编写循环等等。然后,他们编写代码就像编写一个计算机程序——统统都是顺序实行(图1),而完全忽略了数字设计中的基本事实,即所有运行都是并行的。

图1:软件实行是顺序的

偶然这些程序员会使用模仿器,如 Verilator,iverilog 或者 EDA 平台。 然后,他们在逻辑代码中使用一堆$ display饬令,将它们视为顺序的“printf”,并通过这些饬令来使代码运行,而不是使用时钟。 他们的设计在模仿器中只是被单独地“实行”组合逻辑代码。

这些门生向我描述他们的设计,并诠释称他们的设计“不必要时钟就能实行”。

天啊,这都是什么想法?

现实上,任何数字逻辑设计假如使用没偶然钟都是不能工作的。总有一些物理过程会创建输入。而 这些输入必须在某个开始时间都有用 ——这个时间在其设计中形成第一个时钟刻度。 同样地,在接收这些输入一段时间后就要输出。 对于给定的一组输入,所有输出的有用时间在“无时钟”设计中形成下一个“时钟”。 或许第一个时钟刻度是当他们调整好电路板上的最后一个开关的时候,而最后一个时钟刻度是当他们读取到效果的时候。时钟是如何形成的没关系:有一个时钟就可以。

而这导致的效果就是,那些声称他们的设计“没偶然钟”的人诠释他正在以不切现实的体例使用模仿器,或者设计中存在一个外部时钟用于设置输入和读取输出 ——而这正是另外一种体例,注解设计中的确存在一个时钟。

假如你发现你本身正试图以这种体例理解数字逻辑必须有一个时钟才能实行,或你熟悉的某人也是这么尝试理解的,那么本文正适合你们。

接下来,让我们花一两分钟来讨论时钟,以及为什么围绕时钟来构建和设计你的数字逻辑很紧张。

第一部分:硬件设计是并行的

硬件设计学习中的第一部分也是最难的部分,就是硬件设计是并行设计。所有的代码指令并不是依次实行,如统一条指令连着下一条指令(如图1所示),就像计算机程序一样。相反,所有的指令在统一时刻实行,如图2所示。

图2:硬件逻辑并行运行

正是这一点,让许多东西变得不一样。

首先必要改变的是开发人员。你必要学习以并行的体例思考。

假如要通过举例说明两者的区别,硬件循环大概会是个不错的例子。

软件设计中,一个循环是由连续串的指令构成,如图3所示。这些指令构造了一组初始化条件,而真正的逻辑在循环内部实行。通过使用一个循环变量来构造和定义一个循环逻辑,并且这个变量在每次循环中通常都是增长的。计算机CPU一直地重复实行循环中的指令和逻辑,直到循环变量达到了停止条件。循环运行的次数越多,它在程序中运行的时间也就越长。

图3:软件循环

而基于硬件的硬件描述语言循环与软件循环完全不同。恰恰相反,HDL 合成工具使用循环来使得所有逻辑的副本同时并行运行。而用来构造循环逻辑的代码,如定义索引、索引增加、检查索引是否达到停止条件等等,是不必要合成的,通常会被移除。此外,因为合成工具正在构建物理线路和逻辑块,所以实行循环的次数在合成时间之后不能改变。之后,硬件的数量是固定的,不能再改变。

导致的效果便是,硬件循环结构(如下图4所示),与软件循环结构(如上图3所示)有很大的区别。

图4:HDL循环

这有几个后果。例如,硬件循环迭代与软件循环迭代不同,它不必依靠前期的循环迭代的输出。这导致的效果是,运行一个包含一组数据的逻辑循环很难在下一个时钟得到相应。

但是…如今让我们再次回到时钟概念。

时钟是任何 FPGA 设计的核心。统统都围绕着它睁开。事实上,我认为所有的逻辑设计开发都应该从时钟开始。时钟不应该在设计完成后添加, 而是在你一开始思考如何设计架构时就要考虑。

为什么时钟很紧张?

第一步,你要理解数字逻辑设计的统统操作在硬件上实行时都是必要时间的。不仅如此,不同的操作必要的时间总量也是不同的。从芯片上的一部分移动到另一部分也要花费时间。

或许用图表的体例能更直观的诠释这一点。我们将输入置于算法的顶部,逻辑放在中心,而输出则放在底部。时间为轴,从上到下运行,从一个时钟到下一个时钟。这种视觉结果看起来就如下图 5 所示:

图5:三个操作的逻辑耗时

图例 5 展示了几个不同的操作:加法、乘法、以及多轮的 AES 算法——尽管为了讨论的目的,它可以是多轮任意其它算法。我在垂直方向上使用了方框的尺寸,以透露表现每个操作可能必要多少时间。此外,将依靠于其它操作的方框堆叠起来。因此,假如你想要在一个时钟里面做许多轮的 AES 算法,你要晓畅第二轮算法在第一轮算法结束后才会开始。因此,适应这一逻辑将会增长时钟之间的时间间隔,并减慢团体的时钟频率。

如今让我们关注这个粉色方框。

这个粉色框透露表现在硬件电路中虚耗的运行能力,即你本可以用来做更多事情的时间,但由于必要等待时钟,或者等待输入被处理,而导致你什么也不能做。例如,在上面的概念图中,完成乘法运算所花费的时间不必要长达一轮 AES 算法的时间,加法也是。然而,当 AES 算法正在实行时,你不能够对这两个操作效果进行任何的动作,由于这些操作都必要等待下一个时钟来获取他们的下一个输入。这就是图 5 中粉色方框所表达的:余暇电路。另外,因为每一轮 AES 算法都会推迟下一个时钟的到来,所以图 5 中存在大量的余暇电路。因此,该设计的运行速度不会像硬件许可的那么快。

假如我们只使用 AES 算法,那么每一个时钟都恰好完成一轮的 AES 计算。如此一来,就可以削减运行能力的虚耗,从而让整个设计运行得更快。

图 6 展示了这种设计思想。

图6:分解操作加快时钟频率

因为我们将操作分解为更小的操作,每一个都能在时钟单元内完成,因此,我们进步了运行能力。甚至,我们可以通过管道加密算法,而不是一次只加密一个数据块。这种逻辑设计的效果不会比上图 5 所示的更快,但是假如可以保持管道充满,则可以进步 AES 加密吞吐量至 10-14x 之间。

所以,这个设计更赞。

还可以有其它更好的方案吗?当然!假如你认识 AES ,你就知道 AES 算法的每一轮计算中都有一些自力的步骤。这些步骤可再次分解,从而可以再次进步每轮逻辑算法的团体时钟速度。而这可以增长你能实行的加法和乘法运算的次数西安人事考试网报名,以及加密引擎的微管道,以便你能在每个时钟的基础上运行更多的数据。

设计不错。

不过,上图 6 中还有些其它的东西。

首先,箭头透露表现路由耽误。(这个数字不是按比例绘制的,它仅仅是这个讨论例子的示例。)每一块逻辑都必要上一块逻辑将效果传递给它。这意味着即使某个逻辑块不必要时间实行——例如,只是重新排列线路或其它等等,将逻辑块从一个芯片的末端移动到另一块也是必要花费时间的。所以,即使你将操作极简化了,每一轮数据的传递依旧存在耽误。

其次,你可能细致到,没有一个箭头的肇端处在时钟刻度上,即没有一个逻辑块一向运行到下个时钟开始。这是为了演示 启动时间和维持时间的概念。触发器电路,即一种捕捉数据并同步到时钟的电路结构,在下一个时钟到达前必要肯定的时间,此刻数据也已经是固定和确定的。另外,尽管时钟通常被认为是瞬时的,但它从来都不是。它在不同的时刻到达芯片的不同部位。而这再次要求操作之间必要一些缓冲。

通过以上讨论,我们可以得出哪些结论呢?

  1. 逻辑实现必要花费时间。
  2. 逻辑越多花费的时间也越多。
  3. 完成两个时钟刻度之间的逻辑所花费的时间总和(包含例行的耽误、启动和维持时间、时钟不确定性等),限定了时钟速度。时钟之间的逻辑处理越多,时钟速率就越慢。
  4. 完成最慢操作所需的时钟速度,限定了最快操作的速度。正如上述例子中的加法操作。它的实行速度本可以比乘法以及任何一轮单独的 AES 算法都更快,但它的速度在该设计中被其余的逻辑拖慢了。
  5. 硬件定义也会限定时钟速度。即使操作中不包含任何的逻辑,也是必要花费时间的。

因此,平衡的设计尝试在整个设计中将大量雷同的逻辑放在时钟之间。

时钟之间应该放多少逻辑量?

如今你已经知道你必须处理时钟,那么根据上述信息你该怎么修改和构思你的设计?答案是限定时钟之间的逻辑数量。但题目是,这个数量是多少呢?你又该如何得到这个数量呢?

得出时钟之间你能放置多少逻辑数量的一个方法便是,将时钟速度设置为任意速度,然后在与你必要的硬件配套的工具套件中构建你的设计。无论何时,当你的设计无法知足其计时需求时,都必要返回并拆分设计中的组件,或减慢时钟速度。通过使用设计工具,你最终能够找到那条最长的路径。

假如你如许做了,你将自学到一些探索方法,然后通过使用这些方法,就可以找到在运行的硬件的时钟之间可以放置的详细逻辑数量。

例如,我倾向于在 Xilinx 7 系列零件中进行 100MHz 时钟速率的设计。这些设计通常运行在大约 80MHz 速率的Spartan-6 上,或者50MHz的 iCE40上——尽管这些都不是硬性关系。把在一个芯片上正常实行的程序放在另一个上实行,可能会超载,亦可能会时钟检查失败。

下面有一些我曾经在使用时钟时得到的一些粗略的探索性经验。因为只是小我经验,这些方法并不适合所有的设计:

1.通常,我在设计一个32 位的加法时,会使用一个时钟内有 4-8个条款的多路复用器。

假如要使用一个较快的时钟,例如频率为 200 MHz,可能就必要将加法操作从多路复用器上剥离下来。

ZipCPU 的最长路径,现实上是从 ALU 的输出到 ALU 的输入。

这听起来很简单。它甚至吻合前面的经验法则。

但 ZipCPU 的题目在于,如何在较快的速度下将输出路由回输入。

让我们跟踪一下这个路径:追随 ALU,逻辑路径首先通过一个4路多路复用器来决定是否ALU,内存或分频输出必要回写。 然后将该回写效果馈送到旁路电路中,以确定是否必要将其立即传入 ALU 作为其两个输入之一。 只有在该多路复用器末端并且旁路路径实行 ALU 操作时,多路复用器才会产生。 因此,所有这些逻辑步骤都会在通过 ALU 时造成压力。 然而,因为ZipCPU的设计结构,任何在此路线的时钟都可能会按比例减缓 ZipCPU 运行速度。 这意味着有可能这条最长线路仍然是 ZipCPU 中最长的一段线路。

我曾经对以更高的速度运行 ZipCPU 感爱好,这是我尝试分解和优化的第一个逻辑路径。

2.16×16位乘法器必要一个时钟。

偶然,在某些硬件上,我可以在一个时钟上运行 32×32 位的乘法。而在其他硬件上,我必要分解这个操作。 因此,假如我必要一个签名的 32×32 位乘法,我使用我专门为此建立的流水线例程。 该例程包含其中的几种乘法方法,许可我从适合我目前正在工作的硬件的选项中进行选择。

你的硬件可能也还支撑 18×18 位乘法。 一些 FPGA 还支撑在一个优化的硬件时钟内进行乘法和累加。只要你对使用的硬件充足认识,你就知道你能用它做什么。

3. 访问任何 RAM 块都必要一个时钟。 假如可以的话,应尽量避免在该时钟周期调整索引。 同样,避免在此时钟期间做任何有关输出的事情。

尽管我认为这是一条很好的规则,但我已经在 100MHz 的 Xilinx 7 系列设备上违背了其中的两个部分,而没有产生(紧张的)影响。 (在 iCE40 设备上有题目。)

例如,ZipCPU 从寄存器读取数据,给效果加上一个即时数,然后从效果中选择是否应该在寄存器、PC上,照旧条件代码寄存器中加上即时数——都在一个时钟内。

另外一个例子就是,长期以来 Wishbone Scope 根据当前时钟是否从存储器进行读取百度关键词排名,确定从缓冲区内读取的地址。 从这个依靠停止它,必要添加另一个耽误时钟,所以当前版本不会再破坏这个(自我强加的)规则。

这些规则只是我随着时间积累下来的方法经验,用来判定单个时钟内可容纳的逻辑数量。 这些经验法则与设备和时钟速度有关,因此它们可能不适用于你的设计开发。 我建议你积累本身的探索经验,以便你知道在时钟周期之间能做些什么。

下一步

大概我能够提供应任何新的 FPGA 开发人员的最后建议,就是学习 HDL 时要在现实硬件上进行演习,而不仅仅是在模仿器上。与现实硬件组件相干联的工具,其在检查代码和计算所需时间方面都很出色。 此外,以高速时钟构建设计的想法是好的LED灯笼,但这不是硬件设计的最闭幕果。

记住,硬件设计是并行的。 统统都从时钟开始。

最后,假如本文有助于你更好地了解HDL,或者它让你更加疑心了,请随时联系告诉我。 这会让我知道,我未来是否有需要再次回来讨论这个话题。 谢谢!