## 3 ASE Coding
### Look-Up Table Operation
During the stacking operation to register a new symbol to the table or to arrange the table, the index register is referred as the index of the highest entry in the table that has been already occupied. When the counter reaches to the number of culling count number, it is reset to the initial value. Subsequently, the index register is decremented to invalidate the highest occupied entry. Algorithm 3 shows an implementation of the entropy culling. The Initialize() function must be invoked before the compressor and the decompressor start. The \(\mathit{culling\_count}\) is initialized to a defined constant number of matches in the table NUM_CULLING. The EntropyCulling() function decrements the counter \(\mathit{culling\_count}\) and also decrements the number of occupied entries \(k\) when the counter becomes zero. This implements an invalidation of the highest entry in the look-up table. The function is invoked when the symbol \(s\) is hit in the look-up table. Therefore, it is invoked from the ArrangeTable() function. We propose another optimization function in the look-up table operation called Near Neighbor Entry Exchange. This function improves hardware implementation. During the stack operation of the look-up table above, a symbol must move to the lowest entry. Hardware implementation of this operation inevitably needs to multiplex original symbols registered in the higher entries than the matched one in the table, as shown in Figure 3(b). This needs a large combination logic and increases the latency for the selection. When the matched entry is placed at an index \(I\), all \((I-1)\) lower entries must be moved to the next entries and the matched entry moved to the lowest. During these operations, in the worst case, the new lowest entry is selected from \((E-1)\) entries. This needs a large combinational logic to select an entry from \((E-1)\) ones. To avoid this problem, the near neighbor entry exchange performs a lazy stacking operation by moving the matched entry to the one in a limited distance \(d\). Figure 3(d) shows an example when the \(d\) is configured to two entries. The matched entry moves to only two lower place and pushes the higher ones to the next entries. This avoids the large multiplexing connection, and thus, improves the clock frequency because one of \(d\) entries is selected and the delay is normalized through all entries. However, this technique slightly affects the compression ratio. Let us discuss the tradeoff between \(d\) and the compression ratio in the next section. The ArrangeTableNNEE() in Algorithm 3 executes an example of the near neighbor entry exchange. This function increases the steps to exchange a constant number of entries \(d\), which is a distance to the exchanged neighbor. Additionally, in software implementation, the number of entry exchanges is limited to \(d\) times. This means that the number of entry exchanges in the ArrangeTable() function can be improved from \(E\) times in the worst case to the constant \(d\) times. The compressor of ASE coding receives streaming data and encodes original symbols to shortest code bits based on instantaneous entropy calculated from the look-up table occupation, as we have explained above. Because these steps do not have any stall or buffering, it outputs streaming data again. In the decompressor side, when the first bit of compressed data stream is received, the decode operation can start. The decompressor maintains the same look-up table as the compressor side and calculates the corresponding entropy. It picks up the original symbol from the table and finally generates the data stream that is received in the compressor side. During the encode and the decode operations, the entropy culling works to reduce the look-up table occupation. This will improve the size of code bits assigned to the original symbol adaptively.