1. 程式人生 > 其它 >手撕程式碼——同步FIFO

手撕程式碼——同步FIFO

手撕程式碼——同步FIFO

module synfifo(
    input clk,
    input rst_n,
    input rd_en,
    input wr_en,
    output reg full,
    output reg empty,
    input [7:0] datain,
    output reg [7:0] dataout
);
    reg [7:0] RAM_DATA [511:0];
    reg [8:0] r_addr;
    reg [8:0] w_addr;
    reg [8:0] f_cnt;

    wire rd_allow;
    wire wr_allow;
    assign rd_allow = rd_en && !empty;
    assign wr_allow = wr_en && !full;
    //DUALRAM
    always @(posedge clk) begin
        if(wr_allow) begin
            RAM_DATA[w_addr] <=datain;
        end
    end

    always @(posedge clk) begin
        if(rd_allow) begin
            dataout<=RAM_DATA[r_addr];
        end
    end

    //empty和full賦值
    always @(posedge clk ) begin
        if(rst_n) begin
            empty <=1'b1;
        end
        else begin
            empty <= (!wr_en) && (f_cnt[8:1]==8'b0) &&(f_cnt[0]==0 || rd_en);
        end
    end

    always @(posedge clk ) begin
        if(rst_n) begin
            full <=1'b1;
        end
        else begin
            full <= (!rd_en) && (f_cnt[8:1]==8'hff) &&(f_cnt[0]==1 || wr_en);
        end
    end

    //讀寫地址變化
    always @(posedge clk) begin
        if(rst_n) begin
            r_addr <=9'd0;
        end
        else if (rd_allow) begin
            r_addr <=r_addr+1'b1;
        end
        else  begin
            r_addr <=r_addr;
        end
    end

    always @(posedge clk) begin
        if(rst_n) begin
            w_addr <=9'd0;
        end
        else if (wr_allow) begin
            w_addr <=w_addr+1'b1;
        end
        else  begin
            w_addr <=w_addr;
        end
    end

    //資料指標變化
    always @(posedge clk) begin
        if(rst_n)
        begin
            f_cnt <=9'd0;
        end
        else if ((rd_allow && !wr_allow ) ||(!rd_allow && wr_allow))begin
            if (wr_allow) begin
                f_cnt<=f_cnt+1'b1;
            end
            else begin
                f_cnt <=f_cnt-1'b1;
            end
        end
        else begin
            f_cnt <=f_cnt;
        end
    end
endmodule