Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Wraparound issue in dual clock FIFO #5

Open
Tey opened this issue Nov 12, 2018 · 2 comments
Open

Wraparound issue in dual clock FIFO #5

Tey opened this issue Nov 12, 2018 · 2 comments

Comments

@Tey
Copy link

Tey commented Nov 12, 2018

First, thanks for you work, it's really a big time saver!

There's a problem with the way signals are synchronized between read and write clocks in the dual clock FIFO. The bit_synchronizer module is used for wraparound signals, while the handshake_synchronizer module is used for head and tail signals. This means it takes 2 clock cycles to synchronize the wraparound signals, while it may take much more cycles to synchronize the head and tail signals (because of the handshake procedure).

Since the synchronized version of the wraparound signals is used with the synchronized version of the head and tail signals in order to update the FIFO status signals, it may happen that a status flag is wrongly de-asserted because a synchronized wraparound signal changes too fast compared to the synchronized head and tail signals.

Take the following case for example:
image

This is a 16 words FIFO with rdclk period of 2.1 ns and a wrclk period of 9 ns. Read requests are made as soon as there are words available (Empty=0). Write requests are made every 3 wrclk cycles (provided Full=0).

At 452.55 ns, the synchronized head counter is updated. Head and tail read counters were equal before that, so the empty flag was set. This is not the case anymore, so the empty flag is reset. This triggers read requests, until all available words have been read (at 458.85 ns).
Meanwhile, at 455.5 ns, a write request is made. Since the head is at 15, it wraps around and is set to 0. This sets the wraparound write flag, which is synchronized a few read cycles later (at 458.85 ns).
The flag is actually processed a read cycle later (at 460.95 ns), when wraparound_rd changes. When this happens, the head and tail read counters are equal, because the head read counter has not been updated yet, so its value is not in sync with the wraparound read flag. This makes the read process believe that the FIFO is full, so there are words to be read, and the empty flag is reset. This triggers read requests, which produces invalid reads eventually.

I guess the solution to that is to make sure wraparound signals are synchronized along the head and tail signals, with a same handshake_synchronizer module.

BTW, the handshake_synchronizer is very slow and alternative solutions using gray counters (and bit_synchronizer modules) exist for dual clock FIFO which are faster yet safe.

@kevinpt
Copy link
Owner

kevinpt commented Feb 7, 2019

Thanks for pointing this out. I have some pending additions to the library to release soon and this will get fixed up.

@kevinpt
Copy link
Owner

kevinpt commented Feb 7, 2019

As I recall, when I wrote this I avoided Gray counters because there were active patents on them. They seem to be expired now so I will consider that in the next revision.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants