Basics of VHDL programming


VHDL is a Hardware Description programming language used to design hardware systems such as FPGA and is an alternative to Verilog. It stands for Very High Speed IC Description Language. VHDL has finer control and can be used to design low level systems like gates to high level systems like in Verilog.

VHDL is a strongly typed language and is not case sensitive.

A program in VHDL is known as a VHDL model and each VHDL model has two components:

  • entity
  • architecture

In simple terms, Entity can be though of as a class while architecture is a function.

Entity represents the interface specification of the component in the model and the architecture represents the internal structure or implementation of the entity.

A design entity is a basic element in a VHDL model. It can have different levels of abstraction like gate, printed circuit board or the entire system. The different levels of abstraction is classified into:

  • Behavorial
  • Dataflow
  • Structural

In VHDL, a design entity is a module (as in software system) with its inputs and output which are refered as ports.

An entity is declared as:

ENTITY entity_name IS
[GENERIC (generic list);]
[PORT (port list);]
END [entity_name];

Example of entity declaration as a Half Adder gate:

ENTITY half_adder IS
[PORT (x, y, enable : IN BIT;
carry, result : OUT BIT);
END half_adder;

The architecture/ behaviour can be defined as follows:

ARCHITECTURE architecture_name OF entity_name IS
BEGIN
    PROCESS (x, y, enable)
    BEGIN
            <some code statements>
    END PROCESS;
END architecture_name;

Example of architecture for Half adder gate:

BEGIN
    PROCESS (x, y, enable)
    BEGIN
        IF enable = ‘1’ THEN
            result <= x XOR y;
            carry <= x AND y;
        ELSE
            carry <= ‘0’;
            result <= ‘0’;
        END IF;
    END PROCESS;
END half_adder_a;

Note an entity can have multiple architectures. One can think of entity as the function interface and architecture as different method implementations.

There can be three types of architectures like:

  • one can defined structure using design of sub-components and interconnections
  • second type is to have a sequence of statements (dataflow)
  • third type captures the timing and functional characteristics

Key terms in VHDL programming:

  • Packages: collection of declaration, constants and subprograms for entities and architecture
  • Generics: method for storing data (like a variable)
  • Ports: method for a device to communicate with external devices. It defines name, direction and default value for signals.
  • Configuration: method to attach instances to entities
  • Bus: method for communication
  • Driver: source of signal
  • Attribute: information about an VHDL object

Ports

Port defines the interface for signals (information) for the external devices. Port has the following components:

  • Name
  • Mode
  • Data type
  • Initial value of signal (optional)

Syntax:

PORT (signal_name : mode data_type);

Example:

PORT ( input : IN BIT_VECTOR(3 DOWNTO 0);
ready, output : OUT BIT );

Mode in Port defines the direction of signal. It can have the following values:

  • In: data comes in only for reading
  • Out: data goes to an external device
  • Buffer: data is birectional and it takes one direction at a time based on driver
  • Inout: data is birectional and controlled by multiple drivers
  • Linkage: direction of data is not predefined

Generics

Generics defines the method to store data like a variable.

Syntax:

GENERIC (generic_name : type [:= default_value]);

Example:

GENERIC (My_ID : INTEGER := 37);

VHDL programming constructs

  • Comments

Comment is defined by two dashes like:

-- this is a comment
  • Identifier

An letter including underscore and digit like

og
  • Character and strings

Characters are defined by single quotes and strings are defined by double quotes like:

'o' -- this is a character
"opengenus" -- this is a string
  • Bit strings

Bit strings have a special identifer at the beginning followed by a string like:

B"0101" -- binary
O"641" -- octal
X"9A" -- hexadecimal

Data types

VHDL is a strongly typed language. There are three types of data types:

  • Scalar

  • Composite

  • Access

  • Scalar is atomic unit of information like an integer

  • Composite is a data structure like array

  • Access to pointer to a data

Variables are defined in PROCESS section of architecture and used in BEGIN section like:

ARCHITECTURE test_int OF test IS
BEGIN
    PROCESS (X)
        VARIABLE a: INTEGER;
    BEGIN
        a := 1; -- OK
        a := 1.0; -- error as 1.0 is not integer
    END PROCESS;
END test_int;

Accordingly, REAL datatype can be real value between -1 * 10^38 and 1 * 10^38. Example of using REAL:

ARCHITECTURE test_real OF test IS
BEGIN
    PROCESS (X)
        VARIABLE a: REAL;
    BEGIN
        a := 1.01; -- OK
        a := -10.01; -- OK
        a := 1.1E11; -- OK
        a := 1; -- error
    END PROCESS;
END test_real;

Enumerated datatype

Enumerated data types define possible values for a given variable like:

TYPE bit IS ( 0, 1 );

bit can take only 0 and 1.

Complete Example:

TYPE bit IS ( 0, 1 ); 
... some statements ...
ARCHITECTURE test_enum OF test IS
    BEGIN
    PROCESS (X)
        VARIABLE a: binary;
    BEGIN
        a := 0; -- OK
        -- more statements ...
        a := 1; -- OK
        -- more statements ...
    END PROCESS;
END test_enum;

Array

An array in VHDL is defined as follows:

type 2Darray is array ( 0 to 4, 0 to 40 ) of real;

Example of 1D array as a data bus:

TYPE data_bus IS ARRAY(0 TO 31) OF BIT;

Use:

VARIABLE X : data_bus;
VARIABLE Y : BIT;
Y := X(10); -- Y gets value of element at index 10

Record

RECORD is used to group different variables of different types in the same VHDL object like (data_info is a record):

TYPE binary IS ( ON, OFF );
TYPE data_info IS
RECORD
    status : BINARY;
    ID : INTEGER;
END RECORD;
...
VARIABLE data : data_info;
data.status := ON; -- status of the data
data.ID := 30;     -- ID of the data

Subtypes

Subtypes allow user defined constraints on existing data types.

Syntax:

SUBTYPE name IS base_type RANGE <user range>;

Example:

SUBTYPE first_ten IS INTEGER RANGE 0 TO 9;

There are four types of objects in VHDL:

  • Constants
  • Variables
  • Signals
  • Files

Constant

Constants are variables whose data does not change after initialization.

Syntax:

CONSTANT constant_name:type_name[:=value/expression];

Example:

CONSTANT PI : REAL := 3.14;
CONSTANT SPEED : INTEGER;
CONSTANT N : INTEGER := 8*SPEED;

Variable

Syntax for variable:

VARIABLE variable_name : type_name [:= value];

Syntax for assignment of value to a variable:

[label:] name := expression ;

Example:

VARIABLE opcode : BIT_VECTOR(3 DOWNTO 0) := "0000";
VARIABLE freq : INTEGER;
VARIABLE start : time := 0 ns;
VARIABLE finish : time := 0 ns;
-- equivalent to
VARIABLE start, finish : time := 0 ns;

ns is the unit defined by default in VHDL.

Signal

Signal is used for communication between different VHDL components.

Syntax:

SIGNAL signal_name : type_name [:= value]

Example:

SIGNAL day : BIT;
day <= ‘0’ AFTER 5ns, ‘1’ AFTER 10ns;

This brings in the concept of timing model as if day is 0, next statement is executed after 5 nanoseconds and if it is 1, the delay becomes 10 nanoseconds.

There are different types of delay like inertia delay but we shall cover it in a separate post.

Following are the types of operators in VHDL:

  • Miscellaneous operators: **, abs, not
  • Multiplication operators: *, /, mod, rem
  • Sign operator: +, -
  • Addition operators: +, -, &
  • Shift operators: sll, srl, sla, sra, rol, ror
  • Relational operators: =, /=, <, <=, >, >=
  • Logical operators: AND, OR, NAND, NOR, XOR, XNOR

We can use the above operators to do calculations within a VHDL program like:

result <= a AND NOT(B) OR NOT(a) AND b;

There are multiple control flow statements in VHDL. One of them is if statement.

Syntax:

if_statement <=
[if_label : ]
if boolean_expression then
    { sequential_statement }
{ elsif boolean_expression then
    {sequential_statement }}
[else
    { sequential_statement }]
end if [if_label];

Example:

if mode=immediate then
    operand:=immed_operand;
elsif opcode=load or opcode=add or opcode=subtract then
    operand:=memory_operand;
else
    operand:=address_operand;
end if;

There are multiple ways to implement a loop in VHDL. We will explore a simple type with an example.

Example of a nested loop in VHDL:

begin
    count<= count_value;
    loop
        loop
            wait until clk=‘1’ or reset =‘1’;
            exit when reset =‘1’;
            count_value:=(count_value +1) mod 16;

Wait statement is used to pause execution while a condition is statified like:

WAIT FOR 150 ns;

Example:

Summation: PROCESS
BEGIN
    Sum <= A XOR B XOR Cin;
    WAIT UNTIL A = ‘1’;
END PROCESS Summation;

Functions

We can define functions in VHDL as well. Example of function:

FUNCTION add_bits
(a, b : IN BIT)s

Example of using the above function:

ARCHITECTURE behavior OF adder IS
BEGIN
    PROCESS (enable, x, y)
    BEGIN
    IF (enable = '1') THEN
        result <= add_bits(x, y);
        carry <= x AND y;
    ELSE
        carry, result <= '0';
END PROCESS;
END behavior;

Further, we can define several VHDL program components like packages, assertions, subprograms, binding, generic maps and others which is covered in our advanced guide to VHDL programming.

In this article, we have explored all basic VHDL programming concepts and you are good to write most basic programs like implementing a half adder, full adder, stimulating a data flow system and many more.