当前位置:   article > 正文

同步电路与跨时钟域电路设计2——多bit信号的跨时钟域传输(FIFO)_背靠背传输

背靠背传输

参考视频:

芯动力——硬件加速设计方法(3.2、3.3、3.4)

  多个控制信号跨时钟域 仅仅通过简单的同步器 同步有可能是不安全的 。

例子:传递两个同时需要的信号

如何传递两个同时需要的信号(b_loadb_en)?

        将 b_loadb_en同步至a_clk时钟域,

        如果 b_loadb_en这两个信号有一个小的skew,

        将导致在 a_clk时钟域中两个信号并不是在同一时刻起作用,与在b_clk中的逻辑关系不 同

解决方法

        将b_loadb_en信号在b_clk时钟域中合并成一个信号b_lden,然后同步至a_clk中。

 问题:遇到不能合并的情况,怎么办?

例子:译码信号

如果bdec[0]bdec[1]间存在 skew将导致同步至a_clk中后 译码错误,出现误码。

         在这种情况下,建议加入另一个控制信号,确保bdec[0]bec[1]稳定时采信号。

        例如,在bdec[0]bec[1]稳定输出后一到两个周期b_clk域输出一个en信号,通知 a_clk域此时可以采bdec[0]bec[1]信号。

        这样可确保正确采样。

多bit数据流跨时钟域传输

问题:多bit数据流跨时钟域如何传输?

数据流和指示信号不同:

  • 数据流大多具有连续性,即背靠背传输;
  • 数据流要求信号具有较快的传输速度;

解决传输的两个方法:

  1. 两个时钟域通过SRAM来缓冲
  2. 使用FIFO

同步策略 — FIFO

        FIFO( first in first out )是一种先进先出的储存结构

FIFO与普通存储器的区别:

        没有外部读写地址线 ,使用简单。

FIFO缺点:

        只能顺序写入数据,顺序的读出数据,其数据地址 由内部读写指针自动加1完成,不能像普通存储器那 样可以由地址线决定读取或写入某个指定的地址。

FIFO的应用:

        随着IC的发展,模块与模块之间的通信设计中,多时钟的情况已经不可避免;数据在不同时钟域之间的传输很容易引起亚稳态;异步FIFO就是一种简单、快捷的解决方案。

FIFO的功能:

         FIFO的功能类似于一个调节上下游水量的一个蓄水池。

FIFO 的上游结点是FIFO的数据输入端,

        在写信号有效时,数据将被写入FIFO,由FIFO内部的写指针控制,并且在FIFO内部,写指针递增一个单元,同时FIFO的满信号(FIFO fulll Signal)将控制上游结点是否发送数据;

FIFO的下游节点是FIFO 的数据输出端,

        当读信号有效时,FIFO中的数据将被读出,由FIFO内部的读指针控制,并且在FIFO内部读指针递增一个单元,同时FIFO空信号(FIFO empty Signal)将控制下游节点是否读出数据。

FIFO内部的空间已经被写满

        如果FIFO内部的空间已经被写满,则实时生成满信号,以反压上游节点,上游节点停止写新的数据进来,否则就会把已经写好的数据冲掉。

FIFO内部的数据全部被读

        如果FIFO内部的数据全部被读,则实时生成空信号,控制下游节点不再进行数据读操作。否则,下游节点就会将读过的数据重新再读一遍。

从这里也可以看出,空信号和满信号对于FIFO的控制非常重要。

FIFO用途:

        FIFO主要用来调节上下游数据的吞吐量。

用途1:异步FIFO读写分别采用相互异步的不同时钟

        在现代集成电路芯片中,随着设计规模的不断扩大,一个系统中往往含有数个时钟, 多时钟域带来的一个问题就是,如何设计异步时钟之间的接口电路。异步FIFO是这个问题的一种简便、快捷的解决方案,使用异步FIFO可以在两个不同时钟系统之间快速而方便地传输实时数据。

用途2:对于不同宽度的数据接口也可以用FIFO

        例如,单片机位8位数据输出,而DSP可能是16位数据输入,在单片机与DSP连接时就可以使用FIFO来达到数据匹配的目的。

FIFO分类:

FIFO通常来说分为:

  • 同步FIFO:指读时钟和写时钟为同一个时钟,在时钟沿 来临时同时发生读写操作;
  • 异步FIFO:读写时钟不一致,读写时钟是互相独立的,这种结构用途最广。

FIFO常见参数:

FIFO的宽度即FIFO一次读写操作的数据位

FIFO的深度指的是FIFO可以存储多少个N位的数据(如果宽度为N)。FIFO 的深度相当于蓄水池的容量,如果过小,则上游节点总是接收满信号,使得系统的数据吞吐量降低。如果过大,则浪费空间太多。因此,FIFO的深度是一个很关键的参数。

满标志FIFO已满或将要满时由FIFO的状态电路送出的一个信号,以阻止FIFO的写操作继续向FIFO中写数据而造成溢出(overflow)。

空标志FIFO已空或将要空时由FIFO的状态电路送出的一个信号,以阻止FIFO的读操作继续从FIFO中读出数据而造成无效数据的读出(underflow)。

读时钟读操作所遵循的时钟,在每个时钟沿来临时读数据。

写时钟写操作所遵循的时钟,在每个时钟沿来临时写数据。(在FIFO中,读写两个时钟通常都不相同,而且基本上是异步时钟。)

FIFO结构:

 双端口SRAM

        用来存储上游节点写入的数据wdata,下游节点用rdata将其读出。

        SRAM的读写地址采用了每次只递增1的机制,保证了写入和读出按顺序进行,写和读到最高地址后,重新返回零地址。

满信号生成电路

        在上游节点和SRAM之间有一个满信号生成电路。

        这个电路通过判断写时钟域下,写指针和读指针的关系,然后实时生成满信号wfull,以通知上游节点停止写操作。

空信号生成电路

        在下游节点和SRAM之间有一个空信号生成电路,

        这个电路通过判断读时钟域下,写指针和读指针的关系,然后实时生成空信号rempty,以通知下游节点停止读操作。

注意:

        将读指针传递到写时钟域才能产生满信号,将写指针传递到读时钟域才能产生空信号,因此,这里就涉及到如何处理信号传输的亚稳态问题。

FIFO空满状态的判断:

        正确的产生空满标志是任何FIFO设计的关键。

        空满状态产生的原则是:写满而不溢出,能读空而不多读。

空满状态的判断:

空状态:

        当读写地址相等时,说明已经写入的数据,已经全部被读走,此时,FIFO还尚未有新的数据写入,说明FIFO为空。

空状态情况发生:

  • 复位操作时,
  • 当读地址读出FIFO中最后一个字后,追赶上了写地址。

判断条件: 

        如果两个指针的MSB相同,则说明两个指针折回的次数相等。其余位相等,说明FIFO为空。

满状态:

        当写地址超过读地址,写到最高地址后,重新从零开始写,再次追上了读地址。此时,读地址已经读过的地址空间,再一次被写地址写入。而读地址到最高地址之间的数据,还尚未被读。说明此时FIFO处于满的状态。

判断条件:

        如果两个指针的最高有效位MSB不同,说明写指针比读指针多折回了一次;

        如r_addr=0000,而w_addr = 1000,为满。

区分满状态、空状态方法:

        在地址位中添加一个额外的位(extra bit)。

        当写指针增加并越过最后一个FIFO地址时,就将写指针这个未用的MSB加1,其它位回零.

        对读指针也进行同样的 操作。

        此时,对于深度为2^{n}的FIFO,需要的读/写指针位宽为(n+1)位,

例子:深度为8的FIFO

        需要采用4bit的计数器, 0000~1000、 1001~1111,

        MSB作为折回标志位,而低3位作为地址指针。

满状态判断条件:

         如果两个指针的MSB不同,说明写指针比读指针多折回了一 次。

        例子:r_addr=0000,而w_addr = 1000,为满。

空状态判断条件:

        如果两个指针的MSB相同,则说明两个指针折回的次数相等。 其余位相等,说明FIFO为空。

空满标志生成的前提:

        读指针被传递到了写时钟域,写指针被传递到了读时钟域。

       如下图电路所示,各自采用两级同步器来对信号进行同步。

FIFO使用二进制读写指针的问题及解决(格雷码)

        二进制的读写指针位宽通常超过了1bit。

        多bit信号是不可以使用两级同步器的。(比如刚开头的例子)

 解决方法:使用格雷码 

 格雷码的特点:

  1. 格雷码相邻的2个数值之间只会有一位发生变化,其余各位都相 同
  2. 格雷码是一种循环码,0和最大数(2的n次方减1)之间也只有一位不同

         引用格雷码之后,相邻数值只有1位发生翻转,1位翻转所引起的亚稳态的概率远 远要小于几位同时翻转所引起的概率。因此,格雷码能很好的亚稳态出现的概率。

        所以,传输读写指针之前,需要将其先由二进制转为格雷码,然后再发送到对方的时钟域下。

二进制码和格雷码的转换:

二进制码转化为格雷码:

        从最右边第一位开始,依次将每一位与左邻 一位异或(XOR),作为对应格雷码该位的值,最左边一位不变。

格雷码转化为二进制码:

        从左边第二位起,将每位与左边一位解码后的 值异或(XOR),作为该位解码后的值(最左边一位依然不变)。

FIFO 使用gray码判断“空”与“满”

“空”状态的判断:

         空 :依据二者完全相等(包括MSB)(和二进制码判断一样)

“满”的判断:

       由于 gray码除了MSB外,具有镜像对称的特点,当读指针指向7,写指针指向8时,注意地址增加到最大地址7时,然后会返回0,所以此处8和0虽然轮次不同,但是实际上是同一个地址。此时,除了MSB,其余位皆相同,就不能说它为满。

 在gray码上判断为满必须同时满足以下3条:

  • wptr和同步过来的rptr的MSB不相等, 因为wptr必须比rptr多折回一次
  • wptr与rptr的次高位不相等,如上图位置 7和位置15,转化为二进制对应的是 0111和1111,MSB不同说明多折回一 次, 111相同代表同一位置。)
  • 剩下的其余位完全相等 

设计FIFO深度:

设计之前要清楚:

分析清楚数据轻载和重载时数据的传输任务
如果FIFO能在重载的时候满足需求,轻载的时候,肯定可以胜任。

例子:

假设FIFO的写时钟为100MHz,读时钟为80MHz。在FIFO输入侧,每100个写时钟,写入80个数据;读数据侧,假定每个时钟读走一个数据。

请问FIFO深度设置多少可以保证FIFO不会上溢出和下溢出?

在FIFO的输入侧 每100个写时钟,写入80个数据。

其数据传输分布可能有如图所示的几种情况:

重载时数据的传输任务(要求缓存能力最高的情况)

        背靠背的情况:

        第一段的100个写时钟周期中,数据传输发生在后80个;

        第二段的100个写时钟周期中,数据传输发生在前80个。

这样就会有160个周期,在连续传输数据。其他情形下,都没有这么重负荷的数据的传输任务。

分析重载情况:

连续传输数据的周期称为 burst长度。

        重载情况下,burst=160。在 burst长度内,写入端写入160个数据。

burst持续时间=160*写时钟周期

 这段时间内能读出数据的个数=burst持续时间/读时钟周期数

 FIFO depth= burst长度 - 读出数据的长度

所以FIFO深度至少大于等于32才可以。

FIFO深度计算总结: 

  • 写时钟频率: WCLK     写时钟周期=1/WCLK
  • 读时钟频率: RCLK      读时钟周期=1/RCLK
  • 写时每B个时钟周期内会有 A个数据写入FIFO (写入效率A/B)
  • 读时每Y个时钟周期内会有 X个数据读出FIFO(读出效率X/Y)

连续传输数据的周期称为 burst长度burst_length表示这段时间写入的数据量

burst的持续时间:burst长度*写时钟周期 (burst_length / W LK )

读的实际速度:(RCLK*(X/Y)),

burst的持续时间这段时间读出的数据量:burst的持续时间*读的实际速度

                         (burst_length / W LK )*(RCLK*(X/Y))

理论上的 FIFO的最小深度: 写入和读出两者之差为FIFO中残留的数据

                burst_length  -    (burst_length / W LK )*(RCLK*(X/Y))

FIFO设计总结

FIFO设计中的两个关键问题:

  • 格雷码问题
  • 亚稳态问题

这两个问题主要在FIFO结构中的下面红色方框模块中 

读写指针使用格雷码 

 为什么需要格雷码做读写指针?

        由于异步FIFO是工作在两个不同的时钟域。

        如果某个时刻,读地址从0111->1000转变

        同时,写时钟要在这个时刻采样读地址,得到的值有可能是0000~1111中的任一个值

        这个不确定的读地址值会导致空满状态判断错误。

 格雷码的特点:

  1. 格雷码相邻的2个数值之间只会有一位发生变化,其余各位都相 同
  2. 格雷码是一种循环码,0和最大数(2的n次方减1)之间也只有一位不同

例子: 

假设FIFO深度为8,则读写指针可采用格雷码进行编码

采用格雷码,指针每次只变化一次。地址7与地址0,也是每次只变化一次。

 问题:

        假设FIFO深度为6,如果读写指针继续采用格雷码,那么当前首尾指针的所有比特位都不相同。(首地址的指针 000 尾地址的指针 111)

        此时,如果从尾部返回首部,则无法实现消除亚稳态的目的。 

如何解决?

        可将地址为5的指针设定为100,此时其与首地址的指针 “000”相差一个bit位,与地址为4的指针“110”也相差一 个bit位,满足消除亚稳态的要求。

问题1: 如何在2次幂和非2次幂深 度下设计相应的读写指 针?

问题2:什么情况下,需要用格雷 码来进行读写指针编码?

问题3:什么时候不可以使用格雷码

        并不是一定要用格雷码做读写指针,而是当FIFO深度为2次幂的时候,刚好格雷码满足消除亚稳态的需求;在非2次幂FIFO深度情况下,格雷码已经不再适用。

非2次幂FIFO深度情况的解决方法 通常有:

若FIFO深度为偶数,可采用最接近的2次幂的格雷码编码,在此基础上修改;

FIFO深度为一般数值时,可自行设计一种逻辑电路,或者查找表,以实现指针每次只跳变一次的功能

③ 以上方法通常在设计层面较为复杂,若无特定需求,可将FIFO深度设置为2次幂,浪费一些存储空间,来化简控制电路的复杂度。

FIFO中的亚稳态问题 

问题1:FIFO中的亚稳态是否能够真正消除?

        亚稳态不能从根本上消除,但可以通过采取一定的措施使其对电路造成的影响降低。



问题2:若无法消除亚稳态,为什么FIFO还能正确运行?

如果指针为格雷码,失效的后果?

格雷码一次只有一位数据发生变化,这样在进行地址同步的时候,只有两种情况

  • 地址同步正确
  • 地址同步出错,但是只有1位出错

分析地址同步出错 

        假设写地址 000->001         读地址同步出错           写地址变成 000->000

        也就是地址没有发生跳变。

        但是用这个错误的写地址去做空判断不会出错, 最多是让空标志在FIFO不是真正空的时候产生,而不会出现空读的情形。

        gray码:

        保证的是同步后的读写地址即使在出错的情形下依然能够保证 FIFO功能的正确性,当然同步后的读写地址出错总是存在的。

注意:

        gray码 只是在相邻两次跳变之间才会出现只有1位数据不一致的情形 ,超过两个周期则不一定。

        所以,地址总线bus skew一定不能超过一个周期,否则可能出现gray码多位数据跳变的情况,这个时候gray码就失去了作用,因为这时候同步后的地址已经不能保证只有1位跳变了。


问题3:两拍同步或者多拍同步的差异?

         将地址总线连续打两拍 ,为了避免亚稳态传播。

        理论上打两拍不能消除亚稳态现象,因为时钟异步,亚稳态不可避免,但是可以极大降低亚稳态传播的概率。

        多拍能够将亚稳态出现的概率进一步降低。

FIFO静态时序分析:

低频情况下

      STA不需要分析这里的异步时序,因为寄存器都可以在一拍内将亚稳态消除,恢复到正常0/1态。

高频情况下(尤其在28nm工艺以下)

       需要检查两级触发器的延迟,保证延迟低,这样可以系统的MTBF。

问题4:空满标志的判断方法是否有漏洞(虚空、虚满)?

         rptr同步两个“wclk”后,在wclk时钟域与wprt进行比较,生成full信号

        wptr同步两个“rclk”后,在rclk时钟域与rprt进行比较,生成empty信号

分析FIFO空满标志: 

         假设,读指针rptr地址为3,在写时钟控制下,同步两个时钟进入写时钟域,即信号rptr_sync_2

        这时,在写时钟域下,刚好满足“满”的条件,生成满信号。

        但是,此时rptr的值已经更新为5。

        即在FIFO认为自己已经满的时候,读地址,又从里面读走了两个数据。实际FIFO并没有真正的满,只是接近满“虚满”。

结论:

  •  对于full信号的生成机制,同步后的读地址一定是小于或者等于当前的 读地址,所以此时判断FIFO为满不一定是真满,这样更保守;
  • Empty信号的机制同样成立, “空”时,不一定是真“空”

总结:

        异步FIFO通过比较读写地址进行满空判断,但是读写地址属于不同的时钟域,所以在比较之前需要先将读写地址进行同步处理,此机制保证 了FIFO在空满极限情况下,依然留有余量,存在一定的冗余空间。

        这种方法使得FIFO不会发生写满溢出、读空多读的情况。


对FIFO进行逻辑综合、静态时序分析

 从电路结构上分析, FIFO主要包括

  • memory
  • 写时钟域电路
  • 读时钟域电路
  • 跨时钟域同步器

在逻辑综合阶段,这几部分都需要单独处理。

逻辑综合阶段处理:

Memory:需要例化memory compiler生成的库文件。

写时钟域电路、读时钟域电路:分别定义不同的时钟。

静态时序分析:

  • 低频情况下,跨时钟域同步器需要设置wclk和rclk之间的false path。
  • 高频情况下,尤其在28nm工艺以下,需要检查两级触发器的延迟,保证延迟低。

布局布线:

        P&R时,要注意将两级同步器放置在一起,不要被工具自动分开。


 参考视频:

芯动力——硬件加速设计方法(3.2、3.3、3.4)

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/羊村懒王/article/detail/206690
推荐阅读
相关标签
  

闽ICP备14008679号