The following figure shows a diagram of the M x K Circular Buffer described earlier. Each cell contains one sample “x(n)”, where each sample is labelled with its time index “n”. Note there are M=16 rows and K=8 columns. The diagram shows the evolution of the buffer contents over three consecutive time epochs of the buffer. The leftmost column represents the current input samples. There are M=16 samples in total. Fourteen of these labelled in red are input to the buffer over two cycles. The two samples labelled in blue represent history samples from the previous epoch.
Notice how the circular or “serpentine” shift operates on the M x K buffer. From the left to the middle, the buffer is shifted down by 14 samples. The bottom of each column is shifted around to the top of the next column to the right. Samples shifted out of the rightmost column are discarded. Notice how the red input samples “x13” and “x12” in the top two rows on the left become the blue state samples “x13” and “x12” in the bottom two rows in the middle. This is how the Circular Buffer introduces state into the filterbank processing.
The filterbank needs to process each row in the M x K array as a normal FIR filter. This is depicted as the green rectangle in the following figure. Notice, however, how the “state history” inside the green rectangle does not contain the normal “time-shifted” samples one usually sees within the state of an FIR filter. The sample ordering is jumbled and is unrelated over time. This cannot be implemented as a normal finite impulse response (FIR) filter in the AI Engine because the state history is not “linear”. Not only the input sample, but the entire state history would have to be input to the FIR on every cycle. This is not feasible.
However, the yellow boxes reveal a solution. Note how the time indices of the samples within the yellow boxes do exhibit the desired “time-shifted” characteristic of a normal FIR filter state. On each time sample, the state contents within the yellow boxes are shifted by one sample making room for a new one. But these yellow boxes correspond to different logical filters of the filterbank. Consequently, a workable solution may be achieved by mapping logical filters (i.e., different rows in the M x K matrix) to physical AI Engine tiles performing those filters. This mapping changes over time on a sample-by-sample basis as indicated by the following figure, and acts as a “card dealing” operation where the input samples to the desired logical filters are dealt to different physical AI Engine tiles. Inside those AI Engine tiles, the state history exhibits time-shifted state. The outputs of the physical tiles must then undergo an inverse “card dealing” pattern to assign the output samples to the proper logical filter. This “card dealing” permutation is implemented easily in the PL through routing and multiplexing logic resource.