只有最初级的逻辑电路才使用单一的时钟。大多数与数据传输相关的应用都有与生俱来的挑战,即跨越多个时钟域的数据移动,例如磁盘控制器、CDROM/DVD
控制器、调制解调器、网卡以及网络处理器等。当信号从一个时钟域传送到另一个时钟域时,出现在新时钟域的信号是异步信号。在现代 ICPCI 或
AMBA(高级微控制器总线架构)。每个电路都发出一个请求信号,由仲裁逻辑决定谁是“赢家”。获胜的电路会收到一个应答,表示它可以访问总线。该电路于是中断请求,开始使用总线。 不同时钟域电路使用的握手协议有两种基本类型:全握手(Full-handshake)和部分握手(partial-handshake)。每种类型的握手都要用同步器,每种都各有自己的优缺点。对全握手信号,双方电路在声明或中止各自的握手信号前都要等待对方的响应(图 4)。首先,电路 A 声明它的请求信号,然后,电路 B 检测到该请求信号有效后,声明它的响应信号。当电路 A 检测到响应信号有效后,中止自己的请求信号。最后,当电路 B 检测到请求无效后,它中止自己的响应信号。除非电路 A 检测到无效的响应信号,否则它不会再声明新的请求信号。
另一种类型是部分握手,它可以缩短这些事件的过程。使用部分握手信号时,通信双方的电路都不等对方的响应就中止各自的信号,并继续执行握手命令序列。部分握手类型比全握手类型在健壮性方面稍弱,因为握手信号并不指示各自电路的状态,每一电路都必须保存状态信息(在全握手信号里这个信息被送出去)。但是,由于无需等待其它电路的响应,完整的事件序列花费时间较少。 当使用部分握手信号方式时,响应的电路必须以正确的时序产生它的信号。如果响应电路要求先处理完一个请求,然后才能处理下一个请求,则响应信号的时序就很重要。电路用它的响应信号来指示它的处理任务何时完成。一种部分握手方法混合了电平与脉冲信号,而其它的方法则只使用脉冲信号。 在第一种部分握手方法中,电路 A 以有效电平声明其请求信号,电路 B 则以一个单时钟宽度脉冲作为响应。此时,电路 B 并不关心电路 A 何时中止它的请求信号。但为了使这种方法成立,电路 A 中止请求信号至少要有一个时钟周期长,否则,电路 B 就不能区别前一个请求和新的请求。在这种握手方式下,电路 B 为请求信号使用一个电平同步器,电路 A 为响应信号使用一个脉冲同步器。只有当电路 B 检测到请求信号时才发出响应脉冲。这种情况可以使电路 A 通过控制其请求信号的时序,控制同步器接收到的脉冲间隔(图 5)。同样可以用经验估算法确定时序,即信号跨越一个时钟域要花两个时钟周期并且在跨越时钟域前被电路寄存。
在进行信号同步时有一个重要的规则,那就是不应当在设计中的多个地方对同一信号进行同步,即单个信号扇出至多个同步器。因为同步要花一到两个时钟周期,设计者不能确切地预测到每个信号何时跨越一个时钟域。此外,在新时钟域中一组经同步后的信号其时序是不定的,因为同步延迟可以是一到两个时钟周期,这与输入信号到达同步器的时间有关。这种情况会在各个同步信号间形成一种“竞争状况”。这种竞争状况在需要跨越时钟域传输的多组信号间也会发生,例如数据总线、地址总线和控制总线等。因此,不能对组中的每个信号单独使用同步器,也不能对数据或地址总线的每一位单独使用同步器,因为在新的时钟域中,要求每个信号同时有效。 一种解决总线同步问题的方法是使用一个保持寄存器和握手信号。这种电路包括一个保持信号总线的寄存器,以及一个握手机制(图 7)。握手信号指示新时钟域的电路何时可以对总线采样,以及源电路何时可以更换当前寄存器中保存的内容。
用这种总线同步方式,你可以同步握手信号,但不能同步信号总线。信号总线来自于保持寄存器,它在接收电路采样前一直保持稳定。注意,如果传输电路向接收电路提交数据太快以致来不及处理,则应用中的总线同步可能不起作用。 高级数据路径设计 在许多情况下,数据在跨越时钟域时需要“堆积”起来,因此使用单个保持寄存器无法完成工作。例如一种情况是某个传输电路猝发式发送数据,接收电路来不及采样。另一种情况是接收电路采样速度超出传输电路发送数据的速度,但采样的数据宽度不够。这些情况就要使用 FIFO 了。 基本上,设计者使用 FIFO 有两个目的:速度匹配或数据宽度匹配。在速度匹配时,FIFO 较快的端口处理猝发的数据传输,而较慢的端口则维持恒定的数据流。但是,虽然访问方式和速度不同,但进出 FIFO 的平均数据速率必须是相同的,否则 FIFO 就会出现上溢(over flow)或下溢(underflow)问题。与单寄存器设计相同,FIFO 将数据保存在寄存器或存储器中,同时同步状态信号,判断何时可以把数据写入 FIFO 或从 FIFO 中读出。 在速度匹配应用中,每个端口(读或写)的时钟不同。FIFO 中的寄存器使用写端口时钟,就像保持寄存器使用电路时钟来改变寄存器内容一样。信号同步发生在指针逻辑中,而且比握手信号要复杂得多。 现在指针逻辑的设计有多种方法。第一种方法是将读、写选通进行同步,同时在各个时钟域使用计数器来跟踪 FIFO 中可用的项。计数器反映出可用于读写的 FIFO 项目号,计数器也与相应的端口同步。读计数器跟踪包含有效数据的项数,而写计数器则跟踪可以存储数据的项数。当对指针逻辑进行复位时,由于没有数据可读,读计数器从零起始。写计数器则从 FIFO 中项的总数开始计数,即所有项均可用来存储数据。 读选通信号累减读计数器,并与写时钟域同步,因为它同时也累加写计数器。写选通信号则累减写计数器,并与读时钟域同步,因为它同时也累加读计数器。 这种设计需要单时钟宽度脉冲以及用于读、写选通的脉冲同步器,因为当一个电平信号从一个时钟域跨越到另一个更快的时钟域时,在较快时钟域中它能在更多的时钟周期中保持有效。由于只要读或写信号是有效的,每个计数器就会发生变化,因此较快的时钟域就检测到更多的读、写,超出较慢时钟域实际发生的数量。脉冲同步器可以将一个时钟域的时钟宽度脉冲转换为新时钟域的时钟宽度脉冲,每个脉冲都表示一次 FIFO 的读或写。 这种 FIFO 状态技术对读、写状态都不太有利。当 FIFO 中所有项均充满时,写端口状态指示为满,并在读选通触发后继续指示 FIFO 满,因为同步过程会使选通信号延迟送给写计数器。读端口为空时也会出现这种情况,因为同步过程会使写选通信号延迟到达读计数器。 这种设计的另一种考虑是及时检测全满/全空状态。如果 FIFO 还有一项可用,并且有写选通触发,则 FIFO 必须立即置为全满状态。这样才能提前一个时钟给出全满标志,使 FIFO 有足够时间防止下一个数据写入而产生溢出。对 FIFO 的读端口也是这样。这种情况下,如果 FIFO 里只有一个数,并且有读选通触发,则必须置全空状态,以给读电路足够的时间防止读空 FIFO。 这种指针逻辑限制电路在每个时钟周期中访问 FIFO,即使在慢速时钟域中也是这样。这一功能的优点在于访问 FIFO 的电路至少有一个时钟周期来评估 FIFO 的状态。FIFO 可以将所有项都填满数据,而不会出现数据被覆盖或全空无数据可读的情况。这种设计的另一个优点是每一端都可以读其相应的计数器,来判断 FIFO 中还有多少项可用。设计者可以将这种 FIFO设计用在进行多次数据读/写的电路中,而不会造成上溢或下溢的情况。 这种设计的不足之处是由计数器来判断状态,而不是直接比较读、写指针。对大型 FIFO 来说,这些计数器也很大。而且,由于使用脉冲同步时,来自较快时钟域的读、写脉冲在较慢时钟域的脉冲间至少必须有两个时钟周期,因此平均数据速率为最低时钟频率的一半。解决这些问题的一种方法是采用直接指针比较法。 在这种 FIFO 设计中,读、写指针的比较决定了 FIFO 的状态。异步设计中的指针比较更富有挑战性,因为每个指针位于不同的时钟域中,对信号总线的同步要求在同步握手信号期间总线不发生改变。将这种技术用于指针同步的 FIFO 设计可能会很慢。要解决这个问题,FIFO 指针逻辑使用了格雷码,代替指针使用的二进制码。 格雷码在每一次计数增减时只改变其中的一位(表 3)。你可以在格雷码总线上使用同步器,因为每一次总线改变时只有一根信号线有变化,于是就消除了格雷码总线各位通过不同同步器时的竞争情况。这种设计的指针为格雷码计数器。使用二进制指针时需要将其变换成格雷码后的同步指针,而使用变换逻辑会违反对同步信号的限制,即同步的信号在跨越时钟域前要来自触发器。
这种 FIFO 状态技术会给读、写带来不良状态。当 FIFO 满时,写端口的状态指示已满,而在电路从 FIFO 中读出一项后,该状态仍为满,因为同步机制使读指针相对写入一侧的比较逻辑有个延迟。同样,在读出一侧的空状态指示也有这个问题,因为同步机制使写指针相对读出一侧的比较逻辑有延迟。 如果你在设计跨不同时钟域电路时,使用一些技术来降低通信失败的风险,则处理跨时钟域的信号就不再是艰巨的任务。同步机制可以防止接收跨时钟域信号的触发器出现亚稳态,从而避免导致不可预知的电路行为。对于在多个时钟周期内一直保持有效的信号来说,电平同步器的效果很好。对于要转换成新时钟域脉冲的较慢时钟域电平信号,要采用边沿检测同步器。最后,对跨时钟域的脉冲信号应使用脉冲同步器。还要记住,当一个信号总线跨越时钟域时,整个总线要在同一个时钟周期内到达新的时钟域。不要分别同步每一个信号,而要采用一个保持寄存器和握手方式。握手用来表示寄存器中的信号何时有效,何时可以采样。对数据总线来说,握手和一个保持寄存器很有用,但每次向新时钟域传送的数据字不超过一个。 |
|
来自: lansewanmei521 > 《FPGA》