异步FIFO的实现方式_第1页
异步FIFO的实现方式_第2页
异步FIFO的实现方式_第3页
已阅读5页,还剩13页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、异步FIFO的实现方式实验目的本次实验介绍一种异步 FIFO的实现方式。使用FIFO存储器可以在两个不同时钟系统之 间快速而方便的传输数据。另外,在网络接口,图像处理等方面异步FIFO存储器也得到了广泛的应用。因此,异步FIFO存储器具有较大的研究和应用价值。异步FIFO的介绍和整体结构异步FIFO(First In First Out)存储器是指向 FIFO缓冲器中写入数据的时钟域和从FIFO缓冲器中读取数据的时钟域是不同的,这两个时钟之间没有必然的因果关系。异步FIFO是一种先进先出的电路,使用在异步时钟域数据接口的部分,用来存储、缓冲在两个异步时钟之间的数据传输。 在异步电路中,由于时钟

2、之间周期和相位完全独立,所以数据的丢失概率不为零。如何设计一个高可靠性、高速的异步FIFO存储器便成为一个难点。异步FIFO的一般结构如图1所示,都是由一个读时钟域电路、一个写时钟域电路和一 个双端口的RAM来构成的。异步FIFO与同步FIFO所做的工作是相同的, 都是在写信号有效 时写数据到RAM中,在读信号有效时把数据从 RAM中读出,所以对于中间部分的 RAM设计是 比较简单的。另外,读电路和写电路单独实现起来也是比较容易的,只需要按照同步FIFO的工作情况,如果没有写满或读空的状态时每写一个数据就把写地址加1,每读一个数据就把读地址减1。设计难点在于两个时钟域的交叠部分:满、空状态的产

3、生,这也是设计的重点。图1异步FIFO结构针对这个问题,先从对亚稳态的处理开始介绍亚稳态的处理一个触发器进入亚稳态时,既无法预测该单元的输出电平,也无法预测何时输出才能稳定在某个正确的电平上。 在这个稳定期间,触发器输出一些中间级电平, 或者可能处于振荡 状态、并且这种无用的输出电平可以沿信号通道上的各个触发器级联式传播下去。亚稳态发生的原因是由于在同步系统中,如果触发器的建立时间或保持时间不满足,就可能产生亚稳态,此时触发器输出端 Q在亚稳态是指触发器无法在某个规定时间段内达到一个可确认的状 态,逻辑误判有可能通过电路的特殊设计减轻危害(如本设计中将使用的 Gray码计数器),而亚稳态的传播

4、则扩大了故障面,难以处理。在数字集成电路中寄存器要满足建立时间和保持时间。建立时间是在时钟翻转之前数据输入必须有效的时间, 保持时间是在时钟沿之后数据输出必须仍然有效的时间。当一个信号被寄存器锁存时,如果信号和时钟之间不满足这个要求,Q的值是不确定的,并且在未知的时刻会固定到高电平或低电平。此时寄存器进入了亚稳态(Metastability)。解决这一问题的最简单方法是使用同步器,使得在另一个时钟域采样时信号足够稳定。同步器的设计本身就是一个比较麻烦的问题,本次设计中也不深入讨论一些细节性的问题,直接采用两级采样的同步器,避免了使用一级同步器仍可能出现亚稳态的情况。每个这样的同步器都具有一个等

5、于时钟周期的等待时间。这种同步器可以把一些亚稳态的值同步为确定值,但并不一定是正确值, 同时有一些亚稳态也还是无法稳定成确切值的,这种情况称为同步出错。由于同步出错的随机性,很难对它们进行跟踪。如果想进一步降低亚稳态出现 的概率、可以再増加同步器的级数,但是太多的同步器会使系统的性能下降,所以系统中不会用太多的同步器,一般使用两个同步器已经足够。空满状态的判断之所以在前面介绍了亚稳态的问题,是因为这是判断满状态或空状态无法回避的一个问题。因为读电路在读控制时维持一个地址指针,写电路在写控制时维持一个地址指针,简单来说,这两个地址指针直接一比较,就能得到空满的判断结果,但是实际操作起来非常麻烦。

6、 例如对于满状态来说, 这是写入电路所关心的状态,因为满状态下不能继续写入数据,但是空状态对于写电路没有影响。如果写入电路要判断当前FIFO是否为满,就需要把写电路自身维持的写指针和读电路维持的读指针做比较,这个读指针就需要送入写电路中,此时就发生了穿过时钟域的问题,也就是说,读指针要从读时钟域同步到写时钟域,然后参与判断, 此时就需要前面介绍的同步器。同样,对于空状态来说, 这是读出电路所关心的状态,也是由读电路来维持的,因为空状态下再读数就会得到错误的数据,但是满状态下读数是没有影响的。如果读电路要判断当前FIFO是否为空,就需要把写时钟域中的写指针取到读时钟域来,和读时钟域的读指针进行比

7、较得出是否是空状态,同样跨越了时钟域。在跨时钟域系统中希望出现错误的概率越低越好,此时格雷码无疑是最好的一个选择。格雷码属于可靠性编码,是一种误差最小化的编码,它大大减少了由一个状态到下一个状态时电路混淆。由这种编码相邻的两个码组之间只有一位不同,和其他编码同时改变 2位和多位的情况相比更为可靠。表1所示是格雷码与二进制码的对应关系。十进制二进制格雷码NBBBBGGGG000000000100010001200100011300110010401000110501010111601100101701110100810001100910011101101010111111101111101211

8、001010131101101114111010011511111000表1格雷码与二进制码转换真值表由前面的介绍可知通过同步器之后信号稳定的值可能是1也可能是0,可能与输入的值相同也可能与输入的值不同。如果对于二进制码,这显然是灾难性的。例如从十进制的7变到8,二进制码是从0111变为1000,把0111送入同步器之后,由于4位都要变化,所以4位都可能会出现亚稳态,从而在同步器的输出端就会出现各种可能性,这样即使数据稳定 下来,对整个电路的作用也很小。而如果采用格雷码,是从0100变为1100,只是最高位发生了改变,也就只有这一位可能会出现亚稳态的情况。这样经过同步器处理之后,输出端可能得到

9、的值只有两种 0100或1100,其中1100是正确的数值,如果得到这个输出自然是最 好,但即使是0100的输出,也只是和原来的值相同,可以认为没有变化,这也不会对电路 造成负面的影响。相比二进制代码那种变化后什么值都有可能的情况,格雷码显然是一种更易于接受的编码方式。格雷码虽然在跨时钟域方面效果比较好,但在本身计数方面是不足的,也就是说还需要把格雷码转换成二进制码来计数,4位的格雷码转二进制码的代码部分如下:bi n0=gray3Fgray2F gray1A gray0;bi n1=gray3Agray2A gray1;bi n2=gray3Agray2;bi n2=gray3;也可以用fo

10、r循环完成:module gray2(bi n,gray);parameter size=4;output size-1:0 bin;in put size-1:0 gray;reg size-1:0 bin;in teger i;always (gray)for(i=0;i,size;i=i=i+1);bin i=A(gray>>1);en dmodule计数之后还要变回格雷码,转换的方法与上述方式类似。这样使用格雷码作为指针就可 以降低亚稳态带来的影响。接下来要解决的是空满判断的问题,常用的判断方法是附加位比较法。附加位比较法是给每个指针增加一个附加位,对于二进制指针而言, 将

11、存储空间的最后一个存储单元写入数据后,地址将变为零,即地址指针低n-1位清零并向最高位(MSB)也就是附加位进位。读指针也是如此工作。如果两个指针的最高位(MSBs)不同而其余位相同,就说明写指针比读指针多循环了一次,标志FIFO存储器处于满状态。如果包括最高位在内的两个指针完全相同,则说明写指针和读指针经历了相同次数的循环,也就是说FIFO存储器处于空状态。这样读指针和写指针就变成了一个n位指针,其中低n-1位是用来存放FIFO存储器的地址,可以用来对 2n-1个存储单元寻址,而最高位则用来辨别当两个指针的地址相 等时是满状态还是空状态。对二进制指针来说,用这种方式来区分满状态与空状态是可行

12、的。但是,格雷码指针却不能直接使用这种方式,原因有两个。举个4位格雷码的例子,格雷码计数器的低 3位用于存放存储地址,第四位是附加位,这个FIFO存储器的存储容量为 &正确的操作应当是,当写(或读)完一个循环时,地址应该重新开始计数,附加位应该翻转。 然而格雷码指针却并非如此,地址由7到8格雷码由0-100到1-100),指针的附加位改变,但是地址位(低n-1位)却没有重新开始计数,这是由于格雷码是一种镜像码造成的。第二个原因是这种格雷码不能直接产生满状态标志。如果两个格雷码指针都是 Gray-7,这时的FIFO存储器为空状态,在进行一次写操作后写指针将加1,格雷码第4位将变为1而低3

13、位不变,这时的读指针和写指针的最高位将不同而低位相同。如果这样的话,FIFO存储器满标志将置位,这显然是错误的,因而需要对这个4位的格雷码进行修改。想要的结 果是:一个n位的(即包括附加位)格雷码计数器用在异步时钟域间传递数据,但是又希望它 的低n-1位计数器也是格雷码类型的。这样低n-1位就能单独形成一个循环,而不是一种反射码。所以,此时需要的是一个既能产生n位的格雷码序列又能产生n-1位的格雷码序列的计数器。分别实现一个 n位的格雷码计数器和一个 n-1位的格雷码计数器自是非常简单:用 一个计数器来实现一个 n位的格雷码计数器,并将这个计数器的次高位进行修改而低位保持 不变以实现一个n-1

14、位的格雷码计数器,这也不是一件很难的事情。这种既能产生n位格雷 码又能产生n-1位格雷码的计数器被称为”两重格雷码计数器。下面以3位和4位格雷码来说明空满状态的判断标准。3位格雷码表示的就是地址空间,可以有8个存储空间。由于写入和读出并不是按照从000开始的,而是可以以任意一个位置开始,比如存放数据可以按照十进制地址5、6、7、0、1、2、3、4的地址顺序来存放,读出数据也同理,这样为了表示循环,就增加了1位变为4位格雷码。首先说明空状态的判断标准,空状态表示读指针和写指针重合, 此时无论是看3位格雷 码还是4位格雷码都应该是完全相同, 比如写指针指向1010,读指针也必然指向1010,这样

15、判断空状态就只需要判断两个指针是否相同,相同时即为空,不同时即为不空。然后解释满状态的判断标准。满状态判断比较复杂。假设一次写入数据是从十进制地址6开始,连续写入 8个数据。到14,这时存满8个数据,应产生满状态输出,这两个地址形式如下:十进制地址6二进制地址0110格雷码地址0101十进制地址14二进制地址1110格雷码地址1001如果是二进制地址,判断的方法已经介绍过了。 而格雷码地址的前两位是不同的,但后面的两位是相同的。如果扩展成更多位的格雷码, 满状态下依然是这种情况, 即前两位不同, 后面位均相同。这样判断满状态首先要保证除去前两位之后的剩余部分是相同的。然后对于本例来说,需要保证

16、前两部分是01和10,如果地址是以01开头,则满时一 定是10;如果以10开头,满时一定是 01。判断的方法可以有很多种,这里采用先取前两位的异或值,保证相等,此时只可能是0, 1的组合,然后再判断首位不同,这样就只能是 01和10这两种情况。经过这三个条件的判断,就能就保证此时为写满状态。再观察地址以00和11开头的情况,给出地址如下十进制地址2二进制地址0010格雷码地址0011十进制地址10二进制地址1010格雷码地址1111刚才提出的的三个条件依然保证写满状态的正常输出,所以写满状态就以这三个条件作判断标准。F面开始具体设计:顶层模块的端口和功能针对异步FIFO的基本结构和功能,以及保

17、留一些必要的状态信号和控制信号,现确定顶层 模块的端口与功能见表 2:端口名称功能说明rclk输入信号,1位,读时钟wlck输入信号,1位,写时钟rinc输入信号,1位,读使能信号,高电平时生效,表示写入数据wi nc输入信号,1位,写使能信号,高电平时生效,表示读出数据rrst n输入信号,1位,低电平时读指针清零wrst_ n输入信号,1位,低电平时写指针清零Rdata输出信号,8位,从RAM中读出数据Wdata输入信号,8位,待写入RAM数据Wfull输出信号,1位,高电平时表示 FIFO已存满数据,已满Rempty输出信号,1位,高电平时表示 FIFO中数据已全部读出,已空表2顶层模块

18、的端口与功能子模块设计本设计的异步FIFO划分为5个子模块:读指针控制模块、写指针控制模块、存储RAV模块、 读指针同步到写时钟域模块,写指针同步到读时钟域模块。依次介绍如下:两个同步模块这两个同步模块同前文介绍的一样,是两个寄存器连接的一起。写指针同步到读时钟域模块代码如下module syn e_w2r(rwptr2,wptr,rclk,rrst_ n);parameter ADDRSIZE=4;output ADDRSIZE:0 rwptr2; /同步后的写指针in put ADDRSIZE:0 wptr;/同步前的写指针in put rclk,rrst_ n;reg ADDRSIZE:

19、O rwptr2,rwptr1; /两个中间寄存器always (posedge rclk or n egedge rrst_ n)if(!rrst_n)rwptr2,rwptr1<=0; /复位elserwptr2,rwptr1<=rwptr1,wptr; /寄存器串联En dmodule读指针同步到写时钟域模块代码如下:module syn c_r2w(wrptr2,rptr,wclk,wrst_n);parameter ADDRSIZE=4;output ADDRSIZE:0 wrptr2;in put ADDRSIZE:0 rptr;in put wclk, wrst_ n

20、;reg ADDRSIZE:O wrptr2, wrptrl;always (posedge wclk or n egedge wrst_ n)if (!wrst_ n)wrptr2, wrptrl<=0;elsewrptr2,wrptrl<= wrptrl,rptr;en dmodule功能比较简单,故不做仿真验证存储模块module fifomem(rdata, wdata, waddr,raddr, wclke n, wclk,rclke n,rclk);parameter DATASIZE=8;/parameter ADDRSIZE=4;/output DATASIZE-1

21、:0 rdata;input DATASIZE-1:0 wdata;in put wclke n, wclk,rclke n,rclk;/in put ADDRSIZE-1:0 raddr, waddr;/reg DATASIZE-1:0 rdata;数据宽度地址宽度读写控制和时钟 输入读写地址reg DATASIZE-1:0 MEM 0:(1<<ADDRSIZE)-1; /存储体always (posedge rclk)/if (rclke n) rdata = MEMraddr;读时钟读出数据always (posedge wcik)if (wclke n) MEMwaddr

22、<= wdata; /写时钟写入数据en dmodule此模块构造了一个存储器,按读写始终安排输入和输出。编写测试模块如下:module tbmem;parameter DATASIZE=8;parameter ADDRSIZE=4;wire DATASIZE-1:0 rdata;reg DATASIZE-1:0 wdata;reg wclke n, wclk,rclke n,rclk;reg ADDRSIZE-1:0 raddr, waddr;in teger seed1;in itialbeginwclk=0;rclk=0;seed1=20; /初始化waddr=0;raddr=0;

23、endalways #9 wclk=wclk; /生成写时钟always #11 rclk=rclk; /生成读时钟always (posedge wclk)wdata<=$ra ndom(seed1)/256; /产生随机写入数据in itialbeginwclke n=1;rclke n=0;repeat (10) (posedge wclk); /wclke n=O;rclke n=1;repeat (6) (posedge rclk); /wclke n=1;rclke n=1;#99 $stop;end写入10个数据读出6个数据always (posedge wclk) if(

24、wclke n=1) waddr=waddr+1; /写地址生成always (posedge rclk)/读地址生成if(rclke n=1) raddr=raddr+1;fifomem fifomem(rdata, wdata, waddr,raddr, wclke n, wclk,rclke n,rclk);en dmodule仿真波形如图2所示图2存储仿真波形第一行为读出数据,第二行为写入数据,图中第一行和第二行数据是完全对应的。读地址控制模块FIFO存储器空状态是在读时钟域中生成的,这样就可以确保一旦FIFO存储器达到空状态时就能被检测到。也就是说,在读时钟域里读指针可以在读时钟周期

25、内与同步而来的写指 针(包括附加的最高位 MSB进行比较。当读指针与同步的写指针rwptr2相等时,FIFO存储器为空状态,此时FIFO存储器停止读取数据,否则会导致向下溢出(un derflow)。比较读指针和同步的写指针以生成空标志的比较器很容易实现。FIFO存储器的指针总是预先指向下一个内存位置,每进行一次读写操作,相应的指针就增加一次。如果读指针与同步的写指针rwptr2的附加位(这两个指针的最高位MSBs是相等的,则这两个指针经历了相同的循环次数,假如这时两个指针的低位(共n-1位)也相等,FIFO存储器就为空状态。在这个模块中包含了除读同步模块之外的所有读时钟域的逻辑电路。读指针是

26、"两重格雷码计数器”。位指针rptr被同步到写时钟域中,n-1位指针用于产生地址。当读指针rptr的下一个状态rgnext等于同步的写指针rwptr2时,空状态标志将在下一个读时钟的上升沿 被置位。这个模块已经是一个读时钟域的同步时序电路,这有利于进行静态时序分析。模块包含读指针电路和空标志逻辑电路,代码如下:module rptr_empty(rempty,raddr,rptr,rwptr2,ri nc,rclk,rrst_ n);parameter ADDRSIZE=4;output rempty;output ADDRSIZE-1:0 raddr;output ADDRSIZE

27、:O rptr;in put ADDRSIZE:O rwptr2;in put rinc, rclk,rrst_ n;reg ADDRSIZE:O rptr,rbi n,rgn ext,rb next;reg rempty,raddrmsb;always (posedge rclk or n egedge rrst_ n)if(!rrst_ n)beginrptr <=0;raddrmsb<=0;endelsebeginrptr <=rgn ext;raddrmsb <=rg nextADDRSIZEWg nextADDRSIZE-1; endalways (rptr

28、or rinc) begi n:Gray_i ncin teger i;for(i=0;i<=ADDRSIZE;i=i+1)rbin i=A(rptr»i);/if(!rempty)rbn ext=rb in+rinc; /elserbn ext=rb in;rgn ext = (rbn ext>>1)Arb next; / end格雷码转换为二进制码增加FIFO计数二进制转化为格雷码always (posedge rclk or n egedge rrst_ n)if(!rrst_ n)rempty<=1'b1;/复位时输出空elserempty&l

29、t;=(rg next=rwptr2); /否则判断是否满足条件assig n raddr = raddrmsb,rptrADDRSIZE-2:0; /读地址指针en dmodule读地址控制模块主要的部分按代码顺序有复位部分,完成复位功能计数部分,完成格雷码转二进制计数再转换成格雷码;空状态判断部分,复位时输出空,读指针和同步后的写指针相同时出示空状态;最后是一个读地址的拼接输出。为此模块编写测试模块,代码如下:module tbrptr; parameter ADDRSIZE=4;wire rempty;wire ADDRSIZE-1:0 raddr;wire ADDRSIZE:O rpt

30、r; reg ADDRSIZE:O rwptr2;reg rinc, rclk,rrst_ n;in itialbeginrclk=0;rrst_ n=1;ri nc=0;rwptr2=14;#3 rrst_n=0;#4 rrst_ n=1;#6 rin c=1;end always #11 rclk=rclk;in itialbeginrepeat (5) (posedge rclk);(posedge rempty);#20 $stop;end rptr_empty rptr_empty(rempty,raddr,rptr,rwptr2,ri nc,rclk,rrst_ n);en dmo

31、dule仿真波形如图3所示图3读地址控制模块波形中第一行是空状态,一开始复位一次,计数到 0110时与预置的写指针相同,空状态重 新变为高电平。此模块可正常完成地址计数和空状态的生成,功能验证结果正确。写指针控制模块与读指针控制模块代码基本相同。此模块仅在满状态判断部分不相同。代码如下:module wptr_full(wfull,waddr,wptr,wrptr2,wi nc,wclk,wrst_ n);parameter ADDRSIZE = 4;output wfull;output ADDRSIZE-1:0 waddr;output ADDRSIZE:0 wptr;input ADDR

32、SIZE:0 wrptr2;in put wine, wclk, wrst_ n;reg ADDRSIZE:O wptr, wbin, wgnext, wbnext; reg wfull, waddrmsb;wire w_2n dmsb,wr_2 ndmsb; /添加的判断信号always (posedge wclk or n egedge wrst_ n) if (!wrst_ n)beginwptr <= 0;waddrmsb <= 0;endelsebeginwptr <=wg next;waddrmsb <=wg nextADDRSIZEFwg nextADDR

33、SIZE-1; endalways (wptr or wi nc) begi n: Gray_ incin teger i;for(i=0; i<=ADDRSIZE; i=i+1)wb in i= A (wptr»i);/if (!wfull)wbn ext = wbin+winc; /FIFOelsewbn ext = wbin;wgn ext=(wb next>>1) a wbn ext; / end格雷码转二进制计数二进制转格雷码assig n w_2n dmsb = wgn extADDRSIZE a wgn extADDRSIZE-1; / assig n

34、 wr_2 ndmsb = wrptr2ADDRSIZE a wrptr2ADDRSIZE-1; / 位异或写指针前两位异或同步后的读指针前两always (posedge wclk or n egedge wrst_ n)if (!wrst_ n)wfull<=0;elsewfull <= (wg nextADDRSIZE !=wrptr2ADDRSIZE) &&(w_2n dmsb=&& (wg nextADDRSIZE-2:0= wrptr2ADDRSIZE-2:0); /均满足则满_2n dmsb)三个判断条件assig n waddr= w

35、addrmsb,wptrADDRSIZE-2:0;en dmodule由于功能基本相似,此模块不再列出仿真整体仿真结果将五个子模块合成一个顶层模块,代码如下:module fifo_asyn 1(rdata,wfull,rempty,wdata,wi nc,wclk,wrst_ n,ri nc,rclk,rrst_ n); parameter DSIZE = 8;/数据存储宽度parameter ASIZE = 4;/存储地址宽度output 7:0 rdata;outputwfull;output rempty;in put 7:0 wdata;in putwin c,wclk,wrst_

36、n;in putrin c,rclk,rrst_ n;wire 3:0 waddr,raddr;wire 4:0 wptr,rptr,wrptr2,rwptr2;sync_r2wsyn c_r2w(.wrptr2(wrptr2),.rptr(rptr),.wclk(wclk),.wrst_n(wrst_ n); syn e_w2rsyn e_w2r(.rwptr2(rwptr2),.wptr(wptr),.rclk(rclk),.rrst_ n(rrst_ n); fifomem fifomem(.rdata(rdata),.wdata(wdata),.waddr(waddr),.raddr(raddr),.wclke n(win c),.wclk(wclk),.rclke n(rin c),.rclk(rclk);rptr_empty rptr_empty(.rempty(rempty),.raddr(raddr),.rptr(rptr),.rwptr2(rwptr2),.rinc(rin c),.rclk(rclk),.rrst_ n(rrst_ n); wptr_full wptr_full(.wfull(wfull),.waddr(waddr),.wptr(wptr),.wrpt

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论