Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

VHDL - Function/Procedure for any type of array

Tags:

vhdl

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

like image 358
PiCTo Avatar asked Apr 10 '17 13:04

PiCTo


People also ask

What are functions and procedures in VHDL?

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.

What is array type in VHDL?

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.

Where is procedure defined in VHDL?

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.

What is impure function in VHDL?

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.


2 Answers

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.

like image 84
JHBonarius Avatar answered Nov 07 '22 02:11

JHBonarius


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;
like image 25
Paebbels Avatar answered Nov 07 '22 02:11

Paebbels