当前位置:网站首页>Synchronous FIFO

Synchronous FIFO

2022-06-24 08:00:00 A restless Sir Zhang

One article understanding synchronization FIFO

1、FIFO brief introduction

​ FIFO namely First In First Out, It is a first in first out data storage 、 Buffer , We know that the general memory uses the external read-write address to read and write , and FIFO This memory structure does not need external read-write address, but controls read-write through automatic plus one operation , It's up to you FIFO You can only read and write data sequentially . Actually FIFO The process is like running circles , When it is full, it means that the write signal covers the read signal , While reading empty , The read signal catches up with the write signal .

​ FIFO It is a first in first out data buffer , The difference between it and ordinary memory is that there is no external read-write address line , It's very simple to use , The disadvantage is that you can only read and write sequentially , Instead of random reading and writing .

2、 Use scenarios

  1. Data buffering : That is, the data is written too fast , And the interval is long , That is, burst writing . So by setting a certain depth of FIFO, Can play a data temporary storage function , And make the subsequent processing process smooth .
  2. Isolation of clock domain : Mainly asynchronous FIFO. For data transmission in different clock domains , Can pass FIFO In isolation , Avoid the complexity of design and constraints caused by cross clock domain data transmission . such as FIFO At one end of the spectrum is AD, The other end is PCI;AD The acquisition rate of is 16 position 100KSPS, The amount of data per second is 1.6Mbps. and PCI The speed of the bus is 33MHz, The bus width is 32 position
  3. For data interfaces of different widths . For example, a single chip computer is 8 position ,DSP yes 16.

3、FIFO classification

Sync FIFO, Read and write use the same clock . It is generally used as a buffer for interactive data , In other words, its main function is to buffer.
asynchronous FIFO, Different clocks are used for reading and writing , It has two main functions , One is to realize data transmission in different clock domains , Another function is to implement data interfaces with different data widths .

 Insert picture description here
 Insert picture description here

4、 Sync FIFO

Sync fifo It means that the write clock and the read clock are in the same frequency and phase , That is, synchronization fifo Reading and writing work on the same clock .

4.1 Sync fifo The three parts of :

  • fifo Write control logic : Generate write address ( Decide where to write , from 0 Start writing )、 Write valid signal 、 Write full ( Decide if you can still write ) Equal signal ;
  • fifo Read control logic : Generate read address ( Decide where to read , from 0 Start reading )、 Read valid signal 、 Read full ( Decide if you can still read ) Equal signal ;
  • fifo Storage entity (reg、memory)

4.2 Module diagram

 Insert picture description here

Generate respective read / write addresses through read / write pointers , The write pointer points to the next address to be written , The read pointer points to the next address to be read . Effective write enable is to increment the write pointer , A valid read enable is to increment the read pointer .

Dual port memory (DPRAM) Sure Synchronous read or asynchronous read . You can read 、 Write independently . It's fine too Read and write at the same time

For synchronous read operations : It should be in the data FIFO Provide a clear read signal before the output is valid .

4.3 FIFO Working mode

◆ Workflow

After reset , Under the control of write clock and status signal , Data writing FIFO in .RAM Write address from 0 Start , Each time the data is written, the write address pointer is incremented by one , Point to the next storage unit . When FIFO After full , Data will no longer be written to , Otherwise, the data will be lost due to overwriting .

FIFO The data is not empty 、 Or full , Under the control of reading clock and status signal , Data can be transferred from FIFO Middle readout .RAM Read address from 0 Start , Each time the data is read, the read address pointer is incremented by one , Point to the next storage unit . When FIFO After reading empty , You can't read the data anymore , Otherwise, the data read out will be wrong .

FIFO The storage structure is double port RAM, So it is allowed to read and write at the same time . Typical asynchronous FIFO The structure diagram is shown below . The port and internal signal will be explained during code writing .

◆ Reading and writing time

About writing time , as long as FIFO The data in is not full , You can write ; If FIFO Is full , Then it is forbidden to write data again .

About reading time , as long as FIFO The data in is not empty , You can read ; If FIFO Is empty , Then it is forbidden to read the data again .

No matter what , A normal reading and writing FIFO Time period , If reading and writing are done at the same time , It is required to write FIFO The rate cannot be greater than the read rate .

◆ Read empty state

When starting reset ,FIFO No data , The empty status signal is valid . When FIFO After data is written in , The empty status signal is pulled low and invalid . When the read data address catches up with the write address , That is, when the read and write addresses are equal ,FIFO Is empty .

Because it's asynchronous FIFO, So when comparing read and write addresses , Need synchronous shooting logic , It takes some time . Therefore, the indication signal of empty state is not real-time , There will be a certain delay . If new data is written during this delay time FIFO, There will be an empty status indicating that the signal is valid , however FIFO In fact, there is a phenomenon of data in .

Strictly speaking, the empty status indication is wrong . However, the significance of generating empty state is to prevent the read operation from affecting the empty state FIFO Read the data . When an empty status signal is generated , actual FIFO There's data in , It is equivalent to judging the empty state signal in advance , No more reading at this time FIFO Data manipulation is also safe . therefore , The design has no problem in application .

◆ Write full status

When starting reset ,FIFO No data , The full signal is invalid . When FIFO After data is written in , At this time, the read operation does not proceed or the read rate is relatively slow , As long as the write data address exceeds the read data address by one FIFO At depth , A full status signal will be generated . At this time, the write address and read address are also equal , But the meaning is different .

 Insert picture description here

At this time, often use redundant 1bit As the extended bits of the read-write address , To distinguish when the read and write addresses are the same ,FIFO Is the state empty or full . When the read-write address and the extension bit are the same , Indicates that the number of read and write data is consistent , Now FIFO It's empty . If the read and write addresses are the same , The extension bits are the opposite number , Indicates that the number of written data has exceeded one of the number of read data FIFO Depth , here FIFO It's full . Of course , The premise of this condition is that reading operation is prohibited in empty state 、 Write operation is prohibited in full state .

Empathy , Due to the existence of asynchronous delay logic , The full status signal is not real-time . But it is also equivalent to judging the full state signal in advance , No more writing at this time FIFO The operation will not affect the correctness of the application .

5、 Sync FIFO Of Verilog Realization

​ surface 1-1 Sync FIFO port

port attribute
clk The clock
rstn Reset
wr_reg Write requests
data_in Writing data , This time is 8bit
rd_reg Read request
data_out Reading data , Write data together , by 8bit
emptyfifo Empty sign
fullfifo Full logo
wr_usedwfifo Current data volume , This use 8words , finger FIFO How much data remains unread in
almost_empty Near space ,usedw Greater than or equal to a certain value
almost_full Nearly full ,usedw Less than a certain value

Of course fifo There is also an address inside , Read the address , Write enable , Reading enable .

Note the relationship between the request signal and the enable signal , To protect fifo The previous data is correct , The request signal came in but was not satisfied fifo Read and write conditions , Such as fifo Empty or fifo full , The former fifo Reading enablers pull down , The latter write enable will pull down .

as for usedw, stay altera Of IP Representing fifo How many more data are there in , If the data input is 8bit, And fifo It's written in 100 individual 8bit data , be usedw Then for 100, It is also a judgment almost_empty and almost_full The logo of .

5.1 Implementation of storage module

The storage module can be implemented with two ports RAM resources , Use directly in simulation reg Just simulate its behavior ; meanwhile , Need to achieve RAM The depth of is configurable , So add a parameter Control depth .
In the process of implementing this module , Consider the relationship between depth and address bit width , Because different depths correspond to different address bit widths .

depth Address range Address bit width
640-636
320-315
160-154
80-73
40-32
20-11

Here is to use RAM To simulate the

reg [DATA_WIDTH-1:0]mem[DATA_WIDTH-1:0];// depth 8  Data bit width 10

5.2 How to judge read blank / Write full

Remember what I just said ? Actually FIFO Your workflow is like running circles , When it is full, it means that the write signal covers the read signal , While reading empty , The read signal catches up with the write signal .

How to judge read blank : according to FIFO How it works , Obvious , When reading empty , There is no data to read , therefore wr_addr Address and rd_addr Your address should be the same .

How to judge whether it is full : according to FIFO How it works , Because the write signal covers the read signal one circle , Then we can set up Parity bit ( It can also be understood as carry ), The parity check is used to determine whether the “ Ferrule ”, Every jump of parity bit 1 Time , It means that the signal is written or read . Watch out! , Writing a signal is always ahead , It is impossible to lag behind the reading signal . So when it's full at the same time wr_addr Address and rd_addr Your address should be the same .

assign  empty	    	= ({wr_flag,wr_addr} == {rd_flag,rd_addr}) ? 1'b1:1'b0;
assign  full 			= ((wr_addr == rd_addr) && (wr_flag != rd_flag)) ? 1'b1:1'b0;  

5.3 How to calculate FIFO Current data volume ( How much data is left unread )

​ Or the ferrule idea , Because whenever . The write signal is ahead of the read signal , therefore FIFO The current amount of data in must be **( Write the address — Read the address )** To get . Then you may ask when the write address is greater than the read address , without doubt , This must be true , But is it still true that the write address is less than the read address ?

​ without doubt , Of course , Remember the parity bit defined ? By parity bit , You won't have the above problems . The following code is for details .

assign  wr_usedw 	 	= {wr_flag,wr_addr} - {rd_flag,rd_addr};

5.4 Source code

module synchronize_fifo  #(
    parameter   [3:0] DATA_DEPTH  		=    4'd8,  // depth   finger FIFO How many numbers are saved in 
    parameter   [3:0] DATA_WIDTH  		=    4'd8,  // Width   The bit width of each number 
    parameter   [1:0] ADDR_WIDTH 		=    2'd3,   //FIFO Address (000——111)   2^ADDR_WIDTH = DATA_DEPTH
	 parameter	 [1:0] almost_empty_ref = 	  2'd2,
	 parameter	 [2:0] almost_full_ref  = 	  3'd6	 
)(
    input  wire                   clk,
    input  wire                   rstn,
    input  wire                   wr_reg, // Write requests 
    input  wire                   rd_reg, // Read request 
    input  wire  [DATA_WIDTH-1:0] data_in,// Data writing 

    output reg   [DATA_WIDTH-1:0] data_out,// data fetch 
    output wire                   empty,full,
	 output wire						 almost_empty,almost_full, // Nearly full or Reading empty 
	 output wire  [ADDR_WIDTH  :0] wr_usedw // FIFO How much data remains unread in 
 );
wire wr_en,rd_en; // Reading enable , Write enable 
reg [{ADDR_WIDTH-1}:0] wr_addr,rd_addr; // Read the address , Write the address 
reg [DATA_WIDTH-1:0]mem[DATA_WIDTH-1:0];// depth 8  Data bit width 10
reg  wr_flag,rd_flag; // Parity bit   Judge whether it is full according to the highest address or Write empty 
// Write the address 
integer i;
assign wr_en = (!full)  & wr_reg; 		 // If it's full   Then stop writing 
assign rd_en = (!empty) & rd_reg; 		 // If read empty   Stop the read operation 
always @(posedge clk or negedge rstn) 
    if(!rstn)begin
        wr_addr <= 3'd0;
		  wr_flag <= 1'd0;
    end else if(wr_en)
        {wr_flag,wr_addr} <= {wr_flag,wr_addr} +1'b1;
    else 
        {wr_flag,wr_addr} <= {wr_flag,wr_addr};    
// Writing data 
always @(posedge clk or negedge rstn) 
    if(!rstn)begin
		  for(i=0;i<8;i=i+1) 
        mem[i] <= 8'd0;
    end else if(wr_en)
        mem[wr_addr] <= data_in;
    else 
        mem[wr_addr] <= mem[wr_addr];
// Read the address 
always @(posedge clk or negedge rstn) 
    if(!rstn)begin
        rd_addr <= 3'd0; 
		  rd_flag  <= 1'd0;
    end else if(rd_en)
        {rd_flag,rd_addr} <= {rd_flag,rd_addr} + 1'b1;
    else 
        {rd_flag,rd_addr} <= {rd_flag,rd_addr};    
// Reading data 
always @(posedge clk or negedge rstn) 
    if(!rstn)
        data_out  <= 8'd0;
    else if(rd_en)
        data_out <= mem[rd_addr];
    else 
        data_out <= data_out;
//  Judge empty or full 
assign  wr_usedw 	 	= {wr_flag,wr_addr} - {rd_flag,rd_addr};
assign  almost_empty = (wr_usedw < almost_empty_ref) ? 1'b1:1'b0;
assign  almost_full	= (wr_usedw > almost_full_ref ) ? 1'b1:1'b0; 
assign  empty	    	= ({wr_flag,wr_addr} == {rd_flag,rd_addr}) ? 1'b1:1'b0;
//assign  full 		 	= ((wr_addr == rd_addr) && (wr_flag != rd_flag)) ? 1'b1:1'b0;  //FIFO Full hour wr_addr = 000 rd_addr=000
assign  full 		 	= ({~wr_flag,wr_addr} == {rd_flag,rd_addr}) ? 1'b1:1'b0;  //FIFO Full hour wr_addr = 000 rd_addr=000
endmodule //synchronize_fifo

6、TestBench Simulation

 Insert picture description here

This testbench Go first FIFO Write data in , Then read the data , Finally, write the data . The read data is stored 3-10.

So look wr_usedw First from 0-8, Again from 8-0 , And then from 0-8.

and wr_flag The signal also jumps twice , Write the instructions twice .rd_flag The signal jumps once , Description read empty once .

原网站

版权声明
本文为[A restless Sir Zhang]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/175/202206240421142270.html