当前位置:网站首页>Asynchronous FIFO
Asynchronous FIFO
2022-06-22 23:21:00 【Tung flower】
asynchronous FIFO Circuit structure

Dual port SRAM:
Used to store data written by upstream nodes wdata, For downstream nodes rdata Read it out .
SRAM The read / write address of is incremented each time 1 The mechanism of , It ensures that the writing and reading are carried out in sequence , Write and read to the highest address , Return to zero address again .
Full signal generation circuit
At upstream nodes and SRAM There is a full signal generation circuit .
This circuit writes the clock field by judging , The relationship between the write pointer and the read pointer , Then the full signal is generated in real time wfull, To notify the upstream node to stop writing .
Null signal generation circuit
At downstream nodes and SRAM There is an empty signal generation circuit between ,
This circuit reads the clock domain by judging , The relationship between the write pointer and the read pointer , Then the null signal is generated in real time rempty, To notify the downstream node to stop the read operation .
Be careful :
Pass the read pointer to the write clock field to generate a full signal , Pass the write pointer to the read clock field to generate a null signal , therefore , How to deal with the metastable problem of signal transmission is involved here .
Use synchronizer Transmit the signal to the opposite clock domain for Synchronous processing , Synchronizer can be used ( from 2~3 level FF form ) To single bit Synchronous operation of the signal .
FIFO Judgment of empty and full state :
Judge the reading pointer rptr And write pointer wptr The relationship between ( Gray code ):
The read and write pointers add an extra bit to the address bit (extra bit).


“ empty ” Judgment of state :
The read pointer and the write pointer are exactly the same ( Include MSB)
Read pointer :rptr[n-1]
The write pointer :wptr[n-1]
empty=(rptr == wptr)“ full ” The judgment of the :
- wptr And synchronized rptr Of MSB It's not equal , because wptr Must be better than rptr Turn back one more time
- wptr And rptr The second highest order of is not equal ( As shown in the figure above 7 And location 15, Converted to binary, corresponding to 0111 and 1111,MSB Different descriptions are more than one Time , 111 The same represents the same position .)
- The remaining bits are exactly equal
Read pointer :rptr[n-1]
The write pointer :wptr[n-1]
full= (rptr[n-1] != wptr[n-1] )&&(rptr[n-2:0] == wptr[n-2:0])Binary code and gray code conversion :
Binary code to gray code :
Start with the first one on the far right , Connect each bit with the left neighbor in turn An XOR (XOR), As the value of the corresponding gray code bit , The leftmost one remains unchanged .
Conversion formula :
Binary code :B[n-1:0]
Gray code : G[n-1:0]
// Binary to gray code
G[n-1] = B[n-1]
G[i] = B[i+1]^B[i] //i=0、1、2、、、n-2
// Gray code i The value of bit is equal to binary number i Bit and i+1 Exclusive or of bit Example :

Gray code into binary code :
From the second on the left , Decode each bit with a bit on the left Value XOR (XOR), As the decoded value of this bit ( The one on the left is still the same ).
Conversion formula :
Binary code :B[n-1:0]
Gray code : G[n-1:0]
// Gray code to binary
G[n-1] = B[n-1]
B[i] = G[i]^B[i+1] //i=0、1、2、、n-2Example :

Be careful “ vanity ”、“ Empty fullness ”

hypothesis , Read pointer rptr The address is 3, Under the control of the write clock , Synchronize two clocks into the write clock domain , The signal rptr_sync_2.
At this time , Under the write clock field , Just enough “ full ” Conditions , Generate full signal .
however , here rptr The value of has been updated to 5.
That is to say FIFO When you think you are full , Read the address , Read two more data from it . actual FIFO There is no real fullness , Just close to full “ Empty fullness ”.
Conclusion :
- about full Mechanism of signal generation , The read address after synchronization must be less than or equal to the current address Read the address , So judge at this time FIFO Being full is not necessarily true , It's more conservative ;
- Empty The signal mechanism is also established , “ empty ” when , Not necessarily true “ empty ”
summary :
asynchronous FIFO By comparing the read and write addresses, judge whether it is full or empty , But the read and write addresses belong to different clock domains , Therefore, the read and write addresses need to be synchronized before comparison , This mechanism guarantees 了 FIFO At the empty / full limit , There is still room , There is a certain amount of redundant space .
This method makes FIFO There is no write overflow 、 Read empty and read more .
asynchronous FIFO Of Verilog The code description
Empty full flag generation
Take the synchronization of write address to read clock field as an example , Sketch Map :

Binary code address generates gray code address
//write interface pointer
// Generate write address pointer
[email protected](posedge wr_clk or negedge wr_rst_n_i )
if(!wr_rst_n_i)
wr_ptr<= {ADDR_WIDTH+1}{1'b0};
else if(wr_en_i && !full_o)
wr_ptr <=wr_ptr +1'b1;
else
wr_ptr <=wr_ptr;
//############## Binary code -> Gray code ###############
//####### Gray code address
assign gray_wr_ptr = (wr_ptr>>1)^wr_ptr ;
[email protected](*)begin
gray_wr_ptr_next= gray_wr_ptr;
end
//--------------------------------------------------------------------------------
//read interface pointer
// Generate read address pointer
[email protected](posedge rd_clk or negedge rd_rst_n_i )
if(!rd_rst_n_i)
rd_ptr <= {ADDR_WIDTH+1}{1'b0};
else if(rd_en_i && !empty_o)
rd_ptr <=rd_ptr +1'b1;
else
rd_ptr <=rd_ptr;
//############## Binary code -> Gray code ###############
//####### Gray code read address
assign gray_rd_ptr = (rd_ptr>>1)^rd_ptr ;
[email protected](*)begin
gray_rd_ptr_next= gray_rd_ptr;
endGray code addresses are synchronized to each other's addresses
// Gray code write address synchronization two levels Pass to the clock reading field
[email protected](posedge rd_clk or negedge rd_rst_n)
begin
if(! rd_rst_n)
begin
gray_wr2rd_ptr_1 <= {ADDR_WIDTH+1}{1'b0};
gray_wr2rd_ptr_2 <= {ADDR_WIDTH+1}{1'b0};
end
else
begin
gray_wr2rd_ptr_1 <= gray_wr_ptr_next;
gray_wr2rd_ptr_2 <= gray_wr2rd_ptr_1;
end
end
// Gray code read address synchronization two levels Passed to the write clock field
[email protected](posedge wr_clk or negedge wr_rst_n)
begin
if(!wr_rst_n)
begin
gray_rd2wr_ptr_1 <= {ADDR_WIDTH+1}{1'b0};
gray_rd2wr_ptr_2 <= {ADDR_WIDTH+1}{1'b0};
end
else
begin
gray_rd2wr_ptr_1 <= gray_rd_ptr_next;
gray_rd2wr_ptr_2 <= gray_rd2wr_ptr_1;
end
endGenerate empty full flag
//##### The empty full flag is generated
// Full sign
assign full_comb =( {~gray_rd2wr_ptr_2[ADDR_WIDTH],gray_rd2wr_ptr_2[ADDR_WIDTH-1:0]}== gray_wr_ptr );
[email protected](posedge wr_clk or negedge wr_rst_n)
begin
if(!wr_rst_n)
full_o <=1'b0;
else
full_o <= full_comb;
end
// Empty flag
assign empty_comb= (gray_wr2rd_ptr_2==gray_rd_ptr );
[email protected](posedge rd_clk or negedge rd_rst_n)
begin
if(!rd_rst_n)
empty_o <=1'b0;
else
empty_o <= empty_comb;
endRead and write data
Reading data
//read data
[email protected](posedge rd_clk or negedge rd_rst_n_i)
if(!rd_rst_n_i)
begin
rd_data_o<= 0;
end
esle if(rd_en_i && !empty_comb)// Reading enable , And the storage unit is not empty
rd_data_o <= RAM[rd_ptr];Writing data
//write data
interger i;
[email protected](posedge wr_clk or negedge wr_rst_n_i )
if(!wr_rst_n_i)
begin
for(i=0;i<FIFO_DEPTH;i=i+1)begin
RAM[i] <= 0;
end
end
esle if(wr_en_i && !full_comb)
RAM[wr_ptr] <= wr_data_i;Complete code
module async_fifo
#(parameter DATA_WIDTH=32, parameter ADDR_WIDTH=3)
(
//write interface
input wire wr_clk,
input wire wr_rst_n_i,
input wire wr_en_i,
input wire [DATA_WIDTH-1:0] wr_data_i,
//read interface
input wire rd_clk,
input wire rd_rst_n_i,
input wire rd_en_i,
output reg [DATA_WIDTH-1:0] wr_data_o,
//flags
output full_o,
output empty_o
);
wire FIFO_DEPTH = 1<< ADDR_WIDTH;//2^3=8
// RAM definition
reg [DATA_WIDTH-1:0] RAM [0:FIFO_DEPTH-1];
//fifo width :DATA_WIDTH 32bit; fifo depth:FIFO_DEPTH 8
// Read write pointer
reg [ADDR_WIDTH:0] wr_ptr; // The write pointer
reg [ADDR_WIDTH:0] rd_ptr; // Read pointer
// The write pointer Binary system -> Gray code
// Gray code address
reg [ADDR_WIDTH:0] gray_wr_ptr; // Gray code address
reg [ADDR_WIDTH:0] gray_wr_ptr_next;// Gray code write address synchronization 1 pat
// Gray code write address synchronization to read clock
reg [ADDR_WIDTH:0] gray_wr2rd_ptr_1; // Gray code write address synchronization to read clock synchronization 1 pat
reg [ADDR_WIDTH:0] gray_wr2rd_ptr_2; // Gray code write address synchronization to read clock synchronization 2 pat
// Read the address Binary system -> Gray code
// Gray code read address
reg [ADDR_WIDTH:0] gray_rd_ptr; // Gray code read address
reg [ADDR_WIDTH:0] gray_rd_ptr_next; // Gray code read address synchronization 1 pat
// Gray code read address is synchronized to write clock
reg [ADDR_WIDTH:0] gray_rd2wr_ptr_1;// Gray code read address synchronization to write clock synchronization 1 pat
reg [ADDR_WIDTH:0] gray_rd2wr_ptr_2;// Gray code read address synchronization to write clock synchronization 2 pat
// Combinatorial logic empty full flag
wire full_comb;
wire empty_comb;
//######## Read / write address pointer generation ####################
//write interface pointer
[email protected](posedge wr_clk or negedge wr_rst_n_i )
if(!wr_rst_n_i)
wr_ptr<= {ADDR_WIDTH+1}{1'b0};
else if(wr_en_i && !full_o)
wr_ptr <=wr_ptr +1'b1;
else
wr_ptr <=wr_ptr;
//read interface pointer
[email protected](posedge rd_clk or negedge rd_rst_n_i )
if(!rd_rst_n_i)
rd_ptr <= {ADDR_WIDTH+1}{1'b0};
else if(rd_en_i && !empty_o)
rd_ptr <=rd_ptr +1'b1;
else
rd_ptr <=rd_ptr;
//############## Binary code -> Gray code ###############
//####### Gray code address
assign gray_wr_ptr = (wr_ptr>>1)^wr_ptr ;
[email protected](*)begin
gray_wr_ptr_next= gray_wr_ptr;
end
// Gray code write address synchronization two levels Pass to the clock reading field
[email protected](posedge rd_clk or negedge rd_rst_n)
begin
if(! rd_rst_n)
begin
gray_wr2rd_ptr_1 <= {ADDR_WIDTH+1}{1'b0};
gray_wr2rd_ptr_2 <= {ADDR_WIDTH+1}{1'b0};
end
else
begin
gray_wr2rd_ptr_1 <= gray_wr_ptr_next;
gray_wr2rd_ptr_2 <= gray_wr2rd_ptr_1;
end
end
//####### Gray code read address
//####### Gray code read address
assign gray_rd_ptr = (rd_ptr>>1)^rd_ptr ;
[email protected](*)begin
gray_rd_ptr_next= gray_rd_ptr;
end
// Gray code read address synchronization two levels Passed to the write clock field
[email protected](posedge wr_clk or negedge wr_rst_n)
begin
if(!wr_rst_n)
begin
gray_rd2wr_ptr_1 <= {ADDR_WIDTH+1}{1'b0};
gray_rd2wr_ptr_2 <= {ADDR_WIDTH+1}{1'b0};
end
else
begin
gray_rd2wr_ptr_1 <= gray_rd_ptr_next;
gray_rd2wr_ptr_2 <= gray_rd2wr_ptr_1;
end
end
//##### The empty full flag is generated
// Full sign
assign full_comb =( {~gray_rd2wr_ptr_2[ADDR_WIDTH],gray_rd2wr_ptr_2[ADDR_WIDTH-1:0]}== gray_wr_ptr );
[email protected](posedge wr_clk or negedge wr_rst_n)
begin
if(!wr_rst_n)
full_o <=1'b0;
else
full_o <= full_comb;
end
// Empty flag
assign empty_comb= (gray_wr2rd_ptr_2==gray_rd_ptr );
[email protected](posedge rd_clk or negedge rd_rst_n)
begin
if(!rd_rst_n)
empty_o <=1'b0;
else
empty_o <= empty_comb;
end
//##########################################
//write data
interger i;
[email protected](posedge wr_clk or negedge wr_rst_n_i )
if(!wr_rst_n_i)
begin
for(i=0;i<FIFO_DEPTH;i=i+1)begin
RAM[i] <= 0;
end
end
esle if(wr_en_i && !full_comb)
RAM[wr_ptr] <= wr_data_i;
//read data
[email protected](posedge rd_clk or negedge rd_rst_n_i)
if(!rd_rst_n_i)
begin
rd_data_o<= 0;
end
esle if(rd_en_i && !empty_comb)// Reading enable , And the storage unit is not empty
rd_data_o <= RAM[rd_ptr];
endmoduleReference resources
Core power —— Hardware accelerated design method (3.2、3.3、3.4)
边栏推荐
- Spark SQL 访问json和jdbc数据源
- 2021-08-21
- MySQL master-slave synchronization and its basic process of database and table division
- Array and string offset access syntax with curly braces is no longer support
- 启牛app下载证券开户,是安全的吗?有风险嘛?
- Safe and reliable! Tianyi cloud data security management platform passed the evaluation
- Use full function simulation design method
- 冒泡排序 指针
- Spark RDD Programming Guide(2.4.3)
- ArcGIS application (20) the ArcGIS grid image symbol system prompts "this dataset does not have valid histogram required for classificati..."
猜你喜欢

安装typescript环境并开启VSCode自动监视编译ts文件为js文件

2021-08-22

2021-05-02

SourceTree版本管理常用操作

2021-05-02

Experiment 4 operation comparison between NoSQL and relational database

Safe and reliable! Tianyi cloud data security management platform passed the evaluation

How to continuously improve performance| DX R & D mode

保证数据库和缓存的一致性

10 Super VIM plug-ins, I can't put them down
随机推荐
防抖&节流 加强版
Enjoy high-performance computing! Here comes the Tianyi cloud HPC solution
Practice brings true knowledge: the strongest seckill system architecture in the whole network is decrypted. Not all seckills are seckills!!
2021-04-14
PHP7.3报错undefined function simplexml_load_string()
eslint 简单配置
2021-04-14
Mysql database design
C sqlsugar, hisql, FreeSQL ORM framework all-round performance test vs. sqlserver performance test
Do domestic mobile phones turn apples? It turned out that it was realized by 100 yuan machine and sharp price reduction
C language -- 17 function introduction
2020-12-04
Greedy interval problem (2)
os.Args[1:]中命令行参数为空时,不执行内部语句
Which securities company is the safest and best choice for stock trading account opening
2021-04-14
SSH method 2 for adding node nodes in Jenkins
Finding the value of the nth term of Fibonacci sequence by recursion
Phantomjs实用代码段(持续更新中……)
2021-08-21