Multi Pop Fifo

Pop is a multi-bit thermometer encoded

Introduction

In this PPA challenge, you are given a first-in first-out buffer (fifo) that takes one push per cycle but can pop up to NUM_POP entries in a single cycle. The NUM_POP oldest entries are always shown on the pop lanes: lane 0 is the oldest entry, lane 1 the next oldest, and so on. Each cycle, pop_therm_i says which of them are taken. It is thermometer encoded: bit i pops lane i, and the set bits always start from lane 0, so popping n entries sets the n lowest bits.

For example, with entries A (oldest), B, C, D and E in the fifo and NUM_POP = 4, the lanes show A, B, C and D. pop_therm_i = 4'b0111 pops 3 entries and leaves D and E, so the next cycle the lanes show D and E with lanes 2 and 3 not valid.

The boilerplate code works but is slow: for every lane it adds the lane number to the read pointer, wraps it, and reads that slot out of the whole storage. Your task is to keep the same behaviour while improving the timing and area of the design. The synthesis and timing report after each run shows how your design compares with the reference solution.

All the flops should be positive edge triggered with active high resets (if any).

Interface Definition

DEPTH        => Number of entries in the fifo
DATA_W       => Width of each entry
NUM_POP      => Number of pop lanes: the most entries that can be popped in a cycle

push_i       => Push an entry into the fifo
push_data_i  => The entry to push

pop_therm_i  => Thermometer-encoded pop: bit i pops lane i (e.g. 4'b0011 pops the 2 oldest)
pop_data_o   => pop_data_o[i] is the i-th oldest entry (lane 0 is the oldest)
pop_valid_o  => pop_valid_o[i] is high when the fifo holds at least i+1 entries

count_o      => Number of entries currently in the fifo

Interface Requirements

  • The fifo must keep entries in first-in first-out order
  • Push and pop can happen in the same cycle
  • pop_data_o and pop_valid_o must reflect the entries stored at the start of the cycle; pop_data_o[i] is only checked when pop_valid_o[i] is high
  • count_o must reflect the entries stored at the start of the cycle (it updates the cycle after a push or pop)
  • pop_therm_i is always a thermometer code: all ones from bit 0 up, then all zeros (4'b0000, 4'b0001, 4'b0011, 4'b0111 or 4'b1111 for NUM_POP = 4)
  • pop_therm_i only pops lanes that are valid: it never has more bits set than there are entries in the fifo
  • push_i will only be asserted when there's room for the entry (counting the entries popped in the same cycle)

Loading the interactive workspace...