# VHDL: is there a way to create an entity into which constants can be passed?

Lets say we want to create a generic t flip flop counter, the structure of this kind of counter is perfectly repetitive, and you can synthesize one with arbitrary length just using a for generate

however the bound for that for and the length of the output is internal to the file, a constant, is there a way to sort of passing an argument when creating a component so as to define the length of the counter when creating the component instead of in the file?

here is the code of the counter i made

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use ieee.numeric_std.all;

entity counterTst is
port(
enable: in      STD_LOGIC;
clk:        in      STD_LOGIC;
rst:        in      STD_LOGIC;
output: out STD_LOGIC_VECTOR(3 downto 0)
);
end counterTst;

architecture rtl of counterTst is

constant COUNTER_LEN:   integer := 4;

component t_ff  is
port(
rst:    in      STD_LOGIC;
clk:    in      STD_LOGIC;
inp:    in      STD_LOGIC;
t:      out STD_LOGIC
);
end component t_ff;

signal  tin:    STD_LOGIC_VECTOR(COUNTER_LEN-2 downto 0);
signal  tout:   STD_LOGIC_VECTOR(COUNTER_LEN-1 downto 0);

begin

T_CHAIN_GEN:    for i in 0 to COUNTER_LEN-1 generate
START_POS: if i = 0 generate
FF0:    t_ff    port    map(rst, clk, enable, tout(0));
end generate START_POS;

POS_1:  if i = 1 generate
tin(0) <= tout(0) and enable;
FF1:    t_ff    port    map(rst, clk, tin(0), tout(1));
end generate POS_2;

POS_N:  if i > 1 generate
tin(i-1) <= tout(i-1) and tin(i-2);
FFX:    t_ff    port    map(rst, clk, tin(i-1), tout(i));
end generate POS_N;
end generate T_CHAIN_GEN;

output <= tout;

end rtl;

• Either add a generic above your ports or put the constant into a package. – TonyM Jul 7 '19 at 7:12
• Generic with default values. Then in the component instantiation part(in other modules), initialise it with the desired value. – Meenie Leis Jul 8 '19 at 6:32

Yes, it is called a 'generic':

I could show an example here, but there are plenty of example on the WWW once you know what to look for: https://www.nandland.com/vhdl/examples/example-generic.html

Add a generic clause to your entity. It allows you to pass in e.g. constants:

entity counterTst is
generic (
constant COUNTER_LEN : integer -- := 4
);
port (
enable: in  STD_LOGIC;
clk:    in  STD_LOGIC;
rst:    in  STD_LOGIC;
output: out STD_LOGIC_VECTOR(COUNTER_LEN - 1 downto 0)
);
end counterTst;

architecture rtl of counterTst is

-- constant COUNTER_LEN:   integer := 4;


Moreover generic values can be used in you port clause to size ports. A generic can have a default value, thus the user doesn't need to apply it in a generic map. In you case, you shouldn't apply a default value to force the user to think about his choice :).

And here is the usage:

cnt : entity work.counterTst
generic map (
COUNTER_LEN => 4
)
port map (
-- ...
);


Like in a port map, you map generics in a generic map.

Since VHDL 2008, you can also make output an unconstrained port and then infer the counter length from that port, as given during instantiation:

entity counterTst is
port(
enable: in  std_logic;
clk:    in  std_logic;
rst:    in  std_logic;
output: out std_logic_vector
);
end entity;

architecture rtl of counterTst is
constant counter_len: natural := output'length;

-- ...
end architecture;


Just one thing to be careful about: The instantiation will define the full range of output, so it might be an std_logic_vector(counter_len downto 1) or even a dreaded to range. Since you assign output from a local signal, this is not an issue, but it could be problematic if you try to index output directly.

• Quite nifty. Another thing to be careful about (almost a meme at this point) is that VHDL 2008 support can still(!) be rather flaky, with different synthesis/simulation tools supporting a different subset of the standard, if any at all. – Richard the Spacecat Jul 7 '19 at 23:48
• It's e.g. supported by Vivado 2018.3. – Paebbels Jul 8 '19 at 10:58