As you have discovered, the 'image attribute is only declared for scalar types, not arrays or records : the usual approach is to create one's own library of test utilities including to_string
or image
functions in a package at the start of a design, and use it throughout.
It would be perfectly possible to standardise a library of these, and you will probably find many potential "test utility" packages but none has really caught on well enough to deserve becoming a standard.
That being said, you might find the following package a useful starting point.
It encapsulates a couple of custom datatypes with operations on them. No generics, but thanks to overloading, you can use the package as though its functions were generic. (You will notice that the function bodies are incomplete though!) Extending it and adding types is easy cut&paste for the most part; and it keeps a lot of clutter out of the main design.
It may be better to separate out the type declns and the (testbench only) functions into two separate packages; Types
and Types_Test_Utils
. Then Types is used throughout the design, while the test utilities are only exposed to the testbench.
library IEEE;
use IEEE.numeric_std.all;
package Types is
subtype SmallNum is UNSIGNED(7 DOWNTO 0);
subtype BiggerNum is UNSIGNED(19 DOWNTO 0);
subtype Bits is BIT_VECTOR(7 DOWNTO 0);
-- and operations on these types
-- Simulate generic procedures using overloading
function to_string(N : Unsigned) return String;
function to_string(N : Bits) return String;
procedure eq_checker (name : string; sig,should : SmallNum; at : time);
procedure eq_checker (name : string; sig,should : Bits; at : time);
end Types;
package body Types is
function to_string(N : Unsigned) return String is
variable temp : string(1 to (N'length + 3)/4) := (others => 'x');
begin
-- not finished!
return temp;
end to_string;
function to_string(N : Bits) return String is
begin
return "hello";
end to_string;
procedure eq_checker(name : string; sig,should : SmallNum; at : time) is
begin
if (at = now) then
if sig = should then
report to_string(sig) & "has same value" severity note;
else
report to_string(sig) & "has not same value as " & to_string(should) severity note;
end if;
end if;
end procedure eq_checker;
procedure eq_checker(name : string; sig,should : Bits; at : time) is
begin
null;
end procedure eq_checker;
end Types;
And a simple tester for it...
use Work.Types.all;
ENTITY tester IS
END tester;
ARCHITECTURE behavior OF tester IS
Signal a,b : SmallNum := X"AA";
Signal c : BiggerNum := X"ABCDE";
SIGNAL x,y : Bits := X"BB";
BEGIN
process(a,x) is
begin
report "value: " & to_string(X) severity note;
report "and this one: " & to_string(a) severity note;
report "this one too: " & to_string(c) severity note;
end process;
END;