Spartan-6: el mapa falló debido al uso de un pin que no es de reloj para una instancia de búfer global

Estoy tratando de usar Spartan 6 (TQG144) PLL para generar un reloj de alta velocidad. Usé el generador de núcleo IP para configurar el PLL. Aquí está el código VHDL simple que tengo para usar el componente generado:

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;

y aquí está el archivo UCF:

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;

cuando compilo el código me sale este 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; 

El error dice que estoy usando un PIN que no es de reloj para el clk_o1 y no funciona, sin embargo, según los recursos de reloj de Spartan 6 [1], el PIN 85 es un pin GCLK (probé con diferentes PIN). Me pregunto qué tiene de malo que me salga este error.

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

¿Qué componente declarado es el del PLL que proporcionó IPConfig?
@DKNguyen - es clock_gen
Podría buscar un PLL discreto para esto y hacerlo externamente. Tenga en cuenta, sin embargo, que los FPGA son muy exigentes cuando se trata de sincronización y retraso del reloj. Si tiene un Xtal de 10 MHz -> FPGA + PLL discreto de 100 MHz, luego use el PLL del FPGA para ejecutarlo a 100 MHz, luego intente "hablar" entre algún otro dispositivo y el FPGA, podría terminar con problemas de metaestabilidad. Hay maneras de evitar eso, investigación FPGA metastability.

Respuestas (3)

La señal del reloj va a todas partes en el FPGA, por lo que requiere consideraciones especiales de fanout y debe llegar a todos sus destinos con un sesgo mínimo. Eso significa que no puede enrutar relojes a través de un tejido lógico regular o a través de cualquier pin en el FPGA. El reloj solo puede entrar en pines dedicados a él y solo puede enrutarse en el FPGA en redes de distribución de reloj especiales.

El problema con su código es que solo está tratando el reloj como cualquier señal normal anterior en cualquier pin normal anterior. No puedes hacer eso. No puede leer la señal del reloj y escribirla directamente en un pin. El software quiere mantener las señales del reloj aisladas en la red de distribución del reloj y leer el reloj en un pin rompe eso.

Si desea generar la señal del reloj en un pin normal, deberá hacer algo como

if arista_borde(Reloj) entonces SomePin <=no SomePin;

Pero esto no será muy bueno por las razones que mencioné anteriormente. Aunque puedes intentarlo. Pero puede obtener mejores resultados escribiendo un contador que cuente con el reloj y solo emita o cambie cada n ciclos de reloj. Sin embargo, solo haga esto para verificar que el PLL esté funcionando. No intentes esto para registrar algo externamente.

El mensaje de error es en realidad mucho más explícito que la mayoría. Incluso te dice cómo anularlo. Pero la parte importante es la recomendación justo antes de la anulación que le indica cómo obtener una señal de reloj fuera del chip. Parece decir que debe crear una instancia de un componente ODDR2 y usar su objeto Clock Forwarding en el configurador de IP y usarlo para sacar la señal del reloj del chip. Probablemente esté destinado a sincronizar la SDRAM externa. Esa parece ser la forma correcta de hacerlo si realmente desea proporcionar una señal de reloj externa en lugar de simplemente verificar que el PLL esté funcionando.

gracias por la respuesta. ¿Cómo puedo arreglarlo?
El reloj debe colocarse en un pin específico en el FPGA que está conectado a redes de distribución de reloj dedicadas. Entonces, nunca podrá enrutar una señal de reloj a una señal de otro tipo. Las palabras clave especiales como riseing_edge() le dicen al software que se trata de una señal de reloj y la enrutará en una red dedicada. También significa que no puede emitir directamente una señal de reloj en un pin normal (no estoy seguro de si hay pines especiales que puedan emitir la señal de reloj porque nunca he necesitado hacerlo).
Si desea generar la señal del reloj en un pin normal, deberá hacer algo como si rise_edge (Reloj) y luego SomePin <= not SomePin. No puede leer directamente el reloj y escribirlo en una salida. Pero esto no será muy bueno por las razones que mencioné anteriormente. Aunque puedes intentarlo. Pero puede obtener mejores resultados usando un contador que cuente con el reloj y solo emita un pulso o cambie un pulso de 1000 ciclos de reloj o algo así.
Esto es lo que quise decir con pin GCLK. El documento al que hice referencia, página 25, enumera los pines que se pueden usar para el reloj.
@Sina Es posible que el pin no pueda generar un reloj. Mencioné anteriormente que no estaba seguro de si los pines del reloj realmente pueden generar un reloj y parece que no puede. El software quiere mantener las señales de reloj en la red de reloj dedicada de forma predeterminada. El punto es que está tratando de conectar una señal de reloj en la red de distribución de reloj dedicada a algo fuera de ella. Si es posible emitir directamente el reloj, es una función dedicada que no he usado ni oído hablar. Puedo ver casos en los que es posible que desee que el reloj FPGA controle otras cosas, pero nunca lo he usado si está allí.
@Sina El mensaje de error en realidad parece explicar todo y cómo solucionarlo si realmente lo necesita. Parece que necesita hacer un objeto Clock Forward desde la configuración de IP para obtener la señal del reloj fuera del chip correctamente. No se salte la primera mitad del mensaje de error.
¿Quieres decir "CLOCK_DEDICATED_ROUTE = FALSO"? Si es así, el sitio web oficial de Xilinx dice que podría causar muchos problemas de tiempo.
@Sina Bueno, sí. Como he estado describiendo, hay problemas con él si simplemente lo anula directamente y lo fuerza. Pero esa no es la parte del mensaje de error que estoy mirando.

Los pines de reloj en el FPGA son para entradas de reloj , no para salidas. Tienen rutas bien caracterizadas a recursos de reloj interno, como PLL, DCM y los búferes para árboles de reloj.

Los árboles de reloj en sí mismos se enrutan a la mayoría de los dispositivos con reloj en el chip, principalmente los FF en la estructura y en las IOB. En general, NO hay ninguna forma de conectar un árbol de reloj directamente a ningún otro tipo de red dentro del chip, incluidas las entradas a los controladores de pines. Esto es a propósito: mantiene equilibrada la carga en el árbol del reloj para que todos los dispositivos dentro del chip obtengan el reloj con la misma cantidad de retraso (desviación mínima del reloj).

Es por eso que le dicen que use la técnica ODDR2: la ruta desde el árbol del reloj hasta los FF de IOB está bien caracterizada, al igual que la ruta desde esos FF hasta el pin mismo. De hecho, está sintetizando una copia del reloj que sacará del chip, y el retraso entre el original y la copia está estrictamente controlado.

Gracias por toda tu ayuda. ¡Así que la técnica ODDR2 era el camino a seguir! Aquí [1] puede encontrar cómo usar este componente para reenviar la señal del reloj.

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