📄 fifo.txt
字号:
听张老师讲了三节课,加上自己看了些资料总算对FIFO有点眉目了。总结如下:
FIFO(First IN First Out)先进先出电路
实现数据先进先出的存储器件,FIFO的用途:普遍用作数据缓冲器,可以用在电话通讯网络的前端来同步输入的网络数据包。也可以用于顺序数据的缓冲,比如音频信号或视频信号。另一个广泛的应用是在处理器之间的通讯中。
FIFO的基本单元是寄存器,作为存储器件,FIFO的存储能力是由其内部定义的存储寄存器的数量决定 . FIFO存储器一般以数据量的深度X宽度的形式来说明所采用的基本结构
第一代FIFO存储器是基于“导向”理论的,数据从输入端被移到输出端,所需要的时间称为导向时间
每一个数据字需要一个状态触发器,因此对数据锁存的控制只能实现很短的FIFO的操作
以长度为8的FIFO为例说明其工作原理。入图所示
____________________
D, C, B, A ——> | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8|———>
两边的箭头表示数据移动的方向。A,B,C,D表示被处理的数据。1,2,3,4,。。。8表示FIFO的8个存储单元。表明这个FIFO中共有8个寄存器单元。每个寄存器单元可以存储一个数据。所以寄存器的单元越多,FIFO的存储能力就越强。每个寄存器单元的位宽与FIFO的输入和输出端的位宽是一致的。如果要处理的数据A,B,C,D是16位的数据,那么输入输出端及每个寄存器单元的位宽就都是16位。这个FIFO可以命名为8X16FIFO。它在每一个时钟上升沿到来时,数据向右移动一个存储单元。这样在时钟的控制下,数据从左到右通过存储单元
FIFO通常是双端口的存储器,其中一个端口用于写入数据,而另一个端口用于读出数据。可以同时对存储器字存储单元进行写入和读出操作。它的数据吞吐率是普通RAM的两倍。
FIFO型的存储器不需要由地址来存取数据。需要由另外的信号线(或标志)来指明存储器的内容状态。
现在的FIFO存储器采用SRAM单元来实现。它是基于带两个指针的环行FIFO结构的。要写入的数据的存储地址放在写指针中,而FIFO结构中要读出的第一个数据的地址放在读指针中
在复位后,两个指针都指向存储器的同一个字单元。每次写操作后,写指针指向下一个存储单元。对数据字的读取操作,会把读指针指向下一个要读取的数据字
读指针就不断地跟随写指针,当读指针跟上写指针后,FIFO的结构里面为空。
如果写指针追上读指针,FIFO结构里面的数据是满载的。
如果从硬件上来实现循环存储器,可以用双端口的SRAM来存取数据。指针具用二进制计数器的特征,它用于产生SRAM的存储器地址
同步FIFO存储器的基本结构包括存储器阵列,标志逻辑和扩展逻辑(图太难画了,就不贴了)。
存储器阵列由双端口存储单元构成。允许同时对存储单元的两个端口(读端口和写端口)进行存取。
标志逻辑用于比较两个地址指针的值,如果两个值的比较结果为零,FIFO存储器为全空,同时全空标志为真。如果两个值的比较结果等于存储器的容量深度,说明存储器全满,同时全满标志为真。
还可以设置其他一些标志,比如半满,可编程接近满,可编程接近空等。它们也通过对偏移量寄存器中的编程值和存储器阵列中的字的数量进行比较来生成
(在张老师的课上,讲到读写时序的时候,关于标志逻辑,讲的太快,没有太深的体会,还需要看书1)
扩展逻辑通过对多个模块按容量深度扩展结构进行的级联来形成更深的FIFO存储器,采用令牌传递方法来实现逻辑上容量更深的FIFO。
在普通模式下(没有进行容量,深度级联的模式),每一个地址在到达最大值后,会跳会到零。
在容量深度扩展模式下,当地址指针到达最大值后,一个脉冲信号会送到扩展端口,该端口把令牌传到另一个FIFO存储器中,(直到令牌重新传回来,这个地址指针才会增加)(这个地方还有点模糊,有待解决。问过张老师,他却给我讲的是两个FIFO的乒乓操作。由于我的思路不是很清晰,也没有继续问下去。当时张老师也要开始讲课了,不好再打扰。)
可综合的Verilog FIFO存储器
This example describes a synthesizable implementation of a FIFO. The FIFO depth and FIFO width in bits can be modified by simply changing the value of two parameters, `FWIDTH and `FDEPTH. For this example, the FIFO depth is 4 and the FIFO width is 32 bits. The input/output ports of the FIFO are shown in Figure F-1.
Figure F-1. FIFO Input/Output Ports
Input ports
All ports with a suffix "N" are low-asserted.
Clk— Clock signal
RstN— Reset signal
Data_In— 32-bit data into the FIFO
FInN— Write into FIFO signal
FClrN— Clear signal to FIFO
FOutN— Read from FIFO signal
Output ports
F_Data— 32-bit output data from FIFO
F_FullN— Signal indicating that FIFO is full
F_EmptyN— Signal indicating that FIFO is empty
F_LastN— Signal indicating that FIFO has space for one data value
F_SLastN— Signal indicating that FIFO has space for two data values
F_FirstN— Signal indicating that there is only one data value in FIFO
The Verilog HDL code for the FIFO implementation is shown in Example F-1.
Example F-1 Synthesizable FIFO Model
////////////////////////////////////////////////////////////////////
// FileName: "Fifo.v"
// Author : Venkata Ramana Kalapatapu
// Company : Sand Microelectronics Inc.
// (now a part of Synopsys, Inc.),
// Profile : Sand develops Simulation Models, Synthesizable Cores and
// Performance Analysis Tools for Processors, buses and
// memory products. Sand's products include models for
// industry-standard components and custom-developed models
// for specific simulation environments.
//
////////////////////////////////////////////////////////////////////
`define FWIDTH 32 // Width of the FIFO.
`define FDEPTH 4 // Depth of the FIFO.
`define FCWIDTH 2 // Counter Width of the FIFO 2 to power
// FCWIDTH = FDEPTH.
module FIFO( Clk,
RstN,
Data_In,
FClrN,
FInN,
FOutN,
F_Data,
F_FullN,
F_LastN,
F_SLastN,
F_FirstN,
F_EmptyN
);
input Clk; // CLK signal.
input RstN; // Low Asserted Reset signal.
input [(`FWIDTH-1):0] Data_In; // Data into FIFO.
input FInN; // Write into FIFO Signal.
input FClrN; // Clear signal to FIFO.
input FOutN; // Read from FIFO signal.
output [(`FWIDTH-1):0] F_Data; // FIFO data out.
output F_FullN; // FIFO full indicating signal.
output F_EmptyN; // FIFO empty indicating signal.
output F_LastN; // FIFO Last but one signal.
output F_SLastN; // FIFO SLast but one signal.
output F_FirstN; // Signal indicating only one
// word in FIFO.
reg F_FullN;
reg F_EmptyN;
reg F_LastN;
reg F_SLastN;
reg F_FirstN;
reg [`FCWIDTH:0] fcounter; //counter indicates num of data in FIFO
reg [(`FCWIDTH-1):0] rd_ptr; // Current read pointer.
reg [(`FCWIDTH-1):0] wr_ptr; // Current write pointer.
wire [(`FWIDTH-1):0] FIFODataOut; // Data out from FIFO MemBlk
wire [(`FWIDTH-1):0] FIFODataIn; // Data into FIFO MemBlk
wire ReadN = FOutN;
wire WriteN = FInN;
assign F_Data = FIFODataOut;
assign FIFODataIn = Data_In;
FIFO_MEM_BLK memblk(.clk(Clk),
.writeN(WriteN),
.rd_addr(rd_ptr),
.wr_addr(wr_ptr),
.data_in(FIFODataIn),
.data_out(FIFODataOut)
);
// Control circuitry for FIFO. If reset or clr signal is asserted,
// all the counters are set to 0. If write only the write counter
// is incremented else if read only read counter is incremented
// else if both, read and write counters are incremented.
// fcounter indicates the num of items in the FIFO. Write only
// increments the fcounter, read only decrements the counter, and
// read && write doesn't change the counter value.
always @(posedge Clk or negedge RstN)
begin
if(!RstN) begin
fcounter <= 0;
rd_ptr <= 0;
wr_ptr <= 0;
end
else begin
if(!FClrN ) begin
fcounter <= 0;
rd_ptr <= 0;
wr_ptr <= 0;
end
else begin
if(!WriteN && F_FullN)
wr_ptr <= wr_ptr + 1;
if(!ReadN && F_EmptyN)
rd_ptr <= rd_ptr + 1;
if(!WriteN && ReadN && F_FullN)
fcounter <= fcounter + 1;
else if(WriteN && !ReadN && F_EmptyN)
fcounter <= fcounter - 1;
end
end
end
// All the FIFO status signals depends on the value of fcounter.
// If the fcounter is equal to fdepth, indicates FIFO is full.
// If the fcounter is equal to zero, indicates the FIFO is empty.
// F_EmptyN signal indicates FIFO Empty Status. By default it is
// asserted, indicating the FIFO is empty. After the First Data is
// put into the FIFO the signal is deasserted.
always @(posedge Clk or negedge RstN)
begin
if(!RstN)
F_EmptyN <= 1'b0;
else begin
if(FClrN==1'b1) begin
if(F_EmptyN==1'b0 && WriteN==1'b0)
F_EmptyN <= 1'b1;
else if(F_FirstN==1'b0 && ReadN==1'b0 && WriteN==1'b1)
F_EmptyN <= 1'b0;
end
else
F_EmptyN <= 1'b0;
end
end
// F_FirstN signal indicates that there is only one datum sitting
// in the FIFO. When the FIFO is empty and a write to FIFO occurs,
// this signal gets asserted.
always @(posedge Clk or negedge RstN)
begin
if(!RstN)
F_FirstN <= 1'b1;
else begin
if(FClrN==1'b1) begin
if((F_EmptyN==1'b0 && WriteN==1'b0) ||
(fcounter==2 && ReadN==1'b0 && WriteN==1'b1))
F_FirstN <= 1'b0;
else if (F_FirstN==1'b0 && (WriteN ^ ReadN))
F_FirstN <= 1'b1;
end
else begin
F_FirstN <= 1'b1;
end
end
end
// F_SLastN indicates that there is space for only two data words
//in the FIFO.
always @(posedge Clk or negedge RstN)
begin
if(!RstN)
F_SLastN <= 1'b1;
else begin
if(FClrN==1'b1) begin
if( (F_LastN==1'b0 && ReadN==1'b0 && WriteN==1'b1) ||
(fcounter == (`FDEPTH-3) && WriteN==1'b0 && ReadN==1'b1))
F_SLastN <= 1'b0;
else if(F_SLastN==1'b0 && (ReadN ^ WriteN) )
F_SLastN <= 1'b1;
end
else
F_SLastN <= 1'b1;
end
end
// F_LastN indicates that there is one space for only one data
// word in the FIFO.
always @(posedge Clk or negedge RstN)
begin
if(!RstN)
F_LastN <= 1'b1;
else begin
if(FClrN==1'b1) begin
if ((F_FullN==1'b0 && ReadN==1'b0) ||
(fcounter == (`FDEPTH-2) && WriteN==1'b0 && ReadN==1'b1))
F_LastN <= 1'b0;
else if(F_LastN==1'b0 && (ReadN ^ WriteN) )
F_LastN <= 1'b1;
end
else
F_LastN <= 1'b1;
end
end
// F_FullN indicates that the FIFO is full.
always @(posedge Clk or negedge RstN)
begin
if(!RstN)
F_FullN <= 1'b1;
else begin
if(FClrN==1'b1) begin
if (F_LastN==1'b0 && WriteN==1'b0 && ReadN==1'b1)
F_FullN <= 1'b0;
else if(F_FullN==1'b0 && ReadN==1'b0)
F_FullN <= 1'b1;
end
else
F_FullN <= 1'b1;
end
end
endmodule
///////////////////////////////////////////////////////////////////
//
//
// Configurable memory block for fifo. The width of the mem
// block is configured via FWIDTH. All the data into fifo is done
// synchronous to block.
//
// Author : Venkata Ramana Kalapatapu
//
///////////////////////////////////////////////////////////////////
module FIFO_MEM_BLK( clk,
writeN,
wr_addr,
rd_addr,
data_in,
data_out
);
input clk; // input clk.
input writeN; // Write Signal to put data into fifo.
input [(`FCWIDTH-1):0] wr_addr; // Write Address.
input [(`FCWIDTH-1):0] rd_addr; // Read Address.
input [(`FWIDTH-1):0] data_in; // DataIn in to Memory Block
output [(`FWIDTH-1):0] data_out; // Data Out from the Memory
// Block(FIFO)
wire [(`FWIDTH-1):0] data_out;
reg [(`FWIDTH-1):0] FIFO[0:(`FDEPTH-1)];
assign data_out = FIFO[rd_addr];
always @(posedge clk)
begin
if(writeN==1'b0)
FIFO[wr_addr] <= data_in;
end
endmodule
字宽扩展,可以使FIFO存储器有更宽的数据通路
在字宽扩展模式中,读操作,写操作和重传输都一样。要在字宽上扩展多个FIFO存储器,必须同时通过对每个存储器的状态标志进行与操作生成“混合标志”。混合标志也包括全空标志和全满标志。这样才能保证FIFO存储器保持同步。
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -