FPGA Asynchronous FIFO設計思路

FPGA Asynchronous FIFO設計思路異步

 

 將一個多位寬,且在不停變化的數據從一個時鐘域傳遞到另外一個時鐘域是比較困難的。spa

 

 同步FIFO的指針比較好肯定,當FIFO counter達到上限值時候,FIFO爲滿,當FIFO counter0時,FIFO爲空。設計

 

 異步FIFOwriter pointer read pointer兩個指針,writer pointer 老是指向下一個要被寫入的位置,read pointer 老是指向下一個將被讀出的數據。沒有必要使用這樣一種機制:接受端的用戶邏輯先給一個時鐘週期到FIFO,使得指針指向將要讀出的數,而後接收端在用一個時鐘週期來鎖存讀出的數據。指針

 

 怎樣斷定FIFO的空滿,當寫指針追上讀指針時候,FIFO爲滿,當讀指針追上寫指針時候,FIFO爲空,既然當FIFO爲空和滿的時候,都是讀指針和寫指針相等,那該怎麼判斷空滿呢,在讀寫指針前面多加一位,當讀寫指針走過FIFO最後一個地址的時,並從頭再來,這個時候最高位進行翻轉,其餘地址位進行清零處理。若是,讀寫指針最高位相同,說明他們翻轉的次數相同,這種狀況只有讀在寫指針的後面,快要空。若是讀寫指針最高位不一樣,說明他們翻轉的次數不一樣,這種只能是寫指針在讀指針的後面,快要滿。code

 

`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模型,並不能拿來綜合和使用。(待續................)blog

相關文章
相關標籤/搜索