ASYNC
FIFO is a frequency relationship agnostic bus synchronization technique and by
that can be considered practically universal.
It
is convenient to choose the write/read pointers of width by one bit bigger than
needed by FIFO size. The msb then will play the role of “sign”. The pointers
(bus) synchronization is performed with the help of Gray encoding. Gray code
encoding is a popular technique to synchronize a bus because only one bit is
changed at a time. This ensures we always sample or old or new value on the bus
and never – inconsistent one. “g2b” and “b2g” is the logic to convert Gray code
to binary and vice versa. It is out of the scope of this article to depict its
design.
//write pointer
always @ (src_clk)
if (!rst_n)
wr_ptr
<= ‘d0;
else if (push)
wr_ptr
<= wr_ptr + 1’b1;
//read pointer
always @ (dst_clk)
if (!rst_n)
rd_ptr
<= ‘d0;
else if (pop)
rd_ptr
<= rd_ptr + 1’b1;
//full
assign full = (wr_ptr[log(FIFO_SIZE)] ^
rd_ptr_synch[log(FIFO_SIZE)]) &&
(wr_ptr[log(FIFO_SIZE)-1:0] ==
rd_ptr_synch[log(FIFO_SIZE)-1:0]);
//empty
assign empty = (wr_ptr_synch[log(FIFO_SIZE):0] ==
rd_ptr[log(FIFO_SIZE):0]);
The
important thing to remember is the size of the FIFO has to be exactly power
of two. This is because in any other case there will be multiple bit
transitions even with Gray code encoding and thus bus synchronization with only
one bit changed at a time is violated.
Courtesy http://www.shellbr.com.