用于设计多异步时钟设计的综合和脚本技术(完善中)

目录

摘要

1.0 简介

2.0 转移性

3.0 同步器

4.0 静态时序分析

5.0 时钟命名惯例

6.0 设计分区

7.0 综合脚本和时序分析

7.1 分组

7.2 识别错误路径

7.3 执行最小-最大时序分析

8.0 将快速信号同步到慢速时钟域

8.1 通过慢速控制信号

9.0 传递多个控制信号

9.1 问题-同时需要两个控制信号

9.2 问题-两个相移的顺序控制信号

9.3 问题-two encoded的控制信号

10.0 数据路径同步

10.1 时钟域之间的握手数据

10.2 通过FIFO在时钟域之间传递数据

10.3 FIFO满和空

10.4 FIFO指针-实现为二进制计数器

10.5 FIFO指针-实现为格雷码计数器

10.6 格雷码计数器的设计

10.7 格雷码到二进制的转换

10.8 二进制到格雷码转换

10.9 格雷码计数器

11.0 FIFO设计

11.1 FIFO写入和读取操作

11.2 悲观的满标志和空标志

11.3 满和空

12.0 仿真问题

13.0 结论

参考文献

作者和联系信息


本文是对Synthesis and Scripting Techniques for Designing MultiAsynchronous Clock Designs的翻译,带有笔者自己的一点理解,有不确定的地方会以蓝色附上原文。

摘要

设计一个纯粹的单时钟同步设计是一种奢侈,很少有ASIC设计师会知道。大多数设计的ASIC都是由多个异步时钟驱动的,需要特殊的数据、控制信号和验证处理,以确保及时完成稳健的工作设计。

1.0 简介

大多数大学课程教授工程学生设计完全同步(单时钟)逻辑的规定技术。在实际的ASIC设计世界中,很少有单个时钟的设计。本文将详细介绍一些硬件设计、时序分析、合成和仿真方法,以解决多时钟设计问题。

本文并非旨在详尽介绍这一主题,而是为了分享从经验中吸取的技术。

2.0 转移性

引用Dally和Poulton关于亚稳态的书[6]:

“当用时钟对不断变化的数据信号进行采样时……事件的顺序决定了结果。事件之间的时间差越小,确定哪一个先发生的时间就越长。当两个事件发生得非常接近时,决策过程可能需要比分配的时间更长的时间,从而发生同步故障。”

"When sampling a changing data signal with a clock ... the order of the events determines the outcome. The smaller the time difference between the events, the longer it takes to determine which came first. When two events occur very close together, the decision process can take longer than the time allotted, and a synchronization failure occurs."

图1-异步时钟和同步故障

图1显示了当在一个时钟域中生成的信号被另一个时钟域的时钟信号采样时,由于该信号变化时刻过于接近采样时钟的上升沿而发生的同步故障。

同步失败是由于输出变为亚稳态,并且在必须再次采样时没有趋于到合法的稳定状态。图2显示了亚稳态输出可能导致非法信号值在设计的其余部分传播。

图2-亚稳态bdat1输出在整个设计过程中传播无效数据

在任何设计中使用的每个触发器都有指定的建立和保持时间,或者在上升时钟沿前后不允许输入数据改变的时间。该时间窗口被指定为设计参数,以精确地防止数据信号与另一个同步信号变化的时间太近,从而可能导致输出变得亚稳态。

图2所示的亚稳态输出问题有时被称为John Cooley ESNUG效应,或者换句话说,不需要的信息的传播!

(开玩笑的,约翰!☺)

3.0 同步器

再次引用Dally和Poulton[7]关于同步器的内容:

“同步器是一种对异步信号进行采样,并输出转换为与本地时钟或采样时钟同步的信号的设备。” 

"A synchronizer is a device that samples an asynchronous signal and outputs a version of the signal that has transitions synchronized to a local or sample clock."

数字设计师使用的最常见的同步器是双触发器同步器,如图3所示。

 

 图3-双触发器同步器

第一触发器将异步输入信号采样到新的时钟域中,并等待一个完整的时钟周期以允许第一级输出信号上的任何亚稳态衰减,然后通过相同的时钟将第一级信号采样到第二级触发器中,目的是使第二级信号现在是同步到新时钟域的稳定且有效的信号。

理论上,在信号被clock(笔者认为是不同时钟域之间信号传输的意思)到第二级以使第二级信号也变为亚稳态时,第一级信号仍然维持亚稳态是可能的。同步故障间隔时间(MTBF)概率的计算是多个变量的函数,包括用于生成输入信号和为同步触发器计时的时钟频率。在Dally和Poulton[8]中可以找到对MTBF计算的一种描述。

对于大多数同步应用,双触发器同步器足以消除所有可能的亚稳态。

笔者注:MTBF计算公式如下

 4.0 静态时序分析

执行静态时序分析是验证设计中的每个信号路径是否满足所需时钟周期时序的过程,无论是否所有信号路径都是可能的。静态时序分析不用于验证设计的功能,仅用于验证设计是否满足时序目标。理论上,时序验证可以通过在设计放置和布线后使用实际时序值的SDF反向注释运行详尽的门级仿真来完成。这通常被称为动态定时验证。

与动态时序验证相比,静态时序分析有三个主要优势:

(1)静态时序分析工具验证任何两个顺序元素之间的每条路径

(2)静态时序分析不需要任何测试向量的生成

(3)静态时序分析工具比试图通过详尽的门级模拟进行时序验证快几个数量级[4]。

在完全同步的设计中使用Synopsys工具进行时序分析相对容易,无论是在Synopsys design Compiler或design Analyzer环境中使用DesignTime,还是使用PrimeTime。

具有两个或两个以上异步时钟的模块的时序分析容易出错,难度更大,而且可能很耗时。对从一个时钟域生成并锁存到第二个异步时钟域内的序列元件中的信号进行静态时序分析是不准确的,并且在大多数情况下是毫无价值的。由与锁存信号异步的时钟锁存的信号的定时信息是不准确的,因为信号和异步时钟之间的相位关系总是在变化;因此,静态时序分析工具将不得不检查信号和异步时钟之间的无限数量的相位关系。事实是,必须假设在某个时刻从一个时钟域传递到另一个时钟域的信号将违反目标序列元件的建立或保持时间。

没有充分的理由对在一个时钟域中生成并在另一个异步时钟域register(显示?)的信号执行时序分析。假设这些信号确实违反了目标寄存器上的建立和保持时间。这就是为什么需要同步器(见第3.0节),以缓解信号从一个时钟域传递到另一个时钟域时可能出现的问题。

对于具有两个或两个以上异步时钟作为输入的RTL模块,将需要设计者向静态时序分析工具指示应忽略哪些信号路径。这是通过在从一个时钟域到另一个时钟域的信号上“set_false_path”来实现的。除非遵循下面两节中的指导原则,否则这可能是一项乏味且容易出错的工作。

5.0 时钟命名惯例

指南:使用时钟命名约定来识别设计中每个信号的时钟源。

原因:命名约定有助于所有团队成员识别设计中每个信号的时钟域,还可以使用综合脚本中的regular(正则)表达式“wild-carding”更容易地对用于时序分析的信号进行分组。

各种设计团队已经使用了许多有用的时钟命名约定。1995年,设计工程师在为in-Focus投影仪设计视频ASIC时使用了一种方法,该方法要求使用最前面的前缀字符来识别各种异步时钟域。示例包括:uClk用于微处理器时钟,vClk用于视频时钟,dClk用于显示时钟。

每个信号都与设计中的一个时钟域同步,并且每个信号名称必须包括标识该信号的时钟域的前缀字符。由uClk计时的任何信号都将在信号名称中具有u前缀,例如uaddr、udata、uwrite等。由vClk计时时的任何信号在信号名称中将类似地具有v前缀,例如vdata、vhsync、vframe等。相同的信号命名约定用于由设计中的任何其他时钟生成的所有信号。

使用这项技术,ASIC设计团队中的任何工程师都可以很容易地识别设计中任何信号的时钟域源,并直接使用信号或通过同步器传递信号,以便在新的时钟区域内使用。

仅命名约定就大大提高了设计团队的生产力。我们怎么知道生产力提高了?其中一名设计工程师使用自己的命名约定开始了ASIC设计,忽略了其他设计团队成员使用的约定。在对进入和离开他的设计分区的信号感到困惑之后,召开了一次团队会议,“强烈鼓励”不合规的设计师重新命名他设计部分的信号,以符合团队命名惯例。

在更改了信号名称之后,可以更容易地连接到有问题的分区。更改后出现的问题和困惑更少。

6.0 设计分区

指南:每个模块只允许使用一个时钟。

原因:静态时序分析和创建综合脚本更容易在单个时钟模块或单个时钟模块组上完成。

指南:为从一个时钟域传递到另一个时钟域的每组信号创建一个同步器模块。

原因:任何信号从一个时钟域传递到另一个时钟域都会出现建立和保持时间问题。同步器模块无需进行最坏情况(最长时间)时序分析。在第一级和第二级触发器之间只需要最佳情况(最小时间)时序分析,以确保满足所有保持时间。此外,门级模拟可以更容易地被配置为忽略每个同步器的第一级上的建立和保持时间违例。

图4-按时钟边界划分的设计

1995年,在研究用于In Focus投影仪的多异步时钟ASIC设计时,我收到了Steve Golson的电子邮件,他在邮件中强烈建议我在ASIC设计中每个模块只允许使用一个时钟[5]。当时,我们允许每个模块有多个时钟,并试图通过在综合脚本中包含大量set_false_path命令来处理时序分析,以消除无效的时序错误消息。

在考虑了Steve的建议后,我决定完全重新划分我正在进行的ASIC设计,并坚持每个模块只允许一个时钟的建议。我花了两周的时间重新划分整个ASIC。在重新划分设计之后,许多时序分析和综合任务变得微不足道。

通过将设计划分为每个模块只允许一个时钟,静态时序分析变得非常容易。

笔者注:该技术可以在综合脚本中节省大量的set_false_path命令,以消除无效的时序错误消息。

下一个逻辑步骤是对设计进行划分,使得每个输入模块信号在进入模块之前已经同步到同一时钟域。为什么这么重要?如果所有进入和离开模块的信号都与模块中使用的时钟同步,那么设计现在是完全同步的!现在,整个模块可以在没有任何“false_path”的情况下进行静态时序分析,设计编译器可以用于对所有相同的时钟同步模块进行“group”,以在每个时钟域内执行完整的顺序静态时序分析。

上述建议有一个例外。多时钟设计需要至少一些RTL模块将信号从一个时钟域传递到在不同时钟域内计时的模块。对于In Focus ASIC设计,我们创建了单独的同步器模块,允许来自一个且仅一个时钟域的信号传递到将信号同步到新时钟域中的模块中。

使用第5.0节中描述的命名约定,所有处理器时钟生成的信号(u信号)将被用作可能由视频时钟计时的模块的输入。这个模块被称为“sync_u2v”模块,RTL代码只不过是获取每个u信号输入,并通过一对由vClk计时的触发器运行它。除了vClk和复位输入,“sync_u2v”模块的每个其他输入信号都有一个“u”前缀,来自同一模块的每个输出信号都有“v”前缀。

不需要对“sync”模块进行最坏情况下的时序分析,因为我们知道这些模块的每个输入信号都会有时序问题;否则,我们就不必通过同步器传递信号。我们需要在同步器模块内执行的唯一时序分析是每个信号的第一和第二触发器级之间的最小时间(保持时间)分析。

通常,如果有n个异步时钟域,则设计将需要n(n-1)个同步器模块,每对时钟信号两个(例如:使用uClk和vClk信号:所需的两个同步器模件将是sync_u2v和sync_v2u)。只有当没有信号在两个特定时钟域之间通过时,才不需要一对同步器模块。

顺便问一下,重新划分的In Focus ASIC设计发生了什么?在修改所有RTL文件以创建完全同步的模块或同步器模块之后,生成合成脚本的任务变得微不足道。以前包含“set_false_path”命令的所有脚本文件要么被删除,要么被显著简化。所有的时间问题都很容易识别和解决(因为它们都在单时钟域分组内),最终合成运行比预期提前两周完成,使项目重新按计划进行,并完全证明了重新划分设计的决定是合理的。

7.0 综合脚本和时序分析

遵循第6.0节的指导方针,每个模块只允许一个时钟,要求进入非同步器模块的所有信号也在用于为该模块计时的同一时钟域中,并要求同步器模块只允许来自一个其他时钟域的输入信号,有助于简化与多时钟设计相关联的时序分析和综合脚本任务。

用于解决多个时钟域问题的综合脚本命令现在变成了分组、识别错误路径和执行最小-最大时序分析的问题。

7.1 分组

将在每个时钟域内计时的所有非同步器模块分组在一起。在设计中,应为每个时钟域形成一个组。将对这些组进行时间验证,就好像每个组都是单独的、完全同步的设计一样。

7.2 识别错误路径

通常,只有同步器模块的输入需要“set_false_path”命令。如果使用时钟前缀命名方案(见第5.0节),则可以使用通配符来轻松识别所有异步输入。例如,sync_u2v模块的输入应该全部以字母“u”开头。以下dc_shell命令应该足以从时序分析中消除所有异步输入:

set_false_path -from { u* }

7.3 执行最小-最大时序分析

每个时钟域的每一组模块现在都是完全同步的子设计,可以使用DesignTime或PrimeTime等工具来验证最坏情况下的时序(包括建立时间检查)和最佳情况下的时序(包括保持时间检查)。

同步器块被单独地验证时序。不需要最坏情况下的时序检查,因为这些模块仅由触发器组成以同步异步输入信号;因此,不存在长路径延迟,并且输出被完全register。在所有异步输入上设置错误路径之后,进行最佳情况(最小)时序验证,以确保从第一级同步触发器传递到第二级同步触发器的所有信号都满足保持时间。

8.0 将快速信号同步到慢速时钟域

与同步器相关的一个普遍问题是,来自发送时钟域的信号在被采样到较慢时钟域之前可能会改变两次值。在信号从一个时钟域发送到另一个时,必须考虑这个问题。

将较慢的控制信号同步到较快的时钟域中通常不是问题,因为较快的时钟信号将对较慢控制信号采样一次或多次。认识到将较慢信号采样到较快时钟域比将较快信号采样到较慢时钟域引起的潜在问题更少,设计者可能希望利用这一事实并尝试将控制信号引导到较快时钟域。

8.1 通过慢速控制信号

当在时钟域之间传递一个控制信号时,如果遵循其他规则(如下所述),则简单的双触发器同步器通常就足够了。

当试图将控制信号从较快时钟域传递到较慢时钟域时,出现该规则的例外,控制信号必须比较慢时钟的周期时间宽。如果控制信号仅被拉高一个快速时钟周期,则控制信号可能在较慢时钟的上升沿之间变高和变低,并且不会被捕获到较慢时钟域中,如图5所示。

 图5-同步期间错过的较短的控制信号脉冲

这个问题的一个潜在解决方案是在超过采样时钟周期时间的一段时间内使控制信号有效,如图6所示。假设控制信号将被接收机时钟至少采样一次,并且可能采样两次。

图6-保证控制信号采样的加长脉冲

这个问题的第二个潜在解决方案是拉高控制信号,将其同步到新的时钟域,然后将同步的信号通过另一个同步器返回到发送时钟域作为确认信号。尽管同步反馈信号是一种非常安全的技术,可以确认第一控制信号已被识别并采样到新的时钟域中,但在释放控制信号之前,在两个方向上同步控制信号存在相当大的延迟[2]。

 

图7-控制信号的反馈同步 

9.0 传递多个控制信号

工程师在进行多时钟设计时经常犯的错误是,在将多个控制信号从一个时钟域传递到另一个时钟域时,忽略了控制信号排序的重要性。简单地在所有控制信号上使用同步器并不总是足够好,如以下示例所示。

如果控制信号的顺序或对准是重要的,则必须注意将信号正确地传递到新的时钟域中。本节中显示的所有示例都过于简单,但它们与实际设计中经常出现的情况非常相似。

9.1 问题-同时需要两个控制信号

在图8所示的简单示例中,新时钟域中的寄存器需要加载信号和使能信号才能将数据值加载到寄存器中。如果负载信号和使能信号都是从一个时钟域发送的,则控制信号之间的小偏差可能导致两个信号在新时钟域内被重新同步到不同的时钟周期中。在本例中,这将导致寄存器中的数据无法加载。

 图8-问题-在时钟域之间传递多个控制信号

图9-解决方案-在时钟域之间传递控制信号之前合并控制信号

这个简单例子中的问题的解决方法很简单。如图9所示,drive both the load and enable register input signals in the new clock domain from just one control signal. This will remove the potential for the control signals arriving shifted in time.

9.2 问题-两个相移的顺序控制信号

图10中的图表显示了两个使能信号aen1和aen2,它们用于使数据信号能够通过短管道设计顺序传递。问题是,在第一个时钟域中,aen1控制信号可能会在断言aen2控制信号之前稍稍终止,而第二个时钟域可能会尝试在此微小时间间隔的中间对aen1和aen2的控制信号进行采样,从而导致在第二个钟域的启用控制信号链中形成一个周期间隔。这将导致a2输出信号被第二触发器错过。

图10-问题-在时钟域之间传递顺序控制信号

如图11所示,该问题的解决方案是只向新的时钟域发送一个控制信号,并在新的时钟域内生成第二个相移的顺序控制信号。

 

 图11-解决方案-在新时钟域中生成正确顺序信号的逻辑

9.3 问题-two encoded的控制信号

图12-问题-时钟域之间传递的encoded控制信号

图12中的图表显示了two encoded控制信号在时钟域之间传递。如果two encoded信号在采样时略微偏斜,则可能在新时钟域中的一个时钟周期内产生错误解码输出。

如图13所示,这个问题的一个潜在解决方案是发送一个shaped的使能信号,作为新时钟域中的“就绪标志”。发送时钟域必须在asserting the decoder inputs后一个时钟周期generate and enable signal。发送时钟域还必须在de-asserting the decoder inputs之前的一个时钟周期移除使能信号。The sending clock domain must also remove the enable signal one clock cycle before de-asserting the decoder inputs.如前所述,使能信号必须在比接收时钟域的周期时间更长的时间段内被确定为有效。

 图13-解决方案#1-同步和波形使能脉冲在时钟域之间传递的逻辑

在最坏的情况下,the shaped enable signal will either be sampled at the same time as the encoded inputs are sampled into the receiving clock domain, or the shaped enable signal will be de-asserted at the same time as the encoded inputs are de-asserted in the receiving clock domain.在最佳情况下,the shaped enable pulse will be asserted one receiving clock cycle later than the assertion of the encoded inputs and de-asserted one receiving clock cycle before the de-assertion of the encoded inputs.这种方法确保encoded输入在被启用到接收时钟域之前是有效的。

A second potential solution to this problem, as shown in Figure 14, is to decode the signals back in the sending clock domain and then send the decoded outputs (where only one of the outputs is asserted) through synchronizers into the new clock domain. Within the new clock domain, a state machine is used to determine when a new decoded output has been asserted. If there are no decoded outputs, it means that one decoded output has been de-asserted and that another decoded output is about to be asserted. If there are two asserted decoded output signals, the last decoded output signal will cause the state machine to change states and the older decoded output signal will turn off on the next rising clock edge in the new clock domain. It is important that the sender insure that the decoded outputs are each asserted for a time period that is longer than the cycle time of the receiving clock domain.

图14-解决方案#2-检测从不同时钟域传递的独热码控制信号的FSM逻辑

任何时候,当有多个控制信号跨越时钟边界时,必须注意确保所传递的控制信号的顺序是正确的,或者控制信号的任何潜在的错误顺序都不会对设计的正确操作产生不利影响。

10.0 数据路径同步

将数据从一个时钟域传递到另一个时钟域是在时钟域之间传递多个随机变化信号的示例。使用同步器来处理数据传递通常是不可接受的。使用同步器对多位数据变化进行错误采样的机会太多了。

时钟域之间同步数据的两种常见方法是:

(1)使用握手信号在时钟域之间传递数据

(2)使用FIFO(先进先出存储器),使用一个时钟域存储数据,并使用另一个时钟域检索数据。

10.1 时钟域之间的握手数据

数据可以使用两个或三个握手控制信号在时钟域之间传递,这取决于应用场景和设计工程师的偏执狂。当涉及到握手时,使用的控制信号越多,将数据从一个时钟域传递到另一个时钟域的延迟就越长。使用握手的最大缺点是传递和识别每个传输的数据的所有握手信号所需的延迟。

对于许多开放式数据传递应用场景,一个简单的双线握手序列就足够了。发送器将数据放置在数据总线上,然后将“data_valid”信号同步到接收时钟域。当“data_valid”信号在新的时钟域中被识别时,接收器将数据clock到新时钟域的寄存器中(数据应该在发送时钟域内至少有两个上升沿是稳定的),然后通过同步器将“acknowledge”信号传递给发送器。当发送器识别出同步的“acknowledge”信号时,发送器可以更改驱动到数据总线上的值。

在某些情况下,使用第三个控制信号“ready”可能是有用的,该信号通过同步器从接收器发送到发送器,以指示接收器确实“ready”接收数据。当“data_valid”信号为有效时,不应使“ready”信号有效。当“data_valid”信号被无效时,可以将“ready”有效信号传递给发送器。当然,随着不断添加握手信号,同步和识别第三控制信号的等待时间会更长。

10.2 通过FIFO在时钟域之间传递数据

在时钟域之间传递数据最流行的方法之一是使用FIFO。双端口存储器用于FIFO存储。一个端口由发送器控制,发送器每个写入时钟将一个数据字(或串行应用的一个数据位)放入存储器。另一个端口由接收器控制,接收器每个读取时钟从存储器中取出一个数据字。两个控制信号用于指示FIFO是空的、满的还是部分满的。经常使用两个附加控制信号来指示FIFO是几乎满还是几乎空。

理论上,用一个时钟将数据放入shared memory,并用另一个时钟从shared memoryremove数据,这似乎是在时钟域之间传递数据的一个简单而理想的解决方案。在大多数情况下是这样,但生成准确的满标志和空标志可能很有挑战性。

10.3 FIFO满和空

确定FIFO是满的还是空的需要某种类型的数学操作and/or写入和读取指针的比较。问题是,这两个指针是在两个不同的时钟域中生成的,因此在安全地执行数学和比较操作之前,必须将一个或两个指针同步到另一个时钟区域。

10.4 FIFO指针-实现为二进制计数器

任何必须同步到不同时钟域的FIFO指针都不应实现为二进制计数器。

二进制计数器的一个特征是,所有顺序二进制递增的一半操作要求两个或多个计数器位必须改变。尝试将二进制计数器同步到新的时钟域比尝试将多个控制信号同步到新时钟域更成问题。如果一个简单的4位二进制计数器从地址7(二进制0111)变为地址8(二进制1000),则所有四个计数器位将同时改变。

如果同步时钟边缘位于该转换的中间,则可以对任何4位二进制模式进行采样,并将其同步到新的时钟域中,如图15所示。

图15-采样的二进制计数值in mid-transition

新的同步二进制值可能会触发假满或假空标志,或者更糟的是,它可能不会触发真满或真空标记,导致数据因FIFO溢出而丢失,或者导致在FIFO真空时试图读取数据而导致从FIFO读取假数据。

10.5 FIFO指针-实现为格雷码计数器

尽管二进制计数器可以很好地寻址内存,但尝试将二进制计数器同步到新的时钟域是有问题的。在时钟域之间传递指针的更好方法是为两个FIFO指针使用格雷码计数器。格雷码计数器一次只改变一位。如果同步时钟信号出现如果同步时钟信号出现在格雷码计数器转换的中间,则同步值要么是旧值,要么是新值,因为一次只改变一个位。

10.6 格雷码计数器的设计

格雷码计数器的方框图如图16所示。为了设计格雷码计数器,使用寄存器来存储格雷码值。寄存器输出被反馈到格雷码-二进制转换器,二进制值增加1,然后增加的二进制值被传递到二进制-格雷码转换器,该转换器驱动格雷码寄存器的输入。

图16-格雷码计数器框图

10.7 格雷码到二进制的转换

为了将格雷码值转换为等效的二进制码值,以n位格雷码值为例,二进制位0等于格雷码位0与从1到n的所有其他格雷码位的异或。

二进制位1等于格雷码位1,与从2到n等的所有其他格雷码位互斥。二进制最高有效位恰好等于格雷码最高有效位。4位格雷码到二进制转换的方程式如图17所示。

图17-4位格雷码到二进制转换方程

对格雷码-二进制转换器进行编码的最简单方法是用for循环进行编码,并对具有可变索引范围的格雷码向量进行异或归约,其中每次通过循环,索引范围的LSB都会增加,直到我们只剩下bin[MSB]=^gray[MSB:MSB](仅格雷码向量的1位MSB)的简单赋值,如示例1所示。

module gray2bin_bad (bin, gray);
 parameter SIZE = 4;
 output [SIZE-1:0] bin;
 input [SIZE-1:0] gray;
 reg [SIZE-1:0] bin;
 integer i;
 // Syntax Error - variable index range
 always @(gray)
 for (i=0; i<SIZE; i=i+1)
 bin[i] = ^(gray[SIZE-1:i]);
endmodule

示例1-不能用但概念上正确的格雷码到二进制Verilog模型

不幸的是,Verilog不允许使用可变索引范围进行部分选择,因此示例1中的代码虽然在概念上是正确的,但不会编译。

笔者注:verilog2001中加入了generate,使示例1可以被编译。generate具体用法不做赘述。

另一种考虑格雷码到二进制转换的方法是使用填充的0来异或有效的格雷码位,如图18所示。

图18-4位格雷码到二进制转换方程-第二种方法 

该算法的相应参数化Verilog模型显示在示例2中。这个例子在语法上是正确的,可以编译并且确实有效。

module gray2bin (bin, gray);
 parameter SIZE = 4;
 output [SIZE-1:0] bin;
 input [SIZE-1:0] gray;
 reg [SIZE-1:0] bin;
 integer i;
 always @(gray)
 for (i=0; i<SIZE; i=i+1)
 bin[i] = ^(gray>>i);
endmodule

示例2-参数化和校正格雷码到二进制Verilog模型

10.8 二进制到格雷码转换

为了将二进制值转换为等效格雷码值,以n位二进制值为例,格雷码位0等于二进制位0和位1的异或。格雷码位1等于二进制位1和位2的异或等。格雷码最高有效位恰好等于二进制最高有效位。4位二进制到格雷码转换的方程式如图19所示。

图19-4位二进制到格雷码转换方程

对二进制到格雷码转换器进行编码的最简单方法是对简单的连续赋值进行编码,该赋值在二进制矢量和同一二进制矢量的右移版本之间执行逐位异或运算,如示例3所示。这个例子在语法上是正确的,可以编译并且确实有效。

module bin2gray (gray, bin);
 parameter SIZE = 4;
 output [SIZE-1:0] gray;
 input [SIZE-1:0] bin;
 assign gray = (bin>>1) ^ bin;
endmodule

示例3-参数化二进制到格雷码Verilog模型

10.9 格雷码计数器

格雷码计数器的Verilog代码包含一个格雷码到二进制转换器、一个二进制到格雷码转换器,并在转换之间增加二进制值。格雷码计数器的参数化Verilog模型如示例4所示。

module graycntr (gray, clk, inc, rst_n);
 parameter SIZE = 4;
 output [SIZE-1:0] gray;
 input clk, inc, rst_n;
 reg [SIZE-1:0] gnext, gray, bnext, bin;
 integer i;
 always @(posedge clk or negedge rst_n)
 if (!rst_n) gray <= 0;
 else gray <= gnext;
 always @(gray or inc) begin
 for (i=0; i<SIZE; i=i+1)
 bin[i] = ^(gray>>i);
 bnext = bin + inc;
 gnext = (bnext>>1) ^ bnext;
 end
endmodule

示例4-参数化格雷码计数器Verilog模型

11.0 FIFO设计

注:更新后的FIFO设计文件可在Sunburst design网站[1]上找到,建议参考本节中的FIFO设计说明。读者应复习参考论文。

当在两个不同的时钟域之间传递数据时,FIFO或先进先出存储器是大多数工程师的首选设计块。图20显示了FIFO设计的框图。

图20-FIFO框图-按时钟边界划分

11.1 FIFO写入和读取操作

就本文而言,FIFO写入操作是将数据字加载到FIFO中的操作。FIFO写入操作有时被称为FIFO填充、FIFO加载等。

就本文而言,FIFO读取操作是从FIFO中删除数据字的操作。FIFO读取操作有时被称为FIFO排出等。

由于满标志和空标志是由指针生成的,其中至少一个指针必须同步到另一时钟域中,所以时钟周期准确assertion and de-assertion满标志和空闲标志是not completely possible

一种FIFO设计技术是确保在满或空条件发生时准确地assert满或空标志,但de-assert标志可能会晚几个时钟周期。这有时被称为悲观的满标志和空标志。

11.2 悲观的满标志和空标志

悲观满标志是一个满信号,当FIFO变满时立即变为有效,但在晚些时候变为无效(直到几个读取时钟周期后才变为无效)。

因为在测试满状态之前不必同步写指针,所以当FIFO满时,将立即使满标志有效。FIFO实际上可能没有完全满,因为读指针可能已经增加,但新的读指针值可能没有同步到写时钟域。使用图20所示的框图,同步到写入时钟域的读取指针总是比实际读取指针值晚两个写入时钟,因此可能会有两个额外的写入时钟使满标志有效。这通常不是问题,因为满标志只是在两个额外的写入时钟周期内阻止来自数据发送源的更多数据的传输。由于第10.4节和第10.5节中解释的原因,被同步到新时钟域中的指针应该是格雷码计数器。

类似地,因为在测试空条件之前不必同步读取指针,所以当FIFO变空时,空标志将立即被设为有效。FIFO实际上可能不是完全空的,因为写入指针可能已经增加,但新的写入指针值可能尚未同步到读取时钟域。使用图20所示的框图,同步到读时钟域的写指针总是比实际写指针值晚两个读时钟,因此可能会有两个额外的读时钟使空标志有效。这通常不是问题,因为空标志仅仅通知数据接收器数据还没有准备好发送的时间多了额外两个读取时钟周期。同样,由于第10.4节和第10.5节中解释的原因,被同步到新时钟域中的指针应该是格雷码计数器。

11.3 满和空

当两个指针相等时,FIFO已满。当两个指针相等时,FIFO也是空的,因此FIFO指针应该比寻址整个内存范围所需的大一位。额外的位被用作标志,以帮助确定FIFO是空的还是满的。如果额外的指针MSB相等,则意味着FIFO指针已回绕到地址0的次数相等,如果其余FIFO位相等,则FIFO为空。如果额外的指针MSB不相等,则意味着写入指针比读取指针多回一次地址0,如果其余FIFO位相等,则FIFO已满。

12.0 仿真问题

如第4.0节所述,通过同步器跨越时钟边界的信号将经历建立和保持时间违例。这就是为什么在设计中添加了同步器,以滤除在新时钟域时钟信号的上升沿附近变化的信号的亚稳态效应。

当在多时钟设计上进行门级仿真时,触发器的ASIC库模型用建立和保持时间表达式进行建模,以匹配实际触发器的时序规范。ASIC库通常对触发器进行建模,以在发生时序违规时驱动触发器输出X(未知)。当仿真门级同步器时,建立和保持时间冲突可能会导致ASIC库发出建立和保持时序错误消息,并且冲突信号经常被驱动到X值。当试图验证整个门级设计的功能时,这些X值传播到设计的其余部分,从而导致问题。

大多数Verilog仿真器都有一个忽略所有定时检查的命令选项,但这也会忽略设计其余部分所需的定时检查。

对于同步器中使用的任何ASIC库触发器,都可以将建立和保持时间设置更改为零,但这将导致同一类型触发器的所有实例的所有建立和保持时间检查都设置为零,包括您可能想用来测试其余设计的触发器。

您可以从ASIC库中复制触发器,并将其存储到具有不同名称的新Verilog库中,将所有建立和保持时间设置为零,然后修改设计门级网表,用修改后的库触发器替换所有第一级同步器ASIC库触发器,而无需时序检查,但这可能是一个容易出错且乏味的过程,每次生成新的网表时都必须重复,或者每次生成新网表时可能需要创建makefile和脚本来自动进行修改。

Bhatnagar[3]提出的解决这个问题的一个聪明方法是使用Synopsys命令修改设计中仅第一级触发器单元的建立和保持时间的SDF反向注释。Bhatnagar指出,SDF文件是基于实例的,因此更容易实现针对违例cell的建立和保持时间。Bhatnagar指出:与其手动从SDF文件中删除建立和保持时间构造,更好的方法是将SDF文件中的建立和保持次数清零,仅针对违例的触发器,即用零替换现有的建立和保留时间编号。

Bhatnagar进一步指出,设置保持时间为零意味着不可能存在时间冲突,因此不会将未知信息传播到设计的其余部分。Bhatnagar给出的以下dc_shell命令用于使建立和保持时间为零:

set_annotated_check 0 -setup -hold -from REG1/CLK -to REG1/D

对同步器的第一级触发器的输出使用创造性的命名约定可以使通配符表达式能够使用很少的dc_shell命令轻松地对所有第一级触发器SDF设置进行反注释并将建立和保持时间设为零。

13.0 结论

完全同步的单时钟设计技术是众所周知的。综合工具在同步设计方面做得最好。时序分析工具被设计用于报告单时钟同步设计的时序问题。单时钟同步时钟的综合脚本很容易设计创建。本文中的技术旨在使设计看起来像多个单个时钟设计!

• 划分非同步器块,使每个模块只有一个时钟,通过创建时钟域子块,可以更容易地使用静态时序分析工具验证,从而可以轻松地验证正确的时序。

• 对同步器块进行分区,以允许来自一个时钟域的输入,并仅用一个异步时钟对信号进行clock,从而创建可管理的同步器子块,也可以轻松time

• 面向时钟的命名约定有助于识别需要在不同异步时钟域内time的信号。

• 跨越时钟域的多个控制信号需要特别注意,以确保所有控制信号正确地排列到新的时钟域中。

本文中描述的技术是为了促进多块设计的robust开发和验证而开发的。

参考文献

[1] Clifford E.Cummings,“异步FIFO设计的仿真和综合技术”,SNUG 2002(Synopsys用户组会议,加利福尼亚州圣何塞,2002年)用户论文,2002年3月,也可在www.sunbst-Design.com/Papers上获得

[2] 第281号法令http://www.deepchip.com/posts/0281.html

[3] Himanshu Bhatnagar,高级ASIC芯片合成,Kluwer学术出版社,1999年,第202-203页。

[4] Samir Palnitkar,Verilog HDL,数字设计与综合指南,Sunsoft出版社,1996年,第193页。

[5] 史蒂夫·戈尔森,个人交流。

[6] William J.Dally和John W.Poulton,《数字系统工程》,剑桥大学出版社,1998年,第468页。

[7] William J.Dally和John W.Poulton,《数字系统工程》,剑桥大学出版社,1998年,第462-513页。

[8] William J.Dally和John W.Poulton,《数字系统工程》,剑桥大学出版社,1998年,第469-470页。

作者和联系信息

Cliff Cummings是Sunburst Design,Inc.的总裁,是一名独立的EDA顾问和培训师,拥有23年的ASIC、FPGA和系统设计经验,13年的Verilog、SystemVeriliog、综合和方法学培训经验。

Cummings先生自1994年以来一直是IEEE 1364 Verilog标准小组(VSG)的成员,是唯一一位共同开发和合著IEEE 1364 Verifog标准、IEEE 1364.1 Verilog RTL综合标准、Accellera SystemVerilog标准和IEEE 1800 SystemVerilog标准的Verilog和SystemVerilog培训师。

Cummings先生拥有杨百翰大学的BSEE和俄勒冈州立大学的MSEE。

Sunburst Design,Inc.提供Verilog、Verilog-Synthesis和SystemVerilog.培训课程。欲了解更多信息,请访问www.sunbst-design.com网站。

电子邮件地址:cliffc@sunburst-design.com

这篇论文的更新版本可以从网站上下载:www.sunbst-design.com/papers

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值