Featured post

Top 5 books to refer for a VHDL beginner

VHDL (VHSIC-HDL, Very High-Speed Integrated Circuit Hardware Description Language) is a hardware description language used in electronic des...

Sunday, 23 December 2012

If Statement

Definition:

The if statement is a statement that depending on the value of one or more corresponding conditions, selects for execution one or none of the enclosed sequences of statements,.

Simplified Syntax

if condition then

  sequential_statements

end if;

if condition then

  sequential_statements

else

  sequential_statements

end if;

if condition then

  sequential_statements

  elsif condition then

    sequential_statements

  else

    sequential_statements

end if;

Description

The if statement controls conditional execution of other sequential statements. It contains at least one Boolean condition (specified after the if keyword). The remaining conditions are specified with the elsif clause. The else clause is treated as elsif true then. Conditions are evaluated one by one until any of them turns to be true or there are no more conditions to be checked for. When a condition is true then the sequence of statements specified after the then clause is executed. If no condition is met then the control is passed to the next statement after the if statement.

The if statement can be used in a simplified form, often called if-then statement, where neither elsif nor else clause is supported (example 1).

In case when meeting a condition should cause some statements to be executed, but when it is not met some other actions should be performed, the else clause is used (example 2).

The elsif clause is used when different nested conditions have to be checked (example 3). This can be used for prioritizing conditions and signals.

The if statements can be nested (example 4).

Examples

Example 1

I1: if Status_Signal = hold
      then A1: Outputs <= 'X';
    end if I1;

The assignment will be realized only when the condition Status_Signal = hold is true. Otherwise, the statement that follows the end if I1 will be executed.

Example 2

function AND_FUNC (x, y: in Bit) return Bit is
begin
  I2: if x = '1' and y = '1'
        then return '1';
      else return '0';
      end if I2;
end AND_FUNC;

When the variables x and y are both equal to '1', then the function returns the value '1'. Otherwise, '0' is returned.

Example 3

Signal Code_of_Operation : Bit_Vector(1 downto 0);
I3: if Code_of_Operation(1) = '1'
      then F := Operand_1 + Operand_2;
    elsif Code_of_Operation(0) = '1'
      then F := Operand_1 - Operand_2;
      else F := "00000000";
    end if I3;

In this example, the bit number 1 of the Code_of_Operation has a higher priority than bit number 0. When the bit number 1 has a '1'value, then the two operands are added. If not (i.e. it is '0'), then the bit number 0 is checked. If it is '1', then the two operands are subtracted. Otherwise, when both bits of the Code_of_Operation are '0', the F signal is assigned all zeros.

Example 4

if Status = RUN
  then
    if Code_of_Operation = CONC
      then
        F := Operand_1 & Operand_2 ;
      else
        F := "00000000";
    end if;
  Output_1 <= F;
end if;

Nesting of if statements is legal, but you should be careful not to confuse the statement levels.

Important Notes

· One of the most typical errors with the if statements is to skip the space between end and if, at the end of the statement, and writing it as endif.

· If is a sequential statement that cannot be used in the concurrent statements section of an architecture. If assigning a new value to a signal must be influenced by a specific condition, then a conditional signal assignment should be used (which in turn cannot be used inside processes and procedures).

Integer Type

Definition:

The integer type is a scalar whose set of values includes integer numbers of the specified range.

Simplified Syntax

type type_name is integer_left_bound to integer_right_bound;

type type_name is integer_left_bound downto integer_right_bound;

Description

An integer type is a numeric type which consists of integer numbers within the specified range. There is a predefined INTEGER type, which range depends on the implementation, however, must cover at least the range -2147483648 to +2147483647.

A user-defined integer type can be constructed on the basis of the predefined INTEGER type by constraining its range (example 1). The bounds of the range of a user-defined integer type should be in the form of a locally static expression. (In VHDL an expression is said to be locally static if it can be evaluated at compile time.) The value of an expression used as a range for an integer type must also be of integer type, not necessarily the same for both bounds (example 2). Negative bounds are allowed.

All integer types (including user-defined) have the same set of arithmetic operators, defined in the package STANDARD, namely: addition, subtraction, multiplication, division, modulus, and remainder. In all cases both operands and the result are of the integer type.

Besides arithmetic operations, relations can also be checked on such integer operands as: equal, unequal, greater than, less than, greater or equal than, and less or equal than. In all cases, the result is Boolean.

Examples

Example 1

type Voltage_Level is range 0 to 5;
type Int_64K is range -65536 to 65535;
type WORD is range 31 downto 0;

An integer type can be defined either as an ascending or descending range.

Example 2

type MUX_ADDRESS is range (2**(N+1))- 1 downto 0;

The parameter N must have an explicitly stated value (e.g. as a constant).

Important Notes

· It is an error to assign to an integer object a value which is from outside its range.

Library Clause

Formal Definition

A library clause defines logical names for design libraries in the host environment.

Simplified Syntax

library library_name;

Description

The library clause defines the logical names of design libraries, which are used by the design units. A library is a storage facility for previously analysed design units. In practice, this relates mostly to packages.

When a package is to be used in a design, it has to be made visible to the design. In order to specify it, the library clause (making the library visible) and use clause (making particular declarations visible) must be used. See use clause for more details.

There are two predefined libraries, which are used implicitly in every design: STD and WORK. The first of them contains standard packages STANDARD and TEXTIO. The other is a working library, where all user-created and analysed design units are stored.

User-specified packages are stored in the working library WORK.

Examples

library IEEE;
use IEEE.Std_Logic_1164.all;

Such declarations as in the above example must precede each design entity, which uses any of the declarations in the package Std_Logic_1164.

Important Notes

· A library specified in a library clause of the primary design unit (entity, configuration or package) is visible in each secondary unit (architecture or package body) associated to it.

· Library STD (containing packages STANDARD and TEXTIO) need not to be specified. Both packages are automatically included in every design unit.

· Package Std_Logic_1164 is specified in the library IEEE. The library IEEE clause must be used in design units, which will use this package.

· Library clause may contain more than one library names separated by commas.

Loop Statement

Formal Definition

Statement that includes a sequence of statements that is to be executed repeatedly, zero or more times.

Simplified Syntax

loop_label: while condition loop

  sequence_of_statements

  end loop loop_label;

loop_label: for loop_parameter in range loop

  sequence_of_statements

  end loop loop_label;

Description

The loop statement contains a sequence of statements, which are supposed to be repeated many times. The statement also lists the conditions for repeating the sequence or specifies the number of iterations.

A loop statement can have several different forms depending on the iteration scheme preceding the reserved word loop. In its simplest form, no iteration scheme is specified and the loop is repeated indefinitely (Example 1).

In order to exit from an infinite loop, an exit statement has to be used. See exit statement for details. An exit statement can be specified with a condition that must be met to exit the loop (Example 2).

Instead of specifying an infinite loop with a conditional exit statement, a while loop can be used. In such a case the reserved word while with a condition precede the keyword loop. The sequence of statements inside the loop will be executed if the condition of the iteration scheme is true. The condition is evaluated before each execution of the sequence of statements. When the condition is false, the loop is not entered and the control is passed to the next statement after the end loop clause (Example 3).

Another iteration scheme is useful when a discrete range can define the number of iterations. In this case the keyword for with a loop parameter precede the keyword loop. The header of the loop also specifies the discrete range for the loop parameter. In each iteration the parameter takes one value from the specified range, starting from the leftmost value within the range (Example 4).

The discrete range can also be declared in the form of a discrete type (example 5), including an enumerated type.

Examples

Example 1

signal Clock : BIT := '0';
...
Clk_1: process (Clock)
begin
  L1: loop
      Clock <= not Clock after 5 ns;
      end loop L1;
end process Clk_1;

The process (which is a clocking signal generator) contains a loop without an iteration scheme, which will iterate indefinitely.

Example 2

L2: loop
    A:= A+1;
    exit L2 when A > 10;
    end loop L2;

The infinite loop becomes in practice a finite, as the iterations will terminate as soon as the variable A becomes greater than 10.

Example 3

Shift_3: process (Input_X)
variable i : POSITIVE := 1;
begin
  L3: while i <= 8 loop
        Output_X(i) <= Input_X(i+8) after 5 ns;
        i := i + 1;
      end loop L3;
end process Shift_3;

The loop L3 will be repeated as long as the value of the variable i is not greater than 8. When i reaches the value of 9 the loop is no longer repeated.

Example 4

Shift_4: process (Input_X)
begin
  L4: for count_value in 1 to 8 loop
       Output_X(count_value) <= Input_X(count_value + 8) after 5 ns;
      end loop L4;
end process Shift_4;

In the above example the loop statement parameter count_value will cause the loop to execute 8 times, with the value of count_value changing from 1 to 8.

Example 5

Shift_5: process (Input_X)
subtype Range_Type is POSITIVE range 1 to 8;
begin
  L5: for count_value in Range_Type loop
       Output_X(count_value) <= Input_X(count_value +8) after 5 ns;
      end loop L5;
end process Shift_5;

The subtype Range_Type defines the range of integer values from 1 to 8. The parameter count_value changes according to this specification, i.e. from 1 to 8.

Important Notes

· The parameter for a 'for' loop does not need to be specified - the loop declaration implicitly declares it.

· The loop parameter is a constant within a loop, which means that it may not be assigned any values inside the loop.

Literal

Formal Definition

A value that is directly specified in a description of a design.

Full Syntax:

literal ::= numeric_literal

| enumeration_literal

| string_literal

| bit_string_literal

| null

numeric_literal ::= abstract_literal | physical_literal

abstract_literal ::= decimal_literal | based_literal

decimal_literal ::= integer [ . integer ] [ exponent ]

integer ::= digit { [ underline ] digit }

exponent ::= E [ + ] integer | E - integer

based_literal ::= base # based_integer [ . based_integer ] # [ exponent ]

base ::= integer

based_integer ::= extended_digit { [underline] extended_digit }

extended_digit ::= digit | letter

physical_literal ::= [ abstract_literal ] unit_name

enumeration_literal ::= identifier | character_literal

character_literal ::= ' graphic_character '

string_literal ::= " { graphic_character } "

bit_string_literal ::= base_specifier " bit_value "

base_specifier ::= B | O | X

bit_value ::= extended_digit { [ underline ] extended_digit }

Description

There are five classes of literals: numeric literals, enumeration literals, string literals, bit string literals and the literal null.

Numeric literals

The class of numeric literals includes abstract literals (which include integer literals and real literals) and physical literals.

The difference between integer and real literals lies in the decimal point: a real literal includes a decimal point, while an integer literal does not. When a real or integer literal is written in the conventional decimal notation it is called a decimal literal. Example 1 presents several abstract literals - both integer and real.

If a number is written in the exponential form, the letter E of the exponent can be written either in lowercase or in uppercase. If the exponential form is used for an integer number then zero exponent is allowed.

Abstract literals can be written in the form of based literals as well. In such a case the base is specified explicitly (in decimal literals the base is implicitly ten). The base in based literal must be at least two and at most sixteen. The base is specified in decimal notation.

The digits used in based literals can be any decimal digits (0..9) or a letter (either in upper or lower case). The meaning of based notation is as in decimal literals, with the exception of base. Several based literals are presented in Example 1.

A Physical literal consists of an abstract numeric literal followed by an identifier that denotes the unit of the given physical quantity (example 1).

Enumeration literals

The enumeration literals are literals of enumeration types, used in type declaration and in expressions evaluating to a value of an enumeration type. They include identifiers and character literals. Reserved words may not be used in identifiers, unless they are a part of extended identifiers which start and end with a backslash. See identifiers for more information on identifiers. Example 2 presents several enumeration literals.

String Literals

String literals are composed as a sequence of graphic characters (letters, digits, special characters) enclosed between two quotation marks (double quotes). They are usually used for warnings or reports which are displayed during simulation (example 3).

Bit string literals

Bit string literals represent values of string literals that denote sequences of extended digits, range of which depends on the specified base.

The base specifier determines the base of the digits: letter B used as a base specifier denotes binary digits (0 or 1), letter O - octal digits (0 to 7) and letter X - hexadecimal (digits 0 to 9 and letters A to F, case insensitive). Underlines can be used to increase readability and have no impact on the value.

All values specified as bit string literals are converted into binary representation without underlines. Binary strings remain unchanged (only underlines are removed), each octal digit is converted into three bits and each hexadecimal into four bits (example 4).

Examples

Example 1

-- Decimal literals:
14
7755
156E7
188.993
88_670_551.453_909
44.99E-22
-- Based literals:
16#FE# -- 254
2#1111_1110# -- 254
8#376# -- 254
16#D#E1 -- 208
16#F.01#E+2 -- 3841.00
2#10.1111_0001#E8 -- 1506.00
-- Physical literals:
60 sec
100 m
kohm
177 A

Abstract literals written in different forms: as decimal, based and physical literals.

Example 2

State0 Idle
TEST \test\
\out\ \OUT\

This example presents several enumeration literals. Note that such literals are not specified in double quotes. Out is a reserved word and as such cannot be used as an identifier (enumeration literal). It may be, however, a part of an extended literal. Extended literals are case sensitive; therefore, \out\ and \OUT\ are different literals.

Example 3

"ERROR"
"Both S and Q equal to 1"
"X"
"BB$CC"
"{LOW}"
"Quotation: ""REPORT..."""

A string literal may contain any number of characters (including special characters), as long as it fits on one line. It can also be a null string or a one-character long string. If a quotation sign has to be used in a string literal, it is denoted by two double quotes side by side.

Example 4

B"1111_1111" -- binary representation of a vector
B"11111111" -- binary representation of the same vector
X"FF" -- hexadecimal representation of the same vector
O"377" -- octal representation of the same vector

Four methods to denote decimal 255 with bit string literals. In all cases the literals will be converted into binary version, i.e. "11111111".

Important Notes

· Underline character can be used in decimal literals (inserted between adjacent digits) to improve readability. In such a case it has no other meaning than just a space.

· Abstract literals cannot contain any spaces, not even between constituents of the exponent.

· A string literal must fit on one line. If longer sequence of characters in required, it may be obtained by concatenating shorter literals.

Name

Formal Definition

A property of an identifier with respect to some named entity. Each form of declaration associates an identifier with a named entity. In certain places within the scope of a declaration, it is valid to use the identifier to refer to the associated named entity; these places are defined by the visibility rules. At such places, the identifier is said to be the name of the named entity.

Simplified Syntax

simple_name ::= identifier

selected_name ::= prefix . suffix

prefix ::= name | function_call

suffix ::= simple_name

        | character_literal

        | operator_symbol

        | all

indexed_name ::= prefix ( expression { , expression } )

slice_name ::= prefix ( discrete_range )

attribute_name ::= prefix [ signature ] ' attribute_designator [ ( expression ) ]

Description

Any declaration that introduces a named entity defines an identifier which enables reference to such an entity by using this identifier. However, it is not always possible to refer to an entity or part of it by using just its identifier. More general form of reference to entities is by a name. Names can also indicate objects of the access type, elements of the composite type, parts of the composite object or unit attributes which have an identifier in their declaration. The name can have any of the following forms:

· simple name

· operator symbol

· selected name

· indexed name

· slice name

· attribute name

The selected name, indexed name, slice name and attribute name contain prefix, which can be also a name or a function call. Prefix of selected name, indexed name or slice name must indicate a composite unit, which is composed of other units (Example 1).

The prefix of an attribute name can indicate any unit for which such an attribute exists (Example 2).

SIMPLE NAME AND OPERATOR SYMBOL

The simple name consists only of the identifier, which is assigned to a given unit in its declaration. The simple name can also indicate an alias of a given unit (Example 3).

The operator symbol is a string literal, which indicates the function declared for such an operator symbol (Example 4).

THE SELECTED NAME

The selected name serves for indicating a unit declared inside another unit or in a design library. A selected name consists of the prefix, which is the name of a composite unit, followed by a dot (.) and then by a suffix which is either the name of the element (if referenced individually) or the reserved word all (if all elements in the composite unit are referenced to).

The selected name can indicate all the units declared in a library and in a package. It can also define elements of a record, as well as objects indicated by pointers. The prefix is the composite unit in which the units are declared. The suffix can be a simple name, character literal, the operator symbol or the reserved word all. In the latter case, the name refers to all elements declared in a unit. Several selected names are presented in Example 5.

The prefix may also have a form of a selected name (with two dots in total), making the reference more complex. This form is used for example in the use clause. See Example 6.

The prefix in the selected name can indicate design entity, architecture body, subprogram, block, process, generate statement or loop statement. The entity indicated by the suffix of this name must be declared inside a given construct (Example 7).

THE INDEXED NAME

The indexed name indicates an element of an array, which is indicated by an expression list forming the array index. The number of expressions in the list must match the array dimension and the expressions values must fit within the respective index ranges (Example 8).

The index name can have the same form as the function call. In such a case, the name's interpretation depends on the context. If the interpretation of such a name is impossible, then the name is ambiguous.

THE SLICE NAME

The slice name allows indicating a part of a one-dimensional array. The part of the object indicated by the slice name is an object of the same class, e.g. slice name of variable is also a variable. The slice name consists of two elements: a prefix and a discrete range. The prefix is the name of the array, while discrete range defines which elements of the object are accessed through the slice name (Example 9).

The discrete range must be compatible with the array range, i.e. the range bounds must not be outside the range declared for the object and the direction must be the same as in the object's declaration.

The slice name is called a null slice if its discrete range is a null range. Null slices are illegal.

THE ATTRIBUTE NAME

The attribute name consists of two elements: a prefix and an attribute designator (name). The prefix indicates a unit, for which the attribute is specified and the attribute designator specifies the name of the attribute (Example 10).

The specification of an attribute name may contain an expression, but this is restricted only to those predefined attributes which require such expression (see attributes (predefined)for details). User-defined attributes may not be used with expressions.

The prefix can also indicate the unit alias. In such a case, attribute name defines the attribute of the unit and not the unit's alias. There are only three exceptions from this rule: attributes SIMPLE_NAME, PATH_NAME and INSTANCE_NAME (Example 11).

If the prefix indicates a subprogram, enumeration literal or an alias of any of the two, then the attribute name can also contain the signature, which helps to resolve any possible ambiguities arising from multiple objects with the same name (Example 12).

Examples

Example 1

C.X
A(1,10)
B(1 to 2)

C is an object of a record type, A is an object of an array type or a function call (the two numbers can be either indices of a two-dimensional array or two parameters of a function call) and B is an object of an array type.

Example 2

D'STABLE (5 ns)

Prefix D indicates a signal of any type.

Example 3

variable E: BIT_VECTOR (0 to 3);
alias F : BIT_VECTOR (0 to 3) is E;
E := "0000";
F := "1111";

E is a simple name which indicates the E variable, and F is a simple name which indicates alias of the E variable.

Example 4

function "+"(a,b: Integer) return REAL;
G := "+"(7,77);

In this example, "+" is an overloaded operator defined by the associated function (declaration of which is given above the call to the operator).

Example 5

WORK.N_GATES
DATA_RECORD.DAY
PAC_OPER."*"
STD_ULOGIC.'X'
NMOS_GATES.all
REC_PTR.all

The first name gives an access to the package N_Gates in the Work library. The second refers to the element Day of the record Data_Record. Note that both names are constructed in the same way and their correct interpretation is possible only from the context (not presented here). The third name relates to operation of a package. Fourth is a value of a type. Finally, the last two names relate to all declarations in a package and all objects addressed by the value of an access type, respectively.

Example 6

A_LIB.PAC_OPER."+"
STD_LOGIC.STD_ULOGIC.'U'

The first complex name gives an access to the "+" operator defined in the PAC_OPER package stored in the A_LIB library. The second example refers to the value "U" declared by the STD_ULOGIC type within STD_LOGIC package.

Example 7

B_1: block
signal Sig_X: BIT := '0';
begin
  ..................
  Gen_1: for i in 1 to 10 generate
          signal Sig_X : Bit;
          begin
            .................
            Sig_X <= B_1.Sig_X;
          end generate;
end block;

The access to the Sig_X signal declared in the B_1 block statement is possible only by using the specification of the selected name in which the prefix is the label of the block statement (i.e. B_1.Sig_X).

Example 8

type MEM_ARRAY is array (1 to 8) of BIT;
variable Mem_Var : MEM_ARRAY := "01000000";
Mem_Var(7)

The Mem_Var variable is the object of the MEM_ARRAY which is a one-dimensional array. That is why the expression list consists of only one value. The index indicates the array's element equal to '1'.

Example 9

variable MEM : BIT_VECTOR (15 downto 0);
MEM (15 downto 8)

The slice name presented in this example refers to the leftmost eight elements of the variable MEM.

Example 10

signal CLK : BIT;
CLK'EVENT -- An attribute EVENT of the signal CLK

The EVENT attribute allows to check for an event that just occurred on the signal indicated by the prefix (in this example CLK).

Example 11

alias MVL_ALIAS: MVL_ARRAY is MVL_VECTOR;
MVL_ALIAS'RIGHT(1)
MVL_ALIAS'SIMPLE_NAME

Attribute 'RIGHT indicates the right bound of the first range of MVL_VECTOR variable. However, 'SIMPLE_NAME relates to the MVL_ALIAS alias.

Example 12

function "xor" (L,R : STD_ULOGIC) return STD_ULOGIC;
attribute Built_In of "xor": function is TRUE;
"xor"[ STD_ULOGIC, STD_ULOGIC return STD_ULOGIC]'Built_In

The signature appearing in the attribute name specification allows describing the right function which has the Built_In attribute and not the standard one.

Important Notes

· Names must follow the rules of writing identifiers. In particular they must start with a letter and be composed of numbers and underscores. See identifier for details.

· None of the VHDL reserved words may be used as a name for other items.

Next Statement

Formal Definition

The next statement is used to complete execution of one of the iterations of an enclosing loop statement. The completion is conditional if the statement includes a condition.

Simplified Syntax

next;

next loop_label;

next loop_label when condition;

Description

The next statement allows to skip a part of an iteration loop. If the condition specified after the when reserved word is TRUE, or if there is no condition at all, then the statement is executed. This results in skipping all statements below it until the end of the loop and passing the control to the first statement in the next iteration (example 1).

A next statement may specify the name of the loop it is expected to influence. If no label is supported then the statement applies to the innermost enclosing loop (example 2)

Examples

Example 1

Loop_Z:  for count_value in 1 to 8 loop
Assign_1:  A(count_value) := '0';
           next when condition_1;
Assign_2:  A(count_value + 8) := '0';
         end loop Loop_Z;

If the condition_1 in the iteration count_value is TRUE, then the next statement will be executed. The next statement to be executed will be Assign_1 in the iteration count_value+1. Otherwise, the sequence of operations is as specified, i.e. Assign_2 is executed.

Example 2

Loop_X: for count_value in 1 to 8 loop
           Assign_1: A(count_value) := '0';
           k := 0;
Loop_Y:   loop
              Assign_2: B(k) := '0';
              next Loop_X when condition_1;
              Assign_3: B(k + 8) := '0';
              k := k + 1;
           end loop Loop_Y;
        end loop Loop_X;

If condition_1 is TRUE, then the next statement is executed and the control goes to the assignment statement labeled Assign_1 in the next iteration of Loop_X. If not, then the iteration is continued with Assign_3, causing incrementing k.

Important Notes

· The next statement is often confused with the exit statement. The difference between the two is that the exit statement "exits" the loop entirely, while the next statement skips to the "next" loop iteration (in other words, it "exits" the current iteration of the loop).