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

Monday, 31 December 2012

Assertion Statement

Formal Definition

A statement that checks that a specified condition is true and reports an error if it is not.

Simplified Syntax

assert condition

  report string

  severity severity_level;

Description

The assertion statement has three optional fields and usually all three are used.

The condition specified in an assertion statement must evaluate to a boolean value (true or false). If it is false, it is said that an assertion violation occurred.

The expression specified in the report clause must be of predefined type STRING and is a message to be reported when assertion violation occurred.

If the severity clause is present, it must specify an expression of predefined type SEVERITY_LEVEL, which determines the severity level of the assertion violation. The SEVERITY_LEVEL type is specified in the STANDARD package and contains following values: NOTE, WARNING, ERROR, and FAILURE. If the severity clause is omitted it is implicitly assumed to be ERROR.

When an assertion violation occurs, the report is issued and displayed on the screen. The supported severity level supplies an information to the simulator. The severity level defines the degree to which the violation of the assertion affects operation of the process:

· NOTE can be used to pass information messages from simulation (example 1);

· WARNING can be used in unusual situation in which the simulation can be continued, but the results may be unpredictable (example 2);

· ERROR can be used when assertion violation makes continuation of the simulation not feasible (example 3);

· FAILURE can be used when the assertion violation is a fatal error and the simulation must be stopped at once (example 4).

Assertion statements are not only sequential, but can be used as concurrent statements as well. A concurrent assertion statement represents a passive process statement containing the specified assertion statement.

Examples

Example 1

assert Status = OPEN_OK
  report "The call to FILE_OPEN was not successful"
  severity WARNING;

Having called the procedure FILE_OPEN, if the status is different from OPEN_OK, it is indicated by the warning message.

Example 2

assert not (S= '1' and R= '1')
  report "Both values of signals S and R are equal to '1'"
  severity ERROR;

When the values of the signals S and R are equal to '1', the message is displayed and the simulation is stopped because the severity is set to ERROR.

Example 3

assert Operation_Code = "0000"
  report "Illegal Code of Operation"
  severity FAILURE;

Event like illegal operation code are severe errors and should cause immediate termination of the simulation, which is forced by the severity level FAILURE.

Important Notes

· The message is displayed when the condition is NOT met, therefore the message should be an opposite to the condition.

· Concurrent assertion statement is a passive process and as such can be specified in an entity.

· Concurrent assertion statement monitors specified condition continuously.

· Synthesis tools generally ignore assertion statements.

Attributes (predefined)

Formal Definition

A value, function, type, range, signal, or constant that may be associated with one or more named entities in a description.

Simplified Syntax

object'attribute_name

Description

Attributes allow retrieving information about named entities: types, objects, subprograms etc. VHDL standard defines a set of predefined attributes. Additionally, users can define new attributes, and then assign them to named entities by specifying the entity and the attribute values for it. See attributes (user-defined) for details.

Predefined attributes denote values, functions, types, and ranges that characterize various VHDL entities. Separate sets of attributes are predefined for types, array objects or their aliases, signals and named entities.

Each type or subtype T has a basic attribute called T'Base, which indicates the base type for type T (Table 1). It should be noted that this attribute could be used only as a prefix for other attributes.

Table 1. Attributes available for all types

Attribute

Result

T'Base

base type of T

Scalar types have attributes, which are described in the Table 2. Letter T indicates the scalar type.

Table 2. Scalar type attributes

Attribute

Result type

Result

T'Left

same as T

leftmost value of T

T'Right

same as T

rightmost value of T

T'Low

same as T

least value in T

T'High

same as T

greatest value in T

T'Ascending

boolean

true if T is an ascending range, false otherwise

T'Image(x)

string

a textual representation of the value x of type T

T'Value(s)

base type of T

value in T represented by the string s

Discrete or physical types and subtypes additionally have attributes, which are described in Table 3. The discrete or physical types are marked with letter T before their names.

Table 3. Attributes of discrete or physical types and subtypes

Attribute

Result type

Result

T'Pos(s)

universal integer

position number of s in T

T'Val(x)

base type of T

value at position x in T (x is integer)

T'Succ(s)

base type of T

value at position one greater than s in T

T'Pred(s)

base type of T

value at position one less than s in T

T'Leftof(s)

base type of T

value at position one to the left of s in T

T'Rightof(s)

base type of T

value at position one to the right of s in T

Array types or objects of the array types have attributes, which are listed in the Table .4. Aliases of the array type objects have the same attributes. Letter A denotes the array type or array objects below.

Table 4. Attributes of the array type or objects of the array type

Attribute

Result

A'Left(n)

leftmost value in index range of dimension n

A'Right(n)

rightmost value in index range of dimension n

A'Low(n)

lower bound of index range of dimension n

A'High(n)

upper bound of index range of dimension n

A'Range(n)

index range of dimension n

A'Reverse_range(n)

reversed index range of dimension n

A'Length (n)

number of values in the n-th index range

A'Ascending(n)

True if index range of dimension n is ascending, False otherwise

Signal attributes are listed in Table 5. Letter S indicates the signal names.

Table 5. Signals attributes

Attribute

Result

S'Delayed(t)

implicit signal, equivalent to signal S, but delayed t units of time

S'Stable(t)

implicit signal that has the value True when no event has occurred on S for t time units, False otherwise

S'Quiet(t)

implicit signal that has the value True when no transaction has occurred on S for t time units, False otherwise

S'Transaction

implicit signal of type Bit whose value is changed in each simulation cycle in which a transaction occurs on S (signal S becomes active)

S'Event

True if an event has occurred on S in the current simulation cycle, False otherwise

S'Active

True if a transaction has occurred on S in the current simulation cycle, False otherwise

S'Last_event

the amount of time since last event occurred on S, if no event has yet occurred it returns Time'High

S'Last_active

the amount of time since last transaction occurred on S, if no event has yet occurred it returns Time'High

S'Last_value

the previous value of S before last event occurred on it

S'Driving

True if the process is driving S or every element of a composite S, or False if the current value of the driver for S or any element of S in the process is determined by the null transaction

S'Driving_value

the current value of the driver for S in the process containing the assignment statement to S

The named entities have attributes described in Table 6. Letter E denotes the named entities.

Table 6. Attributes of named entities

Attribute

Result

E'Simple_name

a string representing the simple name, character literal or operator symbol defined in the declaration of the item E

E'Path_name

a string describing the path through the design hierarchy, from the root entity or package to the item E

E'Instance_name

a string describing the path through the design hierarchy, from the root entity or package to the item E, but including the names of the entity and architecture bound to each component instance in the path

Paths which can be written using E'Path_name and E'Instance_name are used for reporting and assertion statements. They allow specifying precisely where warnings or errors are generated. E'Simple_name attribute refers to all named entities, E'Path_name and E'Instance_name can refer to all named entities apart from the local ports and generic parameters in the component declaration.

There is one more predefined attribute: 'Foreign' that allows the user to transfer additional information to the simulator. The information contains the instruction for special treatment of a given named entity. The exact interpretation of this attribute, however, depends on its implementation in particular simulator.

Examples

Example 1

type Table is array (1 to 8) of Bit;
variable Array_1 : Table := "10001111";
Array_1'Left, the leftmost value in index range of Table array, is equal to 1.

Example 2

type Table is array (Positive range <>) of Bit;
subtype Table_New is Table (1 to 4);
Table_New'Base, the base type of the Table_New subtype is Table.

Example 3

type New_Range is range 1 to 10;
New_Range'Ascending is TRUE (the New_Range type is of ascending range).

Example 4

type New_Values is (Low, High, Middle);
New_Values'Pred(High) will bring the 'Low' value.

Example 5

type Table is array (1 to 8) of Bit;

Table'Range(1) is the range of the first index of Table type and returns '1 to 8'; Table'Range will have the same interpretation for one dimensional array.

Important Notes

  • Not all predefined attributes are supported by synthesis tools; most tools support 'high, 'low, 'left, 'right, range, 'reverse_range, 'length and 'event. Some also support'last_value and 'stable.

Attributes (user-defined)

Formal Definition

A value, function, type, range, signal, or constant that may be associated with one or more named entities in a description.

Simplified Syntax

attribute attribute_name: type;             -- attribute declaration

attribute attribute_name of item : item_class is expression; -- attribute specification

Description

VHDL allows attaching additional information to design elements through new attributes for specified types. In order to assign an attribute to a given design element, attribute specification is used. The values assigned this way can be referred in the expressions through declared attribute name.

The attribute declaration defines a new attribute within the scope of the given declarative area. It consists of an identifier specification, which represents user defined attribute and type mark that indicates value type for this attribute. A user-defined attribute can be of any VHDL type, except for an access type, file type, and any complex type with elements of any of the two types. See Example 1.

Attribute specification assigns an attribute declared earlier to a chosen named entity. The named entities that can be assigned attributes are: entity, architecture, configuration, procedure, function, package, type, subtype, constant, signal, variable, component, label, literal, units, group, or file. The named entities are enumerated in entity names list. In such a way the attribute is assigned to a given language unit. Finally, the attribute specification contains an expression, which sets an attribute value for the entities listed in the specification. See Example 2.

The attribute specification for most named entities must be declared together with declarations of those entities. For some entities, however, the attribute specification is written in other places.

The attribute specification for library units such as entity, architecture configuration and package cannot be directly placed in the library, which contains library unit declarations. Because of that, the attribute specification is placed in the declaration part of named entity (Example 3).

The attribute specification for a subprogram must be declared in the same visibility region as the subprogram's declaration. In case of overloaded procedures and functions, signatures must be used to point to the subprogram to which the attribute is assigned (Example 4). If no signature is used the attribute relates to all subprograms with the same name.

Functions declared as the operators are always overloaded, and that is why they always require the signature in the attribute specification to differentiate functions (Example 5).

Attribute specifications for ports and generic parameters are placed in the declaration part of the design entity or the block statement to which they belong. The attribute specifications for formal parameters of subprograms are placed in the declaration part of these subprograms (Example 6).

Attribute specifications for labeled statements cannot be located directly in the place of the statements' declarations. Therefore, the attribute specifications for the label connected with any concurrent or sequential statements are placed in the declaration part before the occurrence of a given statement (Example 7).

In case of the sequential statement labels, the attribute specification is placed in the declaration part of the process or subprogram.

The attribute specification for literal must be declared in the same visibility block as the literal declaration. In case when there are several literals with the same names, the attribute specification for a given literal uses a signature in order to distinguish which type a given literal belongs to (Example 8). If no signature is used the attribute can be applied to all literals with the same name.

When specifying attributes reserved words: others and all can be used as entity (item) names. In the first case, the attribute specification refers to all the remaining visible named entities of a given entity class which do not have the attribute value assigned to them. Such an attribute specification must be the last in the declaration that refers to this attribute. When the keyword all is used, the attribute specification refers to all named entities of the given class. Such an attribute specification must be the first in the declaration part, which relates to this attribute. See Example 9.

Examples

Example 1

package Attr_pkg is
attribute Component_symbol : String;
attribute Pin_code : Positive;
attribute Max_delay: Time;
type Point is record
  x, y: Real;
end record;
attribute Coordinate : Point;
    ........
end package Attr_pkg;

The Atrr_pkg contains several attribute declarations, which can be later specified and used in other design units.

Example 2

package Some_declarations is
use Work.Attr_pkg.Component_symbol,
    Work.Attr_pkg.Coordinate,
    Work.Attr_pkg.Pin_code,
    Work.Attr_pkg.Max_delay;
constant Const_1: Positive := 10;
signal Sig_1: Bit_vector (0 to 31);
component Comp_1 is
port ( ... );
end component;
attribute Component_symbol of Comp_1: component is "Counter_16";
attribute Coordinate of Comp_1: component is (0.0, 17.5);
attribute Pin_code of Sig_1: signal is 17;
attribute Max_delay of Const_1: constant is 10 ns;
    .........
end package Some_declarations;

The package Some_declarations specifies attributes, which were declared in the package Attr_pkg.

Example 3

package Test_pkg is
attribute Package_atr : String;
attribute Package_atr of Test_pkg:
package is "Training_package";
    .........
end package Test_pkg;

The specification of a package attribute Package_atr for the package Test_pkg is declared in the declaration part of the package.

Example 4

procedure Sub_values (a, b : in Integer; result: out Integer);
procedure Sub_values (a, b : in Bit_vector; result: out Bit_vector);
attribute Description : String;
attribute Description of
        Sub_values [Integer, Integer, Integer]:procedure is "Integer_sub_values";
attribute Description of
        Sub_values [Bit_vector, Bit_vector, Bit_vector] :
procedure is "Bit_vector_sub_values";

The specification of the attribute Description intended for overloaded procedure Sub_values, which subtracts two values of integer or Bit_vector types, requires signature specification. These signatures (simplified parameter lists) enable to distinguish versions of the procedure.

Example 5

function "-" (a, b : New_logic) return New_logic;
attribute Characteristic : String;
attribute Characteristic of
  "-" [ New_logic, New_logic return New_logic]: function is "New_logic_op";

To identify operator ”-” overloaded for two values of type New_logic it is necessary to use signature that will unambiguously identify the overloading function.

Example 6

procedure Insert (fifo : inout Fifo_type; element: in Elem_type) is
attribute Number of fifo: variable is 50;
attribute Trace of element: constant is "Integer/Decimal";
   .........
end procedure Insert;

The procedure Insert has two formal parameters of different classes. Specifications of attributes Number and Trace for parameters fifo and element, respectively, are placed in the declaration part of the procedure.

Example 7

architecture Struct of ALU is
component Adder is
port (...)
end component;
attribute Coordinate of the_Adder: label is (0.0, 0.12);
begin
the_Adder : Adder port map ( ... );
.........
end architecture Struct;

Specification of the attribute Coordinate for the label the_Adder for component instantiation statement is located in the declarative part of the corresponding architecture body Struct.

Example 8

type Three_level_logic is (Low, High, Idle);
type Four_level_logic is (Low, High, Idle, Uninitialized);
attribute Hex_value : string (1 to 2);
attribute Hex_value of Low [return Four_level_logic]: literal is "F0";
attribute Hex_value of High [return Four_level_logic]: literal is "F1";
attribute Hex_value of Idle [return Four_level_logic]: literal is "F2";
attribute Hex_value of Uninitialized: literal is "F3";

As the literals Low, High, Idle are overloaded, it is necessary to use signature indicating their type in the specification of the attribute Hex_value for these literals. However, this is not necessary for the literal Uninitialized as it is not overloaded.

Example 9

B1: block
signal S1, S2, S3: Std_logic;
attribute Delay_attr: Time;
attribute Delay_attr of all: signal is 100 ps;
begin
   .........
end block;

The Delay_attr relates to all signals in the block B1.

Important Notes

· Common attributes can be declared for objects of different classes using one construct - group. See the group topic for details.

Bit

Formal Definition

The Bit type is predefined in the Standard package as an enumerated data type with only two allowable values: '0' and '1'.

Syntax:

type bit is ('0','1');

Description

The bit type is the basic type to represent logical values. Note that there are only two values defined for the bit type and it is not possible to use it for high impedance and other non-trivial values such as Unknown, Resistive Weak, etc. (see Std_logic).

According to the type definition, its leftmost value is '0', therefore the default value of any object of the bit type is '0'.

As the bit type is defined in the Standard package, it can be used in any VHDL specification without additional declarations.

Signals of the bit type are not resolved which means that such a signal can be assigned to an expression only once in the entire architecture.

Examples

Example 1

signal BitSig1, BitSig2 : bit;
. . .
BitSig1 <= '1';
BitSig2 <= not BitSig1;

The BitSig1 and BitSig2 signals are declared without an initial value, therefore by default they will be assigned the '0' value. In the next statement BitSig1 is assigned the '1' value. This value is complemented in the following statement and is assigned to BitSig2. Any additional assignment either to BitSig1 or BitSig2 would be illegal.

Important Notes

· Unlike in traditional ("hand-based") digital design, logical values 0 and 1 (bit type values '0' and '1') are NOT identical to boolean values (false and true), respectively. In VHDL, the latter items form completely different type (Boolean).

· Logical values for object of the bit type MUST be written in quotes to distinguish them from Integer values.

Bit_Vector

Definition:

The Bit_Vector type is predefined in the Standard package as a standard one-dimensional array type with each element being of the Bit type.

Syntax:

type bit_vector is array (natural range <>) of bit;

Description

The Bit_vector type is an unconstrained vector of elements of the bit type. The size of a particular vector is specified during its declaration (see the example below). The way the vector elements are indexed depends on the defined range and can be either ascending or descending (see range).

Assignment to an object of the Bit_vector type can be performed in the same way as in case of any arrays, i.e. using single element assignments, concatenation, aggregates, slices or any combination of them.

Examples

Example 1

signal DataBus : Bit_vector(7 downto 0);
signal FlagC : Bit;
DataBus(0) <= '1';                           -- 1
DataBus <= '0' & "111000" & FlagC;           -- 2
DataBus <= ('0', others => '1');             -- 3
DataBus <= DataBus(6 downto 0) & DataBus(7); -- 4
DataBus <= "01110001";                       -- 5

There is one bit_vector defined in this example - DataBus. Its range is defined as descending, therefore the most significant bit will be DataBus(7). Line 1, marked in the comment field, illustrates assignment of a single element (bit). The line 2 shows typical use of concatenation. Note that both single bits, groups of bits (with double quotes!) and other signals (as long as their type is compatible) can be used. The line 3 demonstrates the use of aggregates. The line 4 illustrates how slices can be used together with concatenation. The value of DataBus will be rotated left in this example. Finally, in line 5 DataBus is assigned an explicit value, specified with double quotes.

Despite that each of the numbered lines above is correct, it would be illegal to put them together in one specification as shown above, due to the fact that bit_vector is an unresolved type and there can be only one assignment to an object of this type in an architecture.

Important Notes

· Logical values for objects of the Bit_vector type MUST be written in double quotes. Single elements, however, are of the bit type, therefore all values assigned to single elements are specified in single quotes.

Block Statement

Formal Definition

The block statement is a representation of design or hierarchy section, used for partitioning architecture into self-contained parts.

Simplified Syntax

block_label : block (optional_guard_condition)

   declarations

begin

   concurrent statements

end block block_label;

Description

The block statement is a way of grouping concurrent statements in an architecture. There are two main purposes for using blocks: to improve readability of the specification and to disable some signals by using the guard expression (see guard for details).

The main purpose of block statement is organizational only - introduction of a block does not directly affect the execution of a simulation model. For example, both the upper and lower sections of code in Example 1 will generate the same simulation results.

Each block must be assigned a label placed just before the block reserved word. The same label may be optionally repeated at the end of the block, right after the end block reserved words.

A block statement can be preceded by two optional parts: a header and a declarative part. The latter allows to introduce declarations of subprograms, types, subtypes, constants, signals, shared variables, files, aliases, components, attributes, configurations, disconnections, use clauses and groups (i.e. any of the declarations possible for an architecture). All declarations specified here are local to the block and are not visible outside it.

A block header may contain port and generic declarations (like in an entity), as well as so called port map and generic map declarations. The purpose of port map and generic map statements is to map signals and other objects declared outside of the block into the ports and generic parameters that have been declared inside of the block, respectively. This construct, however, has only a small practical importance. The Example 2 illustrates typical block declarations.

If an optional guard condition is specified at the beginning of the block then this block becomes a guarded block. See guard for details.

The statements part may contain any concurrent constructs allowed in an architecture. In particular, other block statements can be used here. This way, a kind of hierarchical structure can be introduced into a single architecture body.

Examples

Example 1

A1: OUT1 <= '1' after 5 ns;
LEVEL1 : block
begin
A2: OUT2 <= '1' after 5 ns;
A3: OUT3 <= '0' after 4 ns;
end block LEVEL1;
A1: OUT1 <= '1' after 5 ns;
A2: OUT2 <= '1' after 5 ns;
A3: OUT3 <= '0' after 4 ns;

Both pieces of code above will behave in exactly the same way during simulation - block construct only separates part of the code without adding any functionality.

Example 2

entity X_GATE is
generic (LongTime : Time; ShortTime : Time);
port (P1, P2, P3 : inout BIT);
end X_GATE;
architecture STRUCTURE of X_GATE is
-- global declarations of signal:
signal A, B : BIT;
begin
LEVEL1 : block
-- local declaration of generic parameters
generic (GB1, GB2 : Time);
-- local binding of generic parameters
generic map (GB1 => LongTime, GB2 => ShortTime);
-- local declaration of ports
port (PB1: in BIT; PB2 : inout BIT );
-- local binding of ports and signals
port map (PB1 => P1, PB2 => B);
-- local declarations:
constant Delay : Time := 1 ms;
signal S1 : BIT;
begin
   S1 <= PB1 after Delay;
   PB2 <= S1 after GB1, P1 after GB2;
end block LEVEL1;
end architecture STRUCTURE;

The signals PB1 and PB2 have here the same values as P1 and B (in port map statement), respectively, and the generics GB1 and GB2 (see generic map statement) have the same values as Long Time and Short Time, respectively. However, such assignment is redundant because a block may use any declarations of an entity, including generics and ports. The Example 2 is presented here only for illustration purpose of the block syntax.

Important Notes

· Guarded blocks are generally not synthesizable.

· Unguarded blocks are usually ignored by synthesis tools.

· It is strongly recommended NOT to use blocks in non-VITAL designs - the package Std_logic_1164 supports mechanisms and multiple value logic which make the reserved words bus, disconnect, guarded and register unnecessary. Also, instead of guarded blocks for modeling sequential behavior it is recommended to used clocked processes.

· VITAL specifications require the use of blocks.

· VHDL supports a more powerful mechanism of design partitioning which is called component instantiation. Component instantiation allows connecting a component reference in one entity with its declaration in another entity.

Boolean

Definition:

The Boolean type is predefined in the Standard package as an enumerated data type with two possible values: false and true.

Syntax:

type boolean is (false,true);

Description

The boolean type is used for conditional operations. Boolean objects can be used with any of the relational operators <, >, <=, >=, = or /=.

According to the definition type, the leftmost value of the Boolean type is false, therefore the default value of any object of the Boolean type is false.

Since the boolean type is defined in the Standard package, it can be used in any VHDL specification without additional declarations.

Examples

Example 1

signal CondSup : boolean;
. . .
CondSup <= true;
. . .
if CondSup then -- could be: if CondSup = true then

The CondSup signal is declared as boolean but without any initial value. Therefore, by default it will be assigned the false value. A conditional operation could have been used instead as shown in the comment, but such a form would contain useless redundancy and should be avoided.

Important Notes

· Unlike in traditional ("hand-based") digital design, boolean values (false and true) are NOT identical to logical 0 and 1, respectively. In VHDL, the latter form is a completely different type and is called the Bit type.