异步FIFO及verilog原码Word下载.docx

上传人:b****5 文档编号:19015282 上传时间:2023-01-03 格式:DOCX 页数:8 大小:20.58KB
下载 相关 举报
异步FIFO及verilog原码Word下载.docx_第1页
第1页 / 共8页
异步FIFO及verilog原码Word下载.docx_第2页
第2页 / 共8页
异步FIFO及verilog原码Word下载.docx_第3页
第3页 / 共8页
异步FIFO及verilog原码Word下载.docx_第4页
第4页 / 共8页
异步FIFO及verilog原码Word下载.docx_第5页
第5页 / 共8页
点击查看更多>>
下载资源
资源描述

异步FIFO及verilog原码Word下载.docx

《异步FIFO及verilog原码Word下载.docx》由会员分享,可在线阅读,更多相关《异步FIFO及verilog原码Word下载.docx(8页珍藏版)》请在冰豆网上搜索。

异步FIFO及verilog原码Word下载.docx

读时钟:

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

写时钟:

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

读指针:

指向下一个读出地址。

读完后自动加1。

写指针:

指向下一个要写入的地址的,写完自动加1。

读写指针其实就是读写的地址,只不过这个地址不能任意选择,而是连续的。

4.FIFO的分类

根均FIFO工作的时钟域,可以将FIFO分为同步FIFO和异步FIFO。

同步FIFO是指读时钟和写时钟为同一个时钟。

在时钟沿来临时同时发生读写操作。

异步FIFO是指读写时钟不一致,读写时钟是互相独立的。

5.FIFO设计的难点

FIFO设计的难点在于怎样判断FIFO的空/满状态。

为了保证数据正确的写入或读出,而不发生益处或读空的状态出现,必须保证FIFO在满的情况下,不能进行写操作。

在空的状态下不能进行读操作。

怎样判断FIFO的满/空就成了FIFO设计的核心问题。

由于同步FIFO几乎很少用到,这里只描述异步FIFO的空/满标志产生问题。

在用到触发器的设计中,不可避免的会遇到亚稳态的问题(关于亚稳态这里不作介绍,可查看相关资料)。

在涉及到触发器的电路中,亚稳态无法彻底消除,只能想办法将其发生的概率将到最低。

其中的一个方法就是使用格雷码。

格雷码在相邻的两个码元之间只由一位变换(二进制码在很多情况下是很多码元在同时变化)。

这就会避免计数器与时钟同步的时候发生亚稳态现象。

但是格雷码有个缺点就是只能定义2^n的深度,而不能像二进制码那样随意的定义FIFO的深度,因为格雷码必须循环一个2^n,否则就不能保证两个相邻码元之间相差一位的条件,因此也就不是真正的各雷码了。

第二就是使用冗余的触发器,假设一个触发器发生亚稳态的概率为P,那么两个及联的触发器发生亚稳态的概率就为P的平方。

但这回导致延时的增加。

亚稳态的发生会使得FIFO出现错误,读/写时钟采样的地址指针会与真实的值之间不同,这就导致写入或读出的地址错误。

由于考虑延时的作用,空/满标志的产生并不一定出现在FIFO真的空/满时才出现。

可能FIFO还未空/满时就出现了空/满标志。

这并没有什么不好,只要保证FIFO不出现overfloworunderflow就OK了。

很多关于FIFO的文章其实讨论的都是空/满标志的不同算法问题。

第一个算法:

CliffordE.Cummings的文章中提到的STYLE#1,构造一个指针宽度为N+1,深度为2^N字节的FIFO(为便方比较将格雷码指针转换为二进制指针)。

当指针的二进制码中最高位不一致而其它N位都相等时,FIFO为满(在CliffordE.Cummings的文章中以格雷码表示是前两位均不相同,而后两位LSB相同为满,这与换成二进制表示的MSB不同其他相同为满是一样的)。

当指针完全相等时,FIFO为空。

这种方法思路非常明了,为了比较不同时钟产生的指针,需要把不同时钟域的信号同步到本时钟域中来,而使用Gray码的目的就是使这个异步同步化的过程发生亚稳态的机率最小,而为什么要构造一个N+1的指针,CliffordE.Cummings也阐述的很明白,有兴趣的读者可以看下作者原文是怎么论述的,CliffordE.Cummings的这篇文章有Rev1.1\Rev1.2两个版本,两者在比较Gray码指针时的方法略有不同,个Rev1.2版更为精简。

第二种算法:

CliffordE.Cummings的文章中提到的STYLE#2。

它将FIFO地址分成了4部分,每部分分别用高两位的MSB00、01、11、10决定FIFO是否为goingfull或goingempty(即将满或空)。

如果写指针的高两位MSB小于读指针的高两位MSB则FIFO为“几乎满”,若写指针的高两位MSB大于读指针的高两位MSB则FIFO为“几乎空”。

它是利用将地址空间分成4个象限(也就是四个等大小的区域),然后观察两个指针的相对位置,如果写指针落后读指针一个象限(25%的距离,呵呵),则证明很可能要写满,反之则很可能要读空,这个时候分别设置两个标志位dirset和dirrst,然后在地址完全相等的情况下,如果dirset有效就是写满,如果dirrst有效就是读空。

这种方法对深度为2^N字节的FIFO只需N位的指针即可,处理的速度也较第一种方法快。

异步FIFO及verilog原码_续

两篇文章的原码

//----------------------STYLE#1--------------------------

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

parameterDSIZE=8;

parameterASIZE=4;

output[DSIZE-1:

0]rdata;

outputwfull;

outputrempty;

input[DSIZE-1:

0]wdata;

inputwinc,wclk,wrst_n;

inputrinc,rclk,rrst_n;

regwfull,rempty;

reg[ASIZE:

0]wptr,rptr,wq2_rptr,rq2_wptr,wq1_rptr,rq1_wptr;

0]rbin,wbin;

reg[DSIZE-1:

0]mem[0:

(1<

<

ASIZE)-1];

wire[ASIZE-1:

0]waddr,raddr;

wire[ASIZE:

0] 

rgraynext,rbinnext,wgraynext,wbinnext;

wire 

rempty_val,wfull_val;

//-----------------双口RAM存储器--------------------

assignrdata=mem[raddr];

always@(posedgewclk)

if(winc&

&

!

wfull)mem[waddr]<

=wdata;

//-------------同步rptr指针-------------------------

always@(posedgewclkornegedgewrst_n)

if(!

wrst_n){wq2_rptr,wq1_rptr}<

=0;

else{wq2_rptr,wq1_rptr}<

={wq1_rptr,rptr};

//-------------同步wptr指针---------------------------

always@(posedgerclkornegedgerrst_n)

rrst_n){rq2_wptr,rq1_wptr}<

else{rq2_wptr,rq1_wptr}<

={rq1_wptr,wptr};

//-------------rempty产生与raddr产生-------------------

//-------------------

//GRAYSTYLE2pointer

begin

rrst_n){rbin,rptr}<

else{rbin,rptr}<

={rbinnext,rgraynext};

end

//Memoryread-addresspointer(okaytousebinarytoaddressmemory)

assignraddr=rbin[ASIZE-1:

0];

assignrbinnext=rbin+(rinc&

~rempty);

assignrgraynext=(rbinnext>

>

1)^rbinnext;

//---------------------------------------------------------------

//FIFOemptywhenthenextrptr==synchronizedwptroronreset

assignrempty_val=(rgraynext==rq2_wptr);

always@(posedgerclkornegedgerrst_n)

 

if(!

rrst_n)rempty<

=1'

b1;

elserempty<

=rempty_val;

//---------------wfull产生与waddr产生------------------------------

always@(posedgewclkornegedgewrst_n)

wrst_n){wbin,wptr}<

else{wbin,wptr}<

={wbinnext,wgraynext};

//Memorywrite-addresspointer(okaytousebinarytoaddressmemory)

assignwaddr=wbin[ASIZE-1:

assignwbinnext=wbin+(winc&

~wfull);

assignwgraynext=(wbinnext>

1)^wbinnext;

//------------------------------------------------------------------

//Simplifiedversionofthethreenecessaryfull-tests:

//assignwfull_val=((wgnext[ADDRSIZE]!

=wq2_rptr[ADDRSIZE])&

//(wgnext[ADDRSIZE-1]!

=wq2_rptr[ADDRSIZE-1])&

//(wgnext[ADDRSIZE-2:

0]==wq2_rptr[ADDRSIZE-2:

0]));

assignwfull_val=(wgraynext=={~wq2_rptr[ASIZE:

ASIZE-1],

wq2_rptr[ASIZE-2:

0]});

wrst_n)wfull<

b0;

elsewfull<

=wfull_val;

endmodule

//---------------------STYLE#2-------------------------

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

output[DSIZE-1:

outputwfull;

outputrempty;

input[DSIZE-1:

inputwinc,wclk,wrst_n;

inputrinc,rclk,rrst_n;

0]wptr,rptr;

async_cmp#(ASIZE)async_cmp(.aempty_n(aempty_n),

.afull_n(afull_n),

.wptr(wptr),.rptr(rptr),

.wrst_n(wrst_n));

fifomem2#(DSIZE,ASIZE)fifomem2(.rdata(rdata),

.wdata(wdata),

.waddr(wptr),

.raddr(rptr),

.wclken(winc),

.wclk(wclk));

rptr_empty2#(ASIZE)rptr_empty2(.rempty(rempty),

.rptr(rptr),

.aempty_n(aempty_n),

.rinc(rinc),

.rclk(rclk),

.rrst_n(rrst_n));

wptr_full2#(ASIZE)wptr_full2(.wfull(wfull),

.wptr(wptr),

.afull_n(afull_n),

.winc(winc),

.wclk(wclk),

.wrst_n(wrst_n));

modulefifomem2(rdata,wdata,waddr,raddr,wclken,wclk);

parameterDATASIZE=8;

//Memorydatawordwidth

parameterADDRSIZE=4;

//Numberofmemoryaddressbits

parameterDEPTH=1<

ADDRSIZE;

//DEPTH=2**ADDRSIZE

output[DATASIZE-1:

input[DATASIZE-1:

input[ADDRSIZE-1:

inputwclken,wclk;

`ifdefVENDORRAM

//instantiationofavendor'

sdual-portRAM

VENDOR_RAMMEM(.dout(rdata),.din(wdata),

.waddr(waddr),.raddr(raddr),

.wclken(wclken),.clk(wclk));

`else

reg[DATASIZE-1:

0]MEM[0:

DEPTH-1];

assignrdata=MEM[raddr];

always@(posedgewclk)

if(wclken)MEM[waddr]<

`endif

moduleasync_cmp(aempty_n,afull_n,wptr,rptr,wrst_n);

parameterN=ADDRSIZE-1;

outputaempty_n,afull_n;

input[N:

inputwrst_n;

regdirection;

wirehigh=1'

wiredirset_n=~((wptr[N]^rptr[N-1])&

~(wptr[N-1]^rptr[N]));

wiredirclr_n=~((~(wptr[N]^rptr[N-1])&

(wptr[N-1]^rptr[N]))|

~wrst_n);

always@(posedgehighornegedgedirset_nornegedgedirclr_n)

dirclr_n)direction<

elseif(!

dirset_n)direction<

elsedirection<

=high;

//always@(negedgedirset_nornegedgedirclr_n)

//if(!

//elsedirection<

assignaempty_n=~((wptr==rptr)&

direction);

assignafull_n=~((wptr==rptr)&

direction);

modulerptr_empty2(rempty,rptr,aempty_n,rinc,rclk,rrst_n);

parameterADDRSIZE=4;

output[ADDRSIZE-1:

0]rptr;

inputaempty_n;

reg[ADDRSIZE-1:

0]rptr,rbin;

regrempty,rempty2;

wire[ADDRSIZE-1:

0]rgnext,rbnext;

rrst_n)begin

rbin<

rptr<

end

elsebegin

=rbnext;

=rgnext;

//incrementthebinarycountifnotempty

//---------

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 幼儿教育 > 育儿知识

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1