Ping-Pong Buffer Controller
Medium · Sequential · SystemVerilog
Design a ping-pong (double-buffer) controller that manages two fixed-depth storage banks, keeping one bank accepting writes while the other is drained by a reader, with an atomic bank-swap when the write bank becomes full.
The module maintains two internal banks, each capable of holding DEPTH words of DATA_W bits. At all times one bank is the **write bank** and the other is the **read bank**. After reset, bank 0 is the write bank and bank 1 is the read bank (initially empty).
**Write port behavior:**
- {wr_ready} is high when the write bank has at least one empty slot. - When {wr_en} is asserted and {wr_ready} is high, {wr_data} is written into the next available slot of the write bank on the rising clock edge and the write pointer advances. - When {wr_en} is asserted but {wr_ready} is low, the write is suppressed — no data is written and no pointer advances.
**Bank-swap:**
- When a write fills the last slot of the write bank (the write pointer reaches DEPTH after the write), the two banks swap roles atomically on the same clock edge: the newly full bank becomes the read bank and {rd_valid} asserts; the previously empty read bank becomes the new write bank. - A swap only occurs when the incoming read bank is empty. If the read bank still contains unread words when the write bank becomes full, both banks are occupied and {wr_ready} deasserts — no further writes are accepted until the reader drains the read bank completely and a swap can occur.