cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
Highlighted
Adventurer
Adventurer
235 Views
Registered: ‎02-20-2017

Hold violation despite large setup slack

Jump to solution

I am encountering a timing failure that seems should be very easy to solve. The simple version of the question:

I have a timing failure at an endpoint. The signal originates in clock domain A (8.4375 MHz) and ends in clock domain B (84.375 MHz). The clocks are synchronous, originating from the same PLL. The endpoint is failing the hold requirement with -1.161ns, but passing setup requirement with 11.588ns of slack. Why can't the router fix this with net delay or adding ZHOLD delay? I have tried phys_opt_design -aggressive_hold_fix and it does nothing. This is the only failing endpoint in the entire design. I even tried forcing some delay in by inserting some combinatorial logic in the path (inverting the signal) and it made no difference. This is Ultrascale platform targeting XCKU035-1FFVA1156C.

 

Details in case more context helps understand what is happening:

I am writing a 5:16 data exchange. This is not an IO interface; all start points and enpoints are internal in synchronous clock domains. The data originates in a 270 MHz clock domain and I want to read it in an 84.375 MHz clock domain. I am writing a simple 5:16 FIFO. I am using a PLL to generate the read clock on CLKOUT0 (84.375 MHz) and a phase reference on CLKOUT1 (8.4375 MHz). The purpose of the phase reference is to reset the read and write pointers to make sure they have the correct respective position to minimize latency while avoiding collisions. I therefore capture the phase reference with a register in both the write clock and read clock domain. That is why the freq of the phase reference is half the greatest common integer divisor of the write and read clocks; both edges of the phase reference will be comfortable captured in the other two domains. The end point in the write clock (270 MHz) domain works just fine. The slower read clock domain is exhibiting the bizarre failure above. Schematic of the design:

jonk_0-1599863420954.png

 
 
 

Path report:

Annotation 2020-09-11 184851.png

Thank you for any input.

0 Kudos
1 Solution

Accepted Solutions
Highlighted
136 Views
Registered: ‎01-22-2015

@jonk 

Thanks for a clear explanation of the problem.

For this discussion, let’s define:

  • CLKX = 8.4375MHz clock
  • CLK10X = 84.375MHz clock

What you are calling “clock sampling” (ie. routing a clock to the data (D) pin of a register) is also called “pulling a clock from the clock tree” – and is discouraged.  I am not sure that Vivado can perform meaningful timing analysis on your clock sampling paths.

However, I understand that your goal is to have a signal, CLKXPH, in the CLK10X clock-domain that tells you the phase (1 or 0) of CLKX.  The following VHDL code snippets show a way to create CLKXPH.  First, a toggle, TOGX, is created in the CLKX domain.  Then, you use TOGX and carefully count clock cycles in the CLK10X domain.

signal TOGX, TOGXP, CLKXPH : std_logic := '0';  
signal CNT1 : integer range 0 to 15 := 0;  

    P1: process(CLKX)
    begin
        if rising_edge(CLKX) then
            TOGX <= not(TOGX);
        end if;
    end process P1;    
    
    P2: process(CLK10X)
    begin
        if rising_edge(CLK10X) then            
            if((CNT1 < 3) or (CNT1 > 7)) then
                CLKXPH <= '1';
            else
                CLKXPH <= '0';
            end if;
            --      
            if(TOGX = TOGXP) then
                CNT1 <= CNT1 + 1;
            else
                CNT1 <= 0;
            end if;
            --
            TOGXP <= TOGX;
        end if;
    end process P2;

Cheers,
Mark

View solution in original post

3 Replies
Highlighted
Adventurer
Adventurer
183 Views
Registered: ‎02-20-2017

Ok I found an easy solution, just phase shift the "phase reference" output of the PLL. I still wonder why the timing engine couldn't solve this with net delay though. Any thoughts?

0 Kudos
Highlighted
137 Views
Registered: ‎01-22-2015

@jonk 

Thanks for a clear explanation of the problem.

For this discussion, let’s define:

  • CLKX = 8.4375MHz clock
  • CLK10X = 84.375MHz clock

What you are calling “clock sampling” (ie. routing a clock to the data (D) pin of a register) is also called “pulling a clock from the clock tree” – and is discouraged.  I am not sure that Vivado can perform meaningful timing analysis on your clock sampling paths.

However, I understand that your goal is to have a signal, CLKXPH, in the CLK10X clock-domain that tells you the phase (1 or 0) of CLKX.  The following VHDL code snippets show a way to create CLKXPH.  First, a toggle, TOGX, is created in the CLKX domain.  Then, you use TOGX and carefully count clock cycles in the CLK10X domain.

signal TOGX, TOGXP, CLKXPH : std_logic := '0';  
signal CNT1 : integer range 0 to 15 := 0;  

    P1: process(CLKX)
    begin
        if rising_edge(CLKX) then
            TOGX <= not(TOGX);
        end if;
    end process P1;    
    
    P2: process(CLK10X)
    begin
        if rising_edge(CLK10X) then            
            if((CNT1 < 3) or (CNT1 > 7)) then
                CLKXPH <= '1';
            else
                CLKXPH <= '0';
            end if;
            --      
            if(TOGX = TOGXP) then
                CNT1 <= CNT1 + 1;
            else
                CNT1 <= 0;
            end if;
            --
            TOGXP <= TOGX;
        end if;
    end process P2;

Cheers,
Mark

View solution in original post

Highlighted
Adventurer
Adventurer
120 Views
Registered: ‎02-20-2017

Ahh thank you for the answer! I didn't realize "clock sampling" was a frowned upon practice. Even though the phase shift solution works, I'd rather implement the proper solution. A toggling register in the slow domain is simple and elegant. Thanks!

0 Kudos