本文转载自: FPGA技术联盟
1、数字系统
开头我们先来说说一个典型的同步电路。可能有很多其他形式,但一个简单的例子足以说明。图1展示了同步电路的形式和时序。
一个值得提及的问题是:到底为什么要使用同步电路?异步逻辑(组合逻辑)不是更快速吗?这个问题的答案有很多,这里只提重要的几点:
同步电路消除了不同路径之间由于速度差异导致的问题。通过一个确定的时间间隔采样来实现的同步电路,使得快路径和慢路径可以以一种相同的形式完成采样;
同步电路不太受电压、温度和压力等外部因素的影响,这使得大规模的工业生产称为可能;
许多的设计被要求具备良好的移植性--也就是说,要非常容易地适应新的技术或者某种改进的技术(比如,从90nn到65nn)。同步电路的确定性行为使其更容易实现技术移植;
同步电路可以简化不同时钟域之间的接口。异步接口通常需要复杂的握手协议来保证数据的完整性;而同步电路自身就已经携带了时序信息,这使得数据可以被方便且正确地互相传递。
同步电路是由组合逻辑和一些时钟元素组成的,比如触发器和寄存器。时钟元素共享同一个时钟,所有的数据传递都发生在时钟的上升沿(或者下降沿,上升沿还是主流)。当上升沿到来时,寄存器把逻辑值从输入D端传递到输出Q端。
Setup Time(建立时间)—Tsu:建立时间是指数据输入在时钟上升沿到来之前必须保持稳定的时间。 Hold Time(保持时间)—Th :保持时间是指数据输入在时钟上升沿到来之后必须保持稳定的时间。
2、时钟
时钟在同步系统种是最重要的因素。下面是两个对时钟所提出的要求。
3、好的状态机设计
同步设计中一个非常强大的武器是状态机(万物皆可状态机)。结合组合逻辑和许多寄存器,状态机能够根据其输入和当前状态做出决策。
状态机的行为是完全同步的,所有决策都是在时钟转换时做出的。状态机有两种传统形式:Mealy状态机和Moore状态机。这些状态机的特性如图2所示。
Moore状态机是两种状态机中较简单的一种。输出只是当前输入的函数。Mealy状态机的输出是当前状态加上输入的函数。
这个额外的路径提供了更多的灵活性,但可能会使对机器的理解复杂化。
Moore状态机/Mealy状态机有什么问题?
图2显示了状态机的Mealy和Moore形式的输出都是当前状态的组合解码,在Mealy形式中是输入的组合解码。虽然这在原则上是好的,但这里有陷阱等着粗心的人。
状态机的输出可能包括以下类型的功能:
锁存使能(低或高脉冲打开或关闭锁存)
三态使能(在片内或片外总线上打开和关闭驱动程序的信号)
寄存器启用(启用同步时钟寄存器)
其他一般控制信号,如计数器启用、标志等。
大多数这些信号都有一个共同的特点——毛刺在任何时候都是绝对不可接受的。当状态寄存器和Mealy或Moore状态机的输入转换时,组合逻辑可能由于门传播延迟的变化而产生毛刺。这些短暂的毛刺很可能包含足够的能量来打开锁存器、时钟寄存器,以造成非常严重的影响。
格雷码不能解决问题吗?
格雷码是一个非常好的设计,因为其每次转化都只有一个bit的变化,这很好地避免了毛刺对状态机转换带来的影响,看起来格雷码似乎与状态机是绝配。但是不要忘了,格雷码每次只有1bit变化的特性是有条件限制的--即转化只能发生在相邻两位。
比如从6跳转到7,或者反之,这样的转化格雷码会只有1bit的变化,但是从6到8则格雷码的变化就不止1bit了。现在的设计越来越复杂,状态机的状态通常都是几十上百,且不同状态之间的跳转及其复杂,这使得不相邻数字状态之间的跳转已成为常态!这无疑让格雷码作用大打折扣!
一个更好的状态机设计
4、同步输入和状态机的复位
复位信号通常是异步的,直接链接到到状态机寄存器的复位端。当复位时,所有寄存器(状态位和输出位)立即被清除。一切都很好,但是当复位被取消时会发生什么呢?
试想一个状态机,它将在取消复位后直接从复位状态转换到其他状态。如果复位在时钟边缘附近解除,那么一些状态位将假定它们的新状态,而另一些可能不会。
5、非法状态--状态机的灾难
对状态机状态的编码有时候并不会用到所有的状态,比如一个有20个状态的状态机,通常会用5个bit来编码,而5bits最大可以有2^5=32个状态,那么其中剩下的32-20=12个状态就是不会用到的非法状态(dead states)。
6、跨时钟域设计
将数据从一个时钟域送入到另一个时钟域是困难的,建立时间和保持时间违规,亚稳态问题,不可靠的数据和其他危险等都有可能发生。实际上,整个同步问题都值得专门写一篇文章来讨论。
现在有A、B两个不同的时钟域。我们不对时钟A/B做任何假设,只设定其为分别独立的两个不同时钟。
我们需要从时钟域A到时钟域B发送一个选通信号(Strobe A-B)和数据(Data A-B),作为回应,接收一个从时钟域B到时钟域A的选通信号(Strobe B-A)和数据(Data B-A)。彼此之间的信息传输必须绝对可靠。为了实现这一点,我们将研究跨时钟域问题的几个方面。
同步
跨时钟域之间的问题与异步输入的问题有些类似。因为不同时钟域之间并无整数倍的关系可循,所以实际上应将其视为一对异步信号,这样就可以用处理异步输入的办法来解决跨时钟域问题,典型方法如图5(即打两拍):
单点信息
假设A块需要向b块发送2bits信息,我们可以简单地复制图5中的电路,每个bit对应一个同步电路。但有一个很严重的问题需要明确:有时会出现一个bit通过了两级同步电路,而另一个bit没有通过的情况。解决方案如图4所示,使用从a块到B块的单bit选通信号,并分别发送其他信息。从A到B的单点选通通知目标块数据A-B有效,初始块确保有足够的建立时间。
切换交换
一个不用担心电平和脉冲宽度的双向握手的好方法是使用切换交换协议。如图6所示。
在这种情况下,通过选通信号Toggle A-B来指定此时传递的数据Data A-B有效,Data B-A的传递同理。如图7所示。
7、锁存器
在创建一组时钟元素时,通常有一个令人信服的理由使用基于锁存器的设计。用锁存器实现的单位寄存器可能只使用传统D型触发器所需的60%的逻辑门。
锁存器关闭时,锁存器的Q输出是稳定的。当锁存器打开时,输入被连续地复制到输出。锁存器在两个潜在的陷阱:
输入端毛刺:锁存器D输入上的任何毛刺都会直接传播到输出。当然,通过确保输入上没有任何毛刺,这是可行的。然而,在同步系统中,总线往往在时钟边缘切换状态,锁存器使能通常跨越时钟传输从而容易产生毛刺。
使能端毛刺:也许比锁存器输入端的毛刺更糟糕的是使能线上的毛刺。如果一个锁存器使能毛刺是异步解码的结果,那你的设计可真是太棒了!本文的第一部分讨论了如何消除毛刺。
基于寄存器的设计没有上面列出的任何缺点。竞争条件很少甚至不存在,控制或D信号上的毛刺不太可能造成伤害,信号可以在一个时钟周期内可靠地锁存住。
基于寄存器的设计可能比基于锁存的设计更大,但它更健壮。如果你一定要用锁存器,那就要小心了!
8、竞争
这是竞争条件的一个经典例子:第一个触发器的输出发生变化时的过渡很可能违反第二个触发器的保持时间。
如果两个触发器的时钟之间存在偏差,则这种情况可能会恶化;如果触发器B的时钟滞后于A的时钟,那么B的输出实际上可能会复制A的输出,而不是增加所需的额外时钟延迟。图10显示了如何修复该问题:
通过在传输路径上增益一个延迟元件确保触发器B在A的转换结果到达B之前有足够的时间完成它的转换。
9、可测试性
如果一切顺利,那么你的芯片将进入量产阶段,全世界(或至少股东们)将为此感到高兴。要做到这一点,你的设计必须要经历严格的测试。可测试性是许多设计中被忽视的一个方面。这里有一些建议可以帮助测试工程师在晚上睡得更好。
把大位宽计数器分成多个小位宽计数器
异步反馈路径是犯罪
即使不考虑它对测试工程师的性格的影响,使用异步反馈的逻辑通常也是不好的,原因有很多。它很难模拟,它很可能依赖于电压、温度和过程,它可能非常容易受到瞬变的影响。
同样糟糕的是,它可能不能够在固定频率的测试仪器上进行测试。如果在你的设计中存在未锁定的反馈路径,确保它们能够从测试人员那里被打破和分析。当然最好是不好使用异步反馈路径。
我们很容易说“我只要快速设计,然后在仿真中找到BUG。”这是一个坏主意,从一开始就注定要失败。模拟器因隐藏设计的古怪细节而臭名昭著。例子包括:
同步触发器不断与亚稳态和故障输入作斗争。它们的行为甚至不能接近你的一般模拟器;你只看到时钟边缘有一个清晰的过渡。从最初阶段开始,跨时钟域的设计必须始终正确。
类似的方式,异步逻辑通常模拟得很差。当然,快速路径和竞争条件可能是隐藏的。一些环境将确定(和可选地纠正)保持时间违反,但这不是正确异步逻辑的万能药。
健壮设计的唯一解决方案是从一开始就正确地进行。你的逻辑必须是:
每一个门,每一行VHDL或Verilog,必须完全理解。不要指望某组模拟会发现你的bug;你可能会忽略测试你设计的一部分,如果它设计得很草率,它就会失败。
有纪律的布局也会使你的设计更加健壮、可理解和可维护。不应该需要通过大量难看的代码或杂乱的逻辑门来理解函数的操作。有组织的门、注释代码和完整的附带文档将为可靠的设计提供基础。
总结
所有的状态机输出都应该是时序逻辑输出(registered)
使用寄存器,别使用锁存器
状态机的输入包括复位都应该被同步
小心数据传递路径上的竞争
提供最好的时钟
一定要小心地进行信号的跨时钟域传递--记得同步
状态机中不要有非法状态
不要使用异步逻辑的反馈路径
小心创建解码逻辑--避免异步逻辑
别过分相信仿真器