VHDL - Function/Procedure for any type of array
Asked Answered
I

2

6

Question:

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.


Possible Solution:

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.

Comment after receiving the first answers:

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)!

Interdigitate answered 10/4, 2017 at 13:44 Comment(3)
btw, the question would imho be better if you'd add some minimal complete verifiable example code, instead of pseudo code..Gimble
@J.H.Bonarius How could I write such an example when my question basically is "How may I express this in VHDL?"? Therefore, if I were able to write the example you are asking for, this question would not exist.Interdigitate
An interesting question. Without VHDL-2008, I don't think you're going to find an answer.Linet
G
4

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.

Gimble answered 10/4, 2017 at 15:34 Comment(4)
I am sorry but how is this an answer to my question? There are no formal parameters (or equivalent) in your example. I guess these should be input ports but then the question is exactly the same: How do you define these ports to accept any signal which is of type array of [...]?Interdigitate
@Interdigitate in your question you state that you already have a solution. What you ask is if there is a solution for VHDL <2008. My answer is no. And if you are expecting c++- like templates: that's also not supported in vhdl2008.Gimble
Please excuse me. I realized I misread you answer by focusing on the code. Your answer was indeed "no, it's not possible to have type generics in <2008" which is correct and which I already knew before posting the question but, as I said in another comment, I hoped for another hack-ish approach to this similarly to the example you give to have function generics in <2008. But your answer is obviously valid to my question so that my previous comment should definitely be ignored. And yes, C++ templates are a very good example of what I was looking for!Interdigitate
I hadn't refreshed and just saw your update; the example you're are adding is indeed already quite elegant. Too bad there is absolutely no way to emulate this in <2008 and it's a shame support for VHDL-2008 is so scarce ... Although the answer from Paebbels is very interesting, I will accept this one as it is using 2008 (as opposed to 2017 in his).Interdigitate
T
3

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;
Teratism answered 10/4, 2017 at 16:18 Comment(10)
This is very interesting but doesn't answer my question as it isn't even part of VHDL (as of right now). Furthermore, as I stated, I would prefer a pre-2008 solution but I must say I wasn't expecting a solution in VHDL-2017! I am pretty sure the answer to my question is that it isn't possible but am still hoping for a nice hack. Out of curiosity, does this still require an instantiation or can it be called as foo(T)(in, sel)?Interdigitate
What I wanted to express is: a) it's not possible right now (2008) because they stripped down the generic types idea to a bare (unusable) minimum in 2008. b) it will never work with <2008. c) I stepped into the same problem and then wrote this language change to get it in a year or so.Teratism
Another LCS handles direct instantiation of generic subprograms directly in the call. The syntax requires the "generic map" keywords otherwise you can't distinguish between overloads with/without generics/parameters :).Teratism
I understand that I cannot do better with VHDL-2008 generics than what I described and therefore, am still hoping for a totally different approach which I couldn't think of (this is basically the reason why I posted this question). If no other answer is posted (with such approach) then I guess I will pick you answer as long as it is edited to clearly state that it is not possible with pre-2008 (even with another approach than through generics) and to answer my previous comment about the necessity of having an instance of the function as in VHDL-2008.Interdigitate
@Interdigitate people are giving you good answers, and you seem to get angry because they are not the answers you want. But what you want is not possible. Please be nice to people that are willing to help you for free.Gimble
@J.H.Bonarius "what you want is not possible [in <2008]" is a perfect answer to my question! The reason why I was insisting on getting another answer was that both answers I had received were stating that "it is not possible in <2008 with type generics" which was only part of the answer. Hence, I still hoped for another approach which would not be using type generics.Interdigitate
@Teratism this is now part of VHDL-2019, isn't it?Interdigitate
@Interdigitate YES it is :)Teratism
How far until the tools start support of VHDL2019 or whatever this latest one is called?Oast
First commercial simulators like Riviera-PRO support VHDL-2019.Teratism

© 2022 - 2024 — McMap. All rights reserved.