学习笔记二:异步FIFO

 
  1 module fifo1 #(parameter DSIZE = 8,
  2                     parameter ASIZE = 4)        //用格雷码的局限性:循环计数深度必须是2的n次幂,否则就失去了每次只变化一位的特性
  3                 (wclk,wrstn,wdata,wfull,winc,rclk,rrstn,rdata,rempty,rinc);
  4         input                         wclk,wrstn,winc;
  5         input    [DSIZE - 1:0]    wdata;
  6         output                    wfull;
  7         
  8         input                        rclk,rrstn,rinc;
  9         output [DSIZE - 1:0] rdata;
 10         output                    rempty;
 11 
 12         reg                        wfull,rempty;                    //空满输出
 13         reg    [ASIZE:0]        rbin,wbin;                        //读写二进制地址
 14         reg    [ASIZE:0]        wptr,rq1_wptr,rq2_wptr,        //读写指针打两拍CDC同步
 15                                     rptr,wq1_rptr,wq2_rptr;
 16         wire    [ASIZE:0]        rbinnext,wbinnext,            //读写指针递增
 17                                     rgraynext,wgraynext;            //读写指针递增对应的格雷码
 18         wire    [ASIZE - 1:0]    waddr,raddr;                    //实际读写mem的地址
 19         
 20         reg    [DSIZE - 1:0]    mem [0:(1<<ASIZE) - 1];    //左移一位表示乘2
 21         
 22         
 23 //---------------------双口RAM存储器 数据读写-----------------------------
 24 assign rdata = mem[raddr];            //
 25 always@(posedge wclk) begin        //
 26     if(winc && !wfull) begin
 27         mem[waddr] <= wdata;
 28     end
 29 end
 30 
 31 //---------------------将读指针CDC到写时钟域------------------------------
 32 always@(posedge wclk or negedge wrstn) begin
 33     if(!wrstn) begin
 34         wq2_rptr <= 5'd0;
 35         wq1_rptr <= 5'd0;
 36     end
 37     else begin
 38         wq1_rptr <= rptr;
 39         wq2_rptr <= wq1_rptr;
 40     end
 41 end
 42 
 43 //---------------------将写指针CDC到读时钟--------------------------------
 44 always@(posedge rclk or negedge rrstn) begin
 45     if(!rrstn) begin
 46         rq2_wptr <= 5'd0;
 47         rq1_wptr <= 5'd0;
 48     end
 49     else begin
 50         rq1_wptr <= wptr;
 51         rq2_wptr <= rq1_wptr;
 52     end
 53 end
 54 
 55 
 56 //读相关指针的产生
 57 always@(posedge rclk or negedge rrstn) begin                
 58     if(!rrstn) begin
 59         rptr <= 5'd0;
 60         rbin <= 5'd0;
 61     end
 62     else begin
 63         rptr <= rgraynext;
 64         rbin <= rbinnext;
 65     end
 66 end
 67 //写相关的指针
 68 always@(posedge wclk or negedge wrstn) begin
 69     if(!wrstn) begin
 70         wbin <= 5'd0;
 71         wptr <= 5'd0;
 72     end
 73     else begin
 74         wbin <= wbinnext;
 75         wptr <= wgraynext;
 76     end
 77 end
 78 
 79 //addr截取与格雷码化指针
 80 assign raddr = rbin[ASIZE - 1:0];                //mem的读地址
 81 assign rbinnext = rbin + (rinc & ~rempty);    //mem的下一个读地址
 82 assign rgraynext = (rbinnext>>1) ^ rbinnext; //mem的读地址对应的格雷码
 83 
 84 assign waddr = wbin[ASIZE - 1:0];
 85 assign wbinnext = wbin + (winc & !wfull);
 86 assign wgraynext = (wbinnext>>1) ^ wbinnext;
 87 
 88 //---------------------rempty产生------------------------------
 89 //FIFO empty when the next rptr == synchronized wptr or on the reset
 90 always@(posedge rclk or negedge rrstn) begin
 91     if(!rclk) begin
 92         rempty <= 1'b1;
 93     else begin
 94         rempty <= (rgraynext == rq2_wptr);
 95     end
 96 end
 97 
 98 //---------------------wfull产生------------------------------
 99 //FIFO full when CDC过来的格雷码(采样值)的最高位+次高位和bin转换过来的格雷码(理论值)均不同,剩下低位都相同
100 always@(posedge wclk or negedge wrstn) begin
101     if(!wrstn) begin
102         wfull <= 0;
103     end
104     else begin
105         wfull <= (wgraynext == {~wq2_rptr[ASIZE,ASIZE-1],wq2_rptr[ASIZE-2:0]});
106     end
107 end
108 
109 endmodule
110 /*Clifford E. Cummings的文章中提到的STYLE #1,构造一个指针宽度为N+1,深度为2^N字节的FIFO(为便方比较将格雷码指
111 针转换为二进制指针)。当指针的二进制码中最高位不一致而其它N位都 相等时,FIFO为满(在Clifford E. Cummings的文章中以
112 格雷码表示是前两位均不相同,而后两位LSB相同为满,这与换成二进制表示的MSB不同其他相同为满是一样的)。当指针完全相等时,
113 FIFO为空。
114 这种方法思路非常明了,为了比较不同时钟产生的指针,需要把不同时钟域的信号同步到本时钟域中来,而使用Gray码的目的就是使这个
115 异步同步化的过程发生亚稳态的机率最小。
116 */ 

 

很好的讲解:

https://www.cnblogs.com/aslmer/p/6114216.html#4067080

https://blog.csdn.net/wyj_2016/article/details/78469272

https://blog.csdn.net/IamSarah/article/details/76085635

https://blog.csdn.net/IamSarah/article/details/76093802

https://blog.csdn.net/tnaig/article/details/81503259

 

posted @ 2019-01-11 14:01  Sean-Zhang  阅读(983)  评论(0)    收藏  举报