I am working with VHDL for Xilinx FPGAs and I am trying to create some hierarchical components. When instantiating a component B inside another component A, what clk is expected to pass to the component B, a direct reference to the clk input port or is a bad practice assigning it to a signal before?
By the simulation a can guess that assigning the clk to a signal before can add some delay, which makes me think this is an valid trick or it could add some unexpected behaviour to the system.
Here is some Dummy operation over a std_logic_vector for example. I created a simple component and a combo component that uses two of simple component. I compared the behaviour of the simple component alone and the combo component in a simulation. Further in the bottom is shown the difference between assigning or not the clk to a signal during the simulation.
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;
Here comes the combo component (note the marked lines 59 and 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;
Test bench:
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;
Passing the clk port reference to component instantiation (LINE 60 commented):
Assigning the clk to a signal and passing the signal to component instantiation (LINE 59 commented):
The clk assignment to a signal gives me the behaviour that I wanted, but I guess I'm break the clk synchronism along the system, since it is adding a unknown (unknown for me at least) delay to clks in some components. Is this a real problem?