but this code is wrong and have error, how I should concatenate them ?
There isn't an implicitly declared concatenation operator (&) defined for multiple array types. You need to either declare an overload operator allowing different types with the same element types to be concatenated (which is burdensome, requiring at least three functions for each possible combination) or make the array values the same type either by using type conversion or as in these first two answers declaring a single unbound array type. The array types are eligible for type conversion, having index ranges compatible with type S3 and the same element type.
Should Array types be declared as SubType of MyCharacters ?
In addiition to named subtypes object declarations shown by Renaud Pacalet subtypes can be defined through subtype indications (a type mark and a constraint) in object declarations:
type mychararray is array(natural range <>) of MyCharacters;
signal S1, S2: mychararray(1 to 8);
signal S3: mychararray(1 to 16);
signal S: mychararray(1 to 32);
The & operator is implicitly declared following the type declaration (a one dimensional array type).
See IEEE Std 1076-2008 6.4 Objects, 6.3 Subtype declarations, 5.3.2 Array types (mychararray is an unbounded array type) and 9.2.5 Adding operators (& concatenation operator).
The Mycharacters type is a scalar enumerated character type (discrete values), mychararray is an array type (elements, here the scalar type Mycharacters).
Renaud Pacalet asks about the use of the string type, your 36 value MyCharacters type requires 6 bit binary values to represent after synthesis, three quarters of the way to the std.STANDARD character type (requiring 8 bit binary values). On the other hand you can convert to ASCII values by adding the position value of a MyCharacters to "110000" (16#30# or 48, noting the 'LEFT index position of your array type is '0') if you include the :, ;, <, =, >, ?, and@ characters before A:
30 0 31 1 32 2 33 3 34 4 35 5 36 6 37 7
38 8 39 9 3a : 3b ; 3c < 3d = 3e > 3f ?
40 @ 41 A 42 B 43 C 44 D 45 E 46 F 47 G
48 H 49 I 4a J 4b K 4c L 4d M 4e N 4f O
50 P 51 Q 52 R 53 S 54 T 55 U 56 V 57 W
58 X 59 Y 5a Z
Instead of declaring type MyCharacters you could use type character with appropriate index constraints in your object declarations:
subtype MyCharacters is character('0' to 'Z');
type mychararray is array(natural range <>) of MyCharacters;
signal S1, S2: mychararray(1 to 8);
signal S3: mychararray(1 to 16);
signal S: mychararray(1 to 32);
Bundle that into a Minimal, Complete and Verifiable example:
entity mychar_concat is
end entity;
architecture foo of mychar_concat is
subtype MyCharacters is character range '0' to 'Z'; -- 16#30# to 16#5A#
type mychararray is array (natural range <>) of
character range '0' to 'Z';
signal S1: mychararray (1 to 8) := "01234567";
signal S2: mychararray (1 to 8) := "89:;<=>?";
signal S3: mychararray (1 to 16) := "@ABCDEFGHIJKLMNO";
signal S: mychararray (1 to 32);
function valuehex (inp: MyCharacters) return string is
variable retval: string (1 to 2);
variable hexval: integer;
variable remainder: integer;
begin
hexval := character'pos(inp) / 16;
retval(1) := character'val(hexval + 48); -- where '0' 'pos is 48.
-- expects inp is less than 'Z', (9 * 16 > 'Z')
remainder := character'pos(inp) rem 16;
if remainder < 10 then
retval(2) := character'val(remainder + 48); -- offset to '0'
else
retval(2) := character'val(remainder + 48 + 7); -- offset to 'A'
end if;
return retval;
end function;
begin
S <= S1 & S2 & S3; -- & implicity declared for mychararray
MONITOR:
process
begin
wait on S;
wait for 0 ns; -- skip "00000000000000000000000000000000" default S
report "S = " & string(S);
report "valuehex(MyCharacters'LEFT) = " &
valuehex(MyCharacters'LEFT) & "H";
report "valuehex(MyCharacters'RIGHT) = " &
valuehex(MyCharacters'RIGHT) & "H";
end process;
end architecture;
ghdl -r mychar_concat
mychar_concat.vhdl:37:9:@0ms:(report note): S = 0123456789:;<=>?@ABCDEFGHIJKLMNO
mychar_concat.vhdl:38:9:@0ms:(report note): valuehex(MyCharacters'LEFT) = 30H
mychar_concat.vhdl:40:9:@0ms:(report note): valuehex(MyCharacters'RIGHT) = 5AH
Where 30H is a '0' and 5AH is a 'Z'. Additionally see 16.2.2 Predefined attributes of types and objects.
We see that we derive 7 bit ASCII or 8 bit ISO/IEC 8859-1 character values (See 15.2 Character set) from MyCharacters values with little effort.
In either case the concatenation operators (array & array, element & array, array & element) are implicitly declared following the declaration of a single dimensional array type (mychararray here).