异步FIFO的Verilog实现

参考:
https://www.cnblogs.com/HolmeXin/p/9448626.html
https://www.cnblogs.com/SYoong/p/6110328.html
https://www.cnblogs.com/alifpga/p/9684653.html
http://bbs.eetop.cn/thread-857651-1-1.html?_dsign=1ad959fa
大佬讨论:http://bbs.eetop.cn/thread-613258-1-1.html




架构:

https://github.com/yllinux/blogPic/blob/master/doc/CummingsSNUG2002SJ_FIFO1.pdf
https://github.com/yllinux/blogPic/blob/master/doc/CummingsSNUG2002SJ_FIFO2.pdf

直接copy的代码:

module afifo
#(
    parameter WIDTH = 8,
    parameter DEPTH = 4
)
(
    input              clk_wr,
    input              clk_rd,
    input              rst_n_rd,
    input              rst_n_wr,
    input              wr_en,
    input              rd_en,
    input  [WIDTH-1:0] data_wr,
    output [WIDTH-1:0] data_rd,
    output reg         rd_empty,
    output reg         wr_full
);

    //defination
    reg  [WIDTH-1 : 0] mem [0 : (1<<DEPTH)-1];        //2^DEPTH numbers
    reg  [DEPTH   : 0] wp, rp;
    reg  [DEPTH   : 0] wr1_rp, wr2_rp, rd1_wp, rd2_wp;
    reg  [DEPTH   : 0] wbin, rbin;


    wire [DEPTH-1 : 0] waddr, raddr;
    wire [DEPTH   : 0] wbin_next, rbin_next;        //bincode
    wire [DEPTH   : 0] wgray_next, rgray_next;        //graycode
    
    wire rd_empty_val, wr_full_val;
    
    //output
    assign data_rd = (rd_en && !rd_empty) ? mem[raddr] : {WIDTH{1'b0}};        //clear "xx" state

    //input
    always@(posedge clk_wr)
        if(wr_en && !wr_full)
            mem[waddr] <= data_wr;

/*----------generate waddr and raddr-------------------------*/
    //gen raddr and read gray code
    always@(posedge clk_rd or negedge rst_n_rd)
        if(!rst_n_rd)
            {rbin, rp} <= 0;
        else
            {rbin, rp} <= {rbin_next, rgray_next};

    assign raddr = rbin[DEPTH-1 : 0];
    assign rbin_next = rbin + (rd_en & ~rd_empty);
    assign rgray_next = rbin_next ^ (rbin_next >> 1);

    //gen waddr and write gray code
    always@(posedge clk_wr or negedge rst_n_wr)
        if(!rst_n_wr)
            {wbin, wp} <= 0;
        else
            {wbin, wp} <= {wbin_next, wgray_next};

    assign waddr = wbin[DEPTH-1 : 0];
    assign wbin_next = wbin + (wr_en & ~wr_full);
    assign wgray_next = wbin_next ^ (wbin_next >> 1);

/*---------------synchro rp and wp--------------------------*/
    //synchro rp
    always@(posedge clk_wr or negedge rst_n_wr)
        if(!rst_n_wr)
            {wr2_rp, wr1_rp} <= 0;
        else
            {wr2_rp, wr1_rp} <= {wr1_rp, rp}; //delay two clock

    //synchro wp
    always@(posedge clk_rd or negedge rst_n_rd)
        if(!rst_n_rd)
            {rd2_wp, rd1_wp} <= 0;
        else
            {rd2_wp, rd1_wp} <= {rd1_wp, wp};

/*---------------empty and full flags--------------------------*/
    //gen rd_empty
    assign rd_empty_val = (rd2_wp == rgray_next);
    always@(posedge clk_rd or negedge rst_n_rd)
        if(!rst_n_rd)
            rd_empty <= 1'b1;
        else
            rd_empty <= rd_empty_val;

    //gen wr_full, two high bit do not equal
    assign wr_full_val = ({~wr2_rp[DEPTH : DEPTH-1], wr2_rp[DEPTH-2 : 0]} == wgray_next);
    always@(posedge clk_wr or negedge rst_n_wr)
        if(!rst_n_wr)
            wr_full <= 1'b0;
        else
            wr_full <= wr_full_val;

endmodule




图 写满

图 假满和读空

图 假空




写了一个同步fifo,初学者可以参考参考

中文翻译的Clifford E. Cummings经典的异步fifo设计
Clifford E. Cummings论文合集

原文地址:https://www.cnblogs.com/yllinux/p/13069179.html