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

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).

Operator Overloading

Definition:

Operator overloading is a declaration of a function whose designator is an operator symbol.

Simplified Syntax

function "operator" (parameters) return type is

function "operator" (parameters) return type is

declarations

  begin

    sequential statements

  end function;

Description

The operator is called overloaded if there is more than one function specifying it for different data and result types. VHDL allows defining operators of the same names as predefined operators, but for different operand types. Both can exist together in one specification, offering greater versatility to the user.

Such functions can be invoked both with prefix notation (Example 1) and usual infix notation (Example 2).

In the case when the operator is called and the operand values belong to different types, it is necessary to use the type conversion or the qualified expression in order to select appropriate operator (Example 3).

Examples

Example 1

type Log4 is ('0', '1', 'Z', 'X');
function "nand" (Left, Right: Log4) return Log4;
function "or" (Left, Right: Log4) return Log4;
signal S1, S2: Log4;
S1 <= "or" ('1', 'Z');
S2 <= "nand"(S1, 'X');

Functions or and nand implement basic logic operations for operands of type Log4 overloading the predefined operations of the same names. In the above example these functions are called using the standard call syntax function (prefix).

Example 2

signal S3, S4: Log4;
S3 <= (S1 nand S2) or 'X';

The operators or and nand are overloaded through the declarations as in the Example 1. Here the overloaded operators are used in the infix form, i.e. with the operator name between the operands.

Example 3

function "or" (Left, Right: Log4) return Bit;
signal S4: Bit;
S4 <= log4('1') or Log4('0');

The or operator is used here in a 4-value logical expression by connecting '1' and '0' operands with the or symbol. The qualified expression was used here to indicate the type of operands (which otherwise would be considered to be of the type BIT).

Important Notes

· Operators "+" and "-" can be defined both as binary operators (with two operands) or unary operators (with one operand).

· Invoking a user-defined overloaded operator always requires evaluation of both operands before the operation is executed (some predefined operators do not evaluate the right operand if the result can be decided from the left operand only).

Null Statement

Formal Definition

A statement which does not perform any action.

Simplified Syntax

null;

Description

The null statement does not perform any action and its only function is to pass on to the next statement. It can be used to indicate that when some conditions are met no action is to be performed. Such an application is useful in particular in conjunction with case statements to exclude some conditions (see example).

Examples

case OPCODE is
  when "001" => TmpData := RegA and RegB;
  when "010" => TmpData := RegA or RegB;
  when "100" => TmpData := not RegA;
  when others => null;
end case;

The example shows an operand detection of a processor, restricted to some simple logical operations performed on registers. All other operations are blocked ("if the OPCODE is other than the explicitly listed, do nothing").

Important Notes

· The keyword null is used not only for "no operation" statements. It has a special meaning for variables of access types ("pointing at no object", which is the default value for such variables - see access type and allocator). There is also a null transaction in waveforms. These three applications of the keyword null should not be confused.

Operators

Definition:

Operators are means for constructing expressions.

Syntax:

adding_operator ::= + | - | &

logical_operator ::= and | or | nand | nor | xor | xnor

miscellaneous_operator ::= ** | abs | not

multiplying_operator ::= * | / | mod | rem

relational_operator ::= = | /= | < | <= | > | >=

shift_operator ::= sll | srl | sla | sra | rol | ror

Description

VHDL has a wide set of different operators, which can be divided into groups of the same precedence level (priority). The table below lists operators grouped according to priority level, highest priority first.

Table 1. Operator priority

miscellaneous operators

** | abs | not

multiplying operators

* | / | mod | rem

sign operators

+ | -

adding operators

+ | - | &

shift operators

sll | srl | sla | sra | rol | ror

relational operators

= | /= | < | <= | > | >=

logical operators

and | or | nand| nor | xor | xnor

The expressions are evaluated form left to right, operations with higher precedence are evaluated first. If the order should be different from the one resulting from this rule, parentheses can be used (Example 1).

The operands, connected with each other by an operator, are evaluated before the operation described by that operator is carried out. For some operators the right operand is evaluated only when the left operand has a certain value assigned to it. The logical operators such as and, or, nand, nor defined for the BIT and BOOLEAN operands belong to those operators.

The operators for the predefined types are defined in the STANDARD package in the STD library. These operators are functions, which always return the same value when they are called with the same values of the actual parameters. These functions are called the pure function (see function for details).

LOGICAL OPERATORS

The logical operators and, or, nand, nor, xor, xnor and not are defined for BIT and BOOLEAN types, as well as for one-dimensional arrays containing the elements of BIT and BOOLEAN. All these operators have the lowest priority, except for the operator not, which has the highest priority. The results of the logical operators for the predefined types are presented in the tables 2 through 8. The BIT type is represented by the values '0' and '1', while the Boolean type by True and False.

Table 2. Operator not

A

not A

True

'1'

False

'0'

False

'0'

True

'1'

Table 3. Operator and

A

B

A and B

True

'1'

True

'1'

True

'1'

True

'1'

False

'0'

False

'0'

False

'0'

True

'1'

False

'0'

False

'0'

False

'0'

False

'0'

Table 4. Operator or

A

B

A or B

True

'1'

True

'1'

True

'1'

True

'1'

False

'0'

True

'1'

False

'0'

True

'1'

True

'1'

False

'0'

False

'0'

False

'0'

Table 5. Operator xor

A

B

A xor B

True

'1'

True

'1'

False

'0'

True

'1'

False

'0'

True

'1'

False

'0'

True

'1'

True

'1'

False

'0'

False

'0'

False

'0'

Table 6. Operator nand

A

B

A nand B

True

'1'

True

'1'

False

'0'

True

'1'

False

'0'

True

'1'

False

'0'

True

'1'

True

'1'

False

'0'

False

'0'

True

'1'

Table 7. Operator nor

A

B

A nor B

True

'1'

True

'1'

False

'0'

True

'1'

False

'0'

False

''0'

False

'0'

True

'1'

False

'0'

False

'0'

False

'0'

True

'1'

Table 8. Operator xnor

A

B

A xnor B

True

'1'

True

'1'

True

'1'

True

'1'

False

'0'

False

''0'

False

'0'

True

'1'

False

'0'

False

'0'

False

'0'

True

'1'

RELATIONAL OPERATORS

The relational operators allow checking relation between operands, i.e. to state whether they are equal, not equal or are ordered in a way defined by operator (Table 9). Both operands must be of the same type, and the result received is always of the Boolean type.

Table 9. Relational operations

=

Equality

/=

Inequality

<

Ordering „less than”

<=

Ordering „less than or equal”

>

Ordering „greater than”

>=

Ordering „greater than or equal”

The operators: equality and inequality are predefined for all types available in the language except the file type. For other relations the operands must be of a scalar type or one-dimensional array types.

The equality operator returns the value TRUE only when both operands have the same values, and FALSE when the values are different. The inequality operator returns the value TRUE when the operators are different and FALSE when they are equal. There are certain rules that are used to compare operands depending on their type: in case of the scalar type, the operand values are equal only when the values are the same. Two values of the composite type are equal only when each value of the left operand corresponds to the value of the right operand and vice versa. In the record the corresponding elements have identical identifiers, and in the array the corresponding elements are those which appear at the same positions of arrays. In particular two null arrays of the same type are always equal.

The operators: <, <=, >, and >= return the TRUE logical value only when the condition in the given relation is met, otherwise the FALSE value is returned (Example 4).

SHIFT OPERATORS

The shift operators are defined for the one-dimensional array with the elements of the type BIT or BOOLEAN. For the shift operator an array is the left operand L and integer is the right operand R. The right operand represents the number of positions the left operand should be shifted. As the result of shifting, the value of the same type as the left operand is returned. Table 10 below shows predefined shift operators.

Table 10. Shift operators

sll

Shift left logical

srl

Shift right logical

sla

Shift left arithmetic

sra

Shift right arithmetic

rol

Rotate left logical

ror

Rotate right logical

The operator sll returns the value of the L left operand, after it has been shifted R number of times. If R is equal to 0 or L is the null array, the left operand L is returned. The single left logical operation replaces L with concatenation of the rightmost (L'Length -1) elements of L and a single value T'Left, where T is the element type of L. If R > the single shift operation is repeated R number of times. If R is a negative number, the value of the expression L srl -R is returned.

The operator srl returns the value of the left operand L after it has been shifted to right R times. In case when R is equal to 0 or L is the null array, the left operand L is returned. The single shifting operation replaces the operand L with the concatenation of the leftmost L'Length -1 elements of L and a single value T'Left, where T is the element type of L. If R is a negative number then the value of expression L sll -R is returned, otherwise the single shift operation is repeated R number of times.

The operator sla returns the value of the left operand L after it has been shifted to the left R number of times. In case when R is equal to 0 or L is the null array the left operand L is returned. The single shift operation replaces L with concatenation of the rightmost L'Length -1 elements of L and a single value L'Right. If R is a negative number, the value of the expression L sra -R is returned, otherwise the single shift operation is repeated R number of times.

The operator sra returns the value of the left operand L after it has been shifted to the right R number of times. In case when R is equal to 0 or L is the null array, the left operand L is returned. The single shift operation replaces L with a value, which is the result of concatenation whose left argument is the leftmost L'Length -1 elements of L and whose right argument is L'Left. If R is a negative number, the value of the expression L sla -R is returned, otherwise the single shift operation is repeated R number of times.

The operator rol returns the value of the L left operand after it has been rotated to the left R times. In case when R is equal to 0 or L is the null array the left operand L is returned. The single shift operation replaces L with a value which is the result of concatenation of the rightmost L'Length -1 elements of L and a single value L'Left. If R > 1 the sing.le shift operation is repeated R times. If R > 1 is a negative number, the expression L ror -R is returned.

The operator ror returns the value of the L left operand after it has been rotated to the right R number of times. In case when R is equal to 0 or L is the null array, the left operand L is returned. The single shift operation replaces L with a value which is the result of concatenation whose left argument is the leftmost L'Length -1 elements of L and whose right argument is L'Right. If R > 1 the single shift operation is repeated R times. If R is a negative number, the expression L rol -R is returned.

ADDING OPERATORS

Adding operators consist of addition, subtraction and concatenation. The adding operators are shown in the Table 11 below.

Table 11. Adding operators

+

Addition

-

Subtraction

&

Concatenation

The adding and subtraction operators perform mathematical operations, and their operands can be of any numeric type.

The concatenation (&) operator is defined for elements of one-dimensional arrays. In the concatenation, the following situations can take place:

· When both operands are one-dimensional arrays of the same type, the concatenation connects the two arrays into one. The new array contains the elements from both arrays. The direction of the new array is the same as the direction in the array of the left operand, but if the left operand is the null array then it is the same as the direction of the right operand. In case when both operands are null arrays, the direction of the right operand is assumed (Example 6).

· When one of the operands is a one-dimensional array and the second operand is a scalar of the same type as the elements of that array, then the result of the concatenation is the same as in the first point. However, in this case the second operand is treated as a one-dimensional array which contains only one element (Example 6).

· In case when both operands are of the same scalar type, then the result of concatenation is one-dimensional array with elements of the same types as the operands (Example 6).

SIGN OPERATORS

Sign operators are unary operators, i.e. have only one, right operand, which must be of a numeric type. The result of the expression evaluation is of the same type as the operand. There are two sign operators (Table 12).

Table 12. Sign operators

+

Identity

-

Negation

When ( + ) sign operator is used, the operand is returned unchanged, but In case of ( - ) sign operator the value of operand with the negated sign is returned. Because of the lower priority, the sign operator in the expression cannot be directly preceded by the multiplication operator, the exponentiation operator (**) or the abs and not operators. When these operators are used then sign operator and its operand should be enclosed in parentheses (Example 7).

MULTIPLYING OPERATORS

The multiplication and division operators are predefined for all integers, floating point numbers. Under certain conditions, they may be used for operations on physical type objects as well. The mod and rem operators, on the other hand, are defined only for the integers. When mod and rem operators are used, then both the operands and the result are of the same integer type. The multiplying operators are shown in the Table 13.

Table 13. Multiplying operators

*

Multiplication

/

Division

mod

Modulus

rem

Remainder

MISCELLANEOUS

The two miscellaneous operators are shown in the Table 14.

Table 14. Miscellaneous operators

**

Exponentiation

abs

Absolute value

The abs operator has only one operand. It allows defining the operand's absolute value. The result is of the same type as the operand.

The exponentiation operator has two operands. This operator is defined for any integer or floating point number. The right operand (exponent) must be of integer type. When the exponent is the positive integer, then the left operand is repeatedly multiplied by itself. When the exponent is the negative number, then the result is a reverse of exponentiation with the exponent equal to the absolute value of the right operand (Example 9). If the exponent is equal to 0 the result will be 1.

Examples

Example 1

v := a + y * x;

The multiplication y*x is carried out first, then a is added to the result of multiplication. This is because the multiplication operator has higher level of priority than the adding operator.

Example 2

variable We1, We2, We3, Wy : BIT := '1';
Wy := We1 and We2 xnor We1 nor We3;

For the initial value of the variables We1, We2, We3 equal to '1', the result is assigned to the variable Wy and is equal to '0'.

Example 3

variable Zm1: REAL := 100.0;
variable Zm2 : BIT_VECTOR(7 downto 0) := ('0','0','0','0','0','0','0','0');
variable Zm3, Zm4 : BIT_VECTOR(1 to 0);
Zm1 /= 342.54 -- True
Zm1 = 100.0 -- True
Zm2 /= ('1', '0', '0', '0', '0', '0', '0', '0') -- True
Zm3 = Zm4 -- True

Example 4

Zm1 > 42.54 -- True
Zm1 >= 100.0 -- True
Zm2 < ('1', '0', '0', '0', '0', '0', '0', '0') -- True
Zm3 <= Zm2 -- True

Example 5

variable Zm5 : BIT_VECTOR(3 downto 0) := ('1','0','1','1');
Zm5 sll 1 -- ('0', '1', '1', '0')
Zm5 sll 3 -- ('1', '0', '0', '0')
Zm5 sll -3 -- Zm5 srl 3
Zm5 srl 1 -- ('0', '1', '0', '1')
Zm5 srl 3 -- ('0', '0', '0', '1')
Zm5 srl -3 -- Zm5 sll 3
Zm5 sla 1 -- ('0', '1', '1', '1')
Zm5 sla 3 -- ('1', '1', '1', '1')
Zm5 sla -3 -- Zm5 sra 3
Zm5 sra 1 -- ('1', '1', '0', '1')
Zm5 sra 3 -- ('1', '1', '1', '1')
Zm5 sra -3 -- Zm5 sla 3
Zm5 rol 1 -- ('0', '1', '1', '1')
Zm5 rol 3 -- ('1', '1', '0', '1')
Zm5 rol -3 -- Zm5 ror 3
Zm5 ror 1 -- ('1', '1', '0', '1')
Zm5 ror 3 -- ('0', '1', '1', '1')
Zm5 ror -3 -- Zm5 rol 3

Example 6

constant B1: BIT_VECTOR := "0000"; -- four element array
constant B2: BIT_VECTOR := "1111"; -- four element array
constant B3: BIT_VECTOR := B1 & B2; -- eight element array, ascending
-- direction, value "00001111"
subtype BIT_VECTOR_TAB is BIT_VECTOR (1 downto 0);
constant B4: BIT_VECTOR_TAB := "01";
constant B5: BIT_VECTOR:= B4 & B2; -- six element array, descending
-- direction, value "011111"
constant B6 : BIT := '0' ;
constant B7 : BIT_VECTOR := B2 & B6;-- five element array, ascending
-- direction, value "11110"
constant B8: BIT := '1';
constant B9: BIT_VECTOR := B6 & B8; -- two element array, ascending
-- direction value "01"
Example 7
z := x * ( -y) -- A legal expression
z := x / (not y) -- A legal expression

The same expressions without parentheses would be illegal.

Example 7

variable A,B :Integer;
variable C : Real;
C:= 12.34 * ( 234.4 / 43.89 );
A:= B mod 2;

Example 8

2 ** 8 = 256
3.8 ** 3 = 54.872
4 ** (-2) = 1 / (4**2) = 0.0625

Important Notes

· All predefined operators for standard types are declared in the package STANDARD.

· The operator not is classified as a miscellaneous operator only for the purpose of defining precedence. Otherwise, it is classified as a logical operator.