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?