Describe how a multi bit synchronizer / async fifo handles the variable delay of each bit
Sigiloso
The standard solution is to encode the pointer into grey-code, where for each incrementation of the pointer, only one bit changes (so the variable delay cannot cause false empty/full glitches as the bits settle). Note that this assumes a power-of two depth FIFO, or the grey-code may flip multiple bits when the pointer hits the non-power-of-2 top and has to be set to the bottom. Also not that in any standard asynchronous design, it is best not to have any combinational logic before a synchronizer (always have a flop). The reason is that even if you think you know the design is glitch-proof, the synthesis tool could do an strange optimizatino and create a circuit that will glitch when you're not expecting it (and that glitch can get sampled by the sychronizer and result in a false pulse on the other sie). This can be avoided by writing structural RTL and using DC constraints to ensure your glitch-proof circuit ends up the in netlist (though why not just avoid these cases all together by adding the flop). Also of note, the create an empty signal, the write-pointer has to be converted to grey-code, flopped (see notes above about combinational logic before synchronizers) and then sent through synchronizers in the write-pointer clock domain. The output of the synchronizers then has to be grey-code decoded, so that it can finally be compared to the read-pointer to determine empty. Note, generating the full signal is just the reverse. For power-of two FIFOs, just add one extra bit to pointers tell the difference between full and empty (if the extra bit is 0, and the pointers are equal, the FIFO is empty, if the extra bit is 1, and the pointers are equal, the FIFO is full). Enough about FIFOs and async-crossings.