represent a collection of values The standard types that fall into this call are:
A data type which consists of vector or a multi-dimensional set of values of the same base type.
type array_name is array (range, ...) of data_type; -- constrained
type array_name is array (range <>, ...) of data_type; -- unconstrained;
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.
-- 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;
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 |
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;
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.
-- probably declared like this
type bit_vector is array (natural range <>) of bit;
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;
VHDL also provides a predefined unconstrained array type called String.
A String is a sequence of characters.
-- probably declared like this
type string is array (positive range <>) of character;
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;
A composite type whose values consist of named elements.
type record_name is record
element_name, ... : data_type;
...;
end record [ record_name ];
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.
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);
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.
type type_name is access data_type;
type incomplete_type_name;
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.
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;
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.
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
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;
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;