参考博客: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