题解 | #同步FIFO#

同步FIFO

http://www.nowcoder.com/practice/3ece2bed6f044ceebd172a7bf5cfb416

`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 [0:DEPTH-1];

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

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

endmodule  

/**********************************SFIFO************************************/
module sfifo#(
    parameter    WIDTH = 8,
    parameter     DEPTH = 16
)(
    input                     clk        , //同步FIFO读写在一个时钟
    input                     rst_n    ,
    input                     winc    ,
    input                      rinc    ,
    input         [WIDTH-1:0]    wdata    ,

    output reg                wfull    ,
    output reg                rempty    ,
    output wire [WIDTH-1:0]    rdata
);
    parameter ADDR_SIZE = 4;

    wire [ADDR_SIZE:0] rbinnext,wbinnext;
    reg [ADDR_SIZE:0] rbin,wbin;
    wire [ADDR_SIZE-1:0] raddr,waddr;
    wire val_rempty,val_wfull;
    //rempty
    assign rbinnext = rbin + (rinc&!rempty);
    always@(posedge clk or negedge rst_n)
    if(!rst_n)
        rbin <= 0;
    else
        rbin <= rbinnext;

    assign raddr = rbin[ADDR_SIZE-1:0];

    assign val_rempty = (rbin == wbin); 
    always@(posedge clk or negedge rst_n)
    if(!rst_n)
        rempty <= 0;
    else
        rempty <= val_rempty;
    //wfull
    assign wbinnext = wbin + (winc&!wfull);
    always@(posedge clk or negedge rst_n)
    if(!rst_n)
        wbin <= 0;
    else
        wbin <= wbinnext;

    assign waddr = wbin[ADDR_SIZE-1:0];

    assign val_wfull = ({!wbin[ADDR_SIZE],wbin[ADDR_SIZE-1:0]}==rbin); 
    always@(posedge clk or negedge rst_n)
    if(!rst_n)
        wfull <= 0;
    else
        wfull <= val_wfull;    
    //DualRAM
    wire wenc;
    assign wenc = winc&!wfull;
    dual_port_RAM #(
    .DEPTH(16),
    .WIDTH(8)
    )DualRAM(
    .wclk (clk),
    .wenc (wenc), 
    .waddr(waddr),  
    .wdata(wdata),          
    .rclk (clk),
    .renc (rinc),
    .raddr(raddr),  
    .rdata(rdata)     
    );

endmodule
全部评论

相关推荐

评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客企业服务