General Description: When the FIFO core is implemented in hardware and I perform timing simulation, I notice that timing problems cause unexpected behavior in the core. The FIFO core also utilizes read and write clocks in different clock domains. These problems may occur even when the functional simulation is successful and the Timing Analyzer shows no problems.
Problems occur when the FIFO core uses two different clock speeds for read and write. The FIFO core BRAMs use two different clock periods. If the faster port is listed first in the PCF and is blocked by the slower port that appears last, the BRAM interface circuit may inadvertently set to the lower timespec, which does not reach the higher speed. As a result, the timing analysis may indicate that your desired speed is achievable when it is not.
NOTE: This issue was fixed in the ISE 5.1i software. Timing Analyzer has been updated so that it handles the different clock domains appropriately.
You can avoid this problem by carefully constraining your design with timing constraints that handle the different clock domains individually. Copy the constraints below into your "design_name.ucf" file.
As the FIFOs are created by CORE Generator, you cannot determine which port is used for the write port and which is used for the read port. Generally, Port A is used for writing and Port B for reading, but this is not always true, especially when the write and read ports are different widths. Smaller widths always go on Port A. The following UCF code does not define which port is used for writing and which is used for reading; either port may be used for either purpose. This code also properly groups items together and strips out unnecessary information.
As an example, we can look at a design with three clocks and many block RAMs. Each block RAM has different combinations of the three clocks driving its CLKA and CLKB clock ports. The UCF example below illustrates how to constrain this design so there are no incorrect block RAM port groupings in the PCF file. The example is large and may cause warnings in NGDBuild if any of the scenarios do not exist. You can ignore most of these warnings, but Xilinx recommends that you check the warnings the first time you run the design.
NOTE: 1. Adjust the clock net names to match the names used in your design, and enter the correct required time values. 2. This is a long set of UCF commands, but all commands are necessary.
---------------------------------------------------------- # Select the individual block RAM ports that are attached to each clock.
# Obviously, only one of the following two grouping specs should be picked up for each FIFO; let the implementation tools sort them out. net clk_100a tnm = BRAMS_PORTA clk100a_brams; net clk_100a tnm = BRAMS_PORTB clk100a_brams;
# Obviously, only one of the following two grouping specs should be picked up for each FIFO; let the implementation tools sort them out. net clk_85m tnm = BRAMS_PORTA clk85m_brams; net clk_85m tnm = BRAMS_PORTB clk85m_brams;
# Obviously, only one of the following two grouping specs should be picked up for each FIFO; let the implementation tools sort them out. net clk_100b tnm = BRAMS_PORTA clk100b_brams; net clk_100b tnm = BRAMS_PORTB clk100b_brams;
# Select everything attached to each clock. net clk_100a tnm = clk_100a_all; net clk_100b tnm = clk_100b_all; net clk_85m tnm = clk_85m_all;
# Create groups that do not belong by determining what BRAM ports are actually in other clk_groups. timegrp non_100a_brams = clk100b_brams : clk85m_brams; timegrp non_100b_brams = clk100a_brams : clk85m_brams; timegrp non_85m_brams = clk100a_brams : clk100b_brams;
# Remove groups that do not belong by excluding BRAM ports that are not in the primary time group. timegrp clk_100a = clk_100a_all except non_100a_brams; timegrp clk_100b = clk_100b_all except non_100b_brams; timegrp clk_85m = clk_85m_all except non_85m_brams;
# Use the normal PERIOD or FROM/TO constraints, using these last three groups : clk_100a, clk_100b and clk_85m.
timespec ts_clk_100a = period 100 MHz; timespec ts_clk_100b = period 100 MHz; timespec ts_clk_85m = period 85 MHz;
This is important for the following reasons:
1. If ports of Block RAMs (or any element) are included in a timing group where they do not belong, it is likely that your timing constraints are not accurate. This is similar to taking 20 flip-flops from your 100-MHz clock domain and putting them into your 10-MHz clock domain.
The timespec priority system usually takes care of this. If this situation occurs, an incorrect constraint might be applied to a path. A path constraint may be more aggressive than necessary and may cause longer runtimes and false timing errors.
The path constraint may also be more conservative than necessary. You may think timing has been successfully met. However, if the part does not work in the lab for an unknown reason, the path constraint may be causing the problem, depending on the order of the constraints in your UCF file.
2. Starting with the 3.1i software, the algorithms used for timing analysis were modified to lower memory usage and speed up run time. This change has some side-effects, most of which relate to set grouping.
Basically, if elements are included that are part of two or more different clock domains, unexpected events can occur; it is best to avoid this situation. To avoid having block RAM ports for more than one set, use the new BRAMS_PORTA and BRAMS_PORTB constraints.