在本系列文章的第一部分我们了解了FIFO的一般结构,并分析了单时钟FIFO的一个特例[1]。第二部分描述了双时钟设计的一种可能的结构。在第三部分我们将探究一种具有新颖结构的双时钟FIFO。这种结构未必更好——只是另一种实现的方法而已。
1 工作原理 至此我们已经解决了用格雷码表示的不同时钟域的所有计算,包括多位二进制计算。本篇所介绍的结构与以往并没有什么不同,唯一的区别在判断引起读写指针相等条件的方法。
如果还记得先前的文章,文中提到读写指针相等意味着无论是满条件还是空条件,依赖于读操作还是写操作导致了指针的相等。在同步FIFO的第一个例子中,这很容易判别,因为两种操作均与一个时钟有关。在第二种结构中,这个条件已被编码于指针中。我们现在将探究双时钟设计的第二种方法。
1.1 方向标志(Direction flags) 在这种结构中,我们让指针轨迹的标志相等。我们称其为“Direction flags(方向标志)”。这个标志告诉状态电路FIFO“当前朝向(headed)”。它假设写操作引起的FIFO朝越来越满的方向与读操作引起的FIFO朝越来越空的方向为FIFO的朝向。
不用说,每边(读操作或写操作)都必须保留独立的方向标志复本(copies)并且维持在保守状态。因此对于写操作一方将有其自己的方向标志来维护保守性。也就是,从读操作一方可能会看到写操作被延迟并且读操作一边也将维持方向标志,它可以根据延迟的写操作来计算。就像先前的双时钟结构,这将确认FIFO没有在吞或吐数据,但这样做是以FIFO尺寸动态缩小为代价的。
FIFO满/空标志的计算基于这些方向标志,其思想是如果FIFO的朝向为向越来越满的方向,并且指针相等,则FIFO真正为满。如果FIFO朝向越来越空的方向,并且指针相等,则FIFO确实为空。
1.2 方向标志的实现 有很多不同的方法实现方向标志:一般的想法是当FIFO的字节计算超过某个预定上限,就认为FIFO“going towards full(趋向满) ”,当字节计算低于预定下限是,就认为FIFO“going towards empty(趋向空)”。
一些设计人员选择“going towards full”的门限为FIFO容量的75%,“going towards empty”的门限为FIFO容量的25%。还有人选择两个门限都为FIFO容量的50%。也有选择80% 和20%的。门限的选择可由自己来决定,要根据设计选择最适合的门限。也可以根据时钟的速度与门限值得关系来确定以便使标志失效的可能性最小,但我不确定门限的选择会让设计的系统变得更好。我认为上限与下限之间有滞后或许更好(滞后的意思是上限与下限之间的差并且“going full”门限要大大超于“going empty”门限)。
我们不妨选择FIFO容量的75%和25%作为门限。这样做比较有效,因为你只需比较指针的高两位就能决定是否越过门限。若用另一些值,你将不得不比较指针的所有位,而这有可能影响你所设计的系统的速度。像以前一样,写操作的一方可以看到写指针和一个被同步的读指针,两个指针均为格雷码。然后,将格雷码指针转换为二进制指针并计算出FIFO中有多少数据。如果FIFO中的数据量大于“going full”门限,就置位方向标志。当FIFO中的数据小于“going empty”门限,就清除方向标志。
同理,读操作看到(格雷码的)读指针和一个被同步的(格雷码的)写指针。在完成格雷码到二进制码的转换后,计算FIFO中的字节数;如果字数小于“going empty”门限,就置位方向标志(此时方向标志的反指向(the opposite sense) 作为写操作一方的方向标志),当字数增加,大于“going full”门限时就清除方向标志。
记住,当选择75%和25%作为门限时,上述计算无需比较指针的全部位。只用指针的高两位就足够了。
1.3 空/满的计算 在写操作一方,如果指针相等并且方向标志置位,则FIFO的满标志置位,同理,在读操作一方,如果方向标志置位并且指针相等,FIFO的空标志置位。注意,这意味着我们不排除空/满标志同时置位的可能性。尽管听起来不合常理,但对于FIFO是正确的条件。你也许会想FIFO怎么可能同时既满又空呢。然而如果你进一步分析,就会发现“满”只是一个写操作一方的流控制机构,“空”只是一个读操作一方的流控制机构。如果FIFO的读写操作两边的Blocks同时流动那么这就是正确的——它并未破坏存储器或指针。当FIFO真的不能再接收数据或当不能再提供更多的数据时FIFO没有报告是非常危险的。仔细分析以前所讲的结构,它证明这种可能性不排除存在于其它结构中。
下面列出了计算方向标志每一边(读或写)的计算(注意公式中的指针已被适当的同步并且转换为二进制):
word_count = wr_ptr - rd_ptr + 1 if wr_ptr > rd_ptr
fifo_size - (rd_ptr - wr_ptr) + 1 if rd_ptr > wr_ptr
direction_flagwr = 1 if word_count > going_full_threshold
0 if word count < going_empty_threshold
direction_flagrd = 1 if word_count < going_empty_threshold
0 if word_count > going_full_threshold
如图1所示为75%和25%门限的特列。在这个特例中,上述字节计算公式仅需要二进制码指针的最高两位,并且不需要加1得到字数的精确值。只需知道是否越过门限而已。
还要记住,在写操作和读操作一边的门限不必相同;可以根据读写时钟频率调整门限值以优化性能。
2 结论
这种结构是在同步FIFO情况下提出的命题中的一种变异。这种同步FIFO是这个结构的一个特例——“going full”和“going empty”的门限分别等于(fifo_size-1)和1。
这种结构的表现比先前所提到的异步结构有着明显的优点码?未必。在一些临界情况下,这种结构可能会有优势——对于时间紧张的情况下N-bit格雷码转换为二进制码也没有问题,但在N+1位(在先前的结构中需要的)格雷码情况下就没有这种优势,或当面积比较紧张的时候为了N+1位转换而占用额外的面积这种结构就不适用了。我的观点是,它们都是真正的非常优秀的结构,因此选择哪种结构取决于你的偏好。
< The end>
[1] 勘误:第一篇中关于Trivial case,应当翻译为“特例”trivial case 指其解不影响全局的事件。一般译作琐事,但很显然在此为琐事不合适,取其意义。
[2] 第二篇文章中出现了the most significant bit.简称MSB,与LSB对应,意为最高位。我们常用简称,往往看到全程不知道怎么翻译了,抱歉。
Adam Luo
文章评论(0条评论)
登录后参与讨论