The purpose of an inter-block connectivity block is to facilitate full-chip integration by simplifying the timing constraints and logical interface of block interconnects. The advantages of using a clean and generic design for interfacing between blocks within a device are evident during top level timing integration. When device top-level nowadays contains thousands of signal connecting between different blocks, it is essential to simplify the top level constraints, so the integration would not require iterations of the block placement and timing to solve timing issues.
For an overview of the reasoning for using a generic sampled inter-block connectivity module, please refer to RTLery blog post about “designing an inter-block connectivity”.
The design of an inter block connectivity FIFO needs to consider all the specific requirements of an inter block interface design and its targets, as well as any regular pipe FIFO. The main requirements of sampled inter-block connectivity are:
- Sampling of all signals at each block boundary both on the output and the input.
- Source side interface should have the same signals as a simple FIFO with flow control signals like full and almostfull indications.
- Destination side should have the same signals as a simple FIFO read interface including empty indication.
- FIFO depth should accommodate stalling and flow control, considering the additional sampling stages. The depth should allow stalled FIFO to re-start flowing without unnecessary “bubbles” where no data is transferred.
To design such a FIFO, one should start with a simple generic FIFO and separate the FIFO load logic from the FIFO storage and extract logic. By adding the sampling stages at the FIFO load logic, we practically add pipe stages to the storage array write operation.
To handle the FIFO flow controls, we need both load and extract sides to have status counters, Monitoring the number of entries in the FIFO and generating full and extract signals accordingly.
Pointer logic for accessing the storage array would also be required at the destination side, so the FIFO array would be accessible.
The load operation of the FIFO begins at the load signal; the data is than loaded into a register at the source block and then at the destination blocks. The load operation is used by the load control logic to advance a counter, indicating that the FIFO has one more entry. This counter increment happens before the actual FIFO at the destination side is loaded.
The load signal itself is also sampled at the source block and the destination blocks. After that the data is loaded into the FIFO at the destination side, using the FIFO write pointer. The load operation at the destination side would affect the status counter and inform that another entry was loaded into the FIFO. At this point, the new entry will be available for extraction.
The FIFO extract operation works in much the same way, the operation is registered in the destination side status counter as soon as the extract signal is asserted, the extract FIFO control logic would decrease the FIFO status counter, indicating the an entry was extracted. If this was the last entry, the empty signal would be asserted. The extract signal, than goes through the sampling over the interface, one at each side and continues to decrement the status counter on the source side. The two status counters are always synchronized, and if no operation is performed, will become equal, so effectively, the whole structure acts as a FIFO.
The FIFO depth calculation is a function of a worst case scenario. The worst case scenario happens when for a long time the FIFO is not extracted and the full indication is asserted and them the destination side starts extracting data from the FIFO continuously while the source side keeps trying to load the FIFO. In this scenario, we want to avoid the case where the FIFO gets temporarily empty, inserting bubbles into the data flow. If bubbles are inserted while the source has constant entries to load, this is an indication that the FIFO is too shallow.
In the above example, if the extract signal is asserted at cycle 1, at cycle 6 the FIFO would be loaded with the first new data after the full indication was de-asserted. This means that for 6 cycles, data is extracted before it is loaded for the first time so 6 entries are needed, so the FIFO does not under run.
Initialization and reset
As the FIFO logic is divided into two separate blocks, the issue of reset is important. If the source side is kept in reset longer, no harm will be done as the destination side does not initiate any activity by itself and would therefore remain empty. On the other hand, if the destination side is kept in reset longer, the status counter on the two sides may not be coherent. This would happen if a data is loaded at the source side while the destination side is reset. The source side status counter would register the entry as loaded, but it will not actually be loaded as the destination side is still in reset.
To prevent this scenario, an initialization signal is added to the interface so the source side is kept in reset until the destination side is ready to receive data, preventing coherency issues.
Designing an inter-block interface FIFO should handle all the requirements of a fully sampled inter-block interface and also the basic functionality of a FIFO. Once this set of features is implemented, the interface FIFO facilitates the block design on both the logical and timing aspects, removing dependencies between the physical design and the logic functionality of the blocks. Adopting interface FIFOs as a design methodology for complex ASIC designs can reduce design, verification, placement and timing efforts and result is faster chip level integration.