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-1088)
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?
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
>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
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.
>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
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.
Read_File/Write_File
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