(完整word版)异步FIFO的实现方式

(完整word版)异步FIFO的实现方式
(完整word版)异步FIFO的实现方式

异步FIFO的实现方式

实验目的

本次实验介绍一种异步FIFO的实现方式。使用FIFO存储器可以在两个不同时钟系统之间快速而方便的传输数据。另外,在网络接口,图像处理等方面异步FIFO存储器也得到了广泛的应用。因此,异步FIFO存储器具有较大的研究和应用价值。

异步FIFO的介绍和整体结构

异步FIFO(First In First Out)存储器是指向FIFO缓冲器中写入数据的时钟域和从FIFO缓冲器中读取数据的时钟域是不同的,这两个时钟之间没有必然的因果关系。异步FIFO是一种先进先出的电路,使用在异步时钟域数据接口的部分,用来存储、缓冲在两个异步时钟之间的数据传输。在异步电路中,由于时钟之间周期和相位完全独立,所以数据的丢失概率不为零。如何设计一个高可靠性、高速的异步FIFO存储器便成为一个难点。

异步FIFO的一般结构如图1所示,都是由一个读时钟域电路、一个写时钟域电路和一个双端口的RAM来构成的。异步FIFO与同步FIFO所做的工作是相同的,都是在写信号有效时写数据到RAM中,在读信号有效时把数据从RAM中读出,所以对于中间部分的RAM 设计是比较简单的。另外,读电路和写电路单独实现起来也是比较容易的,只需要按照同步FIFO的工作情况,如果没有写满或读空的状态时每写一个数据就把写地址加1,每读一个数据就把读地址减1。设计难点在于两个时钟域的交叠部分:满、空状态的产生,这也是设计的重点。

图1 异步FIFO结构

针对这个问题,先从对亚稳态的处理开始介绍

亚稳态的处理

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

在数字集成电路中寄存器要满足建立时间和保持时间。建立时间是在时钟翻转之前数据输入必须有效的时间,保持时间是在时钟沿之后数据输出必须仍然有效的时间。当一个信号被寄存器锁存时,如果信号和时钟之间不满足这个要求,Q的值是不确定的,并且在未知的时刻会固定到高电平或低电平。此时寄存器进入了亚稳态(Metastability)。解决这一问题的最简单方法是使用同步器,使得在另一个时钟域采样时信号足够稳定。

同步器的设计本身就是一个比较麻烦的问题,本次设计中也不深入讨论一些细节性的问题,直接采用两级采样的同步器,避免了使用一级同步器仍可能出现亚稳态的情况。每个这样的同步器都具有一个等于时钟周期的等待时间。这种同步器可以把一些亚稳态的值同步为确定值,但并不一定是正确值,同时有一些亚稳态也还是无法稳定成确切值的,这种情况称为同步出错。由于同步出错的随机性,很难对它们进行跟踪。如果想进一步降低亚稳态出现的概率、可以再増加同步器的级数,但是太多的同步器会使系统的性能下降,所以系统中不会用太多的同步器,一般使用两个同步器已经足够。

空满状态的判断

之所以在前面介绍了亚稳态的问题,是因为这是判断满状态或空状态无法回避的一个问题。因为读电路在读控制时维持一个地址指针,写电路在写控制时维持一个地址指针,简单来说,这两个地址指针直接一比较,就能得到空满的判断结果,但是实际操作起来非常麻烦。例如对于满状态来说,这是写入电路所关心的状态,因为满状态下不能继续写入数据,但是空状态对于写电路没有影响。如果写入电路要判断当前FIFO是否为满,就需要把写电路自身维持的写指针和读电路维持的读指针做比较,这个读指针就需要送入写电路中,此时就发生了穿过时钟域的问题,也就是说,读指针要从读时钟域同步到写时钟域,然后参与判断,此时就需要前面介绍的同步器。同样,对于空状态来说,这是读出电路所关心的状态,也是由读电路来维持的,因为空状态下再读数就会得到错误的数据,但是满状态下读数是没有影响的。如果读电路要判断当前FIFO是否为空,就需要把写时钟域中的写指针取到读时钟域来,和读时钟域的读指针进行比较得出是否是空状态,同样跨越了时钟域。在跨时钟域系统中希望出现错误的概率越低越好,此时格雷码无疑是最好的一个选择。格雷码属于可靠性编码,是一种误差最小化的编码,它大大减少了由一个状态到下一个状态时电路混淆。由这种编码相邻的两个码组之间只有一位不同,和其他编码同时改变2位和多位的情况相比更为可靠。表1所示是格雷码与二进制码的对应关系。

表1 格雷码与二进制码转换真值表

由前面的介绍可知通过同步器之后信号稳定的值可能是1也可能是0,可能与输入的值相同也可能与输入的值不同。如果对于二进制码,这显然是灾难性的。例如从十进制的7变到8,二进制码是从0111变为1000,把0111送入同步器之后,由于4位都要变化,所以4位都可能会出现亚稳态,从而在同步器的输出端就会出现各种可能性,这样即使数据稳定下来,对整个电路的作用也很小。而如果采用格雷码,是从0100变为1100,只是最高位发生了改变,也就只有这一位可能会出现亚稳态的情况。这样经过同步器处理之后,输出端可能得到的值只有两种0100或1100,其中1100是正确的数值,如果得到这个输出自然是最好,但即使是0100的输出,也只是和原来的值相同,可以认为没有变化,这也不会对电路造成负面的影响。相比二进制代码那种变化后什么值都有可能的情况,格雷码显然是一种更易于接受的编码方式。

格雷码虽然在跨时钟域方面效果比较好,但在本身计数方面是不足的,也就是说还需要把格雷码转换成二进制码来计数,4位的格雷码转二进制码的代码部分如下:bin[0]=gray[3]^gray[2]^ gray[1]^ gray[0];

bin[1]=gray[3]^gray[2]^ gray[1];

bin[2]=gray[3]^gray[2];

bin[2]=gray[3];

也可以用for循环完成:

module gray[2](bin,gray);

parameter size=4;

output [size-1:0] bin;

input [size-1:0] gray;

reg [size-1:0] bin;

integer i;

always @(gray)

for(i=0;i,size;i=i=i+1);

bin[i]=^(gray>>1);

endmodule

计数之后还要变回格雷码,转换的方法与上述方式类似。这样使用格雷码作为指针就可以降低亚稳态带来的影响。接下来要解决的是空满判断的问题,常用的判断方法是附加位比较法。附加位比较法是给每个指针增加一个附加位,对于二进制指针而言,将存储空间的最后一个存储单元写入数据后,地址将变为零,即地址指针低n-1位清零并向最高位(MSB)也就是附加位进位。读指针也是如此工作。如果两个指针的最高位(MSBs)不同而其余位相同,就说明写指针比读指针多循环了一次,标志FIFO存储器处于满状态。如果包括最高位在内的两个指针完全相同,则说明写指针和读指针经历了相同次数的循环,也就是说FIFO存储器处于空状态。这样读指针和写指针就变成了一个n位指针,其中低n-1位是用来存放FIFO 存储器的地址,可以用来对2n-1个存储单元寻址,而最高位则用来辨别当两个指针的地址相等时是满状态还是空状态。

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

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

下面以3位和4位格雷码来说明空满状态的判断标准。3位格雷码表示的就是地址空间,可以有8个存储空间。由于写入和读出并不是按照从000开始的,而是可以以任意一个位置开始,比如存放数据可以按照十进制地址5、6、7、0、1、2、3、4的地址顺序来存放,读出数据也同理,这样为了表示循环,就增加了1位变为4位格雷码。

首先说明空状态的判断标准,空状态表示读指针和写指针重合,此时无论是看3位格雷码还是4位格雷码都应该是完全相同,比如写指针指向1010,读指针也必然指向1010,这样判断空状态就只需要判断两个指针是否相同,相同时即为空,不同时即为不空。

然后解释满状态的判断标准。满状态判断比较复杂。

假设一次写入数据是从十进制地址6开始,连续写入8个数据。到14,这时存满8个数据,应产生满状态输出,这两个地址形式如下:

如果是二进制地址,判断的方法已经介绍过了。而格雷码地址的前两位是不同的,但后面的两位是相同的。如果扩展成更多位的格雷码,满状态下依然是这种情况,即前两位不同,后面位均相同。这样判断满状态首先要保证除去前两位之后的剩余部分是相同的。

然后对于本例来说,需要保证前两部分是01和10,如果地址是以01开头,则满时一

定是10;如果以10开头,满时一定是01。判断的方法可以有很多种,这里采用先取前两位的异或值,保证相等,此时只可能是0,1的组合,然后再判断首位不同,这样就只能是01和10这两种情况。经过这三个条件的判断,就能就保证此时为写满状态。

再观察地址以00和11开头的情况,给出地址如下

刚才提出的的三个条件依然保证写满状态的正常输出,所以写满状态就以这三个条件作判断标准。

下面开始具体设计:

顶层模块的端口和功能

针对异步FIFO的基本结构和功能,以及保留一些必要的状态信号和控制信号,现确定顶层模块的端口与功能见表2:

表2 顶层模块的端口与功能

子模块设计

本设计的异步FIFO划分为5个子模块:读指针控制模块、写指针控制模块、存储RAW模块、读指针同步到写时钟域模块,写指针同步到读时钟域模块。依次介绍如下:

两个同步模块

这两个同步模块同前文介绍的一样,是两个寄存器连接的一起。

写指针同步到读时钟域模块代码如下

module syne_w2r(rwptr2,wptr,rclk,rrst_n);

parameter ADDRSIZE=4;

output [ADDRSIZE:0] rwptr2; //同步后的写指针

input [ADDRSIZE:0] wptr; //同步前的写指针

input rclk,rrst_n;

reg [ADDRSIZE:0] rwptr2,rwptr1; //两个中间寄存器

always @(posedge rclk or negedge rrst_n)

if(!rrst_n)

{rwptr2,rwptr1}<=0; //复位

else

{rwptr2,rwptr1}<={rwptr1,wptr}; //寄存器串联

Endmodule

读指针同步到写时钟域模块代码如下:

module sync_r2w(wrptr2,rptr,wclk,wrst_n);

parameter ADDRSIZE=4;

output [ADDRSIZE:0] wrptr2;

input [ADDRSIZE:0] rptr;

input wclk, wrst_n;

reg [ADDRSIZE:0] wrptr2, wrptrl;

always @(posedge wclk or negedge wrst_n)

if (!wrst_n)

{wrptr2, wrptrl}<=0;

else

{wrptr2,wrptrl}<= {wrptrl,rptr};

endmodule

功能比较简单,故不做仿真验证

存储模块

module fifomem(rdata, wdata, waddr,raddr, wclken, wclk,rclken,rclk); parameter DATASIZE=8; // 数据宽度parameter ADDRSIZE=4; // 地址宽度output [DATASIZE-1:0] rdata;

input [DATASIZE-1:0] wdata;

input wclken, wclk,rclken,rclk; //读写控制和时钟input [ADDRSIZE-1:0] raddr, waddr; //输入读写地址reg [DATASIZE-1:0] rdata;

reg [DATASIZE-1:0] MEM [0:(1<

always @(posedge rclk) //读时钟读出数据

if (rclken) rdata = MEM[raddr];

always @(posedge wclk)

if (wclken) MEM[waddr] <= wdata; //写时钟写入数据

endmodule

此模块构造了一个存储器,按读写始终安排输入和输出。编写测试模块如下:

module tbmem;

parameter DATASIZE=8;

parameter ADDRSIZE=4;

wire [DATASIZE-1:0] rdata;

reg [DATASIZE-1:0] wdata;

reg wclken, wclk,rclken,rclk;

reg [ADDRSIZE-1:0] raddr, waddr;

integer seed1;

initial

begin

wclk=0;rclk=0;seed1=20; //初始化

waddr=0;raddr=0;

end

always #9 wclk=~wclk; //生成写时钟

always #11 rclk=~rclk; //生成读时钟

always @(posedge wclk)

wdata<={$random(seed1)/256}; //产生随机写入数据

initial

begin

wclken=1;rclken=0;

repeat (10) @(posedge wclk); //写入10个数据

wclken=0;rclken=1;

repeat (6) @(posedge rclk); //读出6个数据

wclken=1;rclken=1;

#99 $stop;

end

always @(posedge wclk)

if(wclken==1)

waddr=waddr+1; //写地址生成

always @(posedge rclk)

if(rclken==1)

raddr=raddr+1; //读地址生成

fifomem fifomem(rdata, wdata, waddr,raddr, wclken, wclk,rclken,rclk);

endmodule

仿真波形如图2所示

图2 存储仿真波形

第一行为读出数据,第二行为写入数据,图中第一行和第二行数据是完全对应的。

读地址控制模块

FIFO存储器空状态是在读时钟域中生成的,这样就可以确保一旦FIFO存储器达到空状态时就能被检测到。也就是说,在读时钟域里读指针可以在读时钟周期内与同步而来的写指针(包括附加的最高位MSB)进行比较。

当读指针与同步的写指针rwptr2相等时,FIFO存储器为空状态,此时FIFO存储器停止读取数据,否则会导致向下溢出(underflow)。比较读指针和同步的写指针以生成空标志的比较器很容易实现。FIFO存储器的指针总是预先指向下一个内存位置,每进行一次读写操作,相应的指针就增加一次。如果读指针与同步的写指针rwptr2的附加位(这两个指针的最高位MSBs)是相等的,则这两个指针经历了相同的循环次数,假如这时两个指针的低位(共n-1位)也相等,FIFO存储器就为空状态。

在这个模块中包含了除读同步模块之外的所有读时钟域的逻辑电路。读指针是"两重格雷码计数器”。位指针rptr被同步到写时钟域中,n-1位指针用于产生地址。当读指针rptr的下一个状态rgnext等于同步的写指针rwptr2时,空状态标志将在下一个读时钟的上升沿被置位。这个模块已经是一个读时钟域的同步时序电路,这有利于进行静态时序分析。模块包含读指针电路和空标志逻辑电路,代码如下:

module rptr_empty(rempty,raddr,rptr,rwptr2,rinc,rclk,rrst_n);

parameter ADDRSIZE=4;

output rempty;

output [ADDRSIZE-1:0] raddr;

output [ADDRSIZE:0] rptr;

input [ADDRSIZE:0] rwptr2;

input rinc, rclk,rrst_n;

reg [ADDRSIZE:0] rptr,rbin,rgnext,rbnext;

reg rempty,raddrmsb;

always @(posedge rclk or negedge rrst_n)

if(!rrst_n)

begin

rptr <=0;

raddrmsb<=0;

end

else

begin

rptr <=rgnext;

raddrmsb <=rgnext[ADDRSIZE]^rgnext[ADDRSIZE-1];

end

always @(rptr or rinc)

begin:Gray_inc

integer i;

for(i=0;i<=ADDRSIZE;i=i+1)

rbin[i]=^(rptr>>i); //格雷码转换为二进制码

if(!rempty)

rbnext=rbin+rinc; //增加FIFO计数

else

rbnext=rbin;

rgnext = (rbnext>>1)^rbnext; //二进制转化为格雷码

end

always @(posedge rclk or negedge rrst_n)

if(!rrst_n)

rempty<=1'b1; //复位时输出空

else

rempty<=(rgnext==rwptr2); //否则判断是否满足条件

assign raddr = {raddrmsb,rptr[ADDRSIZE-2:0]}; //读地址指针

endmodule

读地址控制模块主要的部分按代码顺序有复位部分,完成复位功能计数部分,完成格雷码转二进制计数再转换成格雷码;空状态判断部分,复位时输出空,读指针和同步后的写指针相同时出示空状态;最后是一个读地址的拼接输出。

为此模块编写测试模块,代码如下:

module tbrptr;

parameter ADDRSIZE=4;

wire rempty;

wire [ADDRSIZE-1:0] raddr;

wire [ADDRSIZE:0] rptr;

reg [ADDRSIZE:0] rwptr2;

reg rinc, rclk,rrst_n;

initial

begin

rclk=0;rrst_n=1;rinc=0;

rwptr2=14;

#3 rrst_n=0;

#4 rrst_n=1;

#6 rinc=1;

end

always #11 rclk=~rclk;

initial

begin

repeat (5) @(posedge rclk);

@(posedge rempty);

#20 $stop;

end

rptr_empty rptr_empty(rempty,raddr,rptr,rwptr2,rinc,rclk,rrst_n);

endmodule

仿真波形如图3所示

图3 读地址控制模块

波形中第一行是空状态,一开始复位一次,计数到0110时与预置的写指针相同,空状态重新变为高电平。此模块可正常完成地址计数和空状态的生成,功能验证结果正确。

写指针控制模块

与读指针控制模块代码基本相同。此模块仅在满状态判断部分不相同。代码如下:

module wptr_full(wfull,waddr,wptr,wrptr2,winc,wclk,wrst_n);

parameter ADDRSIZE = 4;

output wfull;

output [ADDRSIZE-1:0] waddr;

output [ADDRSIZE:0] wptr;

input [ADDRSIZE:0] wrptr2;

input winc, wclk, wrst_n;

reg [ADDRSIZE:0] wptr, wbin, wgnext, wbnext;

reg wfull, waddrmsb;

wire w_2ndmsb,wr_2ndmsb; //添加的判断信号

always @(posedge wclk or negedge wrst_n)

if (!wrst_n)

begin

wptr <= 0;

waddrmsb <= 0;

end

else

begin

wptr <=wgnext;

waddrmsb <=wgnext[ADDRSIZE]^wgnext[ADDRSIZE-1];

end

always @(wptr or winc)

begin: Gray_inc

integer i;

for(i=0; i<=ADDRSIZE; i=i+1)

wbin[i]= ^ (wptr>>i); //格雷码转二进制

if (!wfull)

wbnext = wbin+winc; //FIFO计数

else

wbnext = wbin;

wgnext=(wbnext>>1) ^ wbnext; //二进制转格雷码

end

assign w_2ndmsb = wgnext[ADDRSIZE] ^ wgnext[ADDRSIZE-1]; //写指针前两位异或

assign wr_2ndmsb = wrptr2[ADDRSIZE] ^ wrptr2[ADDRSIZE-1]; //同步后的读指针前两位异或

always @(posedge wclk or negedge wrst_n)

if (!wrst_n)

wfull<=0;

else

wfull <= ((wgnext[ADDRSIZE] !==wrptr2[ADDRSIZE])&&(w_2ndmsb== wr_2ndmsb)

&& (wgnext[ADDRSIZE-2:0]== wrptr2[ADDRSIZE-2:0])); //三个判断条件均满足则满

assign waddr= {waddrmsb,wptr[ADDRSIZE-2:0]};

endmodule

由于功能基本相似,此模块不再列出仿真

整体仿真结果

将五个子模块合成一个顶层模块,代码如下:

module fifo_asyn1(rdata,wfull,rempty,wdata,winc,wclk,wrst_n,rinc,rclk,rrst_n);

parameter DSIZE = 8; //数据存储宽度

parameter ASIZE = 4; //存储地址宽度

output [7:0] rdata;

output wfull;

output rempty;

input [7:0] wdata;

input winc,wclk,wrst_n;

input rinc,rclk,rrst_n;

wire [3:0] waddr,raddr;

wire [4:0] wptr,rptr,wrptr2,rwptr2;

sync_r2w sync_r2w(.wrptr2(wrptr2),.rptr(rptr),.wclk(wclk),.wrst_n(wrst_n)); syne_w2r syne_w2r(.rwptr2(rwptr2),.wptr(wptr),.rclk(rclk),.rrst_n(rrst_n)); fifomem #(DSIZE,ASIZE) fifomem(.rdata(rdata),.wdata(wdata),.waddr(waddr),.raddr(raddr),

.wclken(winc),.wclk(wclk),.rclken(rinc),.rclk(rclk));

rptr_empty #(ASIZE) rptr_empty(.rempty(rempty),.raddr(raddr),.rptr(rptr),.rwptr2(rwptr2),

.rinc(rinc),.rclk(rclk),.rrst_n(rrst_n));

wptr_full #(ASIZE) wptr_full(.wfull(wfull),.waddr(waddr),.wptr(wptr),.wrptr2(wrptr2),

.winc(winc),.wclk(wclk),.wrst_n(wrst_n));

Endmodule

为此模块编写测试模块,代码如下:

module tbfifo;

parameter DSIZE = 8;

parameter ASIZE = 4;

wire [7:0] rdata;

wire wfull;

wire rempty;

reg [7:0] wdata;

reg winc,wclk,wrst_n;

reg rinc,rclk,rrst_n;

integer seed;

initial

begin

wclk=0;rclk=0;seed=11;

winc=0;rinc=0;

wrst_n=1;rrst_n=1;

#2 wrst_n=0;rrst_n=0;

#3 wrst_n=1;rrst_n=1;

end

always #9 wclk=~wclk;

always #11 rclk=~rclk;

always @(posedge wclk)

wdata<={$random(seed)/256};

initial

begin

#20 winc=1;

repeat (12)@(posedge wclk);

winc=0;rinc=1;

repeat (6)@(posedge rclk);

winc=1;rinc=1;

@(posedge wfull);

winc=0;rinc=1;

@(posedge rempty);

#20 $stop;

end

fifo_asyn1 myasynfifo(rdata,wfull,rempty,wdata,winc,wclk,wrst_n,rinc,rclk,rrst_n);

endmodule

仿真波形如图4所示

这是整体效果,从一开始复位信号产生空状态,然后写入一些数据到FIFO之中,再边写边读,但是由于写周期快,所以FIFO之中的数据量逐渐增加,直至出现写满状态。接下来进入只读阶段,连续读出FIFO的数据,直到读空为止,这样所以得工作状态都得到了验证。

图4 仿真波形图

图5是波形最后的部分放大

图5 数值验证

此图中来查看数据准确性:第一行是输出的数据,第四行是输入的数据,在wfull信号出现高电平之后进入只读状态,此时读出的数据89与图中第四行第三个数相等,然后按顺序输出刚写入的数据,数值部分验证正确。

该电路图得到的模块图如图6

图6 整体模块结构图

心得体会

在本次实验中,应用了两级同步器,格雷码,存储器等知识;以及亚稳态的处理,格雷码在跨时钟域方面的应用,顶层模块的编写等方法,让本人学到很多。

同步缓冲器(FIFO)的设计与实现..

同步缓冲器(FIFO)的设计与实现 姓名:崔琦 学号:100260305 班级:2010级电科3班 院系:电气与信息工程学院 专业:电子科学与技术 同组人姓名:梁承润 李建凯 (说明:我们三个人前面的报告部分是一样的,因为课设基本是三个人商议完成,所以就感觉报告部分没什么不同的就只写了一份报告)

目录 1原理与系统设计 (3) 2设计思想 (4) 3源码与注释 (5) 4仿真 (12) 5综合 (15) 6心得体会与建议 (19)

1 原理与系统设计 FIFO(First In First Out)——是一种可以实现数据先入先出的存储器件。FIFO就像一个单向管道,数据只能按固定的方向从管道一头进来,再按相同的顺序从管道另一头出去,最先进来的数据必定是最先出去。FIFO被普遍用作数据缓冲器。 FIFO的基本单元是寄存器,作为存储器件,FIFO的存储能力是由其内部定义的存储寄存器的数量决定的。本题中所设计的是同步FIFO(即输出输入端时钟频率一致),异步复位,其存储能力为(16x8),输出两个状态信号:full与empty,以供后继电路使用。 根据系统要求,画出的系统框图,如图1所示 clock reset 读控制信号写控制信号 input full empty output 图1同步FIFO框图 端口说明: 输入:in_data: 输入数据端口,位宽为8位; read_n: 读使能端,当read_n=0时,可以读出数据; write_n: 写使能端,当write_n=0时,可以写入数据; clock: 时钟信号,在时钟的正边沿进行采样; reset_n: 复位信号,当reset_n=0时,计数器及读写都被清零(即:读写地址指针都指向0) 输出:out_data: 输出数据端口,位宽为8位;; full:FIFO状态信号,当full=1时,表明该FIFO存储器已经写满; empty:FIFO状态信号,当empty=1时,表明该FIFO存储器已经读空;

一个异步FIFO的设计示例

一、异步FIFO 技术规 1. 总体描述 1.1. 功能定义 异步FIFO ( First In First Out)指的是在两个相互独立的时钟域下, 数据从一个时钟域写入FIFO 而另一个时钟域又从这个FIFO 中将数据读出。 本设计用8*256的RAM 实现异步FIFO 。 具体功能: 1. 写使能有效,且FIFO 不为满时,在写时钟的上升沿向FIFO 中写入数据。 2. 读使能有效,且FIFO 不为空时,在读时钟的上升沿从FIFO 中读出数据。 3. 当FIFO 写满时产生满信号,当FIFO 读空时产生空信号。 1.2. 应用围 异步FIFO 是用来作为缓冲的存储器, 它能对数据进行快速、顺序的存储和发送, 主要用来解决不同速率器件间的速率匹配问题。 2. 引脚描述 图1 2.1. 引脚功能描述

2.2.引脚时序描述 当写满时full由低变高,当读空时empty由低变高。只要不为满full就为低,不为空empty就为低。 3.顶层模块划分

图2 顶层模块说明: 1.ram_fifo :存储器模块,用于存放及输出数据; 2.w_addr_reg : 保存访问RAM的写地址; 3.r_addr_reg : 保存访问RAM的读地址; 4.w_addr_adder : 计算RAM下一个写地址; 5.r_addr_adder: 计算RAM下一个读地址; 6.cmp : 将读地址和写地址进行比较产生空满标志。 设计思想说明: FIFO满空的判定:当读地址的值加1之后等于写地址的值时,表明FIFO写满,当写地址的值加一之后等于读地址的值时,表明FIFO读空。在初始状态时FIFO的读地址在RAM 的中间位置,写地址在RAM的开始位置,所以初始状态FIFO不满也不空。空满信号的产生由组合电路产生。 4.功能模块描述

verilog同步和异步FIFO,可直接仿真和综合

EDA/SOPC课程设计报告 题目:同异步FIFO模块的设计与验证 姓名: xxx 学号: 120260320 同组人: xxx 指导教师: xxx 成绩:

目录 目录................................................................................................................................................... II 第1章课程设计的要求 . (1) 1.1 课程设计的目的 (1) 1.2 课程设计的条件 (1) 1.3 课程设计的要求 (1) 第2章课程设计的内容 (2) 2.1 设计思路 (2) 2.2 软件流程图 (3) 2.3 HDL代码阐述 (7) 2.4 ModelSim验证 (13) 第3章课程设计的心得 (21)

第1章课程设计的要求 1.1 课程设计的目的 ●掌握FIFO设计的基本原理与方法 ●培养Verilog语言模块化设计的思想意识 ●完成一个FIFO的设计与验证 ●掌握较大工程的基本开发技能 ●培养综合运用Modelsim工具进行硬件开发的能力 ●培养数字系统设计的基本能力 ●加强对课堂Verilog语言学习的理解与升华 1.2 课程设计的条件 ●设计条件ISE、Modelsim等开发软件的使用 1.3 课程设计的要求 ●设计要求1 设计同步FIFO并验证(包括仿真验证、FPGA验证) ●设计要求2 设计异步FIFO并验证(包括仿真验证、FPGA验证) ●设计要求3 采用Design Compiler完成其逻辑综合,评估其面积和时序 ●设计要求4 完成综合后的SDF反标仿真

(完整版)异步FIFO设计

异步FIFO设计文档 一、概述 在大规模ASIC或FPGA设计中,多时钟系统往往是不可避免的,这样就产生了不同时钟域数据传输的问题,其中一个比较好的解决方案就是使用异步FIFO来作不同时钟域数据传输的缓冲区,这们既可以使相异时钟域数据传输的时序要求变得宽松,也提高了它们之间的传输效率。此文内容就是阐述异步FIFO的设计。 二、设计原理 2.1结构框图 Fig. 2.1.1 如上图所示的同步模块synchronize to write clk,其作用是把读时钟域的读指针rd_ptr采集到写时钟(wr_clk)域,然后和写指针wr_ptr进行比较从而产生或撤消写满标志位wr_full;类似地,同步模块synchronize to read clk 的作用是把写时钟域的写指针wr_ptr采集到读时钟域,然后和读指针rd_ptr进行比较从而产生或撤消读空标志位rd_empty。 另外还有写指针wr_ptr和写满标志位wr_full产生模块,读指针rd_ptr和读模块。RAM产生模块,以及双端口存储rd_empty空标志位 2.2 二进制计数器存在的问题 异步FIFO读写指针需要在数学上的操作和比较才能产生准确的空满标志位,但由于读写指针属于不同的时钟域及读写时钟相位关系的不确定性,同步模块采集另一时钟域的指针时,此指针有可能正处在跳变的过程中,如图Fig.2.2.1所示,那么采集到的值很有可能是不期望的值,当然,不期望的错误结果也会随之发生。

Fig. 2.2.1 上图中,rd_ptr2sync 3和4以及4和5之间的中间态是由于到各寄存器的时钟 rd_clk存在偏差而引起的。二进制的递增操作,在大多数情况下都会有两位或者两以上的bit位在同一个递增操作内发生变化,但由于实际电路中会存在时钟偏差和不同的路径延时,二进制计数器在自增时会不可避免地产生错误的中间结果,如图Fig.2.2.2。 Fig.2.2.2 上升沿到达rd_clk的电路原型以及局部波形的放大。由于Fig.2.2.1上图是 三寄存器的时间各不相同,这就导致了rd_ptr2sync的值从3'b011跳变3'b100的过程中经历了3'b111和3'b101,直到最后一个时钟(rd_clk0)沿的到来rd_ptr2sync 才跳变到正确结果3'b100。中间结果的持续的时间虽然相对短暂,但是这些不正确的结果完全有可能被其它时钟域的同步模块采集到而产生错误的动作,见上图。由此可见,要避免中间结果的产生,其中一个可行的方案就是使被同步模块采集的数据递变时,每次只有一个bit位发生改变。格雷码计数器就是一个不错的选择。 2.3 格雷码计数器的实现 2.3.1 格雷码的表现形式 格雷码一个最大的特点就是在递增或递减的过程中,每次只变化一位,这是它最大的优点。同时它也有自己的局限性,那就是循环计数深度必须是2的n次幂,否则就失去了每次只变化一位的特性。深度为16的二进制及格雷码递变表如下:Binary Gray 0 0000 0000

同步FIFO之VHDL描述

同步F I F O之V H D L描述(1)同步FIFO之VHDL描述 同步FIFO的意思是说FIFO的读写时钟是同一个时钟,不同于异步FIFO,异步FIFO的读写时钟是完全异步的。同步FIFO的对外接口包括时钟,清零,读请求,写请求,数据输入总线,数据输出总线,空以及满信号。下面分别对同步FI FO的对外接口信号作一描述: 1.时钟,输入,用于同步FIFO的读和写,上升沿有效; 2.清零,输入,异步清零信号,低电平有效,该信号有效时,FIFO被清空; 3.写请求,输入,低电平有效,该信号有效时,表明外部电路请求向FIF O写入数据; 4.读请求,输入,低电平有效,该信号有效时,表明外部电路请求从FIF O中读取数据; 5.数据输入总线,输入,当写信号有效时,数据输入总线上的数据被写入到FIFO中; 6.数据输出总线,输出,当读信号有效时,数据从FIFO中被读出并放到数据输出总线上; 7.空,输出,高电平有效,当该信号有效时,表明FIFO中没有任何数据,全部为空; 8.满,输出,高电平有效,当该信号有效时,表明FIFO已经满了,没有空间可用来存贮数据。 使用VHDL描述的FIFO将以上面的接口为基础,并且可以参数化配置FIFO的宽度和深度。先把对外接口描述出来吧。

------------------------------------- -- Designer : skycanny -- Date : 2007-1-29 -- Description : Synchronous FIFO created by VHDL library ieee; use sfifo is generic(width : positive depth : positive ); port ( clk : in std_logic; rst : in std_logic; wq : in std_logic; rq : in std_logic; data : in std_logic_vector(width - 1 downto 0); q : in std_logic_vector(width - 1 downto 0); empty : out std_logic; full : out std_logic ); end entity sfifo;

用FIFO设计AD与DSP之间的接口.

用FIFO设计A/D与DSP之间的接口 摘要:在采用CCD对非透明薄板厚度的测量系统设计中,采用高速A/D和DSP等器件进行电路设计可以确定CCD的像点位置。由于A/D转换器的采样速率和DSP的工作时钟频率相差非常大,为了提高DSP 的工作效率,避免数据丢失和控制方便,采用小容量的FIFO作为两者之间的接口可以产生很好的效果。 关键词:A/D;DSP;FIFO 1前言 在使用CCD对非透明薄板厚度的测量系统设计中,笔者采用高速A/D和DSP等器件设计信号采集和处理电路来确定CCD的像点位置。其具体电路如图1所示,该信号采集和处理电路由CCD驱动电路、加法电路、滤波放大等信号预处理电路、A/D转换电路、FIFO、DSP电路、时序与逻辑控制产生电路、USB总线接口电路等组成。其中DSP芯片选用TI公司生产的TMS320C6211高速数字信号处理芯片它主要用于对A/D转换后的数据进行插值和重心算法处理,从而确定CCD上像元的位置,然后把处理后的数据通过USB总线传输到PC机进行厚度计算、结果显示、存储等后续处理。该电路所需的时钟信号和采样逻辑控制时序由一片FPGA芯片产生。 当模拟信号由ADC转换成数字信号后,往往都需要输入DSPs的CPU作进一步处理。但A/D转换后数据输出与DSP的读外部数据的时钟很难精确地配合。即使DSP能读取到外部总线上的数据,由于A/D速率是4MHz,DSP外部存储器时钟为90MHz,为了读到总线上的数据,DSP外部存储器读写时钟也必须控制在4MHz,这样就大大降低了DSP的使用效率,同时再加上DSP处理数据也需要一定的时间,而不能一味地读取外部数据。所以,为了控制方便,避免数据丢失,设计时应采用小容量的FIFO作为两者之间的接口。本设计选用的FIFO芯片是Cypress公司的CY7C425-25ns。该芯片容量为1k×9bit,存取时间最大为25ns,读写周期最小为35ns。该器件具有半满(HF)、全满(FF)和空(EF)三个标志位输出,可以同时满足深度和宽度级联的需要。 图1 2DSP与FIFO芯片的工作原理 2.1FIFO读写过程 FIFO的一次读写过程如图2所示,由于FIFO是顺序读取数据,因此只需提供读写和其它控制信号线,而不需要一般RAM所需的地址线。若将两路A/D输出的数据存入FIFO中,每片FIFO用8bit两片FIFO即可级联构成16bit的数据宽度。由于FIFO采用的是5V供电,所以经电压转换器件74LVTH244可将5V数据信号电平转换成3.3V,然后与DSP的16Bit外部数据总线相连。再由FIFO的半满信号HF作为外部中断信号,当FIFO存储器半满时,便可

异步fifo设计及时序约束设置

一、前言 跨时钟域的同步处理,使用异步FIFO是常用的方式之一,对于异步FIFO的设计,网上的大部分资料来源于《Simulation and Synthesis Techniques for Asynchronous FIFO Design》一文 其异步FIFO的结构如下图所示 本文不是介绍上图描述的设计。我从基本的数字电路时序开始,介绍异步FIFO的相关问题。最后介绍如何用时序约束保证设计的正确性 二、数字电路时序 对于数字电路来讲,我们的信号在时钟边沿发生变化,Dat1信号是一种理想情况,而Dat2是实际情况,其特点是 一、相对时钟边沿有延时 二、信号变化有一段时间(电平转换时间),在这段时间就是亚稳态 在亚稳态期间进行数据采样,不能获得稳定的值。数字电路中经过时序约束,在T1产生的信号,在T2一定稳定(否则就是不满足时序),所以对于只有一个时钟的数字电路来说,它在T1和T2都能获得稳定的信号(T1时刻的值为0、T2时刻的值为1)

三、跨时钟域时序问题 对于异步时钟而言(相位不同),对于CLK1产生的信号,CLK2有可能在任意时刻进行数据采样 在FIFO的设计中,将会产生2种信号,一种是数据本身(用Data表示),另外一种是指示数据是否有效(用valid表示),注意(valid不一定是一个比特的寄存器,可以是由FIFO中的读写指针产生而来,例如fifo的full或empty状态) 异步FIFO的问题在于,如果CLK2在时钟T2进行采样,那么有可能得到valid有效,而数据无效的情况。这样在CLK2采样取得的设计就是错误的数据。 四、处理异步FIFO的valid和data(理论基础) 我们假设valid为低电平表示没有数据,高电平为有数据,解决的办法就是,当CLK对valid进行采样时,即使valid处于亚稳态期间,数据信号也是稳定的 如上图所以,在T1时刻进行上升沿采样,虽然valid是一个亚稳态状态,但是此时Data 是一个稳定的值,如果在T1时刻采样的valid为1,那么可以得到稳定的Data信号,如果在T1时刻采样的valid为0,那么控制逻辑认为在T1无法获得数据,从而在下一个时钟获取 注意:T2时刻是在下降沿进行采样,而此时的Data信号也是稳定的

【CPLD Verilog】CPLD实现同步FIFO

CPLD实现同步FIFO 1 实现原理 CPLD实现8个字节的同步FIFO,实现8个字节数据的缓存。CPLD内部模块逻辑框图如下所示。 Data_a_we_pulse写数据到FIFO的使能信号。 Data_a_rd_pulse从FIFO读取数据的使能信号。 Data_a_in和Data_a_out分别表示写入FIFO和从FIFO读出的数据的值。 Data_a_we_full指示FIFO写满的状态。 Data_a_rd_nop指示FIFO读空的状态。 2 CPLD代码 module fifo_8B ( clk, reset_n, data_a_in, data_a_we_pulse,

data_a_we_full, data_a_out, data_a_rd_pulse, data_a_rd_nop ); input clk; input reset_n; input [7:0] data_a_in; input data_a_we_pulse; output data_a_we_full; output [7:0] data_a_out; input data_a_rd_pulse; output data_a_rd_nop; //////////////////////////FIFO 写入数据逻辑//////////////////////////// reg [7:0] fifo_mem [7:0]; //FIFO空间,8个8bit的空间 reg [2:0] fifo_we_addr; //FIFO写地址寄存器 reg fifo_we_addr_reverse_pulse; //FIFO写地址翻转状态寄存器,用于指示写//地址是否从最大地址翻转回到最小地址 always@(posedge clk or negedge reset_n) begin if(reset_n == 1'b0)

异步fifo程序

高速异步FIFO的设计与实现 摘要:本文主要研究了用FPGA芯片实现异步FIFO的一种方法。通过对FPGA芯片内部EBRSRAM的深入研究.提出了一种利用格雷码对地址进行编码的异步FIFO设计方案。实践证明.增加了系统可靠性和应用灵活性。 引言 现代集成电路芯片中,随着设计规模的不断扩大.一个系统中往往含有数个时钟。多时钟带来的一个问题就是,如何设计异步时钟之间的接口电路。异步FIFO(First In First Out)是解决这个问题的一种简便、快捷的解决方案。使用异步FIFO可以在两个不同时钟系统之间快速而方便地传输实时数据.在网络接口、图像处理等方面,异步FIFO都得到广泛的应用。异步FIFO是一种先进先出的电路,使用在数据接口部分,用来存储、缓冲在两个异步时钟之间的数据传输。在异步电路中,由于时钟之间周期和相位完全独立,因而数据的丢失概率不为零。如何设计一个可靠性高、速度高的异步FIFO电路便成为一个难点。 1 异步FIFO的工作原理及逻辑框图 本文根据实际工作的需要.给出了一种利用片内RAM构造FIFO器件的设计,重点强调了设计有效.可靠的握手信号FULL和EMPTY的方法。并在LATTICE公司的FPGA芯片LFXP2-5E上实现。LFXP2-5E属于LATIICE 公司XP2系列的一款,他采用优化的FlexiFLASH结构。内部包含有基于查找表的逻辑、分布式和嵌入式存储器,锁相环(PLL)。工程预制的源同步I/0以及增强的Sys DSP块。有166Kbits的EBRSRAM。利用其内部的EBRSRAM可以实现一定容量的异步FIFO.而无需单独购买FIF0器件。 由图1可以看出:异步FIFO一般由四个模块构成:数据存储单元,写地址产生模块,读地址产生模块,标志位产生模块。整个系统分为两个完全独立的时钟域—读时钟域和写时钟域:在写时钟域部分由写地址产生逻辑产生写控制信号和写地址:读时钟域部分,由读地址产生逻辑产生读控制信号和读地址;在标志位产生模块部分,由读写地址相互比较产生空/满标志。异步FIFO的操作过程为:在写时钟的上升沿.当写使能有效时,将数据写入到双口RAM中写地址对应的位置中:在读时钟的上升沿,当读使能有效时。则按先进先出顺序读出数据。在FIFO写满或读空的情况下。分别对满标志FuLL或空标志EMPTY信号置位。来表示FIFO的两种特殊状态。

FPGA异步fifo设计完整报告

目录 一、技术规范 (3) 1、设计完成的功能: (3) 2、系统整体框图: (3) 3、I/O管脚的描述: (3) 4、验证和测试工具选择: (4) 5、说明关键模块: (4) 6、拟选用的FPGA类型: (4) 二、FIFO总体设计方案 (5) 系统功能描述: (5) 电路结构图: (5) 系统的总体输入输出设定 (6) 系统时序分析: (6) 关键模块设计分析: (7) 三、FIFO验证方案 (8) FIFO功能: (8) 1、概述: (8) 2、预确认: (8) 3、模块运行确认: (9) 4、系统运行确认: (9) 四、仿真激励代码 (10) 五、电路设计FIFO源代码 (11)

六、FPGA设计FIFO综合布局布线报告: (16) 综合引脚分配: (16) 电路布局布线: (16) 七、时序仿真报告 (17) 时序仿真波形: (17) 八、FIFO下载代码和引脚分布 (17) 系统输入输出引脚分布: (21) 九、心得体会 (21)

技术规范 1、设计完成的功能: 本实验完成的是8位异步FIFO的设计,其中写时钟100MHz,读时钟为5MHz,其中RAM的深度为256。当写时钟脉冲上升沿到来时,判断写信号是有效,则写一个八位数据到RAM中;当读时钟脉冲上升沿到来时,判断读信号是有效,则从RAM中把一个八位数据读出来。当RAM中数据写满时产生一个满标志,不能再往RAM再写数据;当RAM中数据读空时产生一个满标志,不能再从RAM读出数据。 2、系统整体框图:

3、I/O管脚的描述: 管脚名称方向H/L电平位宽功能描述 rst_n input 3.3V/01全局复位信号 rd_en input 3.3V/01读使能低有效 wr_en input 3.3V/01写使能低有效 rd_empty output 3.3V/01读空标志高有效wr_full output 3.3V/01写满标志高有效rd_data output 3.3V/08数据输出 wr_data input 3.3V/08数据写入 clk_100M input 3.3V/01写数据时钟 clk_5M input 3.3V/01读数据时钟 4、验证和测试工具选择: Modelsim SE6.1f进行前仿真和后仿。在软件QuartusII中进行综合。 5、说明关键模块: 对控制输入的读写地址要进行设计,以便在写满或是读空只产生一个标志,以此来实现对FIFO的缓冲的控制。也就是读地址加1与写地址相等则为读空,产生读空标志;写地址加1与读地址相等则为读空,产生写满标志 6、拟选用的FPGA类型:ep1cq240c8n

(完整word版)异步FIFO的实现方式

异步FIFO的实现方式 实验目的 本次实验介绍一种异步FIFO的实现方式。使用FIFO存储器可以在两个不同时钟系统之间快速而方便的传输数据。另外,在网络接口,图像处理等方面异步FIFO存储器也得到了广泛的应用。因此,异步FIFO存储器具有较大的研究和应用价值。 异步FIFO的介绍和整体结构 异步FIFO(First In First Out)存储器是指向FIFO缓冲器中写入数据的时钟域和从FIFO缓冲器中读取数据的时钟域是不同的,这两个时钟之间没有必然的因果关系。异步FIFO是一种先进先出的电路,使用在异步时钟域数据接口的部分,用来存储、缓冲在两个异步时钟之间的数据传输。在异步电路中,由于时钟之间周期和相位完全独立,所以数据的丢失概率不为零。如何设计一个高可靠性、高速的异步FIFO存储器便成为一个难点。 异步FIFO的一般结构如图1所示,都是由一个读时钟域电路、一个写时钟域电路和一个双端口的RAM来构成的。异步FIFO与同步FIFO所做的工作是相同的,都是在写信号有效时写数据到RAM中,在读信号有效时把数据从RAM中读出,所以对于中间部分的RAM 设计是比较简单的。另外,读电路和写电路单独实现起来也是比较容易的,只需要按照同步FIFO的工作情况,如果没有写满或读空的状态时每写一个数据就把写地址加1,每读一个数据就把读地址减1。设计难点在于两个时钟域的交叠部分:满、空状态的产生,这也是设计的重点。

图1 异步FIFO结构 针对这个问题,先从对亚稳态的处理开始介绍 亚稳态的处理 一个触发器进入亚稳态时,既无法预测该单元的输出电平,也无法预测何时输出才能稳定在某个正确的电平上。在这个稳定期间,触发器输出一些中间级电平,或者可能处于振荡状态、并且这种无用的输出电平可以沿信号通道上的各个触发器级联式传播下去。亚稳态发生的原因是由于在同步系统中,如果触发器的建立时间或保持时间不满足,就可能产生亚稳态,此时触发器输出端Q在亚稳态是指触发器无法在某个规定时间段内达到一个可确认的状态,逻辑误判有可能通过电路的特殊设计减轻危害(如本设计中将使用的Gray码计数器),而亚稳态的传播则扩大了故障面,难以处理。 在数字集成电路中寄存器要满足建立时间和保持时间。建立时间是在时钟翻转之前数据输入必须有效的时间,保持时间是在时钟沿之后数据输出必须仍然有效的时间。当一个信号被寄存器锁存时,如果信号和时钟之间不满足这个要求,Q的值是不确定的,并且在未知的时刻会固定到高电平或低电平。此时寄存器进入了亚稳态(Metastability)。解决这一问题的最简单方法是使用同步器,使得在另一个时钟域采样时信号足够稳定。 同步器的设计本身就是一个比较麻烦的问题,本次设计中也不深入讨论一些细节性的问题,直接采用两级采样的同步器,避免了使用一级同步器仍可能出现亚稳态的情况。每个这样的同步器都具有一个等于时钟周期的等待时间。这种同步器可以把一些亚稳态的值同步为确定值,但并不一定是正确值,同时有一些亚稳态也还是无法稳定成确切值的,这种情况称为同步出错。由于同步出错的随机性,很难对它们进行跟踪。如果想进一步降低亚稳态出现的概率、可以再増加同步器的级数,但是太多的同步器会使系统的性能下降,所以系统中不会用太多的同步器,一般使用两个同步器已经足够。 空满状态的判断 之所以在前面介绍了亚稳态的问题,是因为这是判断满状态或空状态无法回避的一个问题。因为读电路在读控制时维持一个地址指针,写电路在写控制时维持一个地址指针,简单来说,这两个地址指针直接一比较,就能得到空满的判断结果,但是实际操作起来非常麻烦。例如对于满状态来说,这是写入电路所关心的状态,因为满状态下不能继续写入数据,但是空状态对于写电路没有影响。如果写入电路要判断当前FIFO是否为满,就需要把写电路自身维持的写指针和读电路维持的读指针做比较,这个读指针就需要送入写电路中,此时就发生了穿过时钟域的问题,也就是说,读指针要从读时钟域同步到写时钟域,然后参与判断,此时就需要前面介绍的同步器。同样,对于空状态来说,这是读出电路所关心的状态,也是由读电路来维持的,因为空状态下再读数就会得到错误的数据,但是满状态下读数是没有影响的。如果读电路要判断当前FIFO是否为空,就需要把写时钟域中的写指针取到读时钟域来,和读时钟域的读指针进行比较得出是否是空状态,同样跨越了时钟域。在跨时钟域系统中希望出现错误的概率越低越好,此时格雷码无疑是最好的一个选择。格雷码属于可靠性编码,是一种误差最小化的编码,它大大减少了由一个状态到下一个状态时电路混淆。由这种编码相邻的两个码组之间只有一位不同,和其他编码同时改变2位和多位的情况相比更为可靠。表1所示是格雷码与二进制码的对应关系。

双口ram实现同步fifo(源代码)

module fifo_ram(fifo_reset,clk,r,w,read_data,write_data, full,empty,Fcounter); parameter data_width=8; parameter addr_width=9; input fifo_reset,clk,r,w; input[data_width-1:0] write_data; output[data_width-1:0] read_data ; output full,empty; output[addr_width-1:0] Fcounter; reg full,empty; wire[data_width-1:0] read_data ; reg[addr_width-1:0] Fcounter; reg[addr_width-1:0] write_addr; reg[addr_width-1:0] read_addr; wire r_allow=(r&&!empty); wire w_allow=(w&&!full); r_w_ram u1(.w_clk(clk), .r_clk(clk), .w_addr(write_addr), .r_addr(read_addr), .w_allow(w_allow), .r_allow(r_allow), .w_data(write_data), .r_data(read_data));//wire always@(posedge clk,posedge fifo_reset) begin if(fifo_reset) empty<='b1; else empty<=(!w&&(Fcounter[8:1]==0)&&((Fcounter[0]==0)||r)); end always@(posedge clk,posedge fifo_reset) begin if(fifo_reset)

FIFO存储器的设计

FIFO存储器的设计 摘要:FIFO是一种不同时钟域之间传递数据的常用方法,基于FIFO(先进先出)设计的存储器的数据读出顺序与数据写入顺序始终一致。这种存储器主要用在两个处理数据速度不同的数字系统之间,作为数据缓冲器来提供必要的数据缓冲,使这两个数字系统达到同步,这在许多信号处理系统中是必须的。这篇文章介绍了一种容量为1k×9的具有异步和同步功能FIFO存储器的设计方法,这种设计方法也可以用于存储容量更大的存储器的设计。在设计具体逻辑单元时,基于Fundry厂商制定的工艺尺寸规则,优化了部分常用的逻辑电路,来减小版图面积和降低生产成本。 关键词:先进先出存储器;指针;数据缓冲;异步;同步 中图分类号:TN432 文献标识码: A Designing of FIFO memory Abstract :FIFO is a general way to communicate between different clock domains. The memory based on FIFO (First-In, First-Out) keeps track of the order in which date is entered into the memory and reads the date out in the same order. The most common application of a FIFO is as a buffer memory between two digital systems operating at different speeds, providing the necessary data buffering to achieve synchronization, which is a requirement for many signal processing systems. This paper describes a design of a 1k×9 asynchronous and simultaneous FIFO memory, which can also be applied on the larger memory size. Based on the fundry’s rule of the technology, we optimize some units in order to reduce the square of the layout and cost, during designing of the units of the logic. Keywords: FIFO memory; pointer; data buffering; asynchronous; simultaneous 1 引言 存储器是存储数字信息的电路或系统,随着IC产业的迅猛发展,现代数字系统需要高速存储和检索大量信息的能力,存储器在数字电路中越来越重要。最近的调查显示,在世界范围内,存储器芯片大约占了半导体交易的30%。 低功耗高速度的先进先出存储器在大规模数字集成电路中,尤其是在片上系统(System on Chip)中经常作为一个必不可少的模块被用到。在功能上FIFO存储器有点类似一个串行移位寄存器,数据读出顺序与数据写入顺序始终一致。这种存储器主要用在两个处理数据速度不同的数字系统之间,作为数据缓冲器使用[1]。即使这两个系统数据处理速度相同,要想使它们同步也是不可能的,FIFO存储器提供了必要的数据缓冲使其达到同步,这在许多信号处理系统中是必须的。

同步FIFO之VHDL描述

同步FIFO之VHDL描述(1) 作者:skycanny时间:2007-09-28 16:09:38 来自:skycanny的笔记浏览次数:1601 文字大小:【大】【中】【小】同步FIFO之VHDL描述 同步FIFO的意思是说FIFO的读写时钟是同一个时钟,不同于异步FIFO,异步FIFO的读写时钟是完全异步的。同步FIFO的对外接口包括时钟,清零,读请求,写请求,数据输入总线,数据输出总线,空以及满信号。下面分别对同步FIFO的对外接口信号作一描述:1.时钟,输入,用于同步FIFO的读和写,上升沿有效; 2.清零,输入,异步清零信号,低电平有效,该信号有效时,FIFO被清空; 3.写请求,输入,低电平有效,该信号有效时,表明外部电路请求向FIFO写入数据; 4.读请求,输入,低电平有效,该信号有效时,表明外部电路请求从FIFO中读取数据; 5.数据输入总线,输入,当写信号有效时,数据输入总线上的数据被写入到FIFO中; 6.数据输出总线,输出,当读信号有效时,数据从FIFO中被读出并放到数据输出总线上; 7.空,输出,高电平有效,当该信号有效时,表明FIFO中没有任何数据,全部为空; 8.满,输出,高电平有效,当该信号有效时,表明FIFO已经满了,没有空间可用来存贮数据。 使用VHDL描述的FIFO将以上面的接口为基础,并且可以参数化配置FIFO的宽度和深度。先把对外接口描述出来吧。 --------------------------------------------------------------------------------------------------------- -- Designer : skycanny -- Date : 2007-1-29 -- Description : Synchronous FIFO created by VHDL library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_unsigned.all; use ieee.std_logic_arith.all; entity sfifo is generic(width : positive depth : positive ); port ( clk : in std_logic; rst : in std_logic; wq : in std_logic; rq : in std_logic; data : in std_logic_vector(width - 1 downto 0); q : in std_logic_vector(width - 1 downto 0); empty : out std_logic; full : out std_logic ); end entity sfifo; ----------------------------------------------------------------------------------------------------------- 同步FIFO内部通过控制电路和RAM实现,控制电路主要包括写指针管理电路,读指针管理电路,以及FIFO状态判断电路,对于同步FIFO来讲,读和写的指针管理电路实际上就是二进制计数器。

FIFO原理讲解

异 步 FIFO 结 构 (第一部分) 作者:Vijay A.Nebhrajani 翻译:Adam Luo 2006年7月 设计一个FIFO是ASIC设计者遇到的最普遍的问题之一。本文着重介绍怎样设计FIFO——这是一个看似简单却很复杂的任务。 一开始,要注意,FIFO通常用于时钟域的过渡,是双时钟设计。换句话说,设计工程要处理(work off)两个时钟,因此在大多数情况下,FIFO工作于独立的两个时钟之间。然而,我们不从这样的结构开始介绍—我们将从工作在单时钟的一个FIFO特例开始。虽然工作在同一时钟的FIFO在实际应用中很少用到,但它为更多的复杂设计搭建一个平台,这是非常有用的。然后再从特例推广到更为普通的FIFO,该系列文章包括以下内容: 1.单时钟结构 2.双时钟结构——双钟结构1 3.双时钟结构——双钟结构2 4.双时钟结构——双钟结构3 5.脉冲模式FIFO

单时钟FIFO特例 FIFO有很多种结构,包括波浪型(ripple)FIFO,移位寄存器型以及其他一些我们并不关心的结构类型。我们将集中讨论包含RAM存储器的结构类型。其结构如图1所示。 通过分析,我们看到图中有一个具有独立的读端口和独立的写端口的RAM 存储器。这样选择是为了分析方便。如果是一个单端口的存储器,还应包含一个仲裁器保证同一时刻只能进行一项操作(读或写),我们选择双口RAM(无需真正的双口RAM,因为我们只是希望有一个简单的相互独立的读写端口)是因为这些实例非常接近实际情况。 读、写端口拥有又两个计数器产生的宽度为log2(array_size)的互相独立的读、写地址。数据宽度是一个非常重要的参数将在在稍后的结构选择时予以介绍,而现在我们不必过分的关心它。为了一致,我们称这些计数器为“读指针”(read pointer)和“写指针”(write pointer)。写指针指向下一个将要写入的位置,读指针指向下一个将要读取的位置。每次写操作使写指针加1,读操作使读指针加1。 我们看到最下面的模块为“状态”(stauts) 模块。这个模块的任务实给FIFO 提供“空”(empty)和“满”(full)信号。这些信号告诉外部电路FIFO已经达到了临界条件:如果出现“满”信号,那么FIFO为写操作的临界状态,如果出现“空”信号,则FIFO为读操作的临界状态。写操作的临界状态(“full is active”)表示FIFO已经没有空间来存储更多的数据,读操作的临界表示FIFO没有更多

两种异步FIFO的设计及verilog源代码

异步FIFO及verilog原码_1 异步FIFO及verilog原码 这几天看了Clifford E. Cummings的两篇大作《Simulation and Synthesis Techniques for Asynchronous FIFO Design》and 《Simulation and Synthesis Techniques for Asynchronous FIFO Design with Asynchronous Pointer Comparisons》颇有感想,真可谓经典之作,不可错过。 1.什么是FIFO? FIFO是英文First In First Out 的缩写,是一种先进先出的数据缓存器,他与普通存储器的区别是没有外部读写地址线,这样使用起来非常简单,但缺点就是只能顺序写入数据,顺序的读出数据,其数据地址由内部读写指针自动加1完成,不能像普通存储器那样可以由地址线决定读取或写入某个指定的地址。 2.什么情况下用FIFO? FIFO一般用于不同时钟域之间的数据传输,比如FIFO的一端是AD数据采集,另一端是计算机的PCI总线,假设其AD采集的速率为16位100K SPS,那么每秒的数据量为 100K×16bit=1.6Mbps,而PCI总线的速度为33MHz,总线宽度32bit,其最大传输速率为 1056Mbps,在两个不同的时钟域间就可以采用FIFO来作为数据缓冲。 另外对于不同宽度的数据接口也可以用FIFO,例如单片机位8位数据输出,而DSP可能是16位数据输入,在单片机与DSP连接时就可以使用FIFO来达到数据匹配的目的。 3.FIFO的一些重要参数

VLSI课程设计——同步FIFO的设计与实现

VLSI课程设计 同步FIFO设计与实现 班级: 学号: 姓名: 指导教师:

VLSI课程设计报告——同步FIFO设计与实现 一、FIFO概述 FIFO是英文First In First Out的缩写,意为先入先出存储器,由于微电子技术的飞速发展,新一代FIFO芯片容量越来越大,体积越来越小,价格越来越便宜。作为一种新型大规模集成电路,FIFO芯片以其灵活、方便、高效的特性,逐渐在高速数据采集、高速数据处理、高速数据传输以及多机处理系统中得到越来越广泛的应用。 它与普通随机存储器的区别是没有外部读写地址线,这样使用起来非常方便但缺点就是只能顺序读写数据,其读写数据地址依靠内部的读指针和写指针完成。读操作与写操作可以异步进行,写入区上写入的数据按照写入的顺序从读取端的区中读出,类似于吸收写入端与读出端速度差的一种缓冲器。计算机的串口,一般也都具有FIFO缓冲器(不是单一的FIFO存储器,而是嵌入在设备内部)。 二、同步FIFO 同步FIFO(S ynchronous FIFO,下称SFIFO)的意思是说FIFO的读写时钟是同一个时钟,因此时钟频率是相同的,只是在相位上可能有差别,不同于异步FIFO,异步FIFO的读写时钟是完全异步的。SFIFO的对外接口包括时钟,清零,读请求,写请求,数据输入总线,数据输出总线,空以及满信号。查阅资料找到一款成型SFIFO产品的接口描述,如图1: 图1 一款同步FIFO的接口资料 为了更好的理解FIFO的工作方式,我们设定SFIFO的深度为8。SFIFO的难点主要是状态判断,如图2是对空状态和满状态来进行判断的方式。

图2 FIFO空满状态判断 可以看出,当读指针和写指针的值一样的时候,FIFO的状态为空。比较麻烦的是对FIFO是否已经满的状态的判断,因为存在两种情况,第一种情况时写指针比读指针大,比如写指针= 7而读指针= 0,还有一种情况时写指针比读指针小,比如写指针= 2而读指针= 3。由于读写电路在循环的读写RAM,所以在上面的两种情况下FIFO实际上都已经满了。 第一种情况下,写指针–读指针= 7,实际上就是FIFO深度减一; 第二种情况下,(写指针+ 8) –读指针= 7,也是FIFO深度减一。 如此,就可以比较容易的判断出FIFO的状态了。 三、存储器结构及行为级描述 知道了SFIFO的接口和状态控制逻辑,结构框图就很显而易见了。如图3,本设计SFIFO由主RAM阵列,写控制逻辑,写指针控制器,状态判断逻辑,读指针控制器,读控制逻辑,输入寄存器,输出寄存器,复位及时钟逻辑构成。 图3 FIFO结构框图

相关文档
最新文档