Composite types

represent a collection of values The standard types that fall into this call are:

Array

Definition:

A data type which consists of vector or a multi-dimensional set of values of the same base type.


Syntax:


            type array_name is array  (range, ...) of data_type;  -- constrained
            type array_name is array  (range <>, ...) of data_type;  -- unconstrained;
        

Description:

An array is a composite object, which elements are of the same subtype. Each element is uniquely distinguished by an index. The number of indices is the number of dimensions, i.e. one-dimensional array has one index, two-dimensional has two indices, etc.
An array may be either constrained or unconstrained. The array is constrained if the size of the array is constrained. The size of the array can be constrained using a discrete type mark or a range.
The array is said to be unconstrained if its size is unconstrained: the size of the unconstrained array is declared in the form of the name of the discrete type, which range is unconstrained.
The number of elements of unconstrained array type is unknown. The values within an array can be read or written using an indexed name or a slice name.

Example:


            -- declaration of an array type to represent words of data
            type word is array (31 downto 0) of bit;

            -- declaration of an Enumeration type
            type control_state is (initial, idle, active, error);

            subtype Byte is std_logic_vector(7 downto 0);
            type Mem is array (0 to 63) of Byte;
            variable Memory : Mem;
            ...
            if Read then
                Data <= Memory(to_integer(Address));
            elsif Write then
                Memory(to_integer(Address)) := Data;
            end if;
    

Notes

Array Attributes

Description:

VHDL provides a number of attributes to refer to information about the index ranges of array types and objects. Attributes are written by following the array type or object name with the symbol ' and the attribute name.
Given some array type or object A, and an integer N between 1 and the number of dimensions of A, VHDL defines the following attributes:

Identifier Description
A 'left Left bound of index range of A
A 'right Right bound of index range of A
A ' range Index range of A
A 'reverse_range Reverse of index range of A
A 'length Length of index range of A

Example:


        type A is array (1 to 4) of boolean;
        A'left -- A'left = 1
        A'right -- A'right = 4
        A'range -- A'range is 1 to 4
        A'reverse_range -- A'reverse_range is 4 downto 1
        A'length -- A'length = 4

        -- another example
        -- assuming free_map is an array of bits
        count := 0;
        for index in free_map'range loop
            if free_map(index) = '1' then
            count := count + 1;
            end if;
        end loop;
        
    

Bit Vectors

Definition

VHDL provides a predefined unconstrained array type called bit_vector.
A bit_vector is a data type that represents a vector of individual bits.
similar to an array, where each element of the vector is single bit.

Syntax:


        -- probably declared like this
        type bit_vector is array (natural range <>) of bit;
    

Example:


        entity example_entity is
        port (
            input_data : in bit_vector(7 downto 0);
            output_data : out bit_vector(7 downto 0)
        );
        end entity example_entity;

        architecture rtl of example_entity is
        begin
            output_data <= input_data;
        end architecture rtl;
    

Notes:

String

Description:

VHDL also provides a predefined unconstrained array type called String.
A String is a sequence of characters.

Syntax:


        -- probably declared like this
        type string is array (positive range  <>) of character;
        
    

Example:


        library ieee;
        use ieee.std_logic_1164.all;

        entity example_string is
        end entity example_string;

        architecture rtl of example_string is
            -- string declaration and initialization
            signal greeting : string := "Hello, ";
            signal name : string := "John";
            signal full_message : string;
        begin
            -- Concatenate the strings
            full_message <= greeting & name;
        end architecture rtl;

        
    

Notes:

Record

Definition:

A composite type whose values consist of named elements.

Syntax:


            type record_name is record
            element_name, ... : data_type;
            ...;
            end record [ record_name ];
        

Description:

A data type that represents a set of values of different types. Used to define data structures. Not typically used to describe hardware,
but useful for high level modelling. All elements are declared with individual names.
The names of elements in each record must be distinct. However, the same element name can be used in different records. The value of an object of type record is a composite value, consisting of the values of its elements.
The assignment of a value to an object of the type record can be realized either through an aggregate or through individual assignments to elements (selected names).
When individual assignment to elements is used then each element is referenced by the record name followed by a dot and element's name.

Example:


            type Person is record
                FirstName: string (1 to 20);
                Married: boolean;
                Children: natural;
            end record;

          variable V1, V2: Person;
          V1.Children:= 1;
          V2:= ("John", false, 0);
        

Notes

Access

Definition:

A type that allows dynamic memory allocation. An access value is returned by an allocator (equivalent to pointers in C or Pascal).
An access type must be defined for a particular data type, such as a record or scalar type. Access types support the allocation and deallocation of memory during simulation. In VHDL,
dynamic memory allocation is done using the new keyword, and memory can be deallocated using the deallocate procedure from the std.standard package.
Access types are primarily used when the size or number of data elements is not known at compile time, such as linked lists or dynamically growing arrays.


Syntax:


            type type_name is access data_type;

            type incomplete_type_name;
        

Description:

Access type allows to manipulate data, which are created dynamically during simulation and which exact size is not known in advance. Any reference to them is performed via allocators, which work in a similar way as pointers in programming languages. The only objects allowed to be of the access type are variables. The default value of an access type is null. For each incomplete type declaration there must be a corresponding full type declaration with the same name. The complete declaration must appear in the same declarative part. A type declared as incomplete may not be used for any other purposes than to define an access type before the complete type definition is accomplished.

Example:


library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

-- Define a record type called 'node_type'
type node_type is record
    data : integer;
    next : access node_type; -- Pointer to the next node (self-referencing type)
end record;

-- Define an access type 'node_ptr' that points to 'node_type'
type node_ptr is access node_type;

-- Architecture demonstrating the use of access types
architecture AccessTypeExample of Test is
    signal head : node_ptr := null; -- Initial pointer set to null
begin
    process
        variable temp_node : node_ptr;
    begin
        -- Dynamically allocate memory for a new node using the 'new' keyword
        head := new node_type'(data => 1, next => null);

        -- Allocate a second node and link it to the first node
        temp_node := new node_type'(data => 2, next => null);
        head.next := temp_node;

        -- Allocate a third node and link it to the second node
        temp_node := new node_type'(data => 3, next => null);
        head.next.next := temp_node;

        -- Output the linked list
        report "Node 1 data: " & integer'image(head.data);
        report "Node 2 data: " & integer'image(head.next.data);
        report "Node 3 data: " & integer'image(head.next.next.data);

        wait;
    end process;
end AccessTypeExample;
        

Notes

File

Definition:

the file type allows you to read from and write to files, enabling you to perform I/O operations during simulation. This can be particularly useful for reading test vectors, logging outputs, or comparing expected results with actual outputs.


Syntax:


        type new_name is file of type_name;

        file new_name: data_type [ [ open file_kind ] is file_name ];
        file_kind = read_mode | write_mode | append_mode
        file new_name: data_type is [ mode ] file_name;                -- VHDL'87 only
        mode = in | out                                                -- VHDL'87 only

        file_name = string_expression
        

Description:

The file declaration creates one or more file objects of the specified type. Such a declaration can be included in any declarative part in which the objects can be created, that is within architecture bodies, processes, blocks, packages or subprograms. The optional open file_kind allows specifying how the physical file associated with the file object should be opened. The expression must have the predefined type file_open_kind value, which is declared in the Standard package. The file_name must be an expression of predefined type String. The file_name identifies an external file in the host file system that is associated with the file object. This association provides a mechanism for either importing data contained in an external file into the design during simulation or exporting data generated during simulation to an external file. : VHDL provides a set of standard file operations, such as read, write, open, close and more, which are defined in the textio package (found in the std library). These operations allow you to interact with files, line-by-line, for reading or writing data.


procedure file_open (file F: FT;
                     external_name: in string;
                     open_kind: in file_open_kind := read_mode);
procedure file_open (status: out file_open_status;
                     file F: FT;
                     external_name: in string;
                     open_kind: in file_open_kind := read_mode);
procedure file_close (file F: FT);
procedure read (file F: FT; value: out TM);
procedure write (file F: FT; value: in TM);
function endfile (file F: FT) return BOOLEAN;

Example:


        library IEEE;
        use IEEE.STD_LOGIC_1164.ALL;
        use STD.TEXTIO.ALL; -- Import the textio package

        type DataFile is file of string;
        file F: DataFile open write_mode is "FileName";   -- VHDL'93
        file F: DataFile is out "filename";   -- VHDL'87
    

        library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use STD.TEXTIO.ALL; -- Import the textio package

entity File_IO_Example is
end File_IO_Example;

architecture Behavioral of File_IO_Example is
    -- Declare a file object
    file input_file  : text open read_mode is "input_data.txt"; -- Open a file for reading
    file output_file : text open write_mode is "output_data.txt"; -- Open a file for writing

    -- Declare a variable to hold a single line of text
    variable line_buffer : line;
    signal finished : boolean := false;

begin
    process
        variable data_in : integer;
        variable data_out : integer;
    begin
        -- Check if the input file is open and read until the end of file is reached
        while not endfile(input_file) loop
            readline(input_file, line_buffer); -- Read a line from the input file
            read(line_buffer, data_in); -- Read an integer value from the line

            -- Perform a simple operation (e.g., increment the value)
            data_out := data_in + 1;

            -- Write the modified value to the output file
            writeline(output_file, line_buffer); -- Write the line to the output file
            write(line_buffer, data_out); -- Write the updated integer to the line
            writeline(output_file, line_buffer); -- Save the line to the file
        end loop;

        -- Close the files
        file_close(input_file);
        file_close(output_file);

        -- End the simulation
        finished <= true;
        wait until finished;
    end process;
end Behavioral;

    

Notes