# VHDL function that converts a vector to an array

Status
Not open for further replies.

#### shaiko

I want to write a VHDL function that fits a vector to an array.
The problem is, that I don't know how to make a function return an array.
This is what I wrote so far:

Code:
function vector_to_array ( vector , width , depth : unsigned ) return "WHAT_SHOULD I WRITE HERE ???" is
type temp_array is array ( 0 to to_integer ( depth ) ) of unsigned ( to_integer ( width ) - 1 downto 0 ) ;
variable my_array : temp_array := ( others => ( others => '0' ) ) ;
begin
for index in 0 to ( to_integer ( depth ) - 1 )
loop
my_array ( index ) := vector ( ( ( to_integer ( width ) * ( to_integer ( depth ) - index ) ) - 1 ) downto ( to_integer ( width ) * ( to_integer ( depth ) - index ) - to_integer ( width ) ) ) ;
end loop ;
return my_array ;
end function vector_to_array ;

#### std_match

This is the same situation as for "std_logic_vector".

Solution:
Define an unconstrained array type that can be seen by both the function and the caller.
If the function and the caller are in different files, put the type in a package.

shaiko

### shaiko

Points: 2

#### shaiko

you mean like this ?

Code:
type x is array ( 0 to depth ' length - 1 ) of unsigned ( width ' length - 1 downto 0 ) ;

function vector_to_array ( vector , width , depth : unsigned ) return x is
type temp_array is array ( 0 to to_integer ( depth ) ) of unsigned ( to_integer ( width ) - 1 downto 0 ) ;
variable my_array : temp_array := ( others => ( others => '0' ) ) ;
begin
for index in 0 to ( to_integer ( depth ) - 1 )
loop
my_array ( index ) := vector ( ( ( to_integer ( width ) * ( to_integer ( depth ) - index ) ) - 1 ) downto ( to_integer ( width ) * ( to_integer ( depth ) - index ) - to_integer ( width ) ) ) ;
end loop ;
return my_array ;
end function vector_to_array ;

#### TrickyDicky

yes, but why pass in width and depth as unsigned? why not just integer (it makes it much less messy). you also cant return the temp_array_t because it isnt declared externally, you need to return type "x".

shaiko

### shaiko

Points: 2

#### shaiko

So, the whole deal would look exactly like this ?

Code:
package package_functions is

signal array_depth , array_width : positive ;
type generic_array is array ( 0 to array_depth - 1 ) of unsigned ( array_width - 1 downto 0 ) ;
function vector_to_array ( vector : unsigned ; array_width , array_depth : positive ) return generic_array ;

end package package_functions ;

package body package_functions is

function vector_to_array ( vector : unsigned ;  array_depth , array_width : positive ) return generic_array is
variable my_array : generic_array := ( others => ( others => '0' ) ) ;
begin
for index in 0 to ( depth - 1 )
loop
my_array ( index ) := my_array ( ( array_width * ( array_depth - array_width ) ) - 1 downto ( ( array_width * array_depth ) - index ) - array_width ) ;
end loop ;
return my_array ;
end function vector_to_array ;

end package body package_functions ;

#### TrickyDicky

theres problems:

- you cannot create array ranges using signals.
- Why bother even putting ranges on the generic_array type when you clearly want lengths that are not fixed.
- you need to use the index in both sides of the downto indexing when assinging to my_array
- I think you mean vector

You still seem to be lacking the ability to use a VHDL compiler - al of these problems would have fallen out in your own compilation and simulation.

shaiko

### shaiko

Points: 2

#### shaiko

I do use a compiler...
Why bother even putting ranges on the generic_array type when you clearly want lengths that are not fixed.
Well, I tried to define an unconstrained array like this - but it doesn't work:
Code:
package package_functions is

type generic_array is array ;
function vector_to_array ( vector : unsigned ; array_width , array_depth : positive ) return generic_array ;

end package package_functions ;

package body package_functions is

function vector_to_array ( vector : unsigned ;  array_depth , array_width : positive ) return generic_array is
variable my_array : generic_array := ( others => ( others => '0' ) ) ;
begin
for index in 0 to ( depth - 1 )
loop
my_array ( index ) := my_array ( ( array_width * ( array_depth - array_width ) ) - 1 downto ( ( array_width * array_depth ) - index ) - array_width ) ;
end loop ;
return my_array ;
end function vector_to_array ;

end package body package_functions ;

#### TrickyDicky

yes, because you havent followed VHDL syntax! you need to specify the type for the array elements.

in VHDL 2008 this is valid:
type generic_array_t is array(natural range <>) of unsigned;

but in 2002 and previous you must declare a dimension for the element type:

type generic_array_t is array(natural range <>) of unsigned( YOU_MUST_PUT_DIMENSION_HERE downto SOME_OTHER_NUMBER);

Note: Its usually considered good form to separate out your type names from your signal/variable names by use of some type naming, usually something like _type or _t at the end of the type name;

And you havent fixed the other problems I mentioned within your function (the fact the upper bound is constant, and you're assigning my_array to my_array)

shaiko

### shaiko

Points: 2

#### shaiko

If I can't use a function with an unconstrained array then it's useless to me.
I'll simply use "generate" (G_DEPTH , G_WIDTH , G_ENDIAN are entity generics )

Code:
for index in 0 to ( G_DEPTH - 1 )
generate

msb_first : if G_ENDIAN = '1'
generate
memory ( index ) <= data ( ( ( G_WIDTH * ( G_DEPTH - index ) ) - 1 ) downto ( G_WIDTH * ( G_DEPTH - index ) - G_WIDTH ) ) ;
end generate msb_first ;

lsb_first : if G_ENDIAN = '0'
generate
memory ( index ) <= data ( ( G_WIDTH - 1 + ( index * G_WIDTH ) ) downto ( index *  G_WIDTH ) ) ;
end generate lsb_first ;

end generate ;

This shall take care of all the problems - right ?
What do you think ?

#### TrickyDicky

I never said you couldnt use a function with an unconstrained array. I just said you had errors in your function. Just what you were trying to do will required VHDL 2008.

Your generate will fail because when index is 0 you'll be trying to return the range (0 downto - G_WIDTH). Its probably best to use

Code:
YOU_MUST_USE_A_GENERATE_LABEL_USE_VCOM_TO_CLEAN_YOUR_CODE : for index in 0 to ( G_DEPTH - 2 )
generate

msb_first : if G_ENDIAN = '1'
generate
memory ( index ) <= data ( G_WIDTH *(index + 1) -1 downto G_WIDTH*index);
end generate msb_first ;

- - - Updated - - -

And PS - a function would wrap all this up nicely (aslong as you can use VHDL 2008)

memory <= reorganise(data);

shaiko

### shaiko

Points: 2

#### shaiko

Your generate will fail because when index is 0 you'll be trying to return the range (0 downto - G_WIDTH).
Why???
I think it becomes:
Code:
memory ( 0 ) <= data ( ( ( G_WIDTH * G_DEPTH - 1 ) downto ( G_WIDTH * G_DEPTH - G_WIDTH ) ) ;
as long as you can use VHDL 2008...
Any chance all synthesis tools will support VHDL 2008 before 2088 ?
Whose idea where these stupid constrains in the first place??!

P.S: what is VCOM ?

Last edited:

#### TrickyDicky

sorry my bad on the code - I was reading in a hurry.

Whose idea where these stupid constrains in the first place??!

Well, usually you know all your bus widths. And there are always ways around the problem with '93.

vcom is the vhdl compiler command in modelsim.

shaiko

### shaiko

Points: 2

#### shaiko

In VHDL 2008 - is integer type also limited to 32 bits only ?

#### TrickyDicky

Actually, integer is limited by the tool, not the VHDL version. Afaik, all tools use 32 bit integers.

shaiko

Points: 2