博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

FPGA Asynchronous FIFO设计思路

Posted on 2018-10-25 10:07  沉默改良者  阅读(620)  评论(0编辑  收藏  举报

FPGA Asynchronous FIFO设计思路

 

 将一个多位宽,且在不停变化的数据从一个时钟域传递到另一个时钟域是比较困难的。

 

 同步FIFO的指针比较好确定,当FIFO counter达到上限值时候,FIFO为满,当FIFO counter0时,FIFO为空。

 

 异步FIFOwriter pointer read pointer两个指针,writer pointer 总是指向下一个要被写入的位置,read pointer 总是指向下一个将被读出的数据。没有必要使用这样一种机制:接受端的用户逻辑先给一个时钟周期到FIFO,使得指针指向将要读出的数,然后接收端在用一个时钟周期来锁存读出的数据。

 

 怎样判定FIFO的空满,当写指针追上读指针时候,FIFO为满,当读指针追上写指针时候,FIFO为空,既然当FIFO为空和满的时候,都是读指针和写指针相等,那该怎么判断空满呢,在读写指针前面多加一位,当读写指针走过FIFO最后一个地址的时,并从头再来,这个时候最高位进行翻转,其他地址位进行清零处理。如果,读写指针最高位相同,说明他们翻转的次数相同,这种情况只有读在写指针的后面,快要空。如果读写指针最高位不同,说明他们翻转的次数不同,这种只能是写指针在读指针的后面,快要满。

 

`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: chensimin
// 
// Create Date: 2018/10/24 17:31:22
// Design Name: 
// Module Name: beh_fifo
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//////////////////////////////////////////////////////////////////////////////////


module beh_fifo #(

    parameter  ASIZE = 4,
    parameter  DSIZE = 8    )
(

    input       wire                 wclk,
    input       wire                 wrst_n,
    input       wire                 winc,
    input       wire  [DSIZE-1 : 0]  wdata,

    output      wire                 wfull,
    output      wire                 rempty,

    input       wire                 rclk,
    input       wire                 rrst_n,
    input       wire                 rinc,
    output      wire  [DSIZE-1 : 0]  rdata

);


//--------------------------------------------------------------
//写一个数据,指针加一
parameter MEMDEPTH = 1 << ASIZE;
reg [ASIZE   : 0]       wptr;
reg [DSIZE-1 : 0]       ex_mem [0 : MEMDEPTH-1];

always @(posedge wclk or negedge wrst_n)
begin
    if(!wrst_n)
        wptr <= 0;
    else if(winc && !wfull)
    begin
        ex_mem[wptr[ASIZE-1 : 0]] <= wdata;
        wptr <= wptr + 1;
    end
end

//--------------------------------------------------------------
//将rptr读指针,同步到wclk时钟域,打了三拍
reg  [ASIZE   : 0]       wrptr3;
reg  [ASIZE   : 0]       wrptr2;
reg  [ASIZE   : 0]       wrptr1;

always @(posedge wclk or negedge wrst_n)
begin
    if(!wrst_n)
        {wrptr3, wrptr2, wrptr1} <= 0;
    else 
        {wrptr3, wrptr2, wrptr1} <= {wrptr2, wrptr1, rptr};
end

//--------------------------------------------------------------
//读指针加一
reg [ASIZE   : 0]       rptr;
always @(posedge rclk or negedge rrst_n)
begin
    if(!rrst_n)
        rptr <= 0;
    else if(rinc && !rempty)
        rptr <= rptr + 1;
end

//--------------------------------------------------------------
//将写指针同步到读指针时钟域
reg  [ASIZE   : 0]       rwptr3;
reg  [ASIZE   : 0]       rwptr2;
reg  [ASIZE   : 0]       rwptr1;

always @(posedge rclk or negedge rrst_n)
begin
    if(!rrst_n)
        {rwptr3, rwptr2, rwptr1} <= 0;
    else 
        {rwptr3, rwptr2, rwptr1} <= {rwptr2, rwptr1, wptr};
end

//--------------------------------------------------------------

assign rdata  = ex_mem[rptr[ASIZE-1 : 0]];
assign rempty = (rptr == rwptr3);
assign wfull  = (( wptr[ASIZE-1:0] == wrptr3[ASIZE-1:0] ) &&  
                 ( wptr[ASIZE] != wrptr3[ASIZE]         ));


endmodule

以上只是一个很粗糙的FIFO模型,并不能拿来综合和使用。(待续................)