Verilog-同步FIFO

参考博客:https://blog.csdn.net/hengzo/article/details/49683707

1、基本框图

  1)双端口RAM加两个读写指针

  2)写数据、写使能、写满;读数据、读使能、读满

 2、代码思路

  

  1)Full和Empty的产生:使用fifo_counter记录FIFO RAM中的数据个数,等于0时,给出empty信号,等于BUF_LENGTH时,给出full信号

  2)fifo_counter的更新:发生有效写操作时+1,发生有效读操作时-1,同时发生读写操作时不变

  3)读写指针的控制:读写指针宽度与地址宽度相当,地址增加而溢出后,自动变成0。循环指针。初始时刻都指到0,发生有效写时写指针+1,写指针指向将要写的地址;发生有效读时读指针-1,读指针指向将要读的地址。

3、代码

`timescale 1ns / 1ps

module synchronous_fifo
 #(parameter BUF_WIDTH=3,  //地址宽度为3,
    parameter BUF_SIZE=8)   //数据个数,FIFO深度 
(
    input clk,
    input rst_n,
    input wr_en,
    input rd_en,
    input [7:0] buf_in,
    output [7:0] buf_out,
    output buf_full,
    output buf_empty,
    output [BUF_WIDTH:0] fifo_cnt
    );
   

reg [7:0] buf_mem [0:BUF_SIZE-1];  // 双端口RAM
reg [BUF_WIDTH-1:0] rd_ptr,wr_ptr; // 读写指针
reg [7:0] buf_out_reg;
reg [BUF_WIDTH:0] fifo_cnt_reg; // 存入数据的计数,0-8,位宽要比地址位宽大1

//========= 写入 ============
always @(posedge clk) begin
    if(wr_en&&!buf_full) begin
        buf_mem[wr_ptr] <= buf_in;
    end
end

//========= 读出 ============
always @(posedge clk or negedge rst_n) begin
    if(!rst_n) begin
        buf_out_reg <= 8'd0;
    end
    else begin
        if(rd_en&&!buf_empty) begin
            buf_out_reg <= buf_mem[rd_ptr];
        end
        else buf_out_reg <= buf_out_reg;
    end
end

assign buf_out = buf_out_reg;

//========= 数据计数 ============
always @(posedge clk or negedge rst_n) begin
    if(!rst_n) begin
        fifo_cnt_reg <= {(BUF_WIDTH+1){1'b0}};
    end
    else begin
        if((wr_en&&!buf_full)&&((rd_en&&!buf_empty))) 
            fifo_cnt_reg <= fifo_cnt_reg;
        else if(wr_en&&!buf_full)
            fifo_cnt_reg <= fifo_cnt_reg+1'b1;
        else if(rd_en&&!buf_empty)
            fifo_cnt_reg <= fifo_cnt_reg-1'b1;
        else fifo_cnt_reg <= fifo_cnt_reg;
    end
end
assign fifo_cnt = fifo_cnt_reg;

//========= 读写指针控制 ============
always @(posedge clk or negedge rst_n) begin
    if(!rst_n) begin
        rd_ptr <= {BUF_WIDTH{1'b0}};
    end
    else begin
        if(rd_en&&!buf_empty) rd_ptr <= rd_ptr + 1'b1;
        else rd_ptr <= rd_ptr;
    end
end

always @(posedge clk or negedge rst_n) begin
    if(!rst_n) begin
        wr_ptr <= {BUF_WIDTH{1'b0}};
    end
    else begin
        if(wr_en&&!buf_full) wr_ptr <= wr_ptr + 1'b1;
        else wr_ptr <= wr_ptr;
    end
end

//========= 空满判断 ============
assign buf_full = (fifo_cnt_reg == BUF_SIZE)?1'b1:1'b0;
assign buf_empty = (fifo_cnt_reg == {(BUF_WIDTH+1){1'b0}})?1'b1:1'b0;

endmodule

 

 

his is a Full version of ISim.
Time resolution is 1 ps
Simulator is doing circuit initialization process.
Finished circuit initialization process.
Push   1
Push   2
------Poped:   1
Push  10
Push  20
Push  30
Push  40
Push  50
Push  60
Push  70
---Cannot push  80: Buffer Full---
---Cannot push  90: Buffer Full---
---Cannot push 100: Buffer Full---
---Cannot push 110: Buffer Full---
---Cannot push 120: Buffer Full---
---Cannot push 130: Buffer Full---
------Poped:   2
Push   2
------Poped:  10
------Poped:  20
------Poped:  30
------Poped:  40
Push 140
------Poped:  50
Push  50
------Poped:  60
------Poped:  70
------Poped:   2
------Poped: 140
------Poped:  50
---Cannot Pop: Buffer Empty---
---Cannot Pop: Buffer Empty---
---Cannot Pop: Buffer Empty---
---Cannot Pop: Buffer Empty---
---Cannot Pop: Buffer Empty---
---Cannot Pop: Buffer Empty---
Push   5
------Poped:   5

 

posted @ 2020-02-24 10:10  笑着刻印在那一张泛黄  阅读(498)  评论(0编辑  收藏  举报