4
\$\begingroup\$

I'm trying to use Spartan 6 (TQG144) PLL to generate a high speed clock. I used IP core generator to config the PLL. Here is the simple VHDL code I have to use the generated component:

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity clk_test is
    Port (
     clk_o1: out STD_LOGIC;
     clk: in STD_LOGIC
    );
end clk_test;
architecture Behavioral of clk_test is

component clock_gen
port
 (
  CLK_IN1           : in     std_logic;
  CLK_OUT1          : out    std_logic
 );
end component;

begin
    clock: clock_gen port map(
        CLK_IN1 => clk,
        CLK_OUT1 => clk_o1);

end Behavioral;

and here is the UCF file:

NET "clk" TNM_NET = clk;
TIMESPEC TS_clk = PERIOD "clk" 50 MHz HIGH 50%;
NET "clk" LOC = P56 | IOSTANDARD = LVTTL;
NET "clk_o1" LOC = P85 | IOSTANDARD = LVTTL;

when I compile the code, I get this error:

Phase 2.7  Design Feasibility Check
ERROR:Place:1205 - This design contains a global buffer instance,
   <clock/clkout1_buf>, driving the net, <clk_o1_OBUF>, that is driving the
   following (first 30) non-clock load pins off chip.
   < PIN: clk_o1.O; >
   This design practice, in Spartan-6, can lead to an unroutable situation due
   to limitations in the global routing. If the design does route there may be
   excessive delay or skew on this net. It is recommended to use a Clock
   Forwarding technique to create a reliable and repeatable low skew solution:
   instantiate an ODDR2 component; tie the .D0 pin to Logic1; tie the .D1 pin to
   Logic0; tie the clock net to be forwarded to .C0; tie the inverted clock to
   .C1. If you wish to override this recommendation, you may use the
   CLOCK_DEDICATED_ROUTE constraint (given below) in the .ucf file to demote
   this message to a WARNING and allow your design to continue. Although the net
   may still not route, you will be able to analyze the failure in FPGA_Editor.
   < PIN "clock/clkout1_buf.O" CLOCK_DEDICATED_ROUTE = FALSE; >

ERROR:Place:1136 - This design contains a global buffer instance,
   <clock/clkout1_buf>, driving the net, <clk_o1_OBUF>, that is driving the
   following (first 30) non-clock load pins.
   < PIN: clk_o1.O; >
   This is not a recommended design practice in Spartan-6 due to limitations in
   the global routing that may cause excessive delay, skew or unroutable
   situations.  It is recommended to only use a BUFG resource to drive clock
   loads. If you wish to override this recommendation, you may use the
   CLOCK_DEDICATED_ROUTE constraint (given below) in the .ucf file to demote
   this message to a WARNING and allow your design to continue.
   < PIN "clock/clkout1_buf.O" CLOCK_DEDICATED_ROUTE = FALSE; 

The error says I'm using a non-clock PIN for the clk_o1, and it doesn't work, however, based on the Spartan 6 clocking resources [1] PIN 85 is a GCLK pin (I tried different PINs). I wonder what is wrong that I get this error?

[1] https://www.xilinx.com/support/documentation/user_guides/ug382.pdf#page=25

\$\endgroup\$
3
  • \$\begingroup\$ Which component declared is the one for the PLL that the IPConfig provided? \$\endgroup\$
    – DKNguyen
    Jan 25 at 22:39
  • \$\begingroup\$ @DKNguyen - it's clock_gen \$\endgroup\$
    – Sina
    Jan 25 at 22:40
  • \$\begingroup\$ You could look at a discrete PLL for this and do it externally. Note however, that FPGA's are very picky when it comes to clock delay and synchronization. If you have a 10MHz Xtal --> FPGA + discrete 100MHz PLL, then use the FPGA's PLL to run that at 100MHz, then try to "talk" between some other device and the FPGA, you could end up with metastability issues. There are ways around that, research FPGA metastability. \$\endgroup\$
    – rdtsc
    Jan 25 at 22:56

3 Answers 3

5
\$\begingroup\$

Clock signal go everywhere on the FPGA so require special fanout considerations and and must arrive at all their destinations with minimal skew. That means you cannot route clocks through regular logic fabric or through any pin on the FPGA. The clock can only go into pins dedicated to it and can only be routed on the FPGA on special clock distribution networks.

The problem with your code is you are just treating the clock as any old regular signal on any old regular pin. You can't do that. You can't read the clock signal and directly write it to a pin. The software wants to keep the clock signals isolated on the clock distribution network and reading the clock to a pin breaks that.

If you want to output the clock signal on a regular pin you will need to do something like

if rising_edge(Clock) then SomePin <=not SomePin;

But this won't be very good for the reasons I mentioned above. You can try it though. But you may get better results writing a counter that counts on the clock and only outputs or toggles every n clock cycles. Only do this to verify the PLL is working though. Don't try this to actually clock something externally.

The error message is actually far more explicit than most. It even tells you how to override it. But the important part is the recommendation just before the override which tells you how to get a clock signal off chip. It seems to say you should instantiate an ODDR2 component and use its Clock Forwarding object in the IP configurator and use that to get your clock signal off chip. It's probably intended to clock external SDRAM. That sounds like the proper way to do it if you truly want to provide an external clock signal rather than just verifying the PLL is working.

\$\endgroup\$
8
  • \$\begingroup\$ thanks for the answer. how can I fix it? \$\endgroup\$
    – Sina
    Jan 25 at 22:39
  • \$\begingroup\$ The clock has to be put into specific pin on the FPGA that are connected to dedicated clock distribution networks. Then you can't ever route a clock signal into a signal of another type. Special keywords like rising_edge() tell the software that this is a clock signal and it will route it on a dedicated network. It also means you can't directly output a clock signal on a regular pin (I am not sure if there are special pins that can output the clock signal because I have never needed to do it). \$\endgroup\$
    – DKNguyen
    Jan 25 at 22:43
  • \$\begingroup\$ If you want to output the clock signal on a regular pin you will need to do something like if rising_edge(Clock) then SomePin <=not SomePin. You can't directly read the clock and write it to an output. But this won't be very good for the reasons I mentioned above. You can try it though. But you may get better results using a counter that counts on the clock and only outputs a pulse or toggles a pulse 1000 clock cycles or something like that. \$\endgroup\$
    – DKNguyen
    Jan 25 at 22:44
  • 1
    \$\begingroup\$ @Sina The error message actually seems to explain everything and how to work around it if you really need it. Looks like you need to make a Clock Forward object from the IP config to get the clock signal off chip properly. Don't just skip the first half of the error message. \$\endgroup\$
    – DKNguyen
    Jan 25 at 22:52
  • 1
    \$\begingroup\$ @Sina Well, yeah. Like I have been describing there are problems with it if you just directly override it and force it out. But that's not the part of the error message I am looking at. \$\endgroup\$
    – DKNguyen
    Jan 25 at 22:54
5
\$\begingroup\$

Clock pins on the FPGA are for clock inputs, not outputs. They have well-characterized paths to internal clock resources, such as PLLs, DCMs and the buffers for clock trees.

The clock trees themselves are routed to most of the clockable devices on the chip, mostly the FFs in the fabric and in the IOBs. There is NOT, in general, any way to connect a clock tree directly to any other kind of net within the chip — including the inputs to pin drivers. This is on purpose — it keeps the loading on the clock tree balanced so that all devices within the chip get the clock with the same amount of delay (minimal clock skew).

That's why they tell you to use the ODDR2 technique — the path from the clock tree to the IOB FFs is well-characterized, as is the path from those FFs to the pin itself. You are in effect synthesizing a copy of the clock that you will drive off-chip, and the delay between the original and the copy is tightly controlled.

\$\endgroup\$
0
\$\begingroup\$

Thank you all for your help. So the ODDR2 technique was the way to go! Here [1] you can find how to use this component to forward clock signal.

[1] https://www.mikrocontroller.net/topic/354717

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.