Hardware interview practice
Size a Width-Converting Asynchronous FIFO
A 200 MHz producer emits an unstallable burst of sixteen 64-bit beats, one per source cycle. During that burst the 250 MHz consumer is paused. It then runs for at least thirty-two destination cycles before another burst and consumes one 32-bit word per cycle. Design the width conversion, minimum FIFO capacity, and clock-domain crossing.
Question code
write side: 200 MHz, 16 beats x 64 bits, no mid-burst backpressure
read side: 250 MHz, 1 word x 32 bits per accepted cycle
consumer paused for the complete write burst
gap before next burst: at least 32 read-clock cycles
preserve low 32 bits before high 32 bits for each beatWork through one case
Case 1: A burst
Case 2: The source peak
Case 3: Source beat 64'hAABBCCDD_11223344Case 1: Holds 16*64=1024 bits, which is exactly 32 entries of 32 bits.
Case 2: Is 12.8 Gb/s and the active consumer rate is 8.0 Gb/s, so pausing the consumer during the burst requires storage despite the later drain gap.
Case 3: Is read as 32'h11223344 followed by 32'hAABBCCDD.The shown result follows by applying this rule: The capacity calculation uses burst backlog in a common 32-bit storage unit and reaches a minimum of 32 entries. The cases also demonstrate this requirement: Reset both sides under a coordinated flush before traffic; the 32-cycle read gap must drain the full burst, and no next burst may start unless write-side capacity for all sixteen 64-bit entries is guaranteed.
Requirements
- Store each accepted 64-bit source beat atomically in one FIFO entry; on the read side, emit its low 32 bits first and high 32 bits second, advancing the FIFO read pointer only after the high half transfers.
- Provide at least 16 entries of 64 bits, equivalently 32 entries of 32 bits, because one unstallable burst contributes 1024 bits while the consumer drains none.
- Use a true dual-clock FIFO whose Gray-coded read and write pointers each advance by one 64-bit entry, with synchronized pointer crossings and local full/empty decisions; keep the read-side half selector local to clk_r.
- Reset both sides under a coordinated flush before traffic; the 32-cycle read gap must drain the full burst, and no next burst may start unless write-side capacity for all sixteen 64-bit entries is guaranteed.
