Expert Verilog, SystemVerilog & Synthesis TrainingSimulation and Synthesis Techniques for AsynchronousFIFO DesignClifford E. Cummings, Sunburst Design, [email protected] are often used to safely pass data from one clock domain to another asynchronous clock domain. Using aFIFO to pass data from one clock domain to another clock domain requires multi-asynchronous clock designtechniques. There are many ways to design a FIFO wrong. There are many ways to design a FIFO right but stillmake 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 clockdomains 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) isincluded.Post-SNUG Editorial CommentA second FIFO paper by the same author was voted “Best Paper - 1st Place” by SNUG attendees, is listed asreference [3] and is also available for download.SNUG San Jose 2002 Simulation and Synthesis Techniques forRev 1.2 Asynchronous FIFO Design21.0 IntroductionAn asynchronous FIFO refers to a FIFO design where data values are written to a FIFO buffer from one clockdomain and the data values are read from the same FIFO buffer from another clock domain, where the two clockdomains 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 implementedFIFO designs still function properly 90% of the time. Most almost-correct FIFO designs function properly 99%+ ofthe time. Unfortunately, FIFOs that work properly 99%+ of the time have design flaws that are usually the mostdifficult to detect and debug (if you are lucky enough to notice the bug before shipping the product), or the mostcostly to diagnose and recall (if the bug is not discovered until the product is in the hands of a dissatisfiedcustomer).This paper discusses one FIFO design style and important details that must be considered when doing asynchronousFIFO design.The rest of the paper simply refers to an “asynchronous FIFO” as just “FIFO.”2.0 Passing multiple asynchronous signalsAttempting to synchronize multiple changing signals from one clock domain into a new clock domain and insuringthat all changing signals are synchronized to the same clock cycle in the new clock domain has been shown to beproblematic[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 wordsare removed from another port of the same FIFO buffer memory array by control signals from a second clockdomain. 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 reliableway to determine full and empty status on the FIFO.2.1 Synchronous FIFO pointersFor synchronous FIFO design (a FIFO where writes to, and reads from the FIFO buffer are conducted in the sameclock domain), one implementation counts the number of writes to, and reads from the FIFO buffer to increment (onFIFO write but no read), decrement (on FIFO read but no write) or hold (no writes and reads, or simultaneous writeand read operation) the current fill value of the FIFO buffer. The FIFO is full when the FIFO counter reaches apredetermined 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, becausetwo different and asynchronous clocks would be required to control the counter. To determine full and empty statusfor an asynchronous FIFO design, the write and read pointers will have to be compared.2.2 Asynchronous FIFO pointersIn order to understand FIFO design, one needs to understand how the FIFO pointers work. The write pointer alwayspoints to the next word to be written; therefore, on reset, both pointers are set to zero, which also happens to be thenext FIFO word location to be written. On a FIFO-write operation, the memory location that is pointed to by thewrite pointer is written, and then the write pointer is incremented to point to the next location to be written.Similarly, the read pointer always points to the current FIFO word to be read. Again on reset, both pointers are resetto zero, the FIFO is empty and the read pointer is pointing to invalid data (because the FIFO is empty and the emptyflag is asserted). As soon as the first data word is written to the FIFO, the write pointer increments, the empty flag iscleared, and the read pointer that is still addressing the contents of the first FIFO memory word, immediately drivesthat first valid word onto the FIFO data output port, to be read by the receiver logic. The fact that the read pointer isalways pointing to the next FIFO word to be read means that the receiver logic does not have to use two clockperiods to read the data word. If the receiver first had to increment the read pointer before reading a FIFO dataSNUG San Jose 2002 Simulation and Synthesis Techniques forRev 1.2 Asynchronous FIFO Design3word, the receiver would clock once to output the data word from the FIFO, and clock a second time to capture thedata word into the receiver. That would be needlessly inefficient.The FIFO is empty when the read and write pointers are both equal. This condition happens when both pointers arereset to zero during a reset operation, or when the read pointer catches up to the write pointer, having read the lastword from the FIFO.A FIFO is full when the pointers are again equal, that is, when the write pointer has wrapped around and caught upto the read pointer. This is a problem. The FIFO is either empty or full when the pointers are equal, but which?One design technique used to distinguish between full and empty is to add an extra bit to each pointer. When thewrite pointer increments past the final FIFO address, the write pointer will increment the unused MSB while settingthe rest of the bits back to zero as shown in Figure 1 (the FIFO has wrapped and toggled the pointer MSB). Thesame is done with the read pointer. If the MSBs of the two pointers are
View Full Document