关于单关于单关于单关于单bit信号穿越异步时钟边界问题的分析信号穿越异步时钟边界问题的分析信号穿越异步时钟边界问题的分析信号穿越异步时钟边界问题的分析作者winfire联系方式经验专题版在我们的设计中,单一时钟的情况已经很少见了。当我们面对多时钟域时,将一个信号从一个时钟域传递到另外一个时钟域就成为一个必须面对的问题。这里我们仅仅讨论一些简单的情况,希望对刚接触异步时钟的朋友们有所帮助。这篇文章想要讲述的如何将一个单bit信号的有效信号(假设高有效)从一个时钟域传递到另外一个时钟域,这个有效信号以下简称为pulse。共分成4种情况讨论。1,pulse为电平信号,每次足够长,且每2个pulse不连续。2,pulse为单脉冲信号,每2个pulse不连续,且间隔时间足够长。3,pulse为单脉冲信号,pulse可以连续,但是对每一个pulse,接受端消耗速度足够快。4,pulse为单脉冲信号,pulse可以连续,接受端消耗不足够快,但是总消耗速度大于发送速度。解答:由于题目没有说明两个时钟的关系,我们只能当作是完全异步的时钟,且并不知道两者时钟的快慢关系。唯一我们能够确认的是,除非亚稳态,否则setup/holdtime是需要被满足的基本条件。1,这个情况是最简单的,就是将clock1的一个足够长的电平信号传递到clock2,直接在clock2用2个stagingflop采样即可。用2个flops的原因是防止亚稳态传播。2,由于满足pulse不连续且间隔足够长,我们要解决的唯一问题就是防止接受端时钟太慢,而错过了快时钟的只有一个cycle长度的pulse。于是,最简单的做法就是:将这个pulse用快时钟toggle起来,变成了类似于情况1。当然只是类似,并不完全相同,我们需要做一些额外的工作。将toggle起来的电平信号再转换为pulse信号。只需要如图中这样,用一个xor门即可。3,这个条件比较诡异,问题就在于发送端pulse可以连续,但是接收端却能将每一个pulse都接收到。这里面隐含了一个条件:接收端的时钟比发送端要快(或者至少一样快),且接收端允许不停的接收pulse。但是由于没有办法区分采样到的信号是属于第一个pulse的还是第二个pulse的。甚至采到的有可能只是亚稳态,我们没有办法简单将这个pulse直接sync到接收端。怎么将不同的pulse区分开呢?就是这个问题的关键。我们只需要将这个pulse用toggle的思路处理一下,每次来一个pulse,我们可爱的toggle就翻转一下。而接收端只要发现toggle翻转,就认为来了一个pulse。如下图所示。细心的读者已经发现,这不是和情况2的电路一模一样么?对了,就是一模一样,我再帖一遍不是为了篇幅,而是想强调,的确是一模一样。4,这种情况,我们只能用一个称之为pulse-sync的技术。其实,pulse-sync并不神秘,学习过异步FIFO设计的人所掌握的知识,已经远远超过我下面要讲的内容。如果,接收端时钟快于发送端,且总是可以接受,那么此情况就退化成了情况3。可是如果接收端时钟较慢,或者有时候不能接收时。这时候就需要有一个buffer将这些个pulse先寄存起来。由于只是很多个pulse信号,我们只需要用一个counter就可以了,发送端发一个,counter+1,接收端收一个counter-1。这个就是pulse-sync技术的一半了。还有一半呢?就是用gray码将计数器的值跨越异步时钟边界。于是事情就变得很简单了,第一步,我们计算一下背靠背的情况下pulse传输最少需要的counter值。第二步,设一个wr_counter二进制计数器,并用一个bin2gray组合逻辑将counter值转成gray码。第三步,用一个2stagingflops,将gray码传递到接收端时钟域。第四步,不用我说你也知道,设一个rd_counter二进制计数器并用一个bin2gray组合逻辑转换成gray码,与收到的gray码比较。相同则发送完了;不相等,就继续发送,接收端每收一个,rd_counter+1。代码我就不贴了。相信有了以上电路图,代码不费吹灰之力。