FIFO

Posted lizhiqing

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了FIFO相关的知识,希望对你有一定的参考价值。

FIFO(first in first out)

先入先出的数据缓存器,没有外部读写地址线,可同时读写

一、同步fifo

 

技术图片

 

 

fifo状态表示 fifo_empty,fifo_full

一、

 

二、

二、异步fifo

需要引入同步时钟信号,

fifo_full时需要,允许fifo实际未满,但是fifo_full为1,即

 

 

格雷码实现FIFO指针

完美的实现FIFO空或FIFO满条件需要正确取样wr_ptr和rd_ptr的值,在wr_clk和rd_clk时钟域之间传递指针的最好方式是使用格雷码实现指针。

原因:如果同步时钟信号在计数值转换期间到来,这种编码能消除绝大部分的错误。

 

格雷码计数器设计设计流程

下图为格雷码计数器的设计步骤:

  1. 将格雷值转换为二进制值;
  2. 根据条件递增二进制值;
  3. 将二进制值转化为格雷码;
  4. 将计数器的最终格雷值保存到寄存器中。

技术图片

 

 

 一、格雷码到二进制转换器

转换关系表

技术图片

 

 

对于n位计数器来说,格雷值与二进制值的MSB相同:

技术图片

 

 

二进制值非最高位值可以通过二进制值的高一位值与对应位置的格雷码值做异或获得,可以替代做链式推导:

技术图片

 

 

以四位转换器为例,转换公式为:

技术图片

 

 

//转换器verilog代码
module gray_to_bin #(parameter size=4)(
    input       [size-1:0]    gray,
    output  reg    [size-1:0]    bin
);
    integer    i;
always @(gray)
    for(i=0; i<=size; i=i+1)
        bin[i] = ^(gray >> i);  //移位预算符产生的0在异或中不影响最终结果
endmodule

 

 

 

 

 二、二进制码到格雷码转换器

对于n位计数器来说,格雷值与二进制值的MSB相同:

技术图片

 

技术图片

 

 

 

// 二进制码转换为格雷码
module bin_to_gray #(parameter size=4)(
    input    [size-1:0]    bin,
    output    reg    [size-1:0] gray
);
assign gray = bin ^ (bin>>1);
endmodule     

 

 

 

 格雷码计数器verilog代码

module gray_counter#(parameter size=4)(
    input                                 clk, inr, rst_n,
    output    reg    [size-1:0]    gray
); 

reg [size-1:0]    gray_temp, bin_temp, bin;
integer    i;

always @(posedge clk or negedge rst_n)
    begin:gray_registered
        if(!rst_n)
            gray <= {size{1b0}};
        else
            gray <= gray_temp;
    end

always @(gray or inr)
    begin:gray_bin_gray
        for(i=0; i<=size; i=i+1)
            bin[i] = ^(gray>>i);
        bin_temp = bin + inr;
        gray_temp = bin_temp ^ (bin_temp>>1)
    end
endmodulel

逻辑原理图:

技术图片 

异步FIFO满与空的产生:方法一

指针表示方法:

N位指针可以覆盖2^N个地址,如果使用与FIFO大小相同的N表示地址会导致,wr_ptr和rd_ptr相同时,FIFO可能处于fifo_empty或者fifo_full的状态,因此可以增加一位作为地址的MSB,即指针宽度比寻址FIFO存储器所需宽度多一位。

当wr_ptr和rd_ptr完全相同时,表示fifo当前状态为fifo_empty;

当wr_ptr和rd_ptr仅有MSB不相同时,表示fifo当前状态为fifo_full;

技术图片

 

 

 FIFO状态模块原理图,(fifo满产生中MSB比较器‘==‘应该为‘!=’):由于存在XOR门链路,最大操作频率取决于格雷码计数器的速度。

技术图片

 

 

特点:该方法指针以格雷码形式保存,比较和递增操作以二进制形式进行,需要4个格雷码到二进制转化器,需要比较多的逻辑;功能区分明显,逻辑实现比较简单,纠错也比较简单。

 

 异步FIFO满与空的产生:方法二

直接比较读指针与写指针的格雷码,

问题:由于格雷码除最高位以外的值不同于二进制码的对称方式,而是镜像对称,因此需要进行一定的转换,从而实现格雷码之间的对比。

四位格雷码转换三位格雷码转换方法及转换表:

技术图片

技术图片

 

 

 

 

fifo_empty应该由rd_ptr与经rd_clk同步后的wr_ptr_sync计算获得,因为fifo_empty仅对读操作有影响,wr_ptr_sync相对于wr_ptr信号存在延迟,即使出现在同步过程中wr_ptr发生变化,也仅会导致实际fifo不为空,但fifo_empty有效,导致无法读取数据;但是如果由rd_ptr_sync与wr_ptr计算获得则可能导致读空FIFO的操作,从而出错。同理fifo_full也应该由rd_ptr_sync与wr_ptr计算获得。

 

fifo_empty仅对读操作有影响,对写操作没有影响,因此fifo_empty应当由rd_ptr和wr_ptr_sync产生,需要‘立刻’了解到rd_ptr的状态,而wr_ptr可以允许由延迟。

fifo_full仅对写操作有影响,对读操作没有影响,因此fifo_full应当由wr_ptr和rd_ptr_sync产生,需要‘立刻’了解到wr_ptr的状态,而rd_ptr可以允许由延迟。

技术图片

 

以上是关于FIFO的主要内容,如果未能解决你的问题,请参考以下文章

perl中的队列

操作系统:FIFO算法详解及代码演示

Python 子进程挂起命名管道

FIFO:一个进程从不从管道中读取

同一进程使用FIFO两端时无法重新打开FIFO

FIFO IP核仿真