cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
Observer
Observer
2,140 Views
Registered: ‎08-04-2017

Set correct capture clock for sending SDR data

Jump to solution

Hi,

I am using Vivado 2016.4 with an Artix 100T speed grade -1 (Nexys 4 DDR board) FPGA. It is driven by a 100MHz clock, which is then MMCM'd to 200Mhz, and is then used to host the following trivial design (the VHDL may make for easier reading):

 

The 200Mhz clock ("ddr2_clk") directly drives a counter of range 0 to 8, which emits '1' to the D pin of the output FF when it is 8 and '0' otherwise. The output of the FF is connected to an external pin "ddr2_addr". "ddr2_clk" drives this FF, and also connects to a pair of output differential pins "ddr2_clk_p" and "ddr2_clk_n", which an external device then uses to capture the data present on "ddr2_addr".

 

It fails timing due to what I perceive to be an incorrect capture clock path. The clock is source synchronous.

The complete and reproducible VHDL design and constraints file are as follows:

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

library UNISIM;
use UNISIM.VComponents.all;

entity synth_ddr2_address_output_ff is
    port (
        ddr2_addr: out std_logic;
        ddr2_clk_p: out std_logic;
        ddr2_clk_n: out std_logic;
        sysclk: in std_logic
    );
end synth_ddr2_address_output_ff;

architecture Behavioral of synth_ddr2_address_output_ff is
    component ddr2_clkgen is
        port (
            clk: in std_logic;
            q: out std_logic
        );
    end component;

    signal ddr2_clk: std_logic;
    
    signal address_d: std_logic;
    signal ctr: natural range 0 to 8 := 0;
begin
    clkgen: ddr2_clkgen
    port map (
        clk => sysclk,
        q => ddr2_clk
    );

    OBUFDS_inst : OBUFDS
    generic map (
        IOSTANDARD => "SSTL18_II", -- Specify the output I/O standard
        SLEW => "FAST") -- Specify the output slew rate
    port map (
        O => ddr2_clk_p, -- Diff_p output (connect directly to top-level port)
        OB => ddr2_clk_n, -- Diff_n output (connect directly to top-level port)
        I => ddr2_clk -- Buffer input
    );

    ff_proc: process (ddr2_clk)
    begin
        if rising_edge(ddr2_clk) then
            ddr2_addr <= address_d;
        end if;
    end process;

    address_d <= '1' when ctr = 8 else '0';

    testpattern: process (ddr2_clk)
    begin
        if rising_edge(ddr2_clk) then
            if ctr = 8 then
                ctr <= 0;
            else
                ctr <= ctr + 1;
            end if;
        end if;
    end process;

end Behavioral;

XDC constraints file:

# bank voltage configuration
set_property INTERNAL_VREF 0.9 [get_iobanks 34]
set_property CFGBVS GND [current_design]
set_property CONFIG_VOLTAGE 1.8 [current_design]

# define ports
set_property -dict {PACKAGE_PIN E3 IOSTANDARD LVCMOS33} [get_ports sysclk]
set_property -dict {PACKAGE_PIN M4 IOSTANDARD SSTL18_II SLEW FAST} [get_ports ddr2_addr]
set_property -dict {PACKAGE_PIN L6 IOSTANDARD DIFF_SSTL18_II SLEW FAST} [get_ports ddr2_clk_p]
set_property -dict {PACKAGE_PIN L5 IOSTANDARD DIFF_SSTL18_II SLEW FAST} [get_ports ddr2_clk_n]

# define clocks
create_clock -period 10.000 -name sysclk_pin -waveform {0.000 5.000} -add [get_ports sysclk]

set_output_delay -clock [get_clocks -of_objects [get_pins clkgen/MMCME2_ADV_inst/CLKOUT0]]  -min -add_delay -0.315 [get_ports ddr2_addr]
set_output_delay -clock [get_clocks -of_objects [get_pins clkgen/MMCME2_ADV_inst/CLKOUT0]]  -max -add_delay 0.470 [get_ports ddr2_addr]

The failed path looks as follows:

failedtimingpath.PNG

 

The path in detail:

 

realcaptureclock.PNG

 

The source clock path is shown as expected, going from the source clock to the destination FF (circled far right in red)

 

However, the destination clock path (or "capture clock") is only propagating to the MMCM output pin, which in my understanding is incorrect - it should be considering the path all the way to the FF of the external device, which should mean the path from the source clock all the way to the clk_p/clk_n pins (circled blue) + board trace propagation delay.

 

How do I indicate to Vivado that the launch clock goes to the FF as seen, but the capture clock travels all the way over?

 

0 Kudos
Reply
1 Solution

Accepted Solutions
Guide
Guide
3,063 Views
Registered: ‎01-23-2009

If you are really trying to do this as "source synchronous" then you need to do the source synchronous properly.

 

First, you need to forward your clock out of the system properly. It is not recommended to drive an output signal directly from a clock network - you should mirror the clock out using an ODDR. Instantiate an ODDR (I will call it my_oddr) with the C input being the internal clock and the D1 tied to logic 1 and the D2 tied to logic 0; this will forward your clock without having the clock leave the clock network.

 

Next you have to write output constraints in a source synchronous manner. In a source synchronous system, the timing of the output interface is not related to any internal clock, but to the forwarded clock.

 

To do this, you need to create a generated clock on the forwarded output

 

create_generated_clock -name clk_fwd -source [get_pins my_oddr/C] -divide_by 1 [get_ports ddr2_clk_p]

 

Now define your set_output_delays with respect to this clock - these would be the setup time and negative hold time requirement of the device driven by the forwarded interface

 

set_output_delay -clock clk_fwd <value_max> [get_ports ddr2_addr]

set_output_delay -clock clk_fwd -min <value_min> [get_ports ddr2_addr]

 

Also remove the -add_delay - it is not correct when there is only one set of delays specified...

 

Avrum

View solution in original post

5 Replies
Guide
Guide
3,064 Views
Registered: ‎01-23-2009

If you are really trying to do this as "source synchronous" then you need to do the source synchronous properly.

 

First, you need to forward your clock out of the system properly. It is not recommended to drive an output signal directly from a clock network - you should mirror the clock out using an ODDR. Instantiate an ODDR (I will call it my_oddr) with the C input being the internal clock and the D1 tied to logic 1 and the D2 tied to logic 0; this will forward your clock without having the clock leave the clock network.

 

Next you have to write output constraints in a source synchronous manner. In a source synchronous system, the timing of the output interface is not related to any internal clock, but to the forwarded clock.

 

To do this, you need to create a generated clock on the forwarded output

 

create_generated_clock -name clk_fwd -source [get_pins my_oddr/C] -divide_by 1 [get_ports ddr2_clk_p]

 

Now define your set_output_delays with respect to this clock - these would be the setup time and negative hold time requirement of the device driven by the forwarded interface

 

set_output_delay -clock clk_fwd <value_max> [get_ports ddr2_addr]

set_output_delay -clock clk_fwd -min <value_min> [get_ports ddr2_addr]

 

Also remove the -add_delay - it is not correct when there is only one set of delays specified...

 

Avrum

View solution in original post

Observer
Observer
2,103 Views
Registered: ‎08-04-2017

Thankyou for explaining how to constrain it properly - the design now implements and passes timing.

 

However, there is now a methodology warning, which I am puzzled about:

TIMING-18#1 Warning
Missing input or output delay  
An output delay is missing on ddr2_addr relative to clock(s) VIRTUAL_ddr2_clk
Related violations: <none>

 

Running report_clocks reports that the virtual clock doesn't exist at all:

 

Clock Report

... Clock Period(ns) Waveform(ns) Attributes Sources sysclk_pin 10.000 {0.000 5.000} P {sysclk} clkfbin 10.000 {0.000 5.000} P,G {clkgen/MMCME2_ADV_inst/CLKFBOUT} ddr2_clk 5.000 {0.000 2.500} P,G {clkgen/MMCME2_ADV_inst/CLKOUT0} ==================================================== Generated Clocks ==================================================== Generated Clock : clkfbin Master Source : clkgen/MMCME2_ADV_inst/CLKIN1 Master Clock : sysclk_pin Multiply By : 1 Generated Sources : {clkgen/MMCME2_ADV_inst/CLKFBOUT} Generated Clock : ddr2_clk Master Source : clkgen/MMCME2_ADV_inst/CLKIN1 Master Clock : sysclk_pin Multiply By : 2 Generated Sources : {clkgen/MMCME2_ADV_inst/CLKOUT0}

For reference, the constraints file now looks like this:

 

# bank voltage configuration
set_property INTERNAL_VREF 0.9 [get_iobanks 34]
set_property CFGBVS GND [current_design]
set_property CONFIG_VOLTAGE 1.8 [current_design]

# define ports
set_property -dict {PACKAGE_PIN E3 IOSTANDARD LVCMOS33} [get_ports sysclk]
set_property -dict {PACKAGE_PIN M4 IOSTANDARD SSTL18_II SLEW FAST} [get_ports ddr2_addr]
set_property -dict {PACKAGE_PIN L6 IOSTANDARD DIFF_SSTL18_II SLEW FAST} [get_ports ddr2_clk_p]
set_property -dict {PACKAGE_PIN L5 IOSTANDARD DIFF_SSTL18_II SLEW FAST} [get_ports ddr2_clk_n]

# define clocks
create_clock -period 10.000 -name sysclk_pin -waveform {0.000 5.000} -add [get_ports sysclk]
create_generated_clock -name clk_fwd -source [get_pins my_oddr/C] -divide_by 1 [get_ports ddr2_clk_p]

set_output_delay -clock clk_fwd 0.470 [get_ports ddr2_addr]
set_output_delay -clock clk_fwd -min -0.315 [get_ports ddr2_addr]

Do you know what could be the cause of this?

0 Kudos
Reply
Guide
Guide
2,069 Views
Registered: ‎01-23-2009

Clearly your constraints are not being read in, or are failing when they are read in.

 

If your constraints had worked properly:

  - you would see the new generated clock "clk_fwd" in the Clock Report - it is not there

  - the endpoint ddr2_addr would be constrained by the set_output_delay constraints in your file

 

Look through the log file to see if/when the constraint files are supposed to be read in, and look for any error messages that occur then.

 

Avrum

0 Kudos
Reply
Observer
Observer
2,061 Views
Registered: ‎08-04-2017

I just realized that I forgot to actually use the output of the ODDR primitive. The previous severe warning has gone away, to be replaced by this non-severe one:

 

Ports with no output delay but with a timing clock defined on it or propagating through it (1)
    ddr2_clk_p

 However, judging by this thread the warning can be safely ignored.

0 Kudos
Reply
Guide
Guide
2,046 Views
Registered: ‎01-23-2009

Yes, that warning is expected and is fine.

 

Actually, that particular warning message is new - it used to be reported just as an output with no delay, but they have added the extra check to realize that it has a clock defined on the output - specifically recognizing that it is being used as we are using it.

 

Avrum

0 Kudos
Reply