The joys of functions and arrays

  • Thread starter Jeremy Stringer
  • Start date
J

Jeremy Stringer

Guest
Hello all,

I came across (to me) a bit of a tricky problem -

What I wanted to do was to write a function to take an array of
std_logic_vectors and or them together (Well, a little more than that,
but that's the part I was having trouble with). So - the inputs are
defined like this:

subtype slv_3 is std_logic_vector(2 downto 0);
subtype slv_4 is std_logic_vector(3 downto 0);
type slv_3a is array(natural range <>) of slv_3;
type slv_4a is array(natural range <>) of slv_4;

I then went a wrote a function looking something like this (haven't
tested this exact example):

function or_many(a: slv_3a) return std_logic_vector is
begin
return a(a'high) or or_many(a(a'high downto a'low));
end function or_many;

Now - as I wrote this, I observed that the function I was writing had
exactly the same form for both vector sizes - however, I don't know how
to (or whether it is possible to) apply the same code to each vector size.

Does anybody have anything to suggest? I might be looking at this the
wrong way, but a function seemed a nice elegant way to do this, given
the parameters of the code I was writing (same operation done multiple
places). I do understand that I am feeding different types into each
function - part of the question, I guess, is how to define the inputs in
a manner to suit the problem.

(Oh - and it has to synthesise :) )

Thanks,
Jeremy
 
On Thu, 07 Apr 2005 16:17:49 +1200, Jeremy Stringer
<jeremy@_NO_MORE_SPAM_endace.com> wrote:

What I wanted to do was to write a function to take an array of
std_logic_vectors and or them together (Well, a little more than that,
but that's the part I was having trouble with). So - the inputs are
defined like this:

subtype slv_3 is std_logic_vector(2 downto 0);
subtype slv_4 is std_logic_vector(3 downto 0);
type slv_3a is array(natural range <>) of slv_3;
type slv_4a is array(natural range <>) of slv_4;

I then went a wrote a function looking something like this (haven't
tested this exact example):

function or_many(a: slv_3a) return std_logic_vector is
begin
return a(a'high) or or_many(a(a'high downto a'low));
end function or_many;
I think we have a bit of infinite recursion here :)
But no matter, we can see what you are driving at.

Now - as I wrote this, I observed that the function I was writing had
exactly the same form for both vector sizes - however, I don't know how
to (or whether it is possible to) apply the same code to each vector size.
Yeah. Bummer. No, it isn't possible as far as I know.

Problem (1): VHDL <= 2002 doesn't allow any kind of aggregate type
(and that, of course, includes arrays) to contain any kind of
unconstrained aggregate. So you can't declare an
array (natural range <>) of std_logic_vector;
because slv is unconstrained. Hence your need for two separate types
slv_3a and slv_4a. VHDL-200x will lift this restriction, but it
ain't here yet.

Problem (2): VHDL has nothing like type templates. If it had, you
could write a generic templated function and invoke it with an
appropriate type name for the template. My guess is that if
VHDL had been defined about five years later than it was, this
feature would have been there from the start. But it's not.
Package generics in VHDL-200x will provide some of this for us.

Does anybody have anything to suggest? I might be looking at this the
wrong way, but a function seemed a nice elegant way to do this, given
the parameters of the code I was writing (same operation done multiple
places). I do understand that I am feeding different types into each
function - part of the question, I guess, is how to define the inputs in
a manner to suit the problem.
Of course you can write two (or more) functions with the same name
and with different input and output types, and let the overloading
mechanism sort them out. This makes your "client" code (the users
of the function) look very neat, but you must write the function
in full for each new type. If you have only a few different
slv_N subtypes to cope with, this is certainly the right approach.

It may also be possible to use true 2-dimensional arrays...

type slv_a is array
(natural range <>, natural range <>) of
std_logic;

This would allow you to write a truly general function, but
then you have this problem to solve...

subtype slv3 is std_logic_vector(2 downto 0);
subtype slv3_a5 is slv_a (1 to 5, slv3'range);
signal vec3: slv3;
signal vec5x3: slv3_a5;
...
vec5x3(1) <= vec3; -- ILLEGAL
-- wrong number of subscripts on vec5x3;
-- vec5x3(1) isn't an object at all
--
vec5x3(1, slv3_a5'range(2)) <= vec3; -- ILLEGAL
-- can't slice either dimension of a 2d array

-- so you need something like...
for i in slv3'range loop
vec5x3(1,i) <= vec3(i);
end loop;

The result of all this palaver is that IMHO true multi-
dimensional arrays are close to useless in VHDL.

(Oh - and it has to synthesise :) )
I don't know which (if any) synth tools handle true 2D arrays.

Sorry to be so unhelpful!
--
Jonathan Bromley, Consultant

DOULOS - Developing Design Know-how
VHDL, Verilog, SystemC, Perl, Tcl/Tk, Verification, Project Services

Doulos Ltd. Church Hatch, 22 Market Place, Ringwood, BH24 1AW, UK
Tel: +44 (0)1425 471223 mail:jonathan.bromley@doulos.com
Fax: +44 (0)1425 471573 Web: http://www.doulos.com

The contents of this message may contain personal views which
are not the views of Doulos Ltd., unless specifically stated.
 
Jonathan Bromley wrote:
I then went a wrote a function looking something like this (haven't
tested this exact example):

function or_many(a: slv_3a) return std_logic_vector is
begin
return a(a'high) or or_many(a(a'high downto a'low));
end function or_many;

I think we have a bit of infinite recursion here :)
But no matter, we can see what you are driving at.
Woops. <smack fingers> :)

Of course you can write two (or more) functions with the same name
and with different input and output types, and let the overloading
mechanism sort them out. This makes your "client" code (the users
of the function) look very neat, but you must write the function
in full for each new type. If you have only a few different
slv_N subtypes to cope with, this is certainly the right approach.
That was the first approach I looked at - In the end I just wrote
conversion routines to convert to the largest vector size and then back.
The reason that I really don't like repeating functions is that if you
find a bug, it's easy to update one, and forget to update the other :)
(Either that or it just fundamentally bugs the programmer in me :) )

The result of all this palaver is that IMHO true multi-
dimensional arrays are close to useless in VHDL.
Well - hopefully they'll be fixed sooner or later :) VHDL's a funny
language in some ways - I guess the reason I asked the question in the
first place is that the function body seemed so easy to express in an
relatively object-independant manner.

(Oh - and it has to synthesise :) )
I don't know which (if any) synth tools handle true 2D arrays.
Yeah - the language documentation on my simulator mentioned this, and I
seem to recall one of the other engineers complaining about it :)

Sorry to be so unhelpful!
Actually, that was very helpful :) It resolved the questions I had
about what was possible, and it's clarified my understanding of the
language a little. Thanks.

Jeremy
 

Welcome to EDABoard.com

Sponsor

Back
Top