FIFO是英文First In First Out 的缩写,是一种先进先出的数据缓存器,他与普通存储器的区别是没有外部读写地址线,这样使用起来非常简单,但缺点就是只能顺序写入数据,顺序的读出数据, 其数据地址由内部读写指针自动加1完成,不能像普通存储器那样可以由地址线决定读取或写入某个指定的地址。
FIFO一般用于不同时钟域之间的数据传输,比如FIFO的一端是AD数据采集, 另一端是计算机的PCI总线,假设其AD采集的速率为16位 100K SPS,那么每秒的数据量为100K×16bit=1.6Mbps,而PCI总线的速度为33MHz,总线宽度32bit,其最大传输速率为 1056Mbps,在两个不同的时钟域间就可以采用FIFO来作为数据缓冲。另外对于不同宽度的数据接口也可以用FIFO,例如单片机位8位数据输出,而 DSP可能是16位数据输入,在单片机与DSP连接时就可以使用FIFO来达到数据匹配的目的。
FIFO的分类根均FIFO工作的时钟域,可以将FIFO分为同步FIFO和异步FIFO。同步FIFO是指读时钟和写时钟为同一个时钟。在时钟沿来临时同时发生读写操作。异步FIFO是指读写时钟不一致,读写时钟是互相独立的。
FIFO设计的难点 FIFO设计的难点在于怎样判断FIFO的空/满状态。为了保证数据正确的写入或读出,而不发生益处或读空的状态出现,必须保证FIFO在满的情况下,不 能进行写操作。在空的状态下不能进行读操作。怎样判断FIFO的满/空就成了FIFO设计的核心问题。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 module fifo (clk,rstp,din,writep,readp,dout,emptyp,fullp); 2 input clk; 3 input rstp; 4 input[15:0] din; 5 input readp; 6 input writep; 7 output[15:0]dout; 8 output emptyp; 9 output fullp; 10 parameter DEPTH=2,MAX_COUNT=2'b11; 11 12 reg emptyp; 13 reg fullp; 14 reg[15:0] dout; 15 reg[(DEPTH-1):0]tail; 16 reg[(DEPTH-1):0]head; 17 reg[(DEPTH-1):0]count; 18 reg[15:0] fifomem[0:MAX_COUNT]; 19 20 always@(posedge clk) begin 21 if(rstp==1) begin 22 dout<=16'h0000; 23 end 24 else begin 25 dout<=fifomem[tail]; 26 end 27 end 28 29 always@(posedge clk) begin 30 if(rstp==1'b0 && writep==1'b1 && fullp==1'b0) begin 31 fifomem[head]<=din; 32 end 33 end 34 35 always@(posedge clk) begin 36 if(rstp==1'b1) begin 37 head<=2'b00; 38 end 39 else begin 40 if(writep==1'b1 && fullp==1'b0) begin 41 head<=head+1; 42 end 43 end 44 end 45 46 always@(posedge clk) begin 47 if(rstp==1'b1) begin 48 tail<=2'b00; 49 end 50 else begin 51 if(readp==1'b1 && emptyp==1'b0) begin 52 tail<=tail+1; 53 end 54 end 55 end 56 57 always@(posedge clk) begin 58 if(rstp==1'b1) begin 59 count<=2'b00; 60 end 61 else begin 62 case({readp,writep}) 63 2'b00:count<=count; 64 2'b01: 65 if(count!=MAX_COUNT) 66 count<=count+1; 67 2'b10: 68 if(count!=2'b00) 69 count<=count-1; 70 2'b11: 71 count<=count; 72 endcase 73 end 74 end 75 76 always@(count) begin 77 if(count==2'b00) 78 emptyp<=1'b1; 79 else 80 emptyp<=1'b0; 81 end 82 83 always@(count) begin 84 if(count==MAX_COUNT) 85 fullp<=1'b1; 86 else 87 fullp<=1'b0; 88 end 89 endmodule
测试程序:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 module test_fifo; 2 3 reg clk; 4 reg rstp; 5 reg [15:0] din; 6 reg readp; 7 reg writep; 8 wire [15:0] dout; 9 wire emptyp; 10 wire fullp; 11 12 reg [15:0] value; 13 fifo U1 (.clk(clk),.rstp(rstp),.din(din),.readp(readp),.writep(writep),.dout(dout), 14 .emptyp(emptyp),.fullp(fullp)); 15 task read_word; 16 begin 17 @(negedge clk); 18 readp = 1; 19 @(posedge clk) #5; 20 readp = 0; 21 end 22 endtask 23 24 task write_word; 25 input [15:0] value; 26 begin 27 @(negedge clk); 28 din = value; 29 writep = 1; 30 @(posedge clk); 31 #5; 32 din = 16'hzzzz; 33 writep = 0; 34 end 35 endtask 36 initial begin 37 clk = 0; 38 forever begin 39 #10 clk = 1; 40 #10 clk = 0; 41 end 42 end 43 44 initial begin 45 test1; 46 //test2; 47 48 end 49 task test1; 50 begin 51 din = 16'hzzzz; 52 writep = 0; 53 readp = 0; 54 rstp = 1; 55 #50 rstp = 0; 56 #50; 57 write_word (16'h1111); 58 write_word (16'h2222); 59 write_word (16'h3333); 60 read_word; 61 read_word; 62 write_word (16'h4444); 63 repeat (6) begin 64 read_word; 65 end 66 67 write_word (16'h0001); 68 write_word (16'h0002); 69 write_word (16'h0003); 70 write_word (16'h0004); 71 write_word (16'h0005); 72 write_word (16'h0006); 73 write_word (16'h0007); 74 write_word (16'h0008); 75 repeat (6) begin 76 read_word; 77 end 78 end 79 endtask 80 task test2; 81 reg [15:0] writer_counter; 82 begin 83 writer_counter = 16'h0001; 84 din = 16'hzzzz; 85 writep = 0; 86 readp = 0; 87 rstp = 1; 88 #50 rstp = 0; 89 #50; 90 fork 91 begin 92 repeat (500) begin 93 @(negedge clk); 94 if (fullp == 1'b0) begin 95 write_word (writer_counter); 96 #5; 97 writer_counter = writer_counter + 1; 98 end 99 #50; 100 end 101 end 102 103 begin 104 forever begin 105 @(negedge clk); 106 if (emptyp == 1'b0) begin 107 read_word; 108 end 109 #50; 110 end 111 end 112 join 113 end 114 endtask 115 116 117 118 endmodule