微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 硬件工程师文库 > FIFO 同步、异步以及Verilog代码实现

FIFO 同步、异步以及Verilog代码实现

时间:02-11 来源:网络整理 点击:

这个是基于RAM的异步FIFO代码,个人认为代码结构简单易懂,非常适合于考试中填写。记得10月份参加威盛的笔试的时候,就考过异步FIFO的实现。想当初要是早点复习,可能就可以通过威盛的笔试了。
与之前的用RAM实现的同步FIFO的程序相比,异步更为复杂。增加了读写控制信号的跨时钟域的同步。此外,判空与判满的也稍有不同。
module fifo1(rdata, wfull, rempty, wdata, winc, wclk, wrst_n,rinc, rclk, rrst_n);parameter DSIZE = 8; parameter ASIZE = 4;output [DSIZE-1:0] rdata;output wfull;output rempty;input [DSIZE-1:0] wdata;input winc, wclk, wrst_n;input rinc, rclk, rrst_n;reg wfull,rempty;reg [ASIZE:0] wptr, rptr, wq2_rptr, rq2_wptr, wq1_rptr,rq1_wptr;reg [ASIZE: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存储器--------------------assign rdata=mem[raddr];always@(posedge wclk)if (winc && !wfull) mem[waddr] <= wdata;//-------------同步rptr 指针-------------------------always @(posedge wclk or negedge wrst_n)if (!wrst_n) {wq2_rptr,wq1_rptr} <= 0;else {wq2_rptr,wq1_rptr} <= {wq1_rptr,rptr};//-------------同步wptr指针---------------------------always @(posedge rclk or negedge rrst_n)if (!rrst_n) {rq2_wptr,rq1_wptr} <= 0;else {rq2_wptr,rq1_wptr} <= {rq1_wptr,wptr};//-------------rempty产生与raddr产生-------------------always @(posedge rclk or negedge rrst_n) // GRAYSTYLE2 pointerbeginif (!rrst_n) {rbin, rptr} <= 0;else {rbin, rptr} <= {rbinnext, rgraynext};end// Memory read-address pointer (okay to use binary to address memory)assign raddr = rbin[ASIZE-1:0];assign rbinnext = rbin + (rinc & ~rempty);assign rgraynext = (rbinnext>>1) ^ rbinnext;// FIFO empty when the next rptr == synchronized wptr or on resetassign rempty_val = (rgraynext == rq2_wptr);always @(posedge rclk or negedge rrst_n)beginif (!rrst_n) rempty <= 1'b1;else rempty <= rempty_val;end//---------------wfull产生与waddr产生------------------------------always @(posedge wclk or negedge wrst_n) // GRAYSTYLE2 pointerif (!wrst_n) {wbin, wptr} <= 0;else {wbin, wptr} <= {wbinnext, wgraynext};// Memory write-address pointer (okay to use binary to address memory)assign waddr = wbin[ASIZE-1:0];assign wbinnext = wbin + (winc & ~wfull);assign wgraynext = (wbinnext>>1) ^ wbinnext;assign wfull_val = (wgraynext=={~wq2_rptr[ASIZE:ASIZE-1], wq2_rptr[ASIZE-2:0]}); //:ASIZE-1]always @(posedge wclk or negedge wrst_n)if (!wrst_n) wfull <= 1'b0;else wfull <= wfull_val;endmodule
..........................................................................................................................
异步FIFO的Verilog代码 之二

与前一段异步FIFO代码的主要区别在于,空/满状态标志的不同算法。
第一个算法:Clifford E. Cummings的文章中提到的STYLE #1,构造一个指针宽度为N+1,深度为2^N字节的FIFO(为便方比较将格雷码指针转换为二进制指针)。当指针的二进制码中最高位不一致而其它N位都 相等时,FIFO为满(在Clifford E. Cummings的文章中以格雷码表示是前两位均不相同,而后两位LSB相同为满,这与换成二进制表示的MSB不同其他相同为满是一样的)。当指针完全相 等时,FIFO为空。
这种方法思路非常明了,为了比较不同时钟产生的指针,需要把不同时钟域的信号同步到本时钟域中来,而使用Gray码的目的就是使这个异步同步化的过 程发生亚稳态的机率最小,而为什么要构造一个N+1的指针,Clifford E. Cummings也阐述的很明白,有兴趣的读者可以看下作者原文是怎么论述的,Clifford E. Cummings的这篇文章有Rev1.1 \ Rev1.2两个版本,两者在比较Gray码指针时的方法略有不同,个Rev1.2版更为精简。
第二种算法:Clifford E. Cummings的文章中提到的STYLE #2。它将FIFO地址分成

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top