FIFO存储器 FIFO是英文First In First Out 的缩写,是一种先进先出的数据缓存器,他与普通存储器的区别是没有外部读写地址线,这样使用起来非常简单,但缺点就是只能顺序写入数据,顺序的读出数据,其数据地址由内部读写指针自动加1完成,不能像普通存储器那样可以由地址线决定读取或写入某个指定的地址。 在系统设计中,以增加数据传输率、处理大量数据流、匹配具有不同传输率的系统为目的而广泛使用FIFO存储器,从而提高了系统性能.
FIFO参数:
FIFO的宽度,the width,指FIFO一次读写操作的数据位;
FIFO深度,THE DEEPTH,指FIFO可以存储多少个N位的数据;
满标志,FIFO已满或将要满时送出的一个信号,以阻止FIFO的血操作继续向FIFO中写数据而造成溢出(overflow);
空标志,阻止FIFIO的读操作;
1.quartus中直接调用FIFO IP核
2.verilog
异步FIFO代码:
module fifo_module ( input CLK, input RSTn, input Write_Req, input [7:0]FIFO_Write_Data, input Read_Req, output [7:0]FIFO_Read_Data, output Full_Sig, output Empty_Sig, /**********************/ output [7:0]SQ_rS1, output [7:0]SQ_rS2, output [7:0]SQ_rS3, output [7:0]SQ_rS4, output [2:0]SQ_Count /**********************/ ); /************************************/ parameter DEEP = 3'd4; /************************************/ reg [7:0]rShift [DEEP:0]; reg [2:0]Count; reg [7:0]Data; always @ ( posedge CLK or negedge RSTn ) if( !RSTn ) begin rShift[0] <= 8'd0; rShift[1] <= 8'd0; rShift[2] <= 8'd0; rShift[3] <= 8'd0; rShift[4] <= 8'd0; Count <= 3'd0; Data <= 8'd0; end else if( Read_Req && Write_Req && Count < DEEP && Count > 0 ) begin rShift[1] <= FIFO_Write_Data; rShift[2] <= rShift[1]; rShift[3] <= rShift[2]; rShift[4] <= rShift[3]; Data <= rShift[ Count ]; //若深度较大,则需多行代码,且存储器间存在频繁的数据转移 end else if( Write_Req && Count < DEEP ) begin rShift[1] <= FIFO_Write_Data; rShift[2] <= rShift[1]; rShift[3] <= rShift[2]; rShift[4] <= rShift[3]; Count <= Count + 1'b1; end else if( Read_Req && Count > 0 ) begin Data <= rShift[Count]; Count <= Count - 1'b1; end /************************************/ assign FIFO_Read_Data = Data; assign Full_Sig = ( Count == DEEP ) ? 1'b1 : 1'b0; assign Empty_Sig = ( Count == 0 ) ? 1'b1 : 1'b0; /************************************/ assign SQ_rS1 = rShift[1]; assign SQ_rS2 = rShift[2]; assign SQ_rS3 = rShift[3]; assign SQ_rS4 = rShift[4]; assign SQ_Count = Count; /************************************/ endmodule
第一,FIFO 的调用绝对需要控制信号
第二,Full_Sig 和 Empty_Sig 是不适合同步 FIFO 的写操作
改进同步FIFO,放弃了 Empty_Sig 和 Full_Sig,取而代之的是 Left_Sig 。作用如
名字般,该信号用来反馈出 FIFO 目前的“空格数目”
module fifo_module_2 ( input CLK, input RSTn, input Write_Req, input [7:0]FIFO_Write_Data, input Read_Req, output [7:0]FIFO_Read_Data, output [2:0]Left_Sig ); /************************************/ parameter DEEP = 3'd4; /************************************/ reg [7:0]rShift [DEEP:0]; reg [2:0]Count; reg [7:0]Data; always @ ( posedge CLK or negedge RSTn ) if( !RSTn ) begin rShift[0] <= 8'd0; rShift[1] <= 8'd0; rShift[2] <= 8'd0; rShift[3] <= 8'd0; rShift[4] <= 8'd0; Count <= 3'd0; Data <= 8'd0; end else if( Read_Req && Write_Req && Count < DEEP && Count > 0 ) begin rShift[1] <= FIFO_Write_Data; rShift[2] <= rShift[1]; rShift[3] <= rShift[2]; rShift[4] <= rShift[3]; Data <= rShift[ Count ]; end else if( Write_Req && Count < DEEP ) begin rShift[1] <= FIFO_Write_Data; rShift[2] <= rShift[1]; rShift[3] <= rShift[2]; rShift[4] <= rShift[3]; Count <= Count + 1'b1; end else if( Read_Req && Count > 0 ) begin Data <= rShift[Count]; Count <= Count - 1'b1; end /************************************/ assign FIFO_Read_Data = Data; assign Left_Sig = DEEP - Count; /************************************/ endmodule
仿真激励文本
`timescale 1 ps/ 1 ps module fifo_module_2_simulation(); reg CLK; reg RSTn; reg Write_Req; reg [7:0]FIFO_Write_Data; reg Read_Req; wire [7:0]FIFO_Read_Data; wire [2:0]Left_Sig; /*******************/ fifo_module_2 U1 ( .CLK(CLK), .RSTn( RSTn ), .Write_Req(Write_Req), .FIFO_Write_Data(FIFO_Write_Data), .Read_Req(Read_Req), .FIFO_Read_Data(FIFO_Read_Data), .Left_Sig(Left_Sig) ); /*******************/ initial begin RSTn = 0; #10; RSTn = 1; CLK = 0; forever #10 CLK = ~CLK; end /*******************/ reg [4:0]i; always @ ( posedge CLK or negedge RSTn ) if( !RSTn ) begin i <= 5'd0; Write_Req <= 1'b0; Read_Req <= 1'b0; FIFO_Write_Data <= 8'd0; end else case( i ) /**********/ 0: begin Write_Req <= 1'b1; Read_Req <= 1'b0; FIFO_Write_Data <= 8'd1; i <= i + 1'b1; end 1: begin Write_Req <= 1'b1; Read_Req <= 1'b0; FIFO_Write_Data <= 8'd2; i <= i + 1'b1; end 2: begin Write_Req <= 1'b1; Read_Req <= 1'b0; FIFO_Write_Data <= 8'd3; i <= i + 1'b1; end 3: begin Write_Req <= 1'b1; Read_Req <= 1'b0; FIFO_Write_Data <= 8'd4; i <= i + 1'b1; end /**********/ 4: begin Write_Req <= 1'b0; Read_Req <= 1'b1; i <= i + 1'b1; end 5: begin Write_Req <= 1'b0; Read_Req <= 1'b1; i <= i + 1'b1; end 6: begin Write_Req <= 1'b0; Read_Req <= 1'b1; i <= i + 1'b1; end 7: begin Write_Req <= 1'b0; Read_Req <= 1'b1; i <= i + 1'b1; end /**********/ 8: // 0 + 1 < 1 if( Left_Sig <= 1 ) begin Write_Req <= 1'b0; i <= i + 1'b1; end else begin Write_Req <= 1'b1; Read_Req <= 1'b0; FIFO_Write_Data <= FIFO_Write_Data + 1'b1; end 9: // > DEEP - 1 if( Left_Sig >= 3 )begin Read_Req <= 1'b0; i <= i + 1'b1; end else begin Write_Req <= 1'b0; Read_Req <= 1'b1; end /**********/ 10: if( Left_Sig >= 1 ) begin Write_Req <= 1'b1; FIFO_Write_Data <= 8'd5; i <= i + 1'b1; end else begin Write_Req <= 1'b0; i <= i + 1'b1; end 11: if( Left_Sig >= 1 ) begin Write_Req <= 1'b1; FIFO_Write_Data <= 8'd6; i <= i + 1'b1; end else begin Write_Req <= 1'b0; i <= i + 1'b1; end 12: begin if( Left_Sig >= 1 ) begin Write_Req <= 1'b1; FIFO_Write_Data <= 8'd7; end else Write_Req <= 1'b0; if( Left_Sig <= 3 ) begin Read_Req <= 1'b1; end else Read_Req <= 1'b0; i <= i + 1'b1; end 13: begin if( Left_Sig >= 1 ) begin Write_Req <= 1'b1; FIFO_Write_Data <= 8'd8; end else Write_Req <= 1'b0; if( Left_Sig <= 3 ) begin Read_Req <= 1'b1; end else Read_Req <= 1'b0; i <= i + 1'b1; end 14: if( Left_Sig <= 3 ) begin Write_Req <= 1'b0; Read_Req <= 1'b1; i <= i + 1'b1; end else begin Read_Req <= 1'b0; i <= i + 1'b1; end 15: if( Left_Sig <= 3 ) begin Read_Req <= 1'b1; i <= i + 1'b1; end else begin Read_Req <= 1'b0; i <= i + 1'b1; end 16: begin Read_Req <= 1'b0; i <= 5'd16; end endcase endmodule