fpga_feixiang 发表于 2020-10-13 14:31:42

同步FIFO代码

`define BUF_WIDTH   4   //地址宽度为3+1,
`define BUF_SIZE    8    //数据个数,FIFO深度

module fifo_counter( clk,rst_n,buf_in,buf_out,wr_en,rd_en,buf_empty,buf_full,fifo_cnt);
        input clk,rst_n;
        input wr_en,rd_en;
        input buf_in;             // data input to be pushed to buffer
        output reg buf_out;       // port to output the data using pop.
        output wire buf_empty,buf_full;// buffer empty and full indication
        output reg [`BUF_WIDTH-1:0] fifo_cnt;// number of data pushed in to buffer
                                               //写入数据等于8时,满
       
        reg [`BUF_WIDTH-2:0] rd_ptr,wr_ptr;//这个很重要,数据指针3位宽度,0-7索引,8个数据深度,循环指针0-7-0-7
        reg buf_mem;
       
        //判断空满
        assign buf_empty = (fifo_cnt == 0);//buf_empty若是reg类型则错,不能使用assign持续赋值
        assign buf_full= (fifo_cnt == `BUF_SIZE);
       
        always @(posedge clk or negedge rst_n)begin
                if(!rst_n)
                        fifo_cnt <= 0;
                else if((!buf_full&&wr_en)&&(!buf_empty&&rd_en)) //同时读写,数量不变
                        fifo_cnt <= fifo_cnt;
                else if(!buf_full && wr_en)          //写数据
                        fifo_cnt <= fifo_cnt + 1;
                else if(!buf_empty && rd_en)         //读数据
                        fifo_cnt <= fifo_cnt-1;
                else
                        fifo_cnt <= fifo_cnt;
        end
       
        always @(posedge clk or negedge rst_n) begin   //读数据
                if(!rst_n)
                        buf_out <= 0;
                if(rd_en && !buf_empty)
                        buf_out <= buf_mem;
        end
       
        always @(posedge clk) begin
                if(wr_en && !buf_full)
                        buf_mem <= buf_in;
        end
       
        always @(posedge clk or negedge rst_n) begin
                if(!rst_n) begin
                        wr_ptr <= 0;
                        rd_ptr <= 0;
                end
                else begin
                        if(!buf_full && wr_en)
                                wr_ptr <= wr_ptr + 1;
                        if(!buf_empty && rd_en)
                                rd_ptr <= rd_ptr + 1;
                end
        end
       
endmodule

使用Modelsim仿真的程序:
`define BUF_WIDTH   4   //地址宽度为3+1,
`define BUF_SIZE    (8)    //数据个数,FIFO深度

module tb_fifo_counter;
        reg clk,rst_n;
        reg wr_en,rd_en;
        reg buf_in;             // data input to be pushed to buffer
        wire buf_out;       // port to output the data using pop.
    wire buf_empty,buf_full;// buffer empty and full indication
        wire [`BUF_WIDTH-1:0] fifo_cnt;// number of data pushed in to buffer
       
        fifo_counter dut(clk,rst_n,buf_in,buf_out,wr_en,rd_en,buf_empty,buf_full,fifo_cnt);
       
        always #10 clk = ~clk;
       
        reg tempdata = 0;
        initial begin
                clk = 0;
                rst_n = 0;
                wr_en = 0;
                rd_en = 0;
                buf_in = 0;
                #15;
                rst_n = 1;
               
                push(1);
      fork
         push(2);
         pop(tempdata);
      join            //push and pop together   
      push(10);
      push(20);
      push(30);
      push(40);
      push(50);
      push(60);
      push(70);
      push(80);
      push(90);
      push(100);
      push(110);
      push(120);
      push(130);

      pop(tempdata);
      push(tempdata);
      pop(tempdata);
      pop(tempdata);
      pop(tempdata);
      pop(tempdata);
                push(140);
      pop(tempdata);
      push(tempdata);//
      pop(tempdata);
      pop(tempdata);
      pop(tempdata);
      pop(tempdata);
      pop(tempdata);
      pop(tempdata);
      pop(tempdata);
      pop(tempdata);
      pop(tempdata);
      pop(tempdata);
      pop(tempdata);
      push(5);
      pop(tempdata);
               
        end
       
        task push (input data);
                if(buf_full)
                        $display("---Cannot push %d: Buffer Full---",data);
                else begin
                        $display("Push",,data);
                        buf_in = data;
                        wr_en = 1;
                        @(posedge clk);
                        #5 wr_en = 0;
                end
        endtask
       
        task pop(output data);
                if(buf_empty)
                        $display("---Cannot Pop: Buffer Empty---");
                else begin
                        rd_en = 1;
                        @(posedge clk);
                        #3 rd_en = 0;
                        data = buf_out;
                        $display("------Poped:",,data);
                end               
        endtask
       
       
endmodule

程序仿真打印结果:
# Push   1
# Push   2
# ------Poped:   1
# Push10
# Push20
# Push30
# Push40
# Push50
# Push60
# Push70
# ---Cannot push80: Buffer Full---
# ---Cannot push90: 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
# Push50
# ------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

zxopenhl 发表于 2020-10-13 18:42:01

同步FIFO代码
页: [1]
查看完整版本: 同步FIFO代码