How does one declare, if possible, a function intended for a parameter of any type T
where the only constraint on T
is that it was defined as a 1D array
as in
type T is array ( integer range <> ) of a_random_type;
where a_random_type
can be any type
.
The following syntactically incorrect function is an example of what is desired
function measure_size_of_any_array ( a : array ( integer range <> ) ) return natural is
variable r : natural := 0;
begin
for i in a'range loop
r := r + 1;
end loop;
return r;
end function;
which could then be used on any array
type natural_array is array ( integer range <> ) of natural;
type stdlogv_array is array ( integer range <> ) of std_logic_vector;
[...]
variable some_natural_array : natural_array;
variable some_stdlogv_array : stdlogv_array;
[...]
constant size_1 : natural := measure_size_of_any_array(some_natural_array);
constant size_2 : natural := measure_size_of_any_array(some_stdlogv_array);
Obviously, this question is about the way of defining the function and not about the function itself: I am not looking for a'length
.
From Ashenden's VHDL-2008: Just the New Stuff
Generic types can be specified for subprograms.
We can declare a formal generic type in a generic list in the following way:
type indentifier
A function with a generic list takes the form:
function indentifier generic ( ... ) parameter ( ... ) return result_type is ... -- declarations begin ... -- statements end function identifier
which would allow the following definition
function measure_size_of_any_array
generic ( type arr_type )
parameter ( arr : arr_type );
and the following use
function measure_size_of_natural_array is new measure_size_of_any_array
generic ( arr_type => natural_array );
function measure_size_of_stdlogv_array is new measure_size_of_any_array
generic ( arr_type => stdlogv_array );
constant size_1 : natural := measure_size_of_natural_array(some_natural_array);
constant size_2 : natural := measure_size_of_stdlogv_array(some_stdlogv_array);
This provides the desired behavior of sharing the body of the function among different calls, regardless of the type of the elements of the array
but still requires an instantiated function (which can be as local as desired so it isn't that bad).
Because of how little support is being provided for VHDL-2008 by the main vendors (the previous solution wasn't understood by the compilers I tried), a VHDL-87, -93 or -2002 solution will be preferred.
The previous information is my attempt to find a way of writing a VHDL subprogram accepting any argument as long as it is an array
(i.e. to answer the initial question). The expected answer isn't necessarily supposed to use the same approach (namely using VHDL-2008 generic subprograms)!
Both procedures and functions written in VHDL must have a body and may have declarations. Procedures perform sequential computations and return values in global objects or by storing values into formal parameters. Functions perform sequential computations and return a value as the value of the function.
An array is an object that is a collection of elements of the same type. VHDL supports N-dimensional arrays, but VHDL Compiler supports only one-dimensional arrays. Array ele- ments can be of any type. An array has an index whose value selects each element.
Procedures can be defined in a VHDL package. The TextIO package is an example where we can find all the procedures (and functions) we can use to manage FILE in VHDL. Another example is the numeric_std package where we can find all the procedures and functions for signed and unsigned number handling.
An impure function can read or write any signal within its scope, also those that are not on the parameter list. We say that the function has side effects. What we mean by side effects is that it is not guaranteed that the function will return the same value every time it is called with the same parameters.
Pre-2008, defining generics was only allowed at entity level. So you could pass generics to a function by making a special entity for that function. E.g.
entity function_ent is
generic(return_value : natural);
port(output : out natural);
end entity;
architecture func_def of function_ent is
function measure_size_of_any_array return natural is
begin
return return_value;
end function;
begin
output <= measure_size_of_any_array;
end architecture;
However, you want to pass a type as a generic parameter... This is not possible <2008. So, you have to use VHDL-2008.
But when using generics in VHDL, you will always have to map a certain value (or type in vhdl-2008) to them. There is no smart (pre-)compiler that will automatically detect the input type, like in C++.
When you've eventually decided to use VHDL-2008, you can ask yourself: "will I ever use the function without defining an array first?" Likely not. So you might use a generic ("templated") package as something comparable to a C++ class. Example:
package array_pkg is
generic (type element_type);
type array_type is array (natural range <>) of element_type;
function measure_size_of_array(
arr : array_type) return natural;
end package;
package body array_pkg is
function measure_size_of_array(
arr : array_type) return natural is
begin
return arr'length;
end function;
end package body;
entity test is
end entity test;
library ieee;
architecture beh of test is
package natural_array_pkg is new work.array_pkg
generic map (element_type => natural);
signal test_sig1 : natural_array_pkg.array_type(0 to 10);
constant test_out1 : natural := natural_array_pkg.measure_size_of_array(test_sig1);
use ieee.std_logic_1164.all;
package slv_array_pkg is new work.array_pkg
generic map (element_type => std_logic_vector);
signal test_sig2 : slv_array_pkg.array_type(0 to 12)(5 downto 0);
constant test_out2 : natural := slv_array_pkg.measure_size_of_array(test_sig2);
begin
end architecture;
I think this is the closest you can get to templated parameters in current VHDL.
The implementation of generic types is very minimal in VHDL-2008. I have written up several pages of LRM changes to get better generic types in VHDL-2017. The new standard is going to be balloted on in a few months.
The change set is specified in LCS-2016-059.
function foo
generic (
type array_type is array(type is (<>)) of type is private
)
parameter (
input : array_type;
selected : array_type'index
)
return array_type'element is
begin
return input(selected);
end function;
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