Author Topic: Spartan-6 DCM_CLKGEN -- unexpected derived timing constraints  (Read 1111 times)

0 Members and 1 Guest are viewing this topic.

Offline ebastlerTopic starter

  • Super Contributor
  • ***
  • Posts: 6856
  • Country: de
As discussed in another thread here, I have been spending too much time staring at Xilinx timing reports lately... (https://www.eevblog.com/forum/fpga/xilinx-ise-how-to-improve-erratic-timing-optimization/ -- many thanks again for all your helpful comments there!) During that effort, I noticed an unexpected constraint which the timing analysis derives.

I am using a DCM_CLKGEN primitive to generate my 100 MHz main clock from the 25 MHz external clock input. (I chose DCM_CLKGEN for its low power consumption compared to a PLL, and lower output jitter compared to DCM_SP.)

Code: [Select]
 
dcm_clkgen_inst: DCM_CLKGEN
  generic map
   (CLKFXDV_DIVIDE        => 2,
    CLKFX_DIVIDE          => 1,
    CLKFX_MULTIPLY        => 4,
    SPREAD_SPECTRUM       => "NONE",
    STARTUP_WAIT          => FALSE,
    CLKIN_PERIOD          => 40.0,
    CLKFX_MD_MAX          => 0.000)
  port map
   -- Input clock
   (CLKIN                 => clkin1,
    -- Output clocks
    CLKFX                 => clkfx,
    CLKFX180              => clkfx180_unused,
    CLKFXDV               => clkfxdv_unused,
   -- Ports for dynamic phase shift
    PROGCLK               => '0',
    PROGEN                => '0',
    PROGDATA              => '0',
    PROGDONE              => progdone_unused,
   -- Other control and status signals
    FREEZEDCM             => '0',
    LOCKED                => locked_internal,
    STATUS                => status_internal,
    RST                   => '0');

The output frequency on CLKFX is the input frequency multiplied by 4, plain and simple. But the timing analysis thinks it needs to deal with a frequency multipled by 16, the square of the actual multiplier:

Code: [Select]
Timing constraint: PERIOD analysis for net "clock_main_inst/clkfx" derived from
 NET "clk_i_IBUF" PERIOD = 40 ns HIGH 50%;  divided by 16.00 to 2.500 nS and
duty cycle corrected to HIGH 1.250 nS

Likewise, I generate an 48 MHz USB clock by another DCM_CLKGEN. The real multiplier is 48/25 = 1.92, but the timing analysis looks at a period divided by 1.922 = 3.69:

Code: [Select]
Timing constraint: PERIOD analysis for net "clock_usb_inst/clkfx" derived from 
NET "clk_i_IBUF" PERIOD = 40 ns HIGH 50%; divided by 3.69 to 10.851 nS and
duty cycle corrected to HIGH 5.425 nS

Unless I "overrule" these derived constraints by manually setting period constraints for the 100 MHz and 48 MHz clocks, they are carried forward through the full timing analysis of the design. Setting the manual constraints is easy, of course, but I would like to understand what's going on here...

So what gives?! Is this a plain old bug, or is something really happening at that fast rate? (Maybe some feedback mechanism -- although the DCM_CLKGEN mode does not really support that?) Or am I doing something wrong? (The most likely cause...  ;))  Thanks for your insights!
 

Offline dnotq

  • Contributor
  • Posts: 38
  • Country: us
Re: Spartan-6 DCM_CLKGEN -- unexpected derived timing constraints
« Reply #1 on: July 01, 2020, 10:08:32 am »
I too have spent too many hours lately fussing with Xilinx DCM / PLL clocking.  I always use the Core Generator to get the HDL file created quickly, then modify it if necessary.  What I notice about the code you have below is, you don't have any of the "attributes" that the Core Generator produces.

I believe those attributes auto-generate the constraints, and if you don't have the attributes, you need to add the constraints manually.  I don't think the tools look at that actual inputs to the primitive to determine the timing constraints for the design.

I have not tested this, however I was in a situation the other night where ISE was blowing an error that my clock period of 24.444ns did not meet the actual period of 24.4444444ns.  It was very frustrating.  The 24.444 was the "CLKIN_PERIOD" of the primitive (and put there by the Core Generator), but the 24.4444444 was a *calculated* value that was part of timing constraints that were auto-generated during synthesis and used in the mapping or place-and-route.

Even if I changed the 24.444 to 24.4444444 in the primitive, it still bitched about a mis-match (the calculated value being compared is certainly held internally in a float or double, and the text converted to a value would never match exactly).  I even tried manually adding the correct period as a timing constraints in my UCF file, but ISE then warned me that my manual constraints were being ignored due to the auto-generated constraints that were defined during synthesis.

The only thing I could come up with was that those "attributes" were the cause of the auto-constraints, but I did not bother to test that.  I commented out the "CLKIN_PERIOD" parameter, the warning went away, and the timing analysis had the correct values.  I think you need to add the attributes.

Here is the section of my PLL primitive I was fighting with.  Note, I broke the attributes line for posting in the forum.  In the HDL file, it is one long line.

Code: [Select]
architecture xilinx of clk_21m48 is
  attribute CORE_GENERATION_INFO : string;
  attribute CORE_GENERATION_INFO of xilinx : architecture is "clk_21m48,clk_wiz_v3_6,
{component_name=clk_21m48,use_phase_alignment=true,use_min_o_jitter=false,
use_max_i_jitter=false,use_dyn_phase_shift=false,use_inclk_switchover=false,
use_dyn_reconfig=false,feedback_source=FDBK_AUTO,primtype_sel=DCM_SP,
num_out_clk=1,clkin1_period=24.444,clkin2_period=24.444,use_power_down=false,
use_reset=false,use_locked=false,use_inclk_stopped=false,use_status=false,
use_freeze=false,use_clk_valid=false,feedback_type=SINGLE,clock_mgr_type=AUTO,
manual_override=false}";
  -- Input clock buffering / unused connectors
  signal clkin1            : std_logic;
  -- Output clock buffering
  signal clkfb             : std_logic;
  signal clk0              : std_logic;
  signal clkfx             : std_logic;
  signal clkfbout          : std_logic;
  signal locked_internal   : std_logic;
  signal status_internal   : std_logic_vector(7 downto 0);
begin

  -- Input buffering
  --------------------------------------
  clkin1 <= clk_40m909_i;

  -- Clocking primitive
  --------------------------------------

  -- Instantiation of the DCM primitive
  --    * Unused inputs are tied off
  --    * Unused outputs are labeled unused
  dcm_sp_inst: DCM_SP
  generic map
   (CLKDV_DIVIDE          => 2.000,
    CLKFX_DIVIDE          => 20,
    CLKFX_MULTIPLY        => 21,
    CLKIN_DIVIDE_BY_2     => TRUE,
    -- Having this defined causes a warning due to a synthesizer rounding error
    -- since it *calculates* the period and generates constraints that cannot be
    -- overridden by a user constraint in the UCF file.  Stupid.
    --CLKIN_PERIOD          => 24.444,
    CLKOUT_PHASE_SHIFT    => "NONE",
    CLK_FEEDBACK          => "1X",
    DESKEW_ADJUST         => "SYSTEM_SYNCHRONOUS",
    PHASE_SHIFT           => 0,
    STARTUP_WAIT          => FALSE)
  port map
   -- Input clock
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf