¿Es una buena práctica asignar clk a una señal antes de la instanciación de componentes en FPGA?

1

Estoy trabajando con VHDL para los FPGA de Xilinx y estoy tratando de crear algunos componentes jerárquicos. Al crear una instancia de un componente B dentro de otro componente A, ¿qué clk se espera que pase al componente B, una referencia directa al puerto de entrada clk o es una mala práctica asignarlo a una señal antes?

Por la simulación, puedo adivinar que asignar el clk a una señal antes puede agregar algo de retraso, lo que me hace pensar que este es un truco válido o podría agregar algún comportamiento inesperado al sistema.

Aquí hay algunas operaciones ficticias sobre un std_logic_vector, por ejemplo. Creé un componente simple y un componente combinado que usa dos componentes simples. Comparé el comportamiento del componente simple solo y el componente combo en una simulación. Además, en la parte inferior se muestra la diferencia entre asignar o no el clk a una señal durante la simulación.

library ieee;                                                                                                                                
use ieee.std_logic_1164.all;                                                                                                                 
use ieee.numeric_std.ALL;                                                                                                                   

entity SimpleComponent is                                                                                                                    
    generic(                                                                                                                                 
        SC_IN_SIZE : NATURAL := 10                                                                                                           
    );                                                                                                                                       
    port(                                                                                                                                    
        in_clk  : in  std_logic := '0';                                                                                                      
        in_data : in  std_logic_vector(SC_IN_SIZE - 1 downto 0);                                                                             
        out_op  : out std_logic_vector(SC_IN_SIZE - 1 downto 0)                                                                              
    );                                                                                                                                       
end entity;                                                                                                                                  

architecture RTL of SimpleComponent is                                                                                                       

begin                                                                                                                                        

    COUNT_BITS : process(in_clk) is                                                                                                          
    begin                                                                                                                                    
        if rising_edge(in_clk) then                                                                                                          

            out_op <= not in_data;                                                                                                           

        end if;                                                                                                                              
    end process COUNT_BITS;                                                                                                                  

end architecture RTL;                                                                                                                        

Aquí viene el componente combinado (note las líneas marcadas 59 y 60):

library ieee;                                                                                                                                
use ieee.std_logic_1164.all;                                                                                                                 
use ieee.numeric_std.all;                                                                                                                    

entity ComboComponent is                                                                                                                     
    generic(                                                                                                                                 
        CB_IN_SIZE : natural := 10;                                                                                                          
        COMB       : natural := 2                                                                                                            
    );                                                                                                                                       
    port(                                                                                                                                    
        in_clk  : in  std_logic                                 := '0';                                                                      
        in_data : in  std_logic_vector(CB_IN_SIZE - 1 downto 0) := (others => '0');                                                          
        out_op  : out std_logic_vector(CB_IN_SIZE - 1 downto 0) := (others => '0')                                                           
    );                                                                                                                                       
end entity ComboComponent;                                                                                                                   

architecture RTL of ComboComponent is                                                                                                        

    constant SPLITED_BITS : natural := CB_IN_SIZE / COMB;                                                                                    

    component SimpleComponent                                                                                                                
        generic(                                                                                                                             
            SC_IN_SIZE : NATURAL := SPLITED_BITS                                                                                             
        );                                                                                                                                   
        port(                                                                                                                                
            in_clk  : in  std_logic;                                                                                                         
            in_data : in  std_logic_vector(SPLITED_BITS - 1 downto 0) := (others => '0');                                                    
            out_op  : out std_logic_vector(SPLITED_BITS - 1 downto 0) := (others => '0')                                                     
        );                                                                                                                                   
    end component SimpleComponent;                                                                                                           

    type TY_SPLIT is array (COMB - 1 downto 0) of std_logic_vector(SPLITED_BITS - 1 downto 0);                                               

    signal SN_SPLIT_IN  : TY_SPLIT := (others => (others => '0'));                                                                           
    signal SN_SPLIT_OUT : TY_SPLIT := (others => (others => '0'));                                                                           

    signal SN_in_clk : std_logic := '0';                                                                                                     

begin                                                                                                                                        

    SN_in_clk <= in_clk;                                                                                                                     

    GEN_COMP : for I in COMB - 1 downto 0 generate                                                                                           

        GEN_SPLIT_BITS : for B in SPLITED_BITS - 1 downto 0 generate                                                                         

            SN_SPLIT_IN(I)(B)            <= in_data(SPLITED_BITS * I + B);                                                                   
            out_op(SPLITED_BITS * I + B) <= SN_SPLIT_OUT(I)(B);                                                                              

        end generate;                                                                                                                        

        SC_I : component SimpleComponent                                                                                                     
            port map(                                                                                                                        
                in_clk  => in_clk, --LINE 59                                                                                                 
--              in_clk  => SN_in_clk, --LINE 60                                                                                              
                in_data => SN_SPLIT_IN(I),                                                                                                   
                out_op  => SN_SPLIT_OUT(I)                                                                                                   
            );                                                                                                                               
    end generate;                                                                                                                            
end architecture RTL;                                                                                                                        

Banco de pruebas:

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity ComboComponentSim is
    generic(
        CB_IN_SIZE : natural := 20;
        COMB       : natural := 2
    );
end entity ComboComponentSim;

architecture RTL of ComboComponentSim is

    constant SPLITED_BITS : natural := CB_IN_SIZE / COMB;

    component SimpleComponent
        generic(
            SC_IN_SIZE : NATURAL := SPLITED_BITS
        );
        port(
            in_clk  : in  std_logic;
            in_data : in  std_logic_vector(SPLITED_BITS - 1 downto 0) := (others => '0');
            out_op  : out std_logic_vector(SPLITED_BITS - 1 downto 0) := (others => '0')
        );
    end component SimpleComponent;

    component ComboComponent
        generic(
            CB_IN_SIZE : natural := CB_IN_SIZE;
            COMB       : natural := COMB
        );
        port(
            in_clk  : in  std_logic;
            in_data : in  std_logic_vector(CB_IN_SIZE - 1 downto 0) := (others => '0');
            out_op  : out std_logic_vector(CB_IN_SIZE - 1 downto 0) := (others => '0')
        );
    end component ComboComponent;

    signal in_clk    : std_logic                                   := '0';
    signal in_dataCC : std_logic_vector(CB_IN_SIZE - 1 downto 0)   := (others => '0');
    signal in_dataSC : std_logic_vector(SPLITED_BITS - 1 downto 0) := (others => '0');
    signal out_opCC  : std_logic_vector(CB_IN_SIZE - 1 downto 0)   := (others => '0');
    signal out_opSC  : std_logic_vector(SPLITED_BITS - 1 downto 0) := (others => '0');

begin
    CC : component ComboComponent
        port map(
            in_clk  => in_clk,
            in_data => in_dataCC,
            out_op  => out_opCC
        );

    SC : component SimpleComponent
        port map(
            in_clk  => in_clk,
            in_data => in_dataSC,
            out_op  => out_opSC
        );
    stimuls : process
        variable tmp : std_logic_vector(SPLITED_BITS - 1 downto 0) := (others => '0');
    begin
        wait for 5 ns;

        tmp       := "0000000001";
        in_dataSC <= tmp;
        in_dataCC <= tmp & tmp;
        in_clk    <= '1';

        wait for 5 ns;
        in_clk <= '0';
        wait for 5 ns;

        tmp       := "0000000010";
        in_dataSC <= tmp;
        in_dataCC <= tmp & tmp;
        in_clk    <= '1';

        wait for 5 ns;
        in_clk <= '0';
        wait for 5 ns;

        tmp       := "0000000100";
        in_dataSC <= tmp;
        in_dataCC <= tmp & tmp;
        in_clk    <= '1';

        wait for 5 ns;
        in_clk <= '0';

    end process;
end architecture RTL;

Pasando la referencia del puerto clk a la creación de instancias de componente (línea 60 comentada):

Asignarelclkaunaseñalypasarlaseñalalainstanciacióndecomponente(LÍNEA59comentó):

La asignación de clk a una señal me da el comportamiento que quería, pero creo que estoy rompiendo el sincronismo de clk a lo largo del sistema, ya que está agregando un retraso desconocido (al menos desconocido para mí) a clks en algunos componentes . ¿Es este un problema real?

    
pregunta markcfsousa

1 respuesta

0

Cada elemento en el hardware real tiene un retardo, un retardo de cableado o un retardo de puerta lógica. Cada FF se voltea con un cierto retardo después de que se aplica el borde del reloj, lo que se denomina "TCQ", el reloj con el retardo "Q". Sin embargo, en simulaciones de comportamiento simplificadas, este retardo a menudo se descuida en la herramienta de síntesis. Como resultado, la simulación de comportamiento mostraría un giro instantáneo de todos los bits en un registro con borde de reloj. Esto podría crear algunos estados falsos e inesperados si el diseño no se realiza correctamente. Después del mapa y la ruta realistas, cuando todos los retrasos son realísticamente anotados, el comportamiento puede ser diferente. El ejemplo más notorio es un contador asincrónico de "ondulación", donde el simple hecho de TCQ crea transiciones de estado feo, que se verían como transiciones simultáneas en simulaciones de comportamiento simples.

Para evitar el comportamiento falso en las simulaciones de primera ronda, se recomienda incluir retrasos explícitos (pequeños, arbitrarios) en todos los modelos / declaraciones VHDL de reloj a flop. Entonces, las simulaciones de comportamiento no serán diferentes de las anotaciones anteriores.

    
respondido por el Ale..chenski

Lea otras preguntas en las etiquetas