题解 | #异步FIFO#

异步FIFO

https://www.nowcoder.com/practice/40246577a1a04c08b3b7f529f9a268cf

`timescale 1ns/1ns

/***************************************RAM*****************************************/
module dual_port_RAM #(parameter DEPTH = 16,
                       parameter WIDTH = 8)(
     input wclk
    ,input wenc
    ,input [$clog2(DEPTH)-1:0] waddr  //深度对2取对数,得到地址的位宽。
    ,input [WIDTH-1:0] wdata        //数据写入
    ,input rclk
    ,input renc
    ,input [$clog2(DEPTH)-1:0] raddr  //深度对2取对数,得到地址的位宽。
    ,output reg [WIDTH-1:0] rdata       //数据输出
);

reg [WIDTH-1:0] RAM_MEM [DEPTH-1:0];

always @(posedge wclk) begin
    if(wenc)
        RAM_MEM[waddr] <= wdata;
end 

always @(posedge rclk) begin
    if(renc)
        rdata <= RAM_MEM[raddr];
end 

endmodule  

/***************************************AFIFO*****************************************/
module asyn_fifo#(
    parameter   WIDTH = 8,
    parameter   DEPTH = 16
)(
    input                   wclk    , 
    input                   rclk    ,   
    input                   wrstn   ,
    input                   rrstn   ,
    input                   winc    ,
    input                   rinc    ,
    input       [WIDTH-1:0] wdata   ,

    output wire             wfull   ,
    output wire             rempty  ,
    output wire [WIDTH-1:0] rdata
);
    wire wenc, renc;
    assign wenc = (!wfull && winc);
    assign renc = (!rempty && rinc);
    wire [$clog2(DEPTH):0] wptr_gray, rptr_gray;
    reg [$clog2(DEPTH):0] wptr_bin, rptr_bin;
    always@(posedge wclk or negedge wrstn)begin
        if(!wrstn) begin
            wptr_bin <= 0;
        end
        else if(wenc) begin
            wptr_bin <= wptr_bin + 1'b1;
        end
    end

    always@(posedge rclk or negedge rrstn)begin
            if(!rrstn) begin
                rptr_bin <= 0;
            end
            else if(renc) begin
                rptr_bin <= rptr_bin + 1'b1;
            end
    end
    assign wptr_gray = (wptr_bin >> 1) ^ wptr_bin;
    assign rptr_gray = (rptr_bin >> 1) ^ rptr_bin;
    reg [$clog2(DEPTH):0] wptr_gray_next, wptr_gray_r, wptr_gray_rr;
    reg [$clog2(DEPTH):0] rptr_gray_next, rptr_gray_r, rptr_gray_rr;
    always @ (posedge wclk or negedge wrstn) begin
        if(!wrstn) begin
            wptr_gray_next <= 0;
        end
        else begin
            wptr_gray_next <= wptr_gray;
        end
    end
    always @ (posedge rclk or negedge rrstn) begin
        if(!rrstn) begin
            rptr_gray_next <= 0;
        end
        else begin
            rptr_gray_next <= rptr_gray;
        end
    end
    always @ (posedge rclk or negedge rrstn) begin
        if(!rrstn) begin
            wptr_gray_r <= 0;
            wptr_gray_rr <= 0;
        end
        else begin
            wptr_gray_rr <= wptr_gray_r;
            wptr_gray_r <= wptr_gray_next;
        end
    end
    always @ (posedge wclk or negedge wrstn) begin
        if(!wrstn) begin
            rptr_gray_rr <= 0;
            rptr_gray_r <= 0;
        end
        else begin
            rptr_gray_rr <= rptr_gray_r;
            rptr_gray_r <= rptr_gray_next;
        end
    end
    assign rempty = (rptr_gray_next == wptr_gray_rr);
    assign wfull = (wptr_gray_next == {~rptr_gray_rr[$clog2(DEPTH):$clog2(DEPTH) - 1], rptr_gray_rr[$clog2(DEPTH) - 2:0]});
    dual_port_RAM #(.WIDTH(WIDTH), .DEPTH(DEPTH)) asyn_fifo (
        .wclk(wclk),
        .rclk(rclk),
        .wenc(wenc),
        .renc(renc),
        .waddr(wptr_bin[$clog2(DEPTH) - 1:0]),
        .raddr(rptr_bin[$clog2(DEPTH) - 1:0]),
        .wdata(wdata),
        .rdata(rdata)
    );

endmodule

全部评论

相关推荐

求面试求offer啊啊啊啊:这个在牛客不是老熟人了吗
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客企业服务