M.mhr
M.mhr

Reputation: 1749

How to concatenate two arrays in VHDL

I have some types like this :

Type MyCharacters is ('0', '1' ... '9', 'A', 'B', ... 'Z');

Type CharArray_8 is array(1 to 8) of MyCharacters;
Type CharArray_16 is array(1 to 16) of MyCharacters;
Type CharArray_32 is array(1 to 32) of MyCharacters;

and 4 Signals with this types :

Signal S1, S2 : CharArray_8;
Signal S3 : CharArray_16;
Signal S : CharArray_32;

I want to concatinate S1, S2 and S3 and assign the result to S, like this :

S <= S1 & S2 & S3;

but this code is wrong and have error, how I should concatenate them ?

Should Array types be declared as SubType of MyCharacters ?

Upvotes: 4

Views: 6424

Answers (2)

Renaud Pacalet
Renaud Pacalet

Reputation: 28965

No, your array types cannot be declared as subtypes of MyCharacters, which is an enumerated type, not an array type.

Your 3 array types are different and independent types. The concatenation operator (&) is not defined on the combination of them that you use. You could overload it for this specific case but the simplest is probably be to use a common base type, that is, a parent unconstrained array type and declare subtypes of it with fixed ranges:

type mychararray is array(natural range <>) of MyCharacters;
subtype CharArray_8 is mychararray(1 to 8);
subtype CharArray_16 is mychararray(1 to 16);
subtype CharArray_32 is mychararray(1 to 32);

This way, they would all have the same base type and the implicit concatenation operator that is automatically declared with the mychararray type would work on any combination of them (assuming the size of the result is the same as the size of the variable it is assigned to, of course).

Note: I guess that you already know the string type (array of characters)?

Upvotes: 3

user1155120
user1155120

Reputation:

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).

Upvotes: 5

Related Questions