Disaggregation of Expressions vis-a-vis Outgoing Ports in Entity Instantiations
Capability/request summary
As of IEEE 1076-2008, expressions (e.g., aggregates) have been allowed for use within ingoing ports during entity instantiations; in other words, the port sample_in : in bit_vector
is able to be connected to (others => '1')
while it is being instantiated.
Current Status
Currently, and even as of IEEE 1076-2019, aggregates—and expressions in general—are disallowed from being used in connection to outgoing ports; in contrast to the aforementioned example, sample_out : out bit_vector
is unusable with (others => '1')
.
Use Models | Code Examples
Please consider the following code:
Click to expand "pipeliner.vhd"
-- --------------------------------------------------------------------
-- FILE: pipeliner.vhd
-- --------------------------------------------------------------------
entity pipeliner is
generic (
g_NUM_STAGES : natural := 3;
type t_element is private;
type t_array is array (natural) of t_element
);
port (
i_signals : in t_element;
o_signals : out t_element
);
begin
-- Compile-time assertions go here to ascertain
-- that 'input' and 'output' are of equal lengths.
assert i_signals'length = o_signals'length
report "Aggregated input/output tuples are not equal in size."
severity failure;
end entity pipeliner;
architecture behavioral of pipeliner is
constant NUM_ELEMS : positive := i_signals'length;
begin
-- NOTE: Naturally, in a full implementation, a clocked process and
-- a second for...generate clause would be present to drive the
-- actual delay-line logic for the Entity based on the g_NUM_STAGES
-- generic; here, however, for the sake of simplicity, the details
-- have been omitted and a simple re-assignment has replaced them.
per_element : for i in 0 to NUM_ELEMS-1 generate
o_signals(i) <= i_signals(i);
end generate per_element;
end architecture behavioral;
-- --------------------------------------------------------------------
-- END OF FILE: pipeliner.vhd
-- --------------------------------------------------------------------
Now, suppose we want to instantiate and use it externally:
Click to expand "test.vhd"
-- --------------------------------------------------------------------
-- FILE: test.vhd
-- --------------------------------------------------------------------
entity test is
end test;
architecture behavioral of test is
-- Examplar ternary unit type
type trit is ('0', '1', '2');
-- External inputs that will be given to the Piperliner
signal alpha : trit;
signal beta : trit;
signal gamma : trit;
-- Registered (i.e., "delayed") outputs from the Pipeliner
signal alpha_reg : trit;
signal beta_reg : trit;
signal gamma_reg : trit;
begin
-- Here, we expect that the entity constructs a "trit vector" type
-- internally, using it to denote its input/output signals.
test_instance : entity work.pipeliner
generic map (2, trit)
port map (
(alpha, beta, gamma), -- This works, as of VHDL-08.
(alpha_reg, beta_reg, gamma_reg) -- EXPRESSION ERROR!
);
end architecture behavioral;
-- --------------------------------------------------------------------
-- END OF FILE: test.vhd
-- --------------------------------------------------------------------
-
As of present, this would fail with the following error:
[Synth 8-9114] actual of formal out port 'o_signals' cannot be an expression.
-
However, this is inconsistent behavior for a multitude of reasons, including but not limited to the facts that…
- From what was discerned in the Gitter Chatroom, and in accordance with LRM 6.5.6.3, "
[t]he port, signal, shared variable, or expression associated with a given formal port is called the actual corresponding to the formal port
", meaning thatout
ports, at a first glance, do not even seem to be precluded from being able to have aggregated assignments connected to them; -
in
-specified ports are permitted to use aggregated, anonymous types; - Even then, composite signal L.H.S. assignments (e.g.,
(carry_out, sum) <= ('0' & a) + ('0' & b);
) are already permitted; and - The aggregate is static, known at compile-time, and syntactically similar with how
in
aggregates are treated.
- From what was discerned in the Gitter Chatroom, and in accordance with LRM 6.5.6.3, "
-
Therefore, it is in the interest of consistency and usability to permit the usage of disaggregations connected to
out
ports during instantiation.
Currently, it is possible to work-around the above-mentioned issue by employing a syntax similar to the following:
Click to expand "code snippet"
-- [...]
test_instance : entity work.pipeliner
generic map (2, trit)
port map (
(alpha, beta, gamma), -- This works, as of VHDL-08.
o_signals(0) => alpha_reg,
o_signals(1) => beta_reg,
o_signals(2) => gamma_reg
);
-- [...]
Unfortunately, it is a rather verbose and inconvenient workaround for an otherwise-equal task.
Questions
Since I do not have access to a VHDL-2019 compiler, I may have done a mistake in the generic types described in pipeliner.vhd
. If that may be the case, we can disregard the generic types and hard-code i_signals
and o_signals
to be of bit_vector
types; the goal of this proposal is to shed light on aggregated expressions in relation to out
ports, not necessarily describe how generic types work.
Proposed changes
-
WHEREFORE, it is submitted to the IEEE 1076 working group that it is in the interest of VHDL's standardization, consistency, and usability that out
ports be allowed to have expressions—of anonymous aggregations—disaggregated and performed as if they were normal L.H.S. composite signal assignments.