同步FIFO

 同步FIFO设计主要的问题是产生空满标志位

1. 第一种方法是用计数器的方式生成代码及仿真波形如下

//此FIFO具有单拍潜伏期
module syn_fifo
#(
    parameter DATA_WIDTH = 8,//数据宽度为8bit
    parameter ADDR_WIDTH = 3,//地址宽度为4,寻址范围0~15
    parameter RAM_DEPTH = (1 << ADDR_WIDTH)
) 
(
    input clk,
    input rst_n,
    input [DATA_WIDTH-1:0] wdata,
    input wr_en,
    input rd_en,
    output reg [DATA_WIDTH-1:0] rdata,
    output empty, //fifo empty
    output full //fifo full
);
    reg [ADDR_WIDTH-1:0]wr_ptr,rd_ptr;
    reg [DATA_WIDTH-1:0] fifo_mem[RAM_DEPTH-1:0];
    integer i;
    
    wire wr_en_valid;
    wire rd_en_valid;
    reg [ADDR_WIDTH:0]fifo_count;
    
    //产生读写有效信号
    assign rd_en_valid = (rd_en && ~empty);
    assign wr_en_valid = (wr_en && ~full);
    
    //双口RAM建模
    //写端口
    always @(posedge clk or negedge rst_n)
    begin
        if(rst_n == 1'b0)
        begin
            for(i=0;i<= {(ADDR_WIDTH){1'b1}};i=i+1)
                fifo_mem[i] <= {(DATA_WIDTH){1'b0}} ;
        end
        else if (wr_en_valid)
                fifo_mem[wr_ptr] <= wdata ;
    end
    //读端口
    always @(posedge clk or negedge rst_n)
    begin
        if(rst_n == 1'b0)
            rdata <= 0;
        else if (rd_en_valid)
            rdata <= fifo_mem[rd_ptr];
    end
    
    //计数器计数值产生空满标志
    always @(posedge clk or negedge rst_n)
    begin
        if(!rst_n)
            fifo_count <= 0;
        else if(wr_en_valid && !rd_en_valid)
            fifo_count <= fifo_count+1;
        else if(rd_en_valid && !wr_en_valid)
            fifo_count <= fifo_count-1;
    end
    
    //产生读写地址指针 
    always @(posedge clk or negedge rst_n)
    begin
        if(!rst_n)
        begin
            wr_ptr <= 0;
            rd_ptr <= 0;
        end
        else begin
            if(wr_en_valid)
                wr_ptr <= wr_ptr + 1;
            if(rd_en_valid)
                rd_ptr <= rd_ptr +1;
        end    
    end
    
    assign full = (fifo_count == {(ADDR_WIDTH){1'b1}}+1);
    assign empty = (fifo_count == {(ADDR_WIDTH){1'b0}} && ~wr_en_valid);
    
endmodule

仿真代码

`timescale 1ns/1ns
module syn_fifo_tb;
    wire empty,full;
    wire [7:0]rdata;

    reg clk,rst_n;
    reg wr_en,rd_en;
    reg [7:0] wdata;

    integer i;
    initial begin
        clk = 1;
        rst_n = 0;
        wr_en = 0;
        rd_en = 0;
        wdata = 0;
        #40
        rst_n = 1;
        
        #100
        for(i=0;i<9;i=i+1)
        begin
            @(posedge clk);
            wr_en = 1;
            wdata = 2*i+1;
        end
        @(posedge clk);
        wr_en = 0;
        
        #100
        for(i=0;i<8;i=i+1)
        begin
            rd_en = 1;
            @(posedge clk);
        end
        @(posedge clk);
        rd_en=0;
        
        #100;
        $stop;
        
    end
    
    always #10 clk = ~clk;    
    

    syn_fifo syn_fifo_dut
/* #(
    parameter DATA_WIDTH = 8,//数据宽度为8bit
    parameter ADDR_WIDTH = 3,//地址宽度为4,寻址范围0~15
    parameter RAM_DEPTH = (1 << ADDR_WIDTH)
)  */
(
    .clk    (clk),
    .rst_n    (rst_n),
    .wdata    (wdata),
    .wr_en    (wr_en),
    .rd_en    (rd_en),
    .rdata    (rdata),
    .empty    (empty), //fifo empty
    .full     (full)//fifo full
);

endmodule 

仿真波形

 

 2. 第二种方法更好节省硬件开销

module syn_fifo
#(
    parameter DATA_WIDTH = 8,//数据宽度为8bit
    parameter ADDR_WIDTH = 3,//地址宽度为4,寻址范围0~15
    parameter RAM_DEPTH = (1 << ADDR_WIDTH)
) 
(
    input clk,
    input rst_n,
    input [DATA_WIDTH-1:0] wdata,
    input wr_en,
    input rd_en,
    output reg [DATA_WIDTH-1:0] rdata,
    output reg empty, //fifo empty
    output reg full //fifo full
);
    reg [ADDR_WIDTH-1:0]wr_ptr,rd_ptr;
    reg [DATA_WIDTH-1:0] fifo_mem[RAM_DEPTH-1:0];

    integer i;
    
    wire wr_en_valid,rd_en_valid ;
    
    assign wr_en_valid = (wr_en && (~full));
    assign rd_en_valid = (rd_en && (~empty));
    //双口RAM建模
    //写端口
    always @(posedge clk or negedge rst_n)
    begin
        if(rst_n == 1'b0)
        begin
            for(i=0;i<= {(ADDR_WIDTH){1'b1}};i=i+1)
                fifo_mem[i] <= {(DATA_WIDTH){1'b0}} ;
        end
        else if (wr_en_valid)
                fifo_mem[wr_ptr] <= wdata ;
    end
    //读端口
    always @(posedge clk or negedge rst_n)
    begin
        if(rst_n == 1'b0)
            rdata <= 0;
        else if (rd_en_valid)
            rdata <= fifo_mem[rd_ptr];
    end
    
    //产生满标志
    always @(posedge clk or negedge rst_n)
    begin
        if(!rst_n)
            full <= 0;
        else if(wr_en_valid && rd_en_valid)
            ;
        else if(rd_en_valid)
            full <= 0;
        else if(wr_en_valid && (rd_ptr == wr_ptr +3'b1))
            full <= 1;
    end
    
    //产生空标志
    always @(posedge clk or negedge rst_n)
    begin
        if(!rst_n)
            empty <= 1;
        else if(wr_en_valid && rd_en_valid)
            empty <= empty;
        else if(wr_en_valid)
            empty <= 0;
        else if(rd_en_valid && (wr_ptr == rd_ptr +3'b1))
            empty <= 1;
    end
    
    //产生读写地址指针 
    always @(posedge clk or negedge rst_n)
    begin
        if(!rst_n)
            wr_ptr <= 0;
        else if(wr_en_valid)
            wr_ptr <= wr_ptr + 1;    
    end
    //产生读写地址指针 
    always @(posedge clk or negedge rst_n)
    begin
        if(!rst_n)
            rd_ptr <= 0;
        else if(rd_en_valid)
            rd_ptr <= rd_ptr +1;
    end
    
endmodule

仿真代码同上;

仿真波形如下:

 

posted @ 2020-05-07 17:39  Mr_vol  阅读(266)  评论(0)    收藏  举报