Customer question
On a regular basis we receive questions from customers about Incorrect array size warnings or errors.
Declarations for data_out
and result
:
entity with_generic is
generic(datawidth : natural);
port(data_out : out std_logic_vector(datawidth - 1 downto 0));
end entity with_generic;
architecture RTL of with_generic is
signal result : std_logic_vector(7 downto 0);
This linting message tells that array sizes in an assignment do not match. Typically, one side of the assignment is a port and the other side an internal signal. A generic defines the width of the port while the signal width is defined by a constant value.
The core question asked is Why does Sigasi Visual HDL not take into account the value of the generic when calculating the array sizes? After all, in the instantiation the value of the generic was set to match the constant value.
Improving reusabiliy
The intention of this warning is explicitly not to elaborate the generic value. Instead the goal is to help hdl designers improve code reusability.
Because the array size is fixed to 8, the example above will only be valid if the value of the generic is set to 8 in any instantiation. For any other value assigned to the generic, the code will break.
In order to resolve the warning above, the array size should be written in terms of datawidth
so that the code remains valid for other values of the generic.
entity with_generic is
generic(datawidth : natural);
port(data_out : out std_logic_vector(datawidth - 1 downto 0));
end entity with_generic;
architecture RTL of with_generic is
signal result : std_logic_vector(datawidth - 1 downto 0);
One step further
Taking this a step further, the warning could be interpreted more bluntly: stop using the generic since it only gives a false sense of re-usability.
Why would generics be needed to define port or signal widths? VHDL allows to write code without using generics or fixed port widths like in the code example below.
library ieee;
use ieee.std_logic_1164.all;
entity nogenerics is
port(
data_out : out std_logic_vector;
data_in : in std_logic_vector
);
end entity nogenerics;
architecture RTL of nogenerics is
signal intermediate : std_logic_vector(data_out'range);
begin
intermediate <= data_in;
data_out <= intermediate;
end architecture RTL;
The actual port and signal widths are only defined once this design unit is instantiated. No constants or generics are involved, allowing to write less and cleaner code.
Generics can be used to express relations between ports that are checked at compilation or at elaboration time. You can express these relations also with asserts:
assert data_out'length = data_in'length report "port width mismatch" severity failure;
We’re happy to hear your feedback on this linting rule and on how Sigasi Visual HDL can help you to write cleaner code.
See also
- The benefits of early detection (screencast)
- Inspecting Constants and Generics (screencast)
- Install the Sigasi Visual HDL Eclipse Plugin (screencast)
- How to download and install the Sigasi Visual HDL Stand-alone app (screencast)
- Importing a Quartus project in Sigasi Visual HDL (knowledge)