FIFO Pitfalls we fell in ------------------------------------------------- S.Belforte 19-Jan-1998 While developing SVT boards in Pisa, we found 2 slightly different bugs in the way we handled synchronous fifos (CY7C4255-10 to be specific, but the following would apply to any synchronous fifo, like the IDT72205/15/25.. family). These are design shortcomings that the simulation would not spot, therefore particularly dangerous. Both situations have to do with using Synch. FIFO in the so called width expansion mode, i.e. using 2 18-bit chips in parallel to deal with the SVT 23-bit bus. Here are the details to make sure you do not make the same mistakes. ------------------------------------------------------------------------- This is actually quite boring, since I tried to put all details. You may jump at the 2 line SUMMARY at the end and go back to read everything only if you are curious. If you have questions, feel free to ask. The symptoms are "simple". Let's assume we write the following stream of words into the two parallel fifo's: 1111-1111 2222-2222 3333-3333 4444-4444 etc. etc. Where the 4 most significant bytes refer to the first fifo, the 4 ls ones to the second. The first bug results in the following output as latched into the logic downstream of the fifo that controls the fifo reading: BUG#1 --------- 1111-1111 2222-2222 3333-2222 4444-3333 5555-4444 etc. etc. i.e. at a certain time one fifo "repeats" the previous word and stays offset from then on. The second bug gives instead the following result for what the fifo reading logic "sees": BUG#2 ---------- 1111-1111 2222-2222 3333-4444 4444-5555 5555-6666 etc. etc. i.e. at a certain time one fifo "skips" one word and stays like that forever. Both mistakes arise from the same origin, treating the two fifo's as one single chip: it is very easy to get convinced that since the two fifo's share the external control signal, they will always behave in the same way, so the naive designer takes the fifo data sheet and design his interface circuit like if he was dealing with one object that behaves exactely as the data sheet says. The first mistake is the easier to understand: it is the miskate of looking at the status flags of only one of the two chips "since the other chip flags would be the same". Unfortunately this is not true. The fifo empty flag (EF_) is updated on the edge of the read clock, while the internal "empty" status is a consequence of what happens on the write clock edge. When the two frequencies are different, the write edge may happen very close to the reading one, then the EF_ status update may lag one clock cycle depending on internal skew times. Fabrication process variations among chips may cause the EF_ of the two fifo used in depth expansions to become desynchronised, i.e. in response to the writing of a 23-bit word into the two chips, one EF_ will be 1 while the other will still be 0 for until the next clock cycle. In our first board the read enable to the two fifo's (REN_) was sent immediately when EF_ of the first chip becomes 1, while the second chip still has EF_=0. At the next read clock positive edge the EF_=1 chip outputs the newly come data, while the EF_=0 chip still behaves as empty and keeps the previous data on the bus. This causes the second chip to "loose" one step. The two fifo will now be permanently disaligned. This is the situation depicted earlier as BUG#1. This bug can be summarised as "reading from an empty fifo thinking it was not-empty". Here is the example of BUF#1 with expanded details to show what happens: BUG#1 EXPLAINED (Q = fifo output. 1,2 indicates the two chips) ------------------- Q1 Q2 EF_1 EF_2 REN_ 1111-1111 1 1 0 2222-2222 1 0 0 3333-2222 1 1 0 4444-3333 1 1 0 5555-4444 1 1 0 The cure is easy, one has to AND the two EF_ flags and consider the 2-chip combination non-empty only when both fifo's have declared their status as such. In the above example the combined EF_ would be 0 at the second step, so REN_ would 1 and the 3333-2222 combination would not be read. The data flow after the cure would be: BUG#1 CORRECTED ------------------- Q1 Q2 EF_1 EF_2 EF_1 & EF_2 REN_ data latched in next logoic 1111-1111 1 1 1 0 1111-1111 2222-2222 1 0 0 1 2222-2222 2222-2222 1 1 1 0 none (**) 3333-3333 1 1 1 0 3333-3333 4444-4444 1 1 1 0 4444-4444 5555-5555 1 1 1 0 5555-5555 etc. etc. (**) fifo output from this clock cycle is not considered by the fifo reading logic since it did not assert REN_ at the previous cycle In the second board we had made the same mistake of looking at the EF_ of the first chip, but the problem did not appear. This because in this board the REN_ was updated in response to the EF_ transitions only in the next clock cycle. This is legal since the synchronous fifo protocol allows sending REN_ to an empty fifo, it is simply ignored whenever EF_ is low. Unfortunately with this design one is exposed to the symmetric bug: "reading from a not-empty fifo thinking it was empty", which is BUG#2 in the previous example. What happens is that while the last word is being read out, a new word is written and because of internal timing differences in the two chips the first fifo does not realise it immediately and goes through one read clock cycle of EF_=0 (empty), while the second fifo recognizes the new word right away and keeps EF_=1. The fifo readout logic sees EF_=0 from the first chip, but leaves REN_=0 for one more clock cycle, thus causing the second chip to output the newly arrived word but disregarding it, since the logic believes that both fifo's ignore the REN_ signal. It is worth noticing that in this case ANDing the two flags does not help ! ANDING the flags allow one to avoid missing an EF_=0 flag on the "ignored chip", but now the problem is that the "ignored chip" has EF_=1 !!! Here is the blow-up of what happens: BUG#2 EXPLAINED (Q = fifo output. 1,2 indicates the two chips) ------------------- Q1 Q2 EF_1 EF_2 EF1 & EF_2 REN_ data latched in next logic 1111-1111 1 1 1 0 1111-1111 2222-2222 0 1 0 0 2222-2222 2222-3333 1 1 1 0 none (***) 3333-4444 1 1 1 0 3333-4444 4444-5555 1 1 1 0 4444-5555 etc. etc (***) the fifo reading logic does not latch this word internally since it detected an empty situation at the previosu cycle and thus assumes that the two chips have ignored the previous REN_=0 Here the cure is to give up updating REN_ on the clock edge, and instead tie it to the current value of the EF_ flag, making if combinatorial rather then sequential. So one really NEEDS to detect EF_ from both fifo's as soon as they are updated after a read clock positive edge and if one of the fifo is empty the REN_ flag has to be deasserted before the next clock edge. The need to receive signal from the fifo's, process them and send a signal back to the fifo all in one clock cycle limits the speed of the circuit substantially with respect to the case of readig one single fifo chip when the REN_ is updated on the clock edge and one has one full lock cycel to detect EF_ and one to send REN_ to the fifo ! The data flow after the cure would be: BUG#2 CORRECTED ------------------- Q1 Q2 EF_1 EF_2 EF1 & EF_2 REN_ data latched in next logic 1111-1111 1 1 1 0 1111-1111 2222-2222 0 1 0 1 2222-2222 2222-2222 1 1 1 0 none (**) 3333-3333 1 1 1 0 3333-3333 4444-4444 1 1 1 0 4444-4444 5555-5555 1 1 1 0 5555-5555 etc. etc (**) fifo output from this clock cycle is not considered by the fifo reading logic since it did not assert REN_ at the previous cycle -------------------------------------------------------------------------- SUMMARY: ========= 1) AND the EF_ flag from the two fifo chips before using them 2) remove REN_ flag as soon as EF_=0 *before* the next clock edge Indeed recommendation 1) can be found also in some data sheets (Cypress e.g.) if you look carefully. 2) just means that what looks slike a smart trick to speed up things (leaving REN_=0 to an empty fifo) is a dangerous thing. Stefano Belforte - I.N.F.N. PISA tel: +39-50-880-305 fax: +39-50-880-317 e-mail: Stefano.Belforte@pi.infn.it address: INFN - via Livornese 1291 - 56010 S.Piero a Grado PI - Italy