异步FIFO

接着上一个章节,继续介绍FIFO。异步FIFO读/写指针在不同的时钟域产生,如何根据异步指针信号对FIFO的空/满状态进行正确的判断则成为重点。
二进制指针由地址位和状态位组成,地址位随相应的操作递增,指针由内存的以后w位置返回到初始位置时状态位取反。
eg:当读指针从0111到1000变化时,指针的所有位都发生了变换,如果写指针刚好在读指针变换时采样,写得到的读指针有可能是从0000到1111的任意数值。
为了能够在不同时钟域内直接同步指针,可采用格雷码的编码方式,也就是指针每次移动只变化一位,这样就避免额由于指针多位同时变化而无法直接同步的问题。
异步FIFO的FPGA实现,先以在读时钟域下产生状态为例,分为以下几个步骤:
1.将写指针(二进制)转化为格雷码
2.将写指针(格雷码)通过跨时钟转换到读时钟域
3.将写格雷码指针转换为写二进制指针
4.写指针与读指针通过二进制进行比较产生状态
代码如下,写时钟域的状态产生同理而言

// Current read pointer               
always @(posedge clkb or posedge arstb  )
    if (arstb  )
        cur_rptr <= {C_AW+1{1'b0}};
    else
        cur_rptr <= next_rptr;   

// Change binary read pointer to gray code 
generate
//    genvar i;
    for (i=0;i<C_AW+1;i=i+1)
        begin :RBIN2GRAY_GEN
            wire   m;
            assign m = (i == C_AW) ? 1'b0 : cur_rptr[(i+1)%(C_AW+1)]; 
            always @(posedge clkb or posedge arstb  )
                if (arstb  )
                    gray_rptr[i] <= 1'b0;
                else
                    gray_rptr[i] <= cur_rptr[i] ^ m;  
        end
endgenerate              

// Write pointer to Read clock domain
always @(posedge clkb or posedge arstb)        
    if (arstb  )
        begin
            gray_awptr <= {C_AW+1{1'b0}};
            gray_swptr <= {C_AW+1{1'b0}};
        end
    else
        begin
            gray_awptr <= gray_wptr   ;
            gray_swptr <= gray_awptr  ;
        end    

// Convert the Gray pointer to binary                      
generate 
//    genvar i;
    for (i=0;i<C_AW+1;i=i+1)
        begin :WGRAY2BIN_GEN
            always @(posedge clkb or posedge arstb)
                if (arstb  )
                    bin_wptr[i] <= 1'b0;
                else
                    bin_wptr[i] <= ^gray_swptr[C_AW:i];
        end
endgenerate

// empty flag
always @(posedge clkb or posedge arstb)
    if (arstb  )
        rempty  <= 1'b1;
    else      
        rempty  <= (next_rptr == bin_wptr);//(rdiff == 0);

// almost empty flag        
always @(posedge clkb or posedge arstb)
    if (arstb  )         
        arempty <= 1'b1;
    else
        arempty <= (rdiff < (C_HAE + 1));  

always @(posedge clkb or posedge arstb)
    if (arstb  )
        rleft  <= {C_AW+1{1'b0}};
    else
        rleft  <= rdiff       ;       

always @(posedge clkb or posedge arstb)
    if (arstb  )   
        uflw   <= 1'b0;
    else
        uflw   <= rempty & re;      
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值