Manejo de relojes inferidos durante la síntesis de RTL

4

Estoy tratando de sintetizar un diseño en VHDL en un FPGA ProASIC3 usando la herramienta Synplify Pro. El informe de síntesis me da la siguiente advertencia sobre los relojes inferidos.

@W:MT420 :  | Found inferred clock counter_unit| pstate_inferred_clock[1] with period 10.00ns. Please declare a user-defined clock on object "n:bcu_ins.ctr_ins.pstate[1]"

Me remonté a la parte del código donde se está generando la advertencia y la misma se reproduce aquí como referencia.

p_fsm_clk : process(reset_n_in, clk_25mhz_in)
begin
    if (reset_n_in = '0') then
        pstate <= s0;
    elsif rising_edge(clk_25mhz_in) then
        pstate <= nstate;
    end if;
end process p_fsm_clk;

p_fsm : process(pstate,restart_ctr,enable_ctr2,sys_fail)
begin
    start_ctr1 <= '0';
    start_ctr2 <= '0';

    case pstate is
        when s0 =>
        --Reset state. All counters are reset
            if (sys_fail = '0' and restart_ctr = '1') then
                nstate <= s1;   --move to start counter1
            else
                nstate <= s0;
            end if;

        when s1 =>
            start_ctr1 <= '1';  --Initiate counter1
            if (restart_ctr = '1') then
            --restart the counters
                start_ctr1 <= '0';  --reset counter1
                nstate <= s1;
            elsif (enable_ctr2 = '1') then
            --move to start counter2
                nstate <= s2;
            else
                nstate <= s1;
            end if;

        when s2 =>
        --Save the counter1 value and start counter2
            start_ctr2 <= '1';  --assert flag to start counter2
            if (restart_ctr = '1') then
            --restart the counters
                nstate <= s1;
            else
                nstate <= s3;
            end if;

        when s3 =>
            start_ctr2 <= '1';
            if (sys_fail = '1') then
                nstate <= s0;
            elsif (restart_ctr = '1') then
            --restart the counters
                nstate <= s1;
            else
                nstate <= s3;
            end if;

        when others =>
            nstate <= s0;

    end case;
end process p_fsm;

--counter1
p_ctr1 : process(reset_n_in, clk_25mhz_in)
begin
    if (reset_n_in = '0') then
        ctr1 <= 0;  --value on reset
    elsif rising_edge(clk_25mhz_in) then
        if (start_ctr1 = '1') then
        --flag is asserted to start counter1
            ctr1 <= ctr1 + 1;   --increment counter
        else
        --flag de-asserted
            ctr1 <= 0;  --reset the counter
        end if;
    end if;
end process p_offset_cnt;

--save the value of counter1
offset_val <= ctr1 when pstate = s2;

La lógica contiene dos contadores: ctr1 y ctr2 . Los contadores se ejecutan cuando no hay fallas en el sistema. En la primera fase se ejecuta ctr1 , seguido de ctr2 . ctr1 deja de contar cuando ctr2 está habilitado. El valor de ctr1 determina cuánto más tarde se iniciará ctr2 (en términos de un período de reloj de 25MHz), denominado compensación. Este valor de compensación se almacena en un vector de señal, como se puede ver en la última línea del código. El estado s2 se utiliza para capturar el valor de ctr1 antes de restablecerse a 0.

offset_val <= ctr1 when pstate = s2;

Me di cuenta de que esta declaración de asignación está causando el reloj inferido en el diseño (pero no sé por qué). Cuando coloco la misma declaración dentro de un proceso temporizado, la advertencia de reloj inferido desaparece. Sin embargo, mi lógica no funciona correctamente.

Estoy buscando algunas aclaraciones al respecto.

  1. ¿Por qué hay un reloj inferido en pstate [1] en este diseño?
  2. ¿Está bien tener tales declaraciones en el diseño? ¿La presencia de relojes inferidos indica una mala práctica de diseño?
  3. Si no está bien tener relojes inferidos en el diseño, ¿cómo puedo solucionar esto al codificar la lógica de manera diferente?
  4. Si está bien tener relojes inferidos, ¿cómo puedo informarle a la herramienta? ¿Qué período de restricción puedo proporcionar para tales relojes inferidos? ¿Cómo puedo determinar un período significativo para dichos relojes inferidos?
pregunta rvkrysh

1 respuesta

7

Has agregado una etiqueta FPGA , por lo que responderé desde una perspectiva FPGA. Si está creando un ASIC o utilizando algún otro flujo, es posible que se aplique una respuesta diferente.

1. ¿Por qué hay un reloj inferido en pstate[1] en este diseño?

offset_val <= ctr1 when pstate = s2;

Esta línea no describe nada de lo que sucede cuando pstate es no s2 . Esto constituye un pestillo cerrado. En cualquier FPGA que haya usado, esto se implementará mediante la activación de un modo 'pestillo' en un flip flop normal, usando el pin 'reloj' como la 'puerta'. La señal de la puerta en ese punto utiliza el recurso de reloj, pero en última instancia se deriva de otra señal de "datos", en lugar de un reloj "real".

2. ¿Está bien tener tales declaraciones en el diseño? ¿La presencia de relojes inferidos indica una mala práctica de diseño?

Los cierres en general deben evitarse a menos que haya una razón importante para tenerlos, ya que por lo general proporcionan un rendimiento de sincronización deficiente y pueden resultar más peligrosos en el diseño y en las carreras. Un ejemplo en el que deben usarse los pestillos sería si alguna interfaz externa tuviera que usar una entrada sensible al nivel de algún tipo. En su caso, parece que debería ser bastante fácil evitar un pestillo.

3. Si no está bien tener relojes inferidos en el diseño, ¿cómo puedo solucionar esto mediante la codificación de la lógica de manera diferente?

Utilice un proceso cronometrado que contenga la asignación. Esto inferirá un flip-flop para offset_val . Tendría que simular su diseño o probarlo a bordo para asegurarse de que la función es equivalente en su caso particular, pero la filosofía básica en el FPGA debe ser que cualquier asignación que no sea simple a <= b and c; o some_vec <= smaller_vec & another_bit; use una proceso. Hacer esto le dará resultados de tiempo predecibles y facilitará la escritura de restricciones. Hay excepciones, pero este debería ser el punto de partida.

4. Si está bien tener relojes inferidos, ¿cómo puedo informarle a la herramienta? ¿Qué período de restricción puedo proporcionar para tales relojes inferidos? ¿Cómo puedo determinar un período significativo para dichos relojes inferidos?

En el caso de una interfaz externa, la entrada sensible al nivel tendrá un ancho de pulso mínimo, y puede usar esto para crear una restricción de período que constituya el peor caso posible de cómo podría cambiar esa señal. Para cualquier interfaz interna, trabajaría para evitar el bloqueo existente, pero podría aplicarse la misma técnica. Al evitar los pestillos por completo, evita tener que pensar en este tipo de problema.

Además de estos, el diseño de la máquina de estado de dos procesos que se muestra en su código no es necesario. Puede poner toda la máquina y las transiciones de estado en un proceso sincronizado. El proceso resultante sería muy similar al segundo proceso anterior, con todo envuelto en un if (rising_edge(clk)) then y cada aparición de nstate reemplazada con pstate . Debería poder encontrar las respuestas existentes con respecto al diseño de la máquina del estado aquí en EE o más en la etiqueta VHDL de Stack Overflow .

    
respondido por el scary_jeff

Lea otras preguntas en las etiquetas