现在以及过去的四分之一世纪中,实际上大部分数字设计都是基于使用全局时钟信号,以时钟信号控制系统中所有部件的操作。它的优点显而易见:在一个理想的全局时钟的控制下,只要电路的各个功能环节都实现了时序收敛,整个电路就可以可靠的实现预定的功能。
1.1同步电路设计
1.1.1同步电路的定义
所谓同步电路,即电路中的所有受时钟控制的单元,如触发器(Flip Flop)或寄存器(register)都由一个统一的全局时钟控制。如图1.1所示,触发器R1和R2都都由一个统一的时钟clk来控制时序,在R1和R2之间有一堆组合逻辑,这就是一个最简单的同步电路。
图1.1 最简单的同步电路
由时序图可见,触发器R1、R2的输出Q1、Q2只有在时钟上升沿处才会改变其值,而在其他时刻寄存器的输出值都保持不变。这种触发方式我们通常称作时钟上升沿触发,相应的触发器R1、R2被称作上升沿触发器,此时序电路称作上升沿触发时序电路;同样,只要
我们选用不同触发方式的触发器组成电路,我们可以得到下降沿触发时序电路。
在实际电路设计中,根据不同的需求,我们既可以用到上升沿触发的时序电路,又可以用到下降沿触发的时序电路,甚至两者兼用。不过一般情况下在同步电路设计中,我们推荐使用统一的触发方式。
1.1.2 同步电路的时序收敛问题
时序电路的一个首要问题就是时序收敛问题。 在同步设计中,所谓时序收敛,就是保证触发器输入端的数据在时钟信号的有效沿就达到稳定状态,即满足了触发器的建立时间(setup time);同样也保证了触发器输入端数据在时钟有效沿过后的一段时间内保持稳定,即满足触发器的保持时间(hold time) ;图示见图1.2。
(1) Setup time
(2) Hold time
(3) Transition time
图 1.2 setup time, hold time 和 transition time
以图1.1为例,第一级触发器R1的输出Q1在T0上升沿后得到新值,Q1值经过一段组合逻辑后输出连接到下一级触发器R2的输入端D2,经过这段组合逻辑必然要有一段延时
Tdelay输出才能最终稳定,假设触发器R2建立时间为Tsetup2,所谓满足时序收敛首先要满足时钟周期T 〉= Tsetup2 + Tdelay;同样为了保证D2在T1时刻的值能够被无误地锁存,其值必须在一段称作hold time的时间段Thold内保持稳定。这样整个同步电路就可以可靠无误的运行下去。
要保证整个电路时序收敛的确是件复杂而庞大的任务,可幸的是,IC设计发展到今天,设计同步电路时,我们已经可以用RTL来描述同步电路了,这样,在完成了同步电路系统的RTL代码后,只要设定一些合理的约束(如时钟周期值),综合软件DC不但可以完成RTL到物理标准单元库的映射,还可以很方便实现电路的收敛。
进一步地,后端的STA工具,也可以对布局布线之后的电路检查时序收敛情况,以保证同步电路的有效性。
值得一提的是,既然同步电路中控制电路动作的是一个全局的时钟信号,那么这个全局的时钟信号的周期数必须足够大,大到足以让电路中最长的时序路径收敛。在这里,这个最长的时序路径我们可以简单的看成电路中类似图1.1结构的由第一级触发器Q1端经一段组合逻辑到第二级触发器D2延时最长的一段。
1.1.3 同步设计的优点与缺陷
1.1.3.1 同步设计的优点
在功能上,同步电路设计方式具有很多的好处:
z 在同步系统中,只要电路系统在时序上完全收敛,电路设计中令人头疼的竞争和
冒险现象,得到了有效的避免。
z 由于触发器只有在时钟边缘才改变取值,这就很大限度的减少了整个电路受噪声
影响的可能。
在工程上,同步电路之所以如此受欢迎,这跟它得到EDA软件的广泛支持不无关系,正如前面提到的综合软件DC和STA工具,正是有了它们,同步设计才能在今天的数字设计中大行其道。
1.1.3.2 同步设计的缺陷
同步设计并不完美,也有一些问题一直困扰着同步设计者。 其中,最为令人头疼的是时钟偏斜问题(clock skew)。
同步设计成功有一个很重要的前提,就是所有信号在同一时钟跳变沿发生动作。但是在芯片或电路上,要做到这一点却不是那么简单。
图1.3 时钟偏斜问题示意图
如果没有经过处理,全局时钟线到达各个时序元件的时钟端的路径就不可能相同,如图1.3所示,clk到达触发器R1 clk1端的路径小于到达触发器R2 clk2端的路径。这样就得到图1.3所示的时钟波形。我们称这种时钟到达时间在空间上的差别叫做时钟偏斜(clock skew)。
时钟偏斜造成的后果是非常严重的,试想如果clk2和clk1的时钟信号的偏差足够大,它可能会造成整个同步电路发生同步失败。
除了时钟偏斜,同步电路还受到时钟抖动(clock Jitter)的影响,,所谓时钟抖动指的是,芯片某一给定点上时钟周期的暂歇性变化,即时钟周期在不同的时间端可能长短不一。
有关时钟偏斜和时钟抖动的细节详见参考文献[1]。
不过,如今的EDA软件对以上提到的同步电路的缺陷都给予了很好的解决。
比方说,时钟偏斜可以通过用Astro长时钟树的方法解决。而且现在的EDA软件在施加约束的时候也都考虑了时钟抖动等问题。
由此,更能感到EDA软件对同步电路设计的推动作用。
1.1.4 同步电路设计与全异步电路设计
提到同步电路设计,就不能不谈全异步电路设计。
全异步设计跟同步设计最大的不同就是它的电路中所有操作的定时不是通过时钟来实现的。
在同步电路中,在一个全局时钟的控制之下,所有的时序单元在同一上升沿发生动作,前一级的触发器把当前值传递给下一级触发器;而后在下一个时钟跳变沿,时序单元再次同时发生动作,下一级触发器再把它在上一时钟沿得到的钱一级触发器的输出值传递给它的下一级触发器……如此循环下去,就在电路上实现了操作的定时。
在全异步电路中,电路中基本单元的值可以在任意时刻发生跳变,如图1.4是将时钟clk1控制下的电路输出连接到时钟clk2控制的电路的示例。虽然它不是完全意义上的异步电路,但是也可以说明问题。D2的输入端的数据值的跳变并不是在clk2的控制之下,它可能在时钟clk2的任意时间点发生跳变。
图1.4 异步电路示意图
由此可见,在全异步设计中,原来同步设计的避免竞争冒险现象、减少噪声影响的优点就都没有了。不但如此,要实现异步电路模块之间的交互只能通过复杂的握手原理。
而且目前所有的EDA软件都是基于同步设计思想,在如今动辄百万门的设计规模下,很难想象没了EDA软件,设计工作如何进行。
看起来异步设计似乎一无是处,但事实上跟同步电路相比异步电路还是有它的优点的: 在同步设计中必须维持一个全局的时钟到整个电路的时序元件的时钟端,随着如今电路规模的指数级增长,维持这个全局时钟高速翻转的功耗实际上已经成了芯片系统功耗的很大一部分。在低功耗设计越来越得到IC设计者关注的今天,无需全局时钟的异步设计再一次得到了他们的关注。
此外由于同步设计中必须保证整个系统的时序收敛,这就可能因为某个小环节的速度而影响到整个系统的时钟频率的提升,这在人们对芯片处理能力需求越来越高的今天的确时有发生。
因此,随着技术的进步,也许某一天全异步设计也会在如今的商用芯片上占据很大的一席天地。
1.2异步时钟信号交互的问题及其RTL解决
1.2.1介绍
如前一节所述,在ASIC设计中,我们通常采用的是同步时钟的设计方法:在一个理想的全局时钟的控制下,只要电路的各个环节都实现了时序收敛,整个电路就可以可靠的实现预定的功能。这看起来很理想,但是,实际上,用一个统一的时钟来设计一个系统或一块SOC的思想是不可能。 在现实中,无论是一个系统或一块soc中,总是会存在一些低速的设备,跟cpu或core相比它们运行在一个较低的频率上。以PC的北桥芯片为例,它需要负责CPU和内存、显卡及南桥芯片的数据交换,CPU是工作在自己的数GHz的频率,它跟北桥芯片通信是基于自己的远远高于PCI总线的前端总线,内存、显卡和南桥芯片则是工作在的数百兆的频率上,因此北桥芯片一个重要功能就是处理好不同时钟原信号的同步问题。同样,在SOC中,让一些诸如UART、SSI之类低速设备工作在系统总线的高速时钟频率下,既不实际,也造成不必要的功耗浪费。
在应用中,就算强行让所有的设备或模块都工作在同一时钟频率下,也会使为了满足最慢设备或模块的速度而使系统不得不工作在相对较低的频率下,这样显然降低了系统性能。 由此可见,在实际中,完全采用同步的设计方法,既不现实也不经济。异步与同步设计在整个系统或SOC中不可避免的会采用到。
值得注意的是,这里所谓的异步设计并不是前一节所说的IC设计中的全异步设计方法,这里的异步设计针对的是对工作在不同时钟频率下同步电路之间交互问题的处理。
1.2.2 首要问题 :亚稳态
在同步设计中,只要设计中的所有路径满足了时序收敛,整个同步电路就可以可靠无误的运行下去,这些都是同步设计本身所能保证的——都可以通过EDA工具做到。 但是,在包含多个时钟的同步设计中,我们却不能保证这一点。
1.2.2.1 亚稳态现象揭秘及危害
为了说明这个问题,首先介绍几个约定俗成的术语 通常,我们把两个或多个彼此不同频率的时钟称为不同时钟;把两个彼此上升沿不对齐的时钟称作彼此异步时钟,两个不同的时钟不一定是异步时钟,因为他们可能是来自同一参考时钟的分频,两者的相在理论上是严格对齐的;将处于某个时钟控制下的信号或模块称作在工作在某个时钟域下;将处在异步时钟的模块简单说成工作在异步时钟域。 异步时钟域的信号之间不可避免地需要交互,一般的,我们把需要传输到一个不同于它所在时钟域的信号相对于目的时钟域称作异步输入信号(或异步信号)。
图 1.5 亚稳态示意图
[2]
如图1.5所示,信号adat在aclk时钟域;它相对于bclk异步输入信号;aclk、bclk称为异步时钟;adat和bdat1工作在不同时钟域下。 因为处在异步时钟域的信号之间缺乏统一的定时机制,它们都会按照自己所在时钟控制下改变取值,而且每个信号在改变取值的时候都需要一段时间(所谓的transition time,转变时间,见图1.2)。由图1.5的波形图可见,异步信号adat的下降沿正好发生在bclk时钟的上升沿附近,这样就违反了触发器的建立时间或保持时间,从而第二个触发器锁到一个不确定的值,这个值可以是1,也可以是0,更有可能是一个物理上的不定态x。我们把这种违反了触发器保持或建立时间且使触发器锁存到一个无效电平的状态称作亚稳态现象。
值得一提的是,这个不定态x和逻辑上的x并不是同一个概念。逻辑上的x指当前寄存器的值为未知,我们不知道它是1还是0,但能肯定它在物理上是个有效的电平。而亚稳态中出现的不定态x却不一样了,它实质上是因为触发器输入端的信号的电平没有达到触发器内物理器件的有效电平的噪声容限内,导致由接成反馈回路的两个反向器构成的触发器稳定在非有效电平处的第三稳定点。这就可能使后续的电路对此信号产生不同的解释,后续电路可能会把这个信号解释为正确的电平,也有可能解释错误。
这个解释错误又是什么意思呢?
我们知道在ASIC中所有的标准单元都是使用的CMOS工艺,它是由PMOS和NMOS的处在不同的导通关断产生高低电平来区别0和1的状态,而且P管和N管不可能同时处于导通状态,见图1.6。而亚稳态现象的时候却打破了这个原则。最简单的情况,以后续电路为反向器为例,正常的时候D端为1,N管导通,P管关闭,Q端输出为0;当D端为0,P管
导通,N管关闭,Q端为1。现在当D端的输入信号没有达到有效电平的噪声容限的时候(它稳定后的值是1),这时可能会出现P管和N管同时导通或同时截止的现象,这是一个没有定义的状态,既不对应于逻辑0也不对应于逻辑1;更糟的是,这个状态可能会继续往下传播,造成后面的电路的完全功能失效。
D Q
图
1.6 CMOS 工艺Inverter
由此可见,异步信号直接连到异步时钟的触发器输入端的时候不但可能传输一个错误的逻辑信号(信号实际值是1但是异步触发器采到的是0,或反之),更有可能使触发器进入亚稳态现象并将其传播下去,造成严重的系统错误,见图1.7。
事实上,由上面的分析也可见到,亚稳态现象除了会造成系统的错误之外,还会造成非常大的系统功耗损失(双管同时导通产生极其大的泄漏电流)。
图 1.7 亚稳态信号的传播
[2]
1.2.2.2 亚稳态问题的解决及其RTL实现
事实上,由于如今的ASIC都是在超深亚微米的工艺下制成的,电路中的线与线之间不
可避免存在串扰,而亚稳态状态在微小噪声的作用下就可能偏离此状,因此亚稳态现象在现实电路中维持的时间实际上可以说微乎其微。
而且根据Jan M.Rabaey在《数字集成电路设计透视》第一版影印版P534-538中分析得出,只要在采到异步信号后等待足够长的时间,处在亚稳态的触发器就会回复到一个有效的电平状态上去。而这个延时通常通过在采样异步信号的触发器后再加入一级触发器来实现,也就是说,异步信号只有在经过目的时钟域的两级触发器采样后,才会对目的时钟域的后续电路起作用。这样的由双触发器构成的异步信号采样逻辑被称作同步器(synchronizer)。
图1.8 亚稳态现象的解决
[2]
由图1.8可见,虽然第一级触发器在采样异步信号的时候可能进入亚稳态,但是经过一个时钟周期的延时,当第二级触发器采样其输出端信号时,它已经回复到一个有效电平的稳定状态,从而第二级触发器不会再出现亚稳态,从而防止了亚稳态在整个电路中的传播。
其RTL实现如下: module synchronizer ( bclk, //目的时钟,跟aclk异步时钟 reset_b, //全局异步复位信号 adat, //异步输入信号,工作在aclk bdat, //同步器输出 ); input bclk;
input reset_b; input adapt; output bdat;
wire bdat;
reg bdat1; reg bdat2;
always @ (posedge bclk or negedge reset_b) if (reset_b)
{bdat2,bdat1} <= 2’b0; else
{bdat2,bdat1} <= {bdat1,adat};
assign bdat = bdat2;
endmodule 值得注意的是,完全解决亚稳态现象的方法是不存在的。触发器可能正好采到输入信号的变化中点,从此点回复到稳定电平的状态所需要等待的时间为无穷大。这样,第二级触发器同样将采到第一级触发器输出的亚稳态电平而处在亚稳态状态。
但是事实上实际电路的极其小的噪声或环境的变化都会使触发器脱离亚稳态。所以只要满足了足够大小的等待时间,亚稳态问题出现的可能性就可以减小到在工程中可以忽略或接受的地步。 如果系统的工作频率过于高,系统采到亚稳态的本能性就会增大,此时两级触发器构成的同步器不足以解决亚稳态问题,必须通过增加同步器触发器的级数来延长等待时间的方法来解决,带来的代价是异步信号的交互会带来更大的延时。
1.2.3 常见的异步控制信号的同步问题及其RTL实现
从本质上说,亚稳态问题是异步信号连入到目的时钟域固有的问题,它是由同步电路设计的内在机理所造成,正是因为其的不可避免性,可以称它为异步时钟信号交互的物理(或固有的)问题。
在前一节的基础上,我们现在可以撇开亚稳态现象,从逻辑上来考虑一下异步时钟域信号交互所带来的问题。
在这里,我们把异步信号采样到目的时钟域的动作简称为同步。 异步时钟域之间的信号交互无外乎两种类型:控制信号和数据信号。 通常数据信号的同步总是伴随着控制信号的同步,因为我们总是在控制信号的通知下才能知道当前时候数据总线上的数据是否有效。更何况数据的读写总要伴随着读、写、选通等控制信号。因此,在这一节里我们首先谈谈异步控制信号的同步。
1.2.3.1 快时钟同步慢时钟域下的异步控制信号
在这里可能发生的问题是,异步控制信号虽然在自己的慢时钟域内只维持了一个时钟的有效时间,而在快时钟域中,可能已经被采了好几次了。假设这是一个异步读操作请求信号,那么在目的时钟域内,就有可能把这一次读请求误以为是多次读请求。
原始信号
RTL处理后
图 1.9 快时钟同步慢时钟信号示意图
如图1.9所示,clk_slow下的两级触发器rd_en_s2f1和rd_en_s2f2构成的同步器同步clk_slow的信号rd_en。图中clk_fst上升沿1处正好跟rd_en的上升时间重合,所以rd_en_s2f采到的是0而不是1,同样在clk_fst上升沿4处正好又跟rd_en的下降时间重合,所以rd_en_s2f1采到的是1而不是0;因此,在快时钟域clk_fst中,rd_en_s2f一共维持了3个时钟的有效时间,如果不加处理的话,可能clk_fst端的电路会误以为这是三次读操作。
显然,应该在设计上避免这种错误的发生。
这个问题需要在系统定义的时,对接口信号动作的做出规定:
1.跨越不同时钟域的信号只有一个在电路功能上有效的(asserted)电平 (1.1) 2.此信号有效后,在第二次有效前必须回复到无效的状态 (1.2) 这两个规定实际上是相辅相成的。以图1.9为例,rd_en为1有效,在一次有效后它回到了无效状态0。
满足了这两点在RTL上,我们可以作相应处理,仍以图1.9的例子。 module synchronizer ( clk_fst., reset_b, rd_en,
rd_en_s2f );
input clk_fst; input reset_b; input rd_en; output rd_en_s2f;
wire rd_en_s2f;
reg rd_en_s2f1; reg rd_en_s2f2; reg rd_en_s2f3;
always @ (posedge clk_fst or negedge reset_b) if (!reset_b) {rd_en_s2f3,rd_en_s2f2,rd_en_s2f1} <= 3'b111; else
{rd_en_s2f3,rd_en_s2f2,rd_en_s2f1}<={rd_en_s2f2,rd_en_s2f1,rd_en};
always @ (rd_en_s2f3 or rd_en_s2f2) case ({rd_en_s2f3,rd_en_s2f2}) 2'b01 :
rd_en_s2f <= 1'b1; default :
rd_en_s2f <= 1'b0; endcase 这样问题就得到了圆满的解决,解决后的波形见图1.9。
1.2.3.2 慢时钟同步快时钟域下的异步控制信号
慢时钟同步快时钟下的控制信号带来的问题是可能在慢时钟沿的上升沿到来之前,控制信号已经无效,这样就丢失了请求信号,显然造成了功能错误,示意波形见图1.10。 其实还有可能带来更严重的问题,就是在慢时钟临接的两个上升沿的期间,快时钟域下的控制信号可能经过了多次翻转,这样其实就丢掉了数个请求控制信号。
图 1.10慢时钟同步快时钟信号示意图
[2]
对待这个问题,其实有两个处理方法:
1. 在快速时钟域里面对此控制信号采用保持逻辑。直到将通过异步时钟接受 方、的信号反馈后从而确认对方已经收到此有效控制信号才无效此控制信号。
我们称这种同步机制为握手。
其实,异步信号经过反馈保持逻辑之后,就可以按照快时钟同步慢时钟的控制信号的方式来同步此异步信号。
显然在此控制信号也要在逻辑上也满足规定(1.1)和规定(1.2)。 值得一提的是,反馈到快时钟的信号因为已经同步到慢时钟的时钟域,所以它也要需要通过同步器才能在快时钟域里面起作用,具体实现见图1.11。
图1.11握手机制解决慢时钟同步快时钟控制信号原理图
[2]
在此只给出快时钟控制信号的产生保持的RTL代码, 代码以图1.11的图示为例。
module adapt_gen ( aclk, //快时钟 reset_b, //系统复位信号 adat, //原始控制信号 abdat2, //从慢时钟域反馈回来的同步控制信号 adat1 //经过保持后的信号输出 );
input aclk; input reset_b; input adat; input abdat2;
output adat1;
reg adat1;
always @ (posedge aclk or negedge reset_b) if (!reset_b) adat1 <= 1’b else
if (abdat2) adat1 <= 1’b0; else if (adat)
adat1 <= 1’b1; endmoudule
我想细心的读者可能已经发现,这种方法其实并不能解决上面提到的控制信号在两个临接的慢速时钟上升沿间多次翻动的问题;事实上,握手机制默认了这种情况在逻辑上并不存在。也就是说在设计的时候,我们必须在逻辑上保证控制信号adat的两次有效时间有个最小值的限制。这个最小值必须大于控制信号整个反馈回路中的时间和异步时钟同步器中第一级触发器恢复到无效值的时间之和。 第二种方法其实可以解决这个限制。
2. 在快时钟控制信号产生端增加停时钟的逻辑。
它的思想是这样的,当发现控制信号有效之后,由组合逻辑发出停止时钟的如图1.12 所示的stall_b信号(低电平有效)拉平快速时钟的下一个时钟的上升沿。既然时钟都已经停掉了,由触发器输出的控制信号就不会再改变了,这样就可以保证慢速时钟能够采到有效的控制信号。在收到从目的时钟返回的反馈信号之后得知异步时钟已经采到了此控制信号,satll_b信号再会拉高从而恢复快速时钟。 有关停时钟的细节在本书低功耗设计的章节中会有详细叙述,在此就不再赘叙。 仍然以前面rd_en的例子,停时钟的方法应用后的电路图和具体波形见图1.12。
(1)电路图
(2)时序图
图1.12 停时钟解决同步的方法
以下给出停时钟的stall_b信号产生的RTL代码: module stall_logic (
rd_en,
rd_en_ack_s2f, stall_b );
input rd_en;
input rd_en_ack_s2f; output stall_b;
wire stall_b; always @ (rd_en or rd_en_ack_s2f) if (rd_en_ack_s2f) stall_b <= 1’b1; else
if (rd_en) stall_b <= 1’b0; else
stall_b <= 1’b1;
endmodule
同样停时钟的方法也要求在设计时使rd_en信号满足规定(1)和(2)。 因为停了时钟,所以显然在慢时钟相邻的两个上升沿间不可能存在多个rd_en有效信号,方法一不能解决的问题这里我们用釜底抽薪的方法解决了。 理论上,rd_en信号的两次有效之间还是有个最小时间的限制。这个限制要满足rd_en有效的下一个上沿到来之前异步时钟同步器的第一级触发器已经回复到无效状态。只有满足这一点,在异步时钟域端才能把两次不同的异步请求区分开。 在实际应用中,不可能伴随着异步控制信号的同步总是会对应着一系列操作。实际上,快时钟被停的时间会远远大于图中所示的时钟数。
rd_en信号虽然只有在时钟恢复后才能复位,但是我们可以用发出一个rd_en1的信号给异步时钟域,等到接到对方的反馈之后就立刻复位rd_en1,紧接着异步时钟端的同步器的第一级触发器就被复位了,而此时,在逻辑上,可能被停的快时钟还没有被恢复或刚刚恢复,这样在快时钟域内rd_en就不存在那个两次有效间的最短时间的限制,而且异步时钟端也可以区分两次不同的有效信号rd_en了。
事实上,在应用中,实际情况往往如此。
此外控制信号同步后伴随的一些操作的信号必然会具有一些耦合关系,巧妙的利用这些耦合关系可以在没有异步控制信号反馈的情况下达到异步控制信号反馈一样的效果。
最后要说的是,不知道,读者有没有感到疑惑,在第一种方法中我提到目的时钟域的反馈信号再快时钟域中也必须经过同步器才能连入快速时钟域的电路,同步器的正常工作是需要时钟信号的,而此时快速时钟信号已经被停掉了,同步器如何正常工作呢? 解决方法很简单,只要将同步器的时钟信号连到全速时钟上去而不是可关断时钟就行了,在图示中这点可以看地很清楚。
1.2.3.3 未知速度关系时钟域间控制信号的同步
既然不知道两个时钟间的关系,那么前面两节提到的问题就都有可能出现。 如果实际应用中是出现这种情况,我们应该怎么处理呢? 其实,方法在前面已经给出来了。对,就是停时钟的方法。 其实在前一节中谈到慢时钟同步快时钟域的控制信号的时候的处理方法的时候就可以看到解决方法的实质是将其转换为快时钟同步慢时钟的控制信号的方法。由此就可见,两者的处理是相通的。 由前面的分析可以看到,停时钟的方法不但解决了异步信号交互时可能带来的逻辑错误,而且对异步控制信号的限制也是最小的。 结合前两节的内容,读者可以自己详细分析一下未知速度关系下停时钟实现控制信号的同步的波形。
1.2.3.4 总结
综合以上三小节的分析,可以知道,停时钟加反馈的方法是处理不同速时钟间控制信号最保险且限制最小的方法。
1.2.4 异步时钟域的数据同步及其RTL实现
有了控制信号同步的知识作基础,我们就可以讨论异步时钟域的数据的同步问题了。
1.2.4.1 握手机制
我们通常采用的同步异步数据最简单的方法是基于握手机制的。 这种方法通常用在快时钟采样比它慢很多时钟域下的数据的方法。 它的基础是一位写控制信号的同步。 波形示意如图1.13
图1.13 握手同步异步数据
1.2.4.2 FIFO 1.2.4.2.1 简述
显然基于握手机制的数据的同步的方法是最简单的,但是其限制也很大,就是要求被采数据的时钟相对于采样始终必须足够慢,从而确保数据被采到。其实这就是当时控制信号两次有效的时钟沿的最小时钟差的限制。 显然这不能完全满足异步时钟数据交互的应用高速需求。 在这种情况下我们会采用FIFO来解决问题。
简单的说,FIFO是由一个双端口的存储器和一组控制逻辑构成的。
双端口存储器的一个端口用来写memory,而另一个端口用来读memory,读和写可以同时进行,而且读写的时钟可以是完全不相同的时钟(这就符合了我们异步时钟交互的要求)。Memory的读写地址是由后面提到的控制逻辑产生的。
在这里,我们把需要同步的数据端所在时钟域电路的对FIFO的动作称作FIFO写;把目的时钟域电路对FIFO的动作称作FIFO读。
控制逻辑是由读写地址控制指针和FIFO空、满的标志位组成。
一组递增的读写指针是用来实现先写的数据先被读出,即FIFO名字的由来First In First Out。初始时,读写时钟都为0,即指向双端口Memory的同一地址;每一次FIFO写动作都会将数据写入当前写指针对应的存储器地址,然后写指针将会加1,指向一个新的未写的Memory空间;同样每次FIFO读动作,FIFO当前读指针所指的数据将会被读出,然后读指针会加1,指向下一个代读数据的地址空间。这样就实现了数据的先写先读的时序要求,这跟我们异步数据数据同步时前后数据的时序是完全一致的。
FIFO空标志位指示当前FIFO中没有数据未读,此时读写指针值相同;
FIFO空
FIFO满
图1.14 FIFO空/满图示
FIFO满标志位指示当前FIFO已满,不能再写入数据。这是因为任何memory都有大小的限制,此时写指针比读指针小1。
有了这两个标志信号之后,异步时钟读写两端就能实现正确的同步。
因为FIFO完全可以满足时钟没有任何关系的两方间同步,为了区分数据同步的源/目的两端,在这里,我们把读FIFO的一方(同步数据的目的方)称作读者,写FIFO的一方(同步数据的源方)称作写者。
以下是FIFO实现同步的整个过程:
写者需要发送待同步数据到写者时,它首先检查发现FIFO满信号(Full)为无效时,就将数据写到FIFO中,等待读者来读;直到满信号(Full)为有效时,写者停止写动作,等到FIFO满信号(Full)再次无效时,写者恢复将待同步的数据写入FIFO。
同时,读者发现FIFO空信号(Empty)无效后,就开始读FIFO,这样整个同步过程就以读者读到数据宣告成功。
由此可见,借助于FIFO的Full/Empty信号,数据同步就可以准确无误的完成。 但同时这也说明Full/Empty的产生非常关键:
如果Full在FIFO已满的时候没有有效,写者就会继续写FIFO,从而将读者第一个未读的数据给覆盖;
同样如果Empty在FIFO已空的时候没有有效,读者就会继续读FIFO,从而只会得到错误的数据;
显然,这两种情况发生后造成的后果都非常严重。
怎样正确地产生Full/Empty信号呢?在下一节,我们会详细介绍。
综上所述,有了FIFO之后,在同步异步时钟的数据时,电路的行为是这样的: 1. 待同步的数据时钟域的会在其写信号的控制之下,将数据写入到FIFO中。 2. 目的时钟域在发现空标志位无效后,执行FIFO读动作,读出被异步时钟域写入FIFO 的数据。
3. 如果只要同步一个数据那么此时,空标志位再次有效。
4. 如果需要同步多个数据,因为FIFO的读写之间可以不受影响的进行,所以待同步 时钟会一直写FIFO,直到所有的需要同步的数据已经写完;而目的时钟域就根据空标志位来判断是否还有异步数据没有同步过来,直到空标志位再次有效标志这次同步完成。
FIFO的结构图如图:
“Wptr & Full control”模块负责产生FIFO写地址wptr和FIFO满信号full; “Rptr & Empty control”模块负责产生FIFO读地址rptr和FIFO空信号empty; 双端口存储器“Dual Port memory”负责存储暂存的数据。
图1.15 FIFO结构图
1.2.4.2.2问题
看起来在数据同步过程中,我们前面所提到的问题都没有了。 这是解决问题的模型的抽象程度高低给你造成的错觉。
确实,FIFO结构可以有效地解决两个没有任何关系时钟源间数据同步的问题,但是这是以牺牲ASIC中巨大的电路面积的代价为基础的;
更何况,FIFO结构并不可能解决异步时钟的固有的亚稳态问题。只是,亚稳态的问题都被隐藏到FIFO空信号的产生逻辑上了。
要知道当前FIFO是否为空,必然比较读写指针是否相等。
而因为读写指针属于不同的时钟域,两者显然不能直接连到比较器的两端来产生空信号。否则会造成读FIFO的目的时钟域的电路碰到亚稳态现象。
这样就需要将写指针同步到读FIFO的时钟域来,看起来问题又解决了。 可是显然指针是一个多位的信号,从前面的分析我们知道同步多位编码控制信号时,如果编码的多个值同时发生改变时被采到的可能会得到莫名其妙的值,用着这个值来跟读指针比较产生空信号显然是不合适的。
可是我们知道我们正常编码的二进制在加1动作之后不可避免地要有多位数据翻动。 这就要用到格雷码(Gray Code),它的特点是加1操作后,前后两个编码之间只可能有一位数据翻动。
从表1.1可以很直观地看到这一点。
码制 数字 二进制编码 格雷码
0 1 2 3 4 5 6 7
000 001 010 011 100 101 110 111
000 001 011 010 110 111 101 100
表1.1 二进制和格雷码的对比
由此可见,通过以下两个途径可以解决FIFO结构中固有的异步时钟亚稳态问题: 1.以格雷码编码表示读写指针,用格雷码加法器来实现读写地址的加一动作;
2.在1的基础之上,用同步器将读指针同步到FIFO满标志的产生逻辑,同样用同步
器将写指针同步到FIFO空标志的产生逻辑中 由此,给出新的异步FIFO的结构框图,见图1.16:
图
1.16 新的FIFO结构图
1.2.4.2.3 FIFO的RTL实现
考虑到整个FIFO设计的过于庞大,以下将只给出格雷码加法器的代码 module graycntr (
clk,
reset_b,
inc, gray );
parameter SIZE = 4; input iput
output [SIZE-1:0] gray ;
reg [SIZE-1:0] gnext ; reg [SIZE-1:0] gray ; reg [SIZE-1:0] bnext ; reg [SIZE-1:0]bin; integer i;
always @ (posedge clk or negedge reset_b)
if (!reset_b)
gray <= 0; else
gray <= gnext;
always @(gray or inc) begin
for (i=0; i gnext = (bnext>>1) ^ bnext; end endmodule clk ; reset_b ; input inc ; 1.2.4.2.4后记 可能此时,读者会有个疑惑,Full信号的产生逻辑中所用到的读指针是经过同步器采过 后的,这个同步到写时钟域的写指针显然可能不是当前FIFO读指针的值,那如此产生的Full信号还有意义么?同样Empty信号的产生也有类似的问题。而且在简述中曾强调正确产生Full/Empty对于FIFO同步异步数据的正确性的影响至关重要。 现在以Full信号为例来说明这个问题: Full信号的产生是根据比较写指针值和经同步读指针减一后的值是否相等。经过写时钟 下同步器的两级触发器同步延时后,同步后读指针的值可能不是FIFO的当前指针值,这带来的问题并不是Full不能在FIFO为满的时候被置位(有效),恰恰相反,Full信号可能会在FIFO中还有空间未被写入时被置位(有效),因此这不会对数据同步整个过程的正确性产生任何影响。唯一的代价是可能使同步过程的延时可能会拉大,但由于异步的实质这个延时是不可避免的。 同样的道理,读者可以试着对Empty信号的产生进行分析。 由此可见,采用格雷码编码的读写指针的FIFO可以完全满足完全没有任何关系的时钟 信号间的数据的同步。 1.2.4.3总结 经过分析可以知道,数据同步有两种方法,握手机制或FIFO机制。 握手机制在明确知道目的时钟比待同步数据时钟快很多的情况下可以无误地实现数据的同步,其最大的优点是简单,代价小; 对于异步数据同步的情况,FIFO 机制具有最大的适用性,它可以同步源和目的时钟没有任何关系的情况。它最大的缺点就是代价大,耗面积。 1.2.5本节小结 经过四个小节的分析,我们介绍了异步电路设计中固有的亚稳态问题及其危害;也介绍 了异步控制信号和数据同步的方法。 希望大家记住的是: z 亚稳态现象在异步电路设计中并没有完美的解决方案,我们不可能避免亚稳态的出 现; z 但是通过同步器,在空间上我们可以把亚稳态现象控制在电路的一个很小的区域, 在时间上我们可以把亚稳态的出现的时间控制到最小 z 在电路上,无论是异步控制信号的同步还是数据的同步,两者不可能完全割裂开, 异步数据的同步需要异步控制信号的同步,异步控制信号的同步正是为了异步数据的同步 1.3 SOC设计中时钟分配策略 综合前面两节所述,为IC设计者提供以下建议,因为大部分跟时钟有关,所以可以简单地称这些建议为SOC设计中的时钟分配策略。 ¾ 尽可能使用同步设计 原因如下: 对于同步电路,逻辑综合工具和时钟树综合工具能够最大地发挥作用。 可以用STA工具来分析单时钟同步设计的时序收敛问题。 DFT(Design For Test)的插入工作得到最大的简化的 ¾ 注意同步电路设计的缺陷 噪音问题。因为所有的时序元件都会在同一时钟调边沿发生改变,这样会 对数字系统造成很大的辐射噪音。 时钟树上的功耗很大,这在第一节曾经分析过。 ¾ 系统中不同时钟域的数量越少越好 系统中不同时钟域越多,以下问题越难解决 使脚本的书写更加复杂,因为有过多的False path和multi cycle path。 DFT插入更加复杂,因为此时系统中需要有多条独立的Scan chain。 越多的时钟域,发生亚稳态的机会就会越大\\ ¾ 尽可能将异步交互电路归入同一或多个独立的模块 这样不但方便脚本的书写,也方便日后代码的阅读 ¾ 尽可能避免使用latch 这是因为latch在同步设计中会带来以下问题 它是电平触发 只要其控制信号是在其有效电平,latch的输出都会随着输入而改变 它允许周期窃取 优点:可以使系统工作时钟频率更高 缺点::使STA工作更加难做,并且如果跟触发器一起使用的话会令DFT插 入更复杂 ¾ 尽可能减小时钟偏斜 这可以通过使用Astro长时钟树的方法来解决 ¾ 减小时钟延时 可能会因为降低时钟偏斜而导致全局时钟线上产生巨大的时钟延时,这个延时可能会造成系统功能失效和多余的功耗 ¾ 任何异步时钟域交互的环节都要尽可能避免亚稳态现象 参考文献 1. Jan M.Rabaey 《数字集成电路设计透视》 PRENTICE HALL 清华大学出版社 1999年 P533- 538 2. Clifford E. Cummings “Synthesis and Scripting Techniques for Designing Multi-Asynchronous Clock Design” Sunburst Design, Inc 3. Clifford E. Cummings, “Simulation and Synthesis Techniques For Asynchronous FIFO Design” Sunburst Design, Inc 4. Clifford E. Cummings and Don Mills, “Simulation and Synthesis Techniques for Asynchronous FIFO Design with Asynchronous Pointer Comparisons”, SUNG2002 因篇幅问题不能全部显示,请点此查看更多更全内容