首页 > 其他 > 详细

异步FIFO

时间:2020-01-30 16:39:16      阅读:76      评论:0      收藏:0      [点我收藏+]

参考博文:https://blog.csdn.net/alangaixiaoxiao/article/details/81432144

1、概述

  异步FIFO设计的关键是产生“写满”和“读空”信号,这两个信号的产生需要用到读指针rptr和写指针wptr构建组合逻辑进行判断,然而读指针属于读时钟域rclk,写指针属于写时钟域wclk,因此必须进行同步化处理以消除亚稳态。异步FIFO的设计一般采用2种手段进行同步化处理:

  (1)将读指针rptr打2拍到写时钟域,将写指针wptr打两拍到读时钟域,消除亚稳态;

  (2)由于读写指针都是多比特信号,直接对它们进行同步化容易产生亚稳态,且用组合逻辑进行判断容易产生毛刺,因此改用格雷码进行异步时钟域的传输。

 

2、代码

  设计思路有以下几点:

  (1)在指针中添加一个额外的位(extra bit),当写指针增加并越过最后一个FIFO地址时,就将写指针这个未用的MSB加1,其它位回零。对读指针也进行同样的操作。此时,对于深度为2^n的FIFO,需要的                  读/写指针位宽为(n+1)位,如对于深度为8的FIFO,需要采用4bit的计数器,0000~1000、1001~1111,MSB作为折回标志位,而低3位作为地址指针。如果两个指针的MSB不同,说明写指针比读指                    针多折回了一次;如r_addr=0000,w_addr = 1000,为满。如果两个指针完全相同,为空。

  (2)使用gray码解决了一个问题,但同时也带来另一个问题,即在格雷码域如何判断空与满。空的判断标准仍是完全相同,满的判断标准需要满足:

    ■ 格雷码指针的最高位不同,因为wptr必须比rptr多折回一次。

    ■ wptrrptr的次高位不相等,如下表的7(格雷码为0100)和15(格雷码为1000),转化为二进制对应的是01111111MSB不同说明多折回一次,111相同代表同一位置。

    技术分享图片

 

    ■ 其余位完全相同

  (3)对双口RAM的寻址采用二进制码,异步时钟域的交互采用格雷码。

    技术分享图片

 

 1 `timescale 1ns / 1ps
 2 module fifo(rdata, wfull, rempty, wdata, winc, wclk, wrst_n,rinc, rclk, rrst_n);
 3 parameter DSIZE = 8; parameter ASIZE = 4;
 4 output [DSIZE-1:0] rdata;
 5 output wfull;
 6 output rempty;
 7 input [DSIZE-1:0] wdata;
 8 input winc, wclk, wrst_n;
 9 input rinc, rclk, rrst_n;
10 reg wfull,rempty;
11 reg [ASIZE:0] wptr, rptr, wq2_rptr, rq2_wptr, wq1_rptr,rq1_wptr;
12 reg [ASIZE:0] rbin, wbin;
13 reg [DSIZE-1:0] mem[0:(1<<ASIZE)-1];
14 wire [ASIZE-1:0] waddr, raddr;
15 wire [ASIZE:0] rgraynext, rbinnext,wgraynext,wbinnext;
16 wire rempty_val,wfull_val;
17 //-----------------双口RAM存储器--------------------
18 assign rdata=mem[raddr];
19 always@(posedge wclk)
20     if (winc && !wfull) mem[waddr] <= wdata;
21     
22 //-------------在写时钟域 wclk 同步 rptr 指针-------------------------
23 always @(posedge wclk or negedge wrst_n)
24     if (!wrst_n) {wq2_rptr,wq1_rptr} <= 0;
25     else {wq2_rptr,wq1_rptr} <= {wq1_rptr,rptr};
26     
27 //-------------在读时钟域 rclk 同步 wptr 指针---------------------------
28 always @(posedge rclk or negedge rrst_n)
29     if (!rrst_n) {rq2_wptr,rq1_wptr} <= 0;
30     else {rq2_wptr,rq1_wptr} <= {rq1_wptr,wptr};
31     
32     
33 //-------------rempty产生与raddr产生-------------------
34 always @(posedge rclk or negedge rrst_n) // GRAYSTYLE2 pointer
35 begin
36     if (!rrst_n) {rbin, rptr} <= 0;
37     else {rbin, rptr} <= {rbinnext, rgraynext};
38 end
39 // Memory read-address pointer (okay to use binary to address memory)
40 assign raddr = rbin[ASIZE-1:0];
41 assign rbinnext = rbin + (rinc & ~rempty);
42 assign rgraynext = (rbinnext>>1) ^ rbinnext;
43 // FIFO empty when the next rptr == synchronized wptr or on reset
44 assign rempty_val = (rgraynext == rq2_wptr);
45 always @(posedge rclk or negedge rrst_n)
46 begin
47     if (!rrst_n) rempty <= 1b1;
48     else rempty <= rempty_val;
49 end
50 
51 
52 //---------------wfull产生与waddr产生------------------------------
53 always @(posedge wclk or negedge wrst_n) // GRAYSTYLE2 pointer
54     if (!wrst_n) {wbin, wptr} <= 0;
55     else {wbin, wptr} <= {wbinnext, wgraynext};
56 // Memory write-address pointer (okay to use binary to address memory)
57 assign waddr = wbin[ASIZE-1:0];
58 assign wbinnext = wbin + (winc & ~wfull);
59 assign wgraynext = (wbinnext>>1) ^ wbinnext;
60 assign wfull_val = (wgraynext=={~wq2_rptr[ASIZE:ASIZE-1], wq2_rptr[ASIZE-2:0]}); //:ASIZE-1]
61 always @(posedge wclk or negedge wrst_n)
62 if (!wrst_n) wfull <= 1b0;
63 else wfull <= wfull_val;
64 
65 endmodule

3、验证

  留待以后……

  

异步FIFO

原文:https://www.cnblogs.com/wt-seu/p/12242867.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!