FIFO,First In First Out ,是一种先进先出的数据缓存器。
没有外部读写地址线,只能顺序写入数据,顺序的读出数据, 其数据地址由内部读写指针自动加1完成。
不能像普通存储器那样可以由地址线决定读取或写入某个指定的地址。
FIFO一般用于不同时钟域之间的数据传输,根据工作的时钟域,分为同步FIFO和异步FIFO。
同步FIFO是指读时钟和写时钟为同一个时钟。在时钟沿来临时同时发生读写操作。
异步FIFO是指读写时钟不一致,读写时钟是互相独立的。
同步FIFO
1 `timescale 1ns / 1ps 2 ////////////////////////////////////////////////////////////////////////////////// 3 // Company: 4 // Engineer: 5 // 6 // Create Date: 2018/05/02 21:34:02 7 // Design Name: 8 // Module Name: FIFO_16bits_16 9 // Project Name: 10 // Target Devices: 11 // Tool Versions: 12 // Description: synchronous fifo 16bits * 16 13 // 14 // Dependencies: 15 // 16 // Revision: 17 // Revision 0.01 - File Created 18 // Additional Comments: 19 // 20 ////////////////////////////////////////////////////////////////////////////////// 21 `define ADDR_WIDTH 4 //ADDR WIDTH = 4, 22 `define FIFO_DEPTH 16 //FIFO DEPTH 23 `define FIFO_WIDTH 16 //FIFO WIDTH 16 BITS 24 25 module myFIFO( 26 input wire clk, 27 input wire rst_n, 28 input wire wr_en, 29 input wire rd_en, //wire write/read enable 30 input wire [`FIFO_WIDTH:0] buf_in, // data input to be pushed to buffer 31 output reg [`FIFO_WIDTH:0] buf_out, // port to output the data using pop. 32 output wire buf_empty, 33 output wire buf_full, // fifo buffer empty/full indication 34 output reg [`ADDR_WIDTH:0] fifo_cnt // number of data pushed in to buffer,16-> FULL;0-> EMPTY 35 ); 36 37 reg [`ADDR_WIDTH-1:0] rd_ptr,wr_ptr; //ADDR PTR .INDEX ,CYCLE 0->15->0->15 38 reg [`FIFO_WIDTH:0] buf_mem[0:`FIFO_DEPTH-1]; 39 reg rst_nr; 40 //juge full/empty 41 assign buf_empty = (fifo_cnt == 0)?1:0; 42 assign buf_full = (fifo_cnt == `FIFO_DEPTH)?1:0; 43 //Asynchronous reset,synch release 44 // always @(posedge clk)begin 45 // rst_nr <= rst_n; 46 // end 47 //FIFO_CNT 48 always @(posedge clk or negedge rst_n)begin 49 if(!rst_n) 50 fifo_cnt <= 0; 51 else if((!buf_full&&wr_en)&&(!buf_empty&&rd_en)) //WRTITE & READ ,HOLD 52 fifo_cnt <= fifo_cnt; 53 else if(!buf_full && wr_en) //WRITE-> +1 54 fifo_cnt <= fifo_cnt + 1; 55 else if(!buf_empty && rd_en) //READ -> -1 56 fifo_cnt <= fifo_cnt-1; 57 else 58 fifo_cnt <= fifo_cnt; 59 end 60 //READ 61 always @(posedge clk or negedge rst_n) begin 62 if(!rst_n) 63 buf_out <= 0; 64 if(rd_en && !buf_empty) 65 buf_out <= buf_mem[rd_ptr]; 66 end 67 //WRITE 68 always @(posedge clk) begin 69 if(wr_en && !buf_full) 70 buf_mem[wr_ptr] <= buf_in; 71 end 72 //wr_ptr & rd_ptr ,ADDR PTR 73 always @(posedge clk or negedge rst_n) begin 74 if(!rst_n) begin 75 wr_ptr <= 0; 76 rd_ptr <= 0; 77 end 78 else begin 79 if(!buf_full && wr_en) 80 wr_ptr <= wr_ptr + 1; 81 if(!buf_empty && rd_en) 82 rd_ptr <= rd_ptr + 1; 83 end 84 end 85 86 endmodule
testbench
1 `timescale 1ns / 1ps 2 ////////////////////////////////////////////////////////////////////////////////// 3 // Company: 4 // Engineer: 5 // 6 // Create Date: 2018/05/02 21:42:06 7 // Design Name: 8 // Module Name: tb 9 // Project Name: 10 // Target Devices: 11 // Tool Versions: 12 // Description: 13 // 14 // Dependencies: 15 // 16 // Revision: 17 // Revision 0.01 - File Created 18 // Additional Comments: 19 // 20 ////////////////////////////////////////////////////////////////////////////////// 21 `define ADDR_WIDTH 4 //ADDR WIDTH = 4, 22 `define BUF_DEPTH 16 //FIFO DEPTH 23 `define FIFO_WIDTH 16 //FIFO WIDTH 16 BITS 24 25 module tb; 26 reg clk,rst_n; 27 reg wr_en,rd_en; 28 reg [15:0] buf_in; // data input to be pushed to buffer 29 wire [15:0] buf_out; // port to output the data using pop. 30 wire buf_empty,buf_full; // buffer empty and full indication 31 wire [`ADDR_WIDTH-1:0] fifo_cnt; // number of data pushed in to buffer 32 33 myFIFO dut( 34 .clk(clk), 35 .rst_n(rst_n), 36 .buf_in(buf_in), 37 .buf_out(buf_out), 38 .wr_en(wr_en), 39 .rd_en(rd_en), 40 .buf_empty(buf_empty), 41 .buf_full(buf_full), 42 .fifo_cnt(fifo_cnt) 43 ); 44 45 always #10 clk = ~clk; 46 47 reg [15:0] tempdata = 0; 48 initial begin 49 clk = 0; 50 rst_n = 0; 51 wr_en = 0; 52 rd_en = 0; 53 buf_in = 0; 54 #15; 55 rst_n = 1; 56 57 push(1); 58 fork 59 push(2); 60 pop(tempdata); 61 join //push and pop together 62 push(10); 63 push(20); 64 push(30); 65 push(40); 66 push(50); 67 push(60); 68 push(70); 69 push(80); 70 push(90); 71 push(100); 72 push(110); 73 push(120); 74 push(130); 75 push(140); 76 push(150); 77 push(160); 78 push(170); 79 push(180); 80 push(190); 81 82 pop(tempdata); 83 push(tempdata); 84 85 pop(tempdata); 86 pop(tempdata); 87 pop(tempdata); 88 pop(tempdata); 89 push(200); 90 pop(tempdata); 91 push(tempdata); 92 pop(tempdata); 93 pop(tempdata); 94 pop(tempdata); 95 pop(tempdata); 96 pop(tempdata); 97 pop(tempdata); 98 pop(tempdata); 99 pop(tempdata); 100 pop(tempdata); 101 pop(tempdata); 102 pop(tempdata); 103 push(5); 104 pop(tempdata); 105 pop(tempdata); 106 pop(tempdata); 107 pop(tempdata); 108 pop(tempdata); 109 pop(tempdata); 110 pop(tempdata); 111 pop(tempdata); 112 pop(tempdata); 113 pop(tempdata); 114 pop(tempdata); 115 pop(tempdata); 116 pop(tempdata); 117 pop(tempdata); 118 pop(tempdata); 119 120 #3; 121 rst_n = 0; 122 #3; 123 rst_n = 1; 124 push(1); 125 fork 126 push(2); 127 pop(tempdata); 128 join //push and pop together 129 push(10); 130 push(20); 131 push(30); 132 pop(tempdata); 133 pop(tempdata); 134 pop(tempdata); 135 end 136 137 task push (input [7:0] data); 138 if(buf_full) 139 $display("---Cannot push %d: Buffer Full---",data); 140 else begin 141 $display("Push:%d",data); 142 buf_in = data; 143 wr_en = 1; 144 @(posedge clk); 145 #5 wr_en = 0; 146 end 147 endtask 148 149 task pop(output[7:0] data); 150 if(buf_empty) 151 $display("---Cannot Pop: Buffer Empty---"); 152 else begin 153 rd_en = 1; 154 @(posedge clk); 155 #3 rd_en = 0; 156 data = buf_out; 157 $display("------Poped:%d",data); 158 end 159 endtask 160 161 endmodule