跨时钟域传输数据目前用的最多的方法是使用先入先出(FIFO)结构。FIFO可以用于在两个异步时钟域之间传输多比特信号。
通常看到的FIFO应用包括在两个标准总线之间传输数据,以及从可突发访问的存储器中读出数据或者对其写入数据。
现对FIFO处理跨时钟域突发数据的能力进行分析:
在数据传输中,数据可能到达某个时钟域的间隔是完全随机的,有时候或许会面临一个很大的突发数据块。这种情况下,处在另一个时钟域的接收设备只能以指定的速率来处理数据。
异步FIFO的结构如下图所示,一个FIFO被用于缓存数据,这样在设备中就形成了一个数据序列。
通过使用异步FIFO,数据发送端可以随意地间隔发送数据,而接收端也可以其固有的带宽从数据序列里取出数据并进行处理。由于任何由FIFO实现的数据序列的长度都不能无限制,所以需要一些控制来防止FIFO溢出,现有两种选项可以使用:
1)事先定义好的发送速率(可突发或不可突发)、最小接收速率以及对应最大的序列尺寸;
2)握手控制;
注意,发送设备的时钟频率没有必要高于接收端设备,否则容易造成溢出。以较慢的频率将数据送入FIFO,那么,如果不采取握手控制,就必需要理解以上描述会产生溢出的最坏的情况。通常来说,突发发送(写FIFO的速率)一般是以小周期性或非周期性发生,所以FIFO的最大尺寸要大于或等于(具体还要根据数据接收器的属性)突发的尺寸。
握手控制通常有两个标志信号来实现:一个是发送端的满信号,用于提示FIFO已没有多余空间存储数据;另一个是接收端的空信号,用于提示FIFO已没有数据需要处理。管理上述标志信号需要用到状态机,如下图所示:
异步FIFO的简单框图如下所示:
结合上图,FIFO在FPGA内部一般是通过封装一个双口RAM来实现的,在产生空和满信号时,写地址和读地址都必须是异步传递到对方时钟域中。由于两个时钟域异步的自然属性,使得地址总线有些比特在一个时钟沿上被采集,而另一些比特却在下一个时钟沿上被采集,当然这取决于数据是否在第一个触发器的时钟沿到达之前提前足够长时间有效。解决该问题可以通过将二进制地址转换为格雷码的方式进行解决。