![]() |
|
|
|||||||
![]() |
VHDL - The joys of functions and arrays |
|
|
Thread Tools | Search this Thread |
|
|
#1 |
|
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 Jeremy Stringer |
|
|
|
|
#2 |
|
Posts: n/a
|
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: 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 |
|
|
|
#3 |
|
Posts: n/a
|
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 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 about what was possible, and it's clarified my understanding of the language a little. Thanks. Jeremy Jeremy Stringer |
|