Problema del reloj con Spartan 6

6

Tengo un divisor de reloj implementado de la siguiente manera:

module sync_out(
  input clk,            // This is the FPGA system clock
  output reg sync       // This is the generated sync signal to be tested
);
  localparam
    SYNC_OUT_CLOCK_RATIO = 20;

  reg [10:0] counter;   // Clock counter reset when reaching CLOCK_RATIO

  initial begin
    counter <= 0;
    sync <= 0;
  end

  always @(posedge clk) begin
    counter <= counter + 1;

    if(counter == SYNC_OUT_CLOCK_RATIO) begin
      counter <= 0;
      sync <= ~sync;
    end
  end
endmodule

Aquí, clk es el reloj principal, y sync es el reloj dividido que sale de la pizarra. Ahora ISE me da el siguiente error:

Place:1136 - This design contains a global buffer instance,
   <clock_deskew_0/BUFG_inst>, driving the net, <clk>, that is driving the
   following (first 30) non-clock load pins.
   < PIN: sync_apbinterface_0/pclk_test_select[15]_AND_253_o4.A4; >
   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_deskew_0/BUFG_inst.O" CLOCK_DEDICATED_ROUTE = FALSE; >

¿Cuál es exactamente el problema aquí y cómo puedo solucionarlo?

    
pregunta Randomblue

3 respuestas

5

Su pin clk está accionando algunos pines que no son de reloj (entradas LUT por su aspecto). Esto es casi siempre una mala idea.

Abra su diseño en el visor de tecnología y observe los "pines de carga que no son de reloj" que figuran en el archivo de registro ( < PIN: sync_apbinterface_0/pclk_test_select[15]_AND_253_o4.A4; > es el primero) y vea si puede averiguar por qué a LUT está utilizando la entrada CLK.

Si resulta que todo está bien y realmente quieres hacer esto, por el motivo que sea, y te alegrarás de justificar eso a un grupo de ingenieros que se está yendo de la cuenta si todo sale mal, puedes apagar el error. como se describe al final del mensaje de error.

    
respondido por el Martin Thompson
7

En general, no deberías escribir separadores como este. Está creando una señal de reloj fuera de lógica que, como ISE le está diciendo, no es una práctica de diseño recomendada. No solo estás consumiendo (a menudo escaso) las redes de enrutamiento de reloj, sino que también puedes terminar con relojes inestables y con fallas a medida que los bloques lógicos se desplazan a su próximo estado.

ejemplos (en VHDL, lo prefiero a Verilog, pero es un ejemplo bastante simple)

por ejemplo 1: cómo NO hacerlo (crear un reloj a partir de salidas lógicas):

signal counter: integer range 0 to 999;
signal slowclk: std_logic;

gen_slowclk: process(clk, rst)
begin
    if rising_edge(clk) then
        if counter = 0 then
            slow_clk <= not slow_clk;
            counter <= counter'high
        else
            counter <= counter - 1;
        end if;
    end if;

    if rst = '1' then
        slow_clk <= '0';
        counter = counter'high;
    end if;
end process;

use_slow_clk: process(slow_clk, rst)
begin
    if rising_edge(slow_clk) then
        -- ...
    end if;

    if reset = '1' then
        -- ...
    end if;
end process;

Esto crea un slow_clk que es 1000 veces más lento que el reloj principal, y luego usa esa señal de slow_clk como la entrada del reloj en otro proceso. Es un ejemplo de cómo no hacer las cosas. Si examinas tu RTL, verás la salida de la lógica en las entradas de reloj de las FF en el proceso use_slow_clk, lo cual es incorrecto.

Lo que deberías estar haciendo es crear habilitaciones de reloj. Conduce toda su lógica con el reloj original (rápido) y luego crea una señal de habilitación de reloj. La mayoría de los FPGA tienen primitivas de flip-flop que tienen entradas de habilitación de reloj, razón por la cual usted diseñaría de esta manera.

por ejemplo 2: Usar el reloj habilita (la forma recomendada):

signal counter: integer range 0 to 999;
signal slow_ce: std_logic;

gen_slow_ce: process(clk, rst)
begin
    if rising_edge(clk) then
        if counter = 0 then
            slow_ce <= '1';
            counter <= counter'high
        else
            slow_ce <= '0';
            counter <= counter - 1;
        end if;
    end if;

    if rst = '1' then
        slow_ce <= '0';
        counter = counter'high;
    end if;
end process;

use_slow_ce: process(clk, rst)
begin
    if rising_edge(clk) then
        if slow_ce = '1' then
            -- ...
        end if;
    end if;

    if reset = '1' then
        -- ...
    end if;
end process;

Si examina la RTL de este tipo de construcción, verá que todas las FF usan la misma señal de reloj, y eso se proporciona en una red de reloj. El sintetizador reconoce el @if slow_ce = '1' agregado y crea una instancia de un FF con un reloj habilitado; esta es una señal que está diseñada para ser controlada con lógica y para bloquear de manera limpia el FF.

En ambos ejemplos, la lógica en @use_slow _ * @ se ejecuta en la misma frecuencia (1/1000 del reloj principal), pero en el segundo caso solo tiene una red de reloj y está haciendo uso del reloj que habilita el presente en su FPGA, lo que lleva a una mejor síntesis, mejores relojes y un cierre de tiempo más fácil. Esto lleva a diseños FPGA más sanos, lo que lleva a felices diseñadores FPGA. :-)

    
respondido por el akohlsmith
3

Quizás haya un problema con las dos asignaciones simultáneas a counter . Mira si cambiar tu bloque always a esto ayuda:

  always @(posedge clk) begin
    if(counter == SYNC_OUT_CLOCK_RATIO) begin
      counter <= 0;
      sync <= ~sync;
    end else begin
      counter <= counter + 1;
    end
  end
    
respondido por el Justin

Lea otras preguntas en las etiquetas