We’ve been through a simple synchronizer and constraints. Now we need to move data from one clock domain to another. There are a couple of ways to do this, but one thing I am hoping to see is efficiency. So you might be thinking FIFO, but try to think of how else it might be done.
You need to pass some control information from one clock domain to another, say a 32 bit bus with a wr_en control signal. The data will be written infrequently, so you don’t have to worry about it coming too fast for you to pass it in a simple way.
This could be done with a FIFO, but FIFOs take a lot of resources. Note I said that the data is infrequent and you have time to pass it simply. Given the above diagram, you could use a pulse synchronizer.
wr_req is converted into a a toggle through U6, U7 and U8. The heart of a pulse synchronizer is a toggle synchronizer, U1, U2, U3 and U5. The output from U3 is a single RX_CLOCK pulse. Data must be held constant until captured, so either it must be guaranteed stable or an acknowledge is sent back from TX to RX (not shown). Writing constraints is similar to the simple synchronizer, with an addition to do with the data:
Data has at most 2 RX CLOCK cycles of delay to settle. To be conservative, apply a 1 clock cycle max delay, which gives an entire clock cycle to settling time.
The circuit above could be reduced by generating a toggle wr_en, thus removing a clock of latency and also a FF.
(Sorry for the quick post today. My daughter has a play this week. If you spot any errors, shout out and I’ll update.)