Simulation and Synthesis Techniques for Asynchronous
FIFO Design
Clifford E. Cummings, Sunburst Design, Inc. cliffc@sunburst-design.com ABSTRACT
FIFOs are often used to safely pass data from one clock domain to another asynchronous clock domain. Using a
FIFO to pass data from one clock domain to another clock domain requires multi-asynchronous clock design techniques. There are many ways to design a FIFO wrong. There are many ways to design a FIFO right but still make it difficult to properly synthesize and analyze the design.
This paper will detail one method that is used to design, synthesize and analyze a safe FIFO between different clock domains using Gray code pointers that are synchronized into a different clock domain before testing for "FIFO full" or "FIFO empty" conditions. The fully coded, synthesized and analyzed RTL Verilog model (FIFO Style #1) is included. Post-SNUG Editorial Comment
A second FIFO paper by the same author was voted “Best Paper - 1st Place” by SNUG attendees, is listed as reference [3] and is also available for download.
1.0
Introduction
An asynchronous FIFO refers to a FIFO design where data values are written to a FIFO buffer from one clock domain and the data values are read from the same FIFO buffer from another clock domain, where the two clock domains are asynchronous to each other.
Asynchronous FIFOs are used to safely pass data from one clock domain to another clock domain.
There are many ways to do asynchronous FIFO design, including many wrong ways. Most incorrectly implemented
FIFO designs still function properly 90% of the time. Most almost-correct FIFO designs function properly 99%+ of the time. Unfortunately, FIFOs that work properly 99%+ of the time have design flaws that are usually the most difficult to detect and debug (if you are lucky enough to notice the bug before shipping the product), or the most costly to diagnose and recall (if the bug is not discovered until the product is in the hands of a dissatisfied customer). This paper discusses one FIFO design style and important details that must be considered when doing asynchronous
FIFO design.
The rest of the paper simply refers to an “asynchronous FIFO” as just “FIFO.”
2.0
Passing multiple asynchronous signals
Attempting to synchronize multiple changing signals from one clock domain into a new clock domain and insuring that all changing signals are synchronized to the same clock cycle in the new clock domain has been shown to be problematic[1]. FIFOs are used in designs to safely pass multi-bit data words from one clock domain to another.
Data words are placed into a FIFO buffer memory array by control signals in one clock domain, and the data words are removed from another port of the same FIFO buffer memory array by control signals from a second clock domain. Conceptually, the task of designing a FIFO with these assumptions seems to be easy.
The difficulty associated with doing FIFO design is related to generating the FIFO pointers and finding a reliable way to determine full and empty status on the FIFO.
2.1
Synchronous FIFO pointers
For synchronous FIFO design (a FIFO where writes to, and reads from the FIFO buffer are conducted in the same clock domain), one implementation counts the number of writes to, and reads from the FIFO buffer to increment (on
FIFO write but no read), decrement (on FIFO read but no write) or hold (no writes and reads, or simultaneous write and read operation) the current fill value of the FIFO buffer. The FIFO is full when the FIFO counter reaches a predetermined full value and the FIFO is empty when the FIFO counter is zero.
Unfortunately, for asynchronous FIFO design, the increment-decrement FIFO fill counter cannot be used, because two different and asynchronous clocks would be required to control the counter. To determine full and empty status for an asynchronous