Your code finally has to map onto the resources present on the device. Make an effort to understand the key arithmetic, storage, and logic elements in the architecture you are targeting. Then, as you code the functionality of the design, anticipate the hardware resources to which the code will map. Understanding this mapping gives you an early insight into any potential problem.
The following examples demonstrate how understanding the hardware resources and mapping can help make certain design decisions:
- For larger than 4-bit addition, subtraction, and
add-sub, a carry chain is generally used and one LUT per 2-bit addition is used
(that is, an 8-bit by 8-bit adder uses 8 LUTs and the associated carry chain). For
ternary addition or in the case where the result of an adder is added to another
value without the use of a register in between, one LUT per 3-bit addition is used
(that is, an 8-bit by 8-bit by 8-bit addition also uses 8 LUTs and the associated
carry chain).
If more than one addition is needed, it may be advantageous to specify registers after every two levels of addition to cut device utilization in half by allowing a ternary implementation to be generated.
- In general, multiplication is targeted to DSP
blocks. Signed bit widths less than 18x25 (18x27 in UltraScale devices) map into a single DSP Block. Multiplication
requiring larger products might map into more than one DSP block. DSP blocks have
pipelining resources inside them.
Pipelining properly for logic inferred into the DSP block can greatly improve performance and power. When a multiplication is described, three levels of pipelining around it generates best setup, clock-to-out, and power characteristics. Extremely light pipelining (one-level or none) might lead to timing issues and increased power for those blocks, while the pipelining registers within the DSP lie unused.
- Two SRLs with depths of 16 bits or less can be mapped into a single LUT, and single SRLs up to 32 bits can also be mapped into a single LUT.
- For conditional code resulting in standard MUX
components:
- A 4-to-1 MUX can be implemented into a single LUT, resulting in one logic level.
- An 8-to-1 MUX can be implemented into two LUTs and a MUXF7 component, still resulting in effectively one logic (LUT) level.
- A 16-to-1 MUX can be implemented into four LUTs and a combination of MUXF7 and MUXF8 resources, still resulting in effectively one logic (LUT) level.
A combination of LUTs, MUXF7, and MUXF8 within the same CLB/slice structure results in a very small combinational delay. Hence, these combinations are considered as equivalent to only one logic level. Understanding this code can lead to better resource management, and can help in better appreciating and controlling logic levels for the data paths.
For general logic, take into account the number of unique inputs for a given register. From that number, an estimation of LUTs and logic levels can be achieved. In general, 6 inputs or fewer always results in a single logic level. Theoretically, two levels of logic can manage up to 36 inputs. However, for all practical purposes, you should assume that approximately 20 inputs is the maximum that can be managed with two levels of logic. In general, the larger the number of inputs and the more complex the logic equation, the more LUTs and logic levels are required.