In this article I have documented a conversation I had during an interview where I had to apply all my knowledge of CDC in one go. This was one of the most interesting series of questions I was asked on CDC at a big Tech firm.
The interviewer was able to test all of my CDC knowledge in on go. Which is why I still remember this conversation. I have presented it here in the same way the conversation unfolded. I recommend you read the question and take a moment to think about the solution before you read mine.
If you need a refresher or a reference guide on this topics. You will not have to look beyond this article I wrote.
There are two asynchronous clocks, one with a period of 5ns and another 7ns. I want to transfer a pulse from the 5ns clock to 7ns clock. Can you design a CDC circuit?
Me: How frequent is this pulse going to be? Can it come and go in any cycle or stay up for more than one source clock?
This pulse is going to be rather rare compared to the clock frequency and will stay up for only 1 cycle whenever it arrives.
Me: We could just extend that pulse for three source cycles and use a multi-flop synchroniser to send it across. In the destination domain we can just take the positive edge of the synchronised extended pulse.
Can I be sure of this circuit even when the frequencies of the clocks change?
Me: No, it will have to be revisited based on frequency numbers.
Can you make it robust to handle any frequency relationship?
Me: We could use a toggle synchroniser. Wherein on the source side whenever we get a pulse we toggle a flop. The toggled signal goes to the other domain and it’s rising edge is detected by the destination.
That is a good solution. But does it place any constraints on how frequent this pulse can be?
Me: Yes, a second pulse should not arrive during the time the first one is still being synchronised.
Can we do something to remove this constraint?
Me: Can I add more elements and make this circuit more complex?
Feel free to use anything you can think of.
Me: Does the pattern of pulses need to be accurately reproduced in the destination domain? i.e if I have a 101101 pattern in the source, should it be the same in the destination?
It is not possible to ensure that because the clock frequencies could be anything. You just need to transfer an equal number of ‘High’ voltage states to the other clock.
Me: We can have a counter at source to keep incrementing whenever it gets a pulse and then transfer this counter value to the destination, where another piece of logic can generate the high state for those many clocks.
What specific scheme will you use to transfer this counter?
Me: I’ll use the Mux-Recirculation (or MCP) technique, meaning I’ll keep the data bus (counter) until I can send a valid pulse to the other end (using toggle synchroniser) and receive an ack from the other end. Then I’ll update the count with whatever is the new counter value and start this process again.
Let’s say we are using a 2-Flop synchroniser for sending the qualifier pulse. What will be the latency of the entire operation of sending the counter.
Me: Max latency in one direction will be 1 source clock (for toggling) and 3 destination cycles (worst case for 2 flops). For the ack to come back it will be the same amount. (with src and dst periods reversed)
i.e 1 + 3 source cycles + 1+3 destination cycles.
Sticking to the idea of the counter, can we do something to reduce this latency?
Me: I can use a register 1 -deep FIFO to write the counter value to a register, and transfer a not empty pulse to the other end and from there I can do a read operation and transfer the empty signal to the source end and enable writing again. With this we can reduce 1 cycle latency in each direction.
In the paper on CDC by Clifford Cummings, he talks about a 1-deep / 2 -register FIFO which is essentially the same thing we have come up with in this discussion. An RTL implementation of the system discussed here can be found here