AdDraw / buffer_size_est

Simple TB and equation in order to estimate buffer size required to not overfill it
MIT License
0 stars 0 forks source link

Asynchronous write and read clocks are tricky #6

Open AdDraw opened 1 year ago

AdDraw commented 1 year ago

To properly estimate the buffer size, I think it comes down to stuff like clock phases etc between each other.

Because of this, we sometimes need more buffer space/words than estimations show. Additionally, Asynchronous FIFO has a 2cycle(due to 2ff synchronizers) synchronisation delay for pointers, thus read that happens will update the counters on the write side in 2 cycles, even though in a synchronous fifo, read would happen almost instantaneously and overall making it all work.

TODO:

AdDraw commented 1 year ago

Currently fullness of the FIFO is based on the a_wr_ptr - a_rd_ptr_bin, where a_rd_ptr_bin is the read pointer from the B clock domain which has been synchronized to A clock domain using a dual flip-flop synchronizer, which means that it lags 2 A clock cycles behind B clock domain's read pointer(the one that represents the actual state)

AdDraw commented 1 year ago

Possible fix in 16fd40d59df208e56e0f0073b3e8cd39731b44a4

Main thing was that buffer size equation sometimes underestimated the minimum fifo size required. This was due to 3 things for async buffers:

  1. Pointer synchronization
    • wr_ptr from wr clock domain(A) crosses over to rd clock domain(B) in 2 rd clocks
    • rd_ptr is the same but it takes it to cross from domain B to A in 2 wr clocks
  2. Start reading only when FIFO is not empty & issue read a cycle later
    • this will take about a single read cycle to go from empty deassertedtoread` asserted and sampled
      • This was also the problem for the Sync FIFO

Above points cut into the time frame reader can read from the FIFO before next burst of data comes(or continuous data stream still writes to the fifo) meaning that to better estimate the minimum fifo size should be bigger and delays between clock domains etc have to be accounted for.

Overall the time fifo can read should be equal to:

time_to_read = time_to_write - time_for_rd_ptr_sync - time_for_wr_ptr_sync - time_to_assert&sample_read_after_empty_deasserts

where:

2 for sync was chosen as deafult, but should be changed to SYNCHRONIZER_STAGES

AdDraw commented 1 year ago

More problems:

For async clocks that have aligned rising edges above equations work, but they do not work for cases where risign edges are misaligned.

Ex. rd_freq: 4Hz, wr_freq: 6Hz does not work

TODO: fix this