湘潭大学物理与光电工程学院 吴修英
湖南进芯电子科技有限公司 黄嵩人
信号的跨时钟域传输很容易产生亚稳态,而亚稳态对于SOC的稳定运行又是潜在的巨大危险。异步信号的跨时钟域处理又分为一位信号的同步和多位数据信号的同步。本文所研究的异步FIFO为多位数据信号的同步,主要作为不同时钟域之间数据传输的中间缓存使用,大大降低了异步信号可能带来的亚稳态[1]。FIFO是一种先入先出存储器,没有外部读写地址线,因此只能顺序写入和读出,待写入及读出的数据位置由内部读写地址指针产生。
本项目所研发DSP采用改进型哈佛架构[2],集成有CPU及浮点处理器FPU。具有三组独立的地址总线及三组独立的数据总线。因此CPU对指令的读取和对数据的操作可以同时进行,因此大大提高了CPU的运行速度,而flash、eeprom等非易失存储器的存取速度远低于CPU的运行速度,若是使用CPU直接和低速存储器进行通信,则造成CPU的资源巨大浪费,为了匹配速度上的差别,为此特设计了异步FIFO模块以实现速度的匹配。该DSP集成了I2C、SPI、PWM和EQEP等多种外设。
如图1所示为异步FIFO的设计框图。
图1 异步FIFO工作原理图
根据异步FIFO的工作原理,先定义出异步FIFO的主要端口信号及相关参数如下:
FIFO的深度:FIFO存储体中所能容纳的数据的总数。
FIFO的宽度:FIFO进行一次读或者写操作的数据位的位数。FIFO满标志:满标志位是由其状态电路发出的指示信号,表示FIFO已满或者将要满,以阻止外部继续对其进行写操作而造成数据丢失。
FIFO空标志:空标志位是由其状态电路发出的指示信号,表示FIFO已空或者将要空,以阻止外部继续对其进行读操作而造成读出无效的数据。
读数据时钟rclk:读操作所遵循的时钟,在每个有效时钟沿来临时读出数据。
写数据时钟wclk:写操作所遵循的时钟,在每个有效时钟沿来临时写入数据。
读数据指针rptr:指向下一个将要读出的数据的地址,读完后自动加1。
写数据指针wptr:指向下一个将要写入的数据的地址,写入后自动加1。
异步FIFO的设计主要包括两大模块,一个是用于存储数据的存储体的设计,该存储体一般使用代工厂提供的IP核;另一个是FIFO的读写控制器的设计。控制器主要是读写地址产生逻辑和空满标志产生逻辑。
通过对读指针和写指针的比较,就可以产生FIFO空或者满标志位。由于读写指针是属于不同的时钟域,而不同时钟域之间直接比较会产生亚稳态的问题,因此要对其读指针和写指针进行比较的前提是将这两个信号先同步到同一个时钟域。在此设计中使用两级D触发器串联来构成同步器,以对对这两个信号进行同步[3]。
一般计数器的设计会采用二进制直接设计,这在同一个时钟域里没有什么大的问题,但对于跨时钟域的设计采用二进制计数器则容易产生毛刺,而导致不稳定,因为二进制数从一个数值变换到另一个数值时可能多位数据位都会跳变,比如由1111到0000的跳变。而跳变的位数越多,在采样时越容易产生错误。为了减小这种错误的发生,采用格雷码对该计数器进行设计是一个很好的选择,因为格雷码在计数时由一个值跳变到下一个计数值时仅有一位发生跳变,这就大大降低了采样错误的可能性。由于设计者大多习惯于二进制计数制,所以设计中采用二进制计数,但是要将二进制数再转换为格雷码以降低误码率。
根据二进制数与格雷码之间的关系,可知二进制数到格雷码转换的公式为:
Gray =(bin[n-1:0])^{1’b0,bin[n-1:1]};
格雷码到二进制数的转换公式为:
bin[i] = ^(gray[n-1:i])
FIFO何时为空,何时为满?对于FIFO的读写指针,总是指向下一个待读出或者写入的位置。约定在复位后读写指针同时回到初始位置,此时FIFO已经为空,只能对其进行写人操作,写入后如果再对其进行读操作,如果读时钟大于写时钟,那么读指针总会赶上写指针。那么当读指针等于写指针的时候就认为FIFO已空,此时产生有效的空标志位。与之相比满标志位的产生相对复杂些,如果写指针已经指向FIFO的顶端并且此时还在继续写操作,则写指针又回到FIFO的底部并开始向上增长,如果写指针又“追赶上”了读指针,则认为FIFO已满。但是满和空的条件都是读写指针指向FIFO同一位置[4]。究竟如何让硬件判断是满还是空?为了区分两种标志位,采用增加最高位地址位的办法,低位地址用来作为指针对存储体进行寻址,最高位作为空满标志的判断位。若是读写指针的低位相同且最高位也相同,则空标志位有效;若是读写指针的低位相同但最高位不同,则满标志位有效。
该模块采用两级D触发器的级连采样同步,将格雷码表示的读指针同步到写指针的时钟域,采用两级同步可以很好的消除亚稳态,对于频率很高的设计,建议采用三级DFF同步采样。采用同样的设计方法亦可实现写指针到读指针的同步模块wr_to_re的设计。Verilog设计主要部分代码如下:
该模块用来实现FIFO的读控制,主要用来产生读寻址指针、读比较指针和二进制数到格雷码的转换。在设计中读寻址指针比读比较指针少一位,器设计原理见3.3节空满标志位的产生。基于同样的原理可设计出写控制器模块wr_ctrl。模块verilog设计代码如下:
根据上述对异步FIFO的理论分析及功能设计,采用业界流行的verilog语言对设计的模块进行RTL级建模。对于验证测试采用流行的EDA工具Synopsys公司的Ncverilog仿真工具,建立相应的Test bench,对所设计的异步FIFO的RTL级描述进行功能验证[5]。仿真波形如图2所示,对比仿真波形及功能需求可知,该异步FIFO的设计完全符合功能要求。该异步FIFO 成功应用于所研发的项目32位浮点型DSP中,实现了从外挂SPI Flash中缓存数据和程序,实现高速CPU和低速外设之间的速度匹配。其中的格雷码使用也大大降低了产生亚稳态的可能性。
当wclk周期为100ns,rclk周期为200ns时,仿真波形如下:
当wclk周期为200ns,rclk周期为100ns时,仿真波形如下:
图2 异步FIFO仿真波形图
[1]李广军,林永生.Verilog HDL高级数字设计(第二版)[M].北京:电子工业出版社,2014.2:383-391.
[2]TMS320F28335 Digital Signal Controllers Data Manual.pdf[OL].2007.6:58-64.
[3]周润德,等译.数字集成电路—电路、系统与设计(第二版)[M].北京:电子工业出版社,2010.11:392-396.
[4]Simulation and Synthesis Techniques for Asynchronous FIFO design.pdf[OL].
[5]夏宇闻,杨雷,陈先勇等译.SystemVerilog验证方法学[M].北京:航空航天大学出版社,2007,5:173-187.