Velocity Reviews > VHDL > Set whole row in 2D array

# Set whole row in 2D array

Tricky
Guest
Posts: n/a

 12-24-2009
with a 2D array, is it possible to assign an entire row in 1 go?

I have the following 2D array

type A_t is array(natural range <>, natural range <>) of natural;
variable A : A_t(0 to 4, 0 to 4) := ( (1,1,1,1,1),
(2,2,2,2,2),
(3,3,3,3,3),
(4,4,4,4,4),
(5,5,5,5,5)
);

And when I try this:

A(1, 0 to 4) := (9,9,9,9,9);

I get what I think is a bit of an odd error:

** Error: D:/Current_Work/ADWEP/VHDL/play_TB.vhd(25): (vcom-108
Badly formed indexed name of "a". Index #2 is a range.
** Error: D:/Current_Work/ADWEP/VHDL/play_TB.vhd(25): Target type
std.standard.integer in variable assignment is different from
expression type.
** Error: D:/Current_Work/ADWEP/VHDL/play_TB.vhd(25): (vcom-1152)
Index value 5 is out of index range 0 to 4 of sub-array #1 of a_t.

How does it come to the conclusion Im trying to assign index value 5?

logic_guy
Guest
Posts: n/a

 12-26-2009
I think the problem is that, in an assignment statement, "0 to 4" is
used to refer to a slice of a vector and each element of A is a single
natural, not a vector.

You might try this:
type natural_vector is array(0 to 4) of natural;
type natural_array is array(0 to 4) of natural_vector;
variable A : natural_array := ( (1,1,1,1,1),
(2,2,2,2,2),
(3,3,3,3,3),
(4,4,4,4,4),
(5,5,5,5,5)
);

A(1)(0 to 4) := (9,9,9,9,9);

Charles Bailey

Tricky
Guest
Posts: n/a

 12-27-2009
I know about this method - unfortunatly, in the situation I have, it
is not possible.
Guess Ill have to write a function to get it done?

logic_guy wrote:
> I think the problem is that, in an assignment statement, "0 to 4" is
> used to refer to a slice of a vector and each element of A is a single
> natural, not a vector.
>
> You might try this:
> type natural_vector is array(0 to 4) of natural;
> type natural_array is array(0 to 4) of natural_vector;
> variable A : natural_array := ( (1,1,1,1,1),
> (2,2,2,2,2),
> (3,3,3,3,3),
> (4,4,4,4,4),
> (5,5,5,5,5)
> );
>
> A(1)(0 to 4) := (9,9,9,9,9);
>
> Charles Bailey

Jonathan Bromley
Guest
Posts: n/a

 12-27-2009
On Sun, 27 Dec 2009 00:18:44 -0800 (PST), Tricky wrote:

>I know about this method - unfortunatly, in the situation I have, it
>is not possible.

Yes, you have a true 2-dimensional array and there is no way
in VHDL to pick rows and columns of it - only individual
elements.

>Guess Ill have to write a function to get it done?

That's the easiest, for sure. You can create functions
to slice by row or by column, and procedures to write
by row or column.

Could I ask why you're using a 2-d array in preference
to an array of arrays? (There are plenty of good possible
reasons; I'm just interested.)
--
Jonathan Bromley

Tricky
Guest
Posts: n/a

 12-27-2009
Basically I load a bitmap from a file, and the array length is set at
load time (from the bitmap header). I cant have arrays of arrays,
because the line length is unknown until you actually load the source
image (with output image a function of the input size). I originally
did it with a 1d array type, but offsetting leads to long winded array
indexing and 2d arrays are just neater. (I have the same functions to
cope with the 1d/2d type declaration and type conversion functions).
As someone who works in video processing, these functions have proved
invaluable.

I was in a situation where I wanted to dump an entire line to an
output array (thats actually an image) before writing it to a file
becuase it would have been quicker than a function, if it was
possible, because the model generated entire lines at a time. Guess
Ill either have to use the 1D types and do the crappy line/pixel
offsetting, or just dump the lines into the 2D type pixel by pixel, or
I could write some line dump functions! Oh well, not back at work for
a week, so Ill probably think of something better by then.

This is all simulation - not synthesis.

Jonathan Bromley wrote:
> On Sun, 27 Dec 2009 00:18:44 -0800 (PST), Tricky wrote:
>
> >I know about this method - unfortunatly, in the situation I have, it
> >is not possible.

>
> Yes, you have a true 2-dimensional array and there is no way
> in VHDL to pick rows and columns of it - only individual
> elements.
>
> >Guess Ill have to write a function to get it done?

>
> That's the easiest, for sure. You can create functions
> to slice by row or by column, and procedures to write
> by row or column.
>
> Could I ask why you're using a 2-d array in preference
> to an array of arrays? (There are plenty of good possible
> reasons; I'm just interested.)
> --
> Jonathan Bromley

Jonathan Bromley
Guest
Posts: n/a

 12-27-2009
On Sun, 27 Dec 2009 08:05:18 -0800 (PST), Tricky wrote:

>Basically I load a bitmap from a file, and the array length is set at
>load time (from the bitmap header). I cant have arrays of arrays,
>because the line length is unknown until you actually load the source

Yes, that's the same reason I have done it.

>I originally
>did it with a 1d array type, but offsetting leads to long winded array
>indexing and 2d arrays are just neater.

Agreed. Functions to read/write a 2-d array will surely always
be nicer than hand-cranked indexing.

>I was in a situation where I wanted to dump an entire line to an
>output array (thats actually an image) before writing it to a file
>becuase it would have been quicker than a function

Using a procedure you can easily pass the 2-d array by reference
and there's no significant speed overhead. I don't think this
is excessively painful:

type T_line is array(natural range <>) of natural;
type T_image is array(
natural range <>, -- rows/lines
natural range <> -- columns/pixels
) of natural;

function get_line (image: in T_image; line_num: in natural)
return T_line is
variable result: T_line(T_image'range(2));
begin
for i in result'range loop
result(i) := image(line_num, i);
end loop;
return result;
end;

procedure write_line (
image: inout T_image; -- Assumed to be (0 to R-1, 0 to C-1)
line_num: in natural;
line: in T_line ) is
alias normalized_line: T_line(0 to line'length-1) is line;
begin
-- check sizes match
assert line'length = image'length(2);
for i in normalized_line'range loop
image(line_num, i) := normalized_line(i);
end loop;
end;

If you allow your 2-d image to have non-normalized
subscripts it all gets just a little messier. Best
not to go there.
--
Jonathan Bromley

KJ
Guest
Posts: n/a

 12-30-2009
On Dec 27, 11:05*am, Tricky <(E-Mail Removed)> wrote:
> Basically I load a bitmap from a file, and the array length is set at
> load time (from the bitmap header). I cant have arrays of arrays,
> because the line length is unknown until you actually load the source
> image (with output image a function of the input size). I originally
> did it with a 1d array type, but offsetting leads to long winded array
> indexing and 2d arrays are just neater. (I have the same functions to
> cope with the 1d/2d type declaration and type conversion functions).
> As someone who works in video processing, these functions have proved
> invaluable.
>
> I was in a situation where I wanted to dump an entire line to an
> output array (thats actually an image) before writing it to a file
> becuase it would have been quicker than a function, if it was
> possible, because the model generated entire lines at a time. Guess
> Ill either have to use the 1D types and do the crappy line/pixel
> offsetting, or just dump the lines into the 2D type pixel by pixel, or
> I could write some line dump functions! Oh well, not back at work for
> a week, so Ill probably think of something better by then.
>

You also might want to look at making a package with a protected type
with access functions and procedures. This allows you to hide all of
the gory details within the functions and procedures while providing
an easy to understand interface that you don't need to keep re-
understanding how it works everytime you use it

Get_Pixel/Set_Pixel
Get_Line/Set_Line
Get_Height/Set_Height
Get_Width/Set_Width
Get_Bmp_Type/Set_Bmp_Type -- i.e. color, grayscale, black/white, etc.
etc.

I've found this method works very well for handling images in
testbenches. If you work with images now, you'll probably work with
them again in the future. Having a simple to use BMP package (TIFF
package, JPEG package, etc.) that you've already debugged and got
working will come in handy for that future work.

Also, by creating pairs of procedures/functions even if you don't have
a need for them *now* it will allow you to more easily create a
testbench to verify your BMP package is working properly...

Img1.Set_Width(100)
assert (Img1.Get_Width = 100) report "OOPS" severity ERROR;

Kevin Jennings