同步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
仿真代码同上;
仿真波形如下:

浙公网安备 33010602011771号