====== More ====== ===== Records ===== architecture EXAMPLE of AGGREGATE is type MONTH_NAME is (JAN, FEB, MAR, APR, MAY, JUN, JUL, AUG, SEP, OCT, NOV, DEC); type DATE is record DAY : integer range 1 to 31; MONTH : MONTH_NAME; YEAR : integer range 0 to 4000; end record; type PERSON is record NAME : string (0 to 8); BIRTHDAY : DATE; end record; signal TODAY : DATE; signal STUDENT_1 : PERSON; signal STUDENT_2 : PERSON; begin TODAY <= (26, JUL, 1988); STUDENT_1 <= ("Franziska", TODAY); STUDENT_2 <= STUDENT_1; STUDENT_2.BIRTHDAY.YEAR <= 1974; end EXAMPLE; * Elements of different type * Possible assignments * record <= record * record <= aggregate * record.element <= value === Notes === In contrast to array types, records admit different data types within the newly created structure. Three choices exist for value assignments: The most obvious method is to assign one record to another (’**STUDENT_2 <= STUDENT_1**’). This does not allow to set individual values, however. Again, aggregates are commonly used for this purpose, i.e. the different element values are grouped together (e.g. ’**TODAY <= (26, JUL, 1988)**’). The single elements are addressed via RECORD.ELEMENT constructs, like ’**STUDENT_2.BIRTHDAY.YEAR <= 1974**’. As can be seen, this syntax applies also to nested records. ===== Type Conversion ===== architecture EXAMPLE of CONVERSION is type MY_BYTE is array (7 downto 0) of std_logic; signal VECTOR: std_logic_vector(7 downto 0); signal SOME_BITS : bit_vector(7 downto 0); signal BYTE : MY_BYTE; begin SOME_BITS <= VECTOR; -- wrong SOME_BITS <= Convert_to_Bit(VECTOR); BYTE <= VECTOR; -- wrong BYTE <= MY_BYTE(VECTOR); end EXAMPLE; * Data types have to match for assignment * Type conversion functions * Type cast * Closely related types * integer <-> real * Arrays with the same length, index set and element types === Notes === Matching data types are a strict language requirement in assignment operations. This can always be achieved via type conversion functions that have to be defined by the user for all necessary pairs of data types. If the data types in question are so called "closely related", the call of a conversion function can be replaced by a more simple type cast. ’integer’ and ’real’ are closely related, for example, i.e. the following code line represents legal VHDL: **REAL_SIGNAL <= real(INTEGER_SIGNAL);** The syntax is similar to a function call, except that the desired data type is used directly as prefix. ===== Subtypes ===== architecture EXAMPLE of SUBTYPES is type MY_WORD is array(15 downto 0) of std_logic; subtype SUB_WORD is std_logic_vector(15 downto 0); subtype MS_BYTE is integer range 15 downto 8; subtype LS_BYTE is integer range 7 downto 0; signal VECTOR : std_logic_vector(15 downto 0); signal SOME_BITS : bit_vector(15 downto 0); signal WORD_1 : MY_WORD; signal WORD_2 : SUB_WORD; begin SOME_BITS <= VECTOR; -- wrong SOME_BITS <= Convert_to_Bit(VECTOR); WORD_1 <= VECTOR; -- wrong WORD_1 <= MY_WORD(VECTOR); WORD_2 <= VECTOR; -- correct WORD_2(LS_BYTE) <= "11110000"; end EXAMPLE; * Subsets of existing types * Same type as the original type * More readable signal assignments * Eliminates type casts and type conversions * Symbolic names for array ranges === Notes === Arrays are also called closely related when they are built of the same data type for their elements and coincide in their length and index set. Consequently, type casts occur frequently when dealing with vector operations as bit vectors (’**bit_vector**’, ’**std_(u)logic_vector**’) themselves do not have a numerical interpretation associated with them. The arithmetic and relational operators for bit vectors operate with ’**signed**’ or ’**unsigned**’ data types that interprete the bit values as 2-complement (sign bit + absolute value) of an arbitrary integer number or binary representation of a positive integer value, respectively. These new data types are built of the same basic types (’**bit**’, ’**std_logic**’), i.e. whenever numerical operations are to be carried out with vectors, their interpretation is provided via the corresponding type cast expression. Of course, the type and operator definitions must be made available first (’**use IEEE.numeric_bit/std.all**’). ===== Aliases ===== architecture EXAMPLE of ALIAS is signal DATA : bit_vector(9 downto 0); alias STARTBIT: bit is DATA(9); alias MESSAGE: bit_vector(6 downto 0) is DATA(8 downto 2); alias PARITY: bit is DATA(1); alias STOPBIT: bit is DATA(0); alias REVERSE: bit_vector(1 to 10) is DATA; function CALC_PARITY(data: bit_vector) return bit is ... begin STARTBIT <= ‘0’; MESSAGE <= "1100011"; PARITY <= CALC_PARITY(MESSAGE); REVERSE(10) <= ‘1’; end EXAMPLE; * Given new names to already existing objects * Make it easier to handle complex data structures Aliases are not always supported by synthesis tools === Notes === Instead of declaring a completely new data type it is possible to declare so called "subtypes", if the new type that is required is just a somewhat restricted version of another type. Subtypes have the same type as their original type and are therefore compatible to the basic type without the need for type casts or conversion functions. Subtypes can also be used to create symbolic names for array ranges. This is synthesizable alternative to the ’**alias**’ construct in VHDL. Aliases are used to give another name to already existing objects. This way it is possible to break down complex data structures into simpler parts that can be accessed directly.