I am trying to create a generic driver for an SPI based IO expander. The idea is to pass initialization values in the instantiation, that matches the requested IO setup.
My current attempt look like this :
entity max7301_simple is
generic (
IO_cfg : array (1 to 7) OF integer range 0 to 255 := (16#55#, 16#55#, 16#55#, 16#55#, 16#55#, 16#55#, 16#55#)
);
port (
-- Application interface :
clk_i : in std_logic; -- input clock, xx MHz.
rst_i : in std_logic; -- sync reset.
en_i : in std_logic; -- enable, forces re-init of pins on MAX7301.
output_i : in std_logic_vector(27 downto 0); --data to write to output pins on MAX7301
irq_o : out std_logic; -- IRQ, TODO: what triggers, change on inputs ?
input_o : out std_logic_vector(27 downto 0); --data read from input pins on MAX7301
-- MAX7301 SPI interface
sclk : out std_logic; -- SPI clock
din : in std_logic; -- SPI data input
dout : out std_logic; -- SPI read data
cs : out std_logic -- SPI chip select
);
end max7301_simple;
The problem is with the IO_cfg array, i have tried various attempts w/wo init values etc. And cannot seem to figure how to specify the array.
I belive to have read that you can pass an array as generic, but still haven't got much luck with it. Xilinx ISE just tells med "syntax error near 'array' " wich is not informative enough to get me forward.
Any help would be appreciated
I always need 7 values, when instantiating this module.
You are allowed to use an array as a generic parameter however you are not allowed to declare it there, on-the-fly as an anonymous type.
You have to first declare your integer array type in a separate package (which can be in the same file or in a separate one) and then use
the package in your entity and when you instantiate it.
Here is an example of how you can do it:
-- package declaration
package mytypes_pkg is
type my_array_t is array (1 to 7) of integer range 0 to 255;
end package mytypes_pkg;
-- entity "uses" the package
use work.mytypes_pkg.all;
entity max7301_simple is
generic (
IO_cfg : my_array_t := (16#55#, 16#55#, 16#55#, 16#55#, 16#55#, 16#55#, 16#55#)
);
-- ports [...]
end max7301_simple;
Be careful to also use
the package in the architecture that instantiates your entity.
(Optional reading)
Why is it really a syntax error to write it like you did?
Looking at the VHDL grammar in the VHDL (2002) standard, each generic parameter's declaration is a interface_constant_declaration
and you have the following grammar rules:
[§ 4.3.2]
interface_constant_declaration ::=
[ constant ] identifier_list : [ in ] subtype_indication [ := static_expression ]
[§ 4.2]
subtype_indication ::=
[ resolution_function_name ] type_mark [ constraint ]
The type reference can only be the name of an existing type (type_mark
) or the restriction of an existing type.
I propose a bit more generic approach by using 2008 VHDL standard and predefined attributes - this allows passing an array of any length. Define your type in your package like this:
package data_types is
type array_of_integers is array(natural range <>) of integer;
end package;
Now in your code pass generic array as follows:
generic(
COEFFICIENTS : array_of_integers := (-1, 0, 1)
);
Now software will be using a default indexing scheme. It can be taken into account with predetermined 'left attribute (reference can be found at: http://www.csee.umbc.edu/portal/help/VHDL/attribute.html):
-- First coefficient
... <= COEFFICIENTS(COEFFICIENTS'left);
-- Second coefficient
... <= COEFFICIENTS(COEFFICIENTS'left + 1);
Generally you should use this array in some kind of loop or generate statement:
GENERATE_STATEMENT: for entry in 0 to COEFFICIENTS'length-1 generate
out(entry) <= std_logic_vector(to_signed(COEFFICIENTS(COEFFICIENTS'left + entry), out(entry)'length));
end generate;
As a little side note for Quartus II users - it is also possible to use generic arrays in .bdf schematic files. Set parameter type to Auto and rewrite parameter value in this format - A(D"-1", D"0", D"1"), where D stands for decimal data type (Useful link: http://quartushelp.altera.com/14.0/mergedProjects/assign/asd/asd_tab_param.htm)
If you don't mind a less-constrained generic, you can do:
generic (IO_cfg : integer_vector);
As long as you have a VHDL-2008 compiler.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With