Product Documentation
Cadence VHDL-AMS Overview
Product Version 22.09, April 2022

4


VHDL-AMS Language Elements

A VHDL-AMS design consists of any number of design files (ASCII text files) containing descriptions of the basic design units. There is no fixed relationship between design files and design units: a single design file can contain one or more design units. You cannot split a design unit across more than one design file.

The VHDL-AMS language is not case sensitive, so you can freely mix upper and lower case characters (apart from when they are used for character literals).

For an overview of the main features of the VHDL-AMS language you can use with the Virtuoso AMS Designer simulator, see

For detailed information on these topics, see the VHDL-AMS LRM.

Entity and Architecture

Design units are divided into two categories: design entities and architectures. A combination of one of each of these two types forms the basic hardware unit of a VHDL-AMS description. You can have only one entity of a given name but you can pair that entity with different architectures, as needed. Each alternative architecture can describe a different implementation, but the interface, as defined by the entity, is always the same.

Entities

An entity declaration defines the interface between a given design entity and the environment in which it is used. It can also specify declarations and statements that are part of the design entity. An entity declaration can be shared by multiple design entities, each with a different architecture. An entity declaration can potentially represent a class of design entities, each with the same interface.

entity_declaration ::=
    entity identifier is
[generic (generic_interface_list);]
[port (port_interface_list);]      {entity_declarative_part}
end [entity][identifier];

Architectures

An architecture body defines the body of a design entity. It specifies the relationships between the inputs, outputs, quantities, and terminals of a design entity and can be expressed in terms of structure, dataflow, equations, or behavior. Such specifications can be partial or complete.

architecture_body ::=
    architecture identifier of entity_name is
     {block_declarative_part}
begin
[concurrent_statement_part}
end [ architecture ] [ architecture_simple_name] ;
architectural_statement ::= 
    simultaneous_statement | concurrent_statement

The identifier defines the simple name of the architecture body; distinguishing architecture bodies associated with the same entity declaration. The entity name identifies the name of the entity declaration.

Both the entity declaration and architecture body must reside in the same library.

Multiple implementations of One Interface

VHDL-AMS supports the use of multiple architectures for a given entity. This is useful, for example, in the context of logic synthesis because the output of synthesis tools is often a VHDL-AMS gate-level netlist that has the same entity declaration as the original RTL description:

RTL Description --> work.entityname(behaviour) 
Gate-level net-list --> work.entityname(post_synth)

If the component entityname is instantiated within a design, you use a VHDL-AMS configuration to specify which of the two alternative architectures to load prior to simulation. There are two supported methods of specifying configurations: configuration specifications (an architecture declarative item), and configuration declaration (a primary library unit).

Configuration specification allows a component instance (or instances) to be bound to a specific entity/architecture pair by specifying the binding within the architecture that instantiates the design entities.

Packages and Libraries

Packages and libraries are used to group and organize the information used in designs.

Packages

Packages are used to group multiple elements under a single name. Packages might group related declarations into a separate, independent, and reusable set of subprograms that provides operations on a particular type of data, or might group the declarations needed to model a design.

Packages can also be used to separate the implementation of items from the external view of the items. In this case, a package declaration specifies the external view and the implementation is defined in the body of the package.

package_declaration ::=
    package identifier is
{package_declarative_item}
end [package][identifier];

The package declaration is a primary design unit and as such can be analyzed and placed in the working library (or in a different library, if required). The declarations contained in a package (or in a library) can be made available to a design entity by using a use clause.

use_clause ::=
    use selected_name {, selected_name };

To make all the declarations contained within the package visible, use the reserved word all as the suffix of the identifier. For example, the following statement makes visible all the declarations in the fastpak package.

use fastpak.all

Libraries

Libraries are used to store packages and design units. Analyzed designs are typically stored in a working library, named work. Items in the work library can be accessed simply by using a use clause, because all design entities have access to the work library by default.

Library units can also be stored in other libraries, referred to as resource libraries. To access the items in a resource library, you insert a library clause immediately before the design unit that accesses the resource libraries.

library_clause ::= 
library identifier {, ...};

Declarations

A declaration introduces the name of an object, defines its type, and can provide an initial value. See the following topics for descriptions of specific declarations:

Natures

A nature declaration declares a nature and defines the across and through types of the nature.

nature_declaration ::= 
    nature identifer is nature_definition ;
nature_definition ::= 
    scalar_nature_definition | composite_nature_definition
subnature_declaration ::= 
    subnature identifier is  subnature_indication;
nature_mark ::= 
    nature_name | subnature_name
subnature_indication ::= 
    nature_mark [index_constraint]

Types

You can declare the following VHDL-AMS types:

Scalar Types

Scalar types consist of integer types, enumeration types, physical types, and floating point types.

Integer types have whole number values.

integer_type_definition ::=
    range simple_expression (to | downto) simple_expression

Enumeration types allow for setting names for encoded values of some signals.

enumeration_type_definition ::= 
    ((identifier | character_literal){,...})

Physical types represent physical properties like mass, length, and time.

physical_type_definition ::=
    range simple_expression (to | downto) simple_expression
     units 
      identifier ;
{identifier = physical_literal ;}
end units [identifier]
physical_literal ::= 
    [decimal_literal | based_literal] unit_name

Floating point types represent real numbers.

floating_type_definition ::=
    range simple_expression (to | downto) simple_expression

Composite Types

Terminal objects of an array nature consist of identical elements associated with some index value. The branch types defined by an array nature definition are array types.

array_nature_definition ::=
    unconstrained_nature_definition | constrained_nature_definition
unconstrained_nature_definition ::=
    array ( index_subtype_definition { , index_subtype_definition } )
     of subnature_indication 
constrained_nature_definition ::=     array index_constraint of subnature_indication

A record nature is a composite nature where terminal objects of a record nature consist of named terminals. The branch types defined by a record nature definition are record types.

record_nature_definition ::=
    record 
      nature_element_declaration 
{nature_element_declaration}
end record [record_nature_simple_name]
nature_element_declaration ::=     identifier_list: element_subnature_definition
element_subnature_definition ::= 
    subnature_indication

Access Types

Access types link data objects, similar to pointer types found in programming languages.

access_type_definition ::= 
access subtype_indication

File Types

File types define objects representing files in the host system environment.

file_type_definition ::= 
file of type_mark

The type_mark defines the subtype of the values contained in the file.

Scalar Nature

A scalar nature declaration defines a scalar nature and its branch types, and declares the name of the reference terminal that is of the nature.

scalar_nature_definition ::= 
    type_mark across 
    type_mark through
identifier reference

The type marks must denote floating-point types. The simple nature of a scalar nature is the nature itself.

Objects and Interface Objects

An object is a named item that has a value of a specified type. In the case of a terminal, it has a specified nature. See the following topics for more information:

Constant

You use a constant to provide a name and an explicitly defined type for a value. You must declare a constant before you can use it in a model.

constant_declaration ::=
constant identifier {,...}:subtype_indication [:=expression];

You can declare constants that are real, integer, and boolean types.

If you are using the Spectre or UltraSim solver with the simulation front end SFE parser, you can also declare constants that are arrays of these types and use these arrays in analog simultaneous statements. For example, you can declare the following:

constant const_array: Real_vector := ( 1.0, 2.0 );

Generic

A generic is a constant in the interface of an entity.

entity_declaration ::=
entity identifier is
[generic (generic_interface_list);]
...
end [entity][identifier];

A generic interface list that is accessed from an analog context (such as in a simultaneous statement) can consist of scalar objects or arrays of real, integer, or boolean objects.

generic_interface_list ::=
    (identifier {,...}:subtype_indication[:=expression])
    {;...}

For example, if you are using the Spectre or UltraSim solver with the simulation front end (SFE) parser, you can declare a generic in the following way and use it in an analog simultaneous statement:

entity child is
generic ( genericArg : real_vector(0 to 1) := (0.0, 0.0) );
...
end child;

Generic declarations specify parameters you can change when you instantiate an architecture in a design.

For each generic, you can specify a type and an optional default value. You can define a type to have a valid range of values.

The following example illustrates how to declare a generic in an entity. The resistor entity declares r, which represents the resistance value, as a generic. Terminal ports tr1 and tr2 represent circuit nodes whose nature is electrical. The rbehavior architecture declares Vr as an analog branch quantity representing the branch voltage across tr1 and tr2.

entity resistor is
    generic(r : real := 1.0 );
    port(terminal tr1, tr2 : electrical);
end resistor; 

architecture rbehavior of resistor is 
    quantity Vr across Ir through tr1 to tr2; 
begin 
    Vr == Ir*r; 
end architecture rbehavior;

Variable

Variables must be declared before they can be used in a model. Variables are data objects and serve for local storage of temporary data. Non-shared variables can occur in sequential environment only, i.e., inside a PROCESS statement or a subprogram. Shared variables can occur in any statement and can be accessed by more than one process.

variable_declaration ::=
[shared] variable identifier {,...}:subtype_indication [:=expression];

Signal

Internal signals in an architecture body are defined using signal declarations. Signals represent interconnection wires.

signal_declaration ::=
    signal identifier {,...} : subtype_indication [:=expression];

Attribute

The attributes of signals can be used to find information about their history of transactions and events. The table below lists the predefined attributes that Cadence supports. Additional information on these attributes can be found in LRM 14.1. In the following table, T = scalar type, subtype, or terminal; A = array type; S = signal; E = named entity; N = nature; and Q = quantity.

Array quantities cannot be used in attributes.

Attribute Value Returned

A’ascending[(N)]

(Digital only): TRUE if the Nth index range of A is defined with an ascending range; FALSE otherwise.

A’high[(N)]

(Digital only): Upper bound of the Nth index range of A.

A’left[(N)]

(Digital only): Left bound of the Nth index range of A.

A’length[(N)]

(Digital only): Number of values in the Nth index range.

A’low[(N)]

(Digital only): Lower bound of the Nth index range of A.

A’range[(N)]

(Digital only): The range A’left(N) to A’right(N) if the Nth index range of A is ascending; otherwise the range A’left(N) downto A’right(N).

A’reverse_range[(N)]

(Digital only): The range A’right(N) downto A’left(N) if the Nth index range of A is ascending; otherwise the range A’right(N) to A’left(N).

A’right[(N)]

(Digital only): Right bound of the Nth index range of A.

E’instance_name

(Digital only): A string describing the hierarchical path starting at the root of the design hierarchy and descending to the named entity, including the names of instantiated design entities.

E’path_name

(Digital only): A string describing the hierarchical path starting at the root of the design hierarchy and descending to the named entity, excluding the names of instantiated design entities.

E’simple_name

(Digital only): The simple name, character literal, or operator symbol of the named entity.

Q’above(E)

TRUE if Q - E is sufficiently larger than 0.0, FALSE if Q - E is sufficiently smaller than 0.0, Q’above(E)’delayed otherwise.

Q’delayed[(T)]

A quantity equal to Q delayed by T.

Q’dot

The derivative with respect to time of Q at the time when the software evaluates the attribute.

Q’dot’dot

The second derivative with respect to time of Q at the time when the software evaluates the attribute.

Q’integ

The time integral of Q from time 0 to the time when the software evaluates the attribute.

Q’ltf(NUM,DEN)

The Laplace transfer function of each scalar subelement of Q with NUM as the numerator and DEN as the denominator polynomials. Num and Den must be aggregates of constants or scalar references. For examples of use, see “Examples of Attribute Use: Q’ltf”.

Q’ramp[(MAX_T_RISE [,MAX_T_FALL])]

A quantity where each scalar subelement follows the corresponding scalar subelement of Q linearly with the specified rise and fall times.

Q’slew[(MAX_RISING_SLOPE [,MAX_FALLING_SLOPE])]

A quantity where each scalar subelement follows the corresponding scalar subelement of Q, but its derivative with respect to time is limited by the specified slopes.

S’delayed[(T)]

A signal equivalent to signal S delayed T units of time.

S’driving

(Digital only): FALSE, if the prefix denotes a scalar signal and the current value of the driver for S in the current process is determined by the null transaction; TRUE otherwise.

S’driving_value

(Digital only): If S is a scalar signal, the current value of the driver for S in the current process. If S is a composite signal, the aggregate of the values of R’driving_value for each element R of S. If S is a null slice, a null slice.

S’event

TRUE or FALSE, depending on whether an event has just occurred on signal S.

S’last_active

The amount of time that has elapsed since the last time at which signal S was active.

S’last_event

The amount of time that has elapsed since the last event occurred on signal S.

S’last_value

The previous value of S, immediately before the last change of S.

S’quiet[(T)]

A signal that has the value TRUE when the universal time of the last transaction on S is less than the universal time correspond to NOW - T, and the value FALSE otherwise.

S’ramp[(TRISE[,TFALL])]

A quantity where each scalar subelement follows the corresponding scalar subelement of S. If the value of any parameter is greater than 0.0, the corresponding value change is linear from the current value of the scalar subelement of S to its new value, whenever that subelement has an event.

S can also be a signal array.

S’slew[(RISING_SLOPE [,FALLING_SLOPE])]

A quantity where each scalar subelement follows the corresponding scalar subelement of S. If the value of RISING_SLOPE is less than REAL’HIGH, or if the value of FALLING_SLOPE is greater than REAL’LOW, the corresponding value change is linear from the current value of the scalar subelement of S to its new value, whenever that subelement has an event.

S can also be a signal array.

S’stable[(T)]

A signal that has the value TRUE when the universal time of the last event on S is less than the universal time corresponding to NOW - T, and the value FALSE otherwise.

S’transaction

A signal whose value toggles to the inverse of its previous value in each simulation cycle in which signal S becomes active.

T’ascending

TRUE if T is defined with an ascending range; FALSE otherwise.

T’base

The base type of T.

T’high

The upper bound of T.

T’left

The left bound of T.

T’leftof(X)

The value that is to the left of the parameter in the range of T.

T’low

The lower bound of T.

T’pos(X)

The position number of the value of the parameter.

T’pred(X)

The value whose position number is one less than that of the parameter.

T’reference

The across quantity whose plus terminal is T and whose minus terminal is the reference terminal of the nature of T.

T’right

The right bound of T.

T’rightof(X)

The value that is to the right of the parameter in the range of T.

T’succ(X)

The value whose position number is one greater than that of the parameter.

T’val(X)

The value whose position number is the universal_integer value corresponding to X.

Examples of Attribute Use: Q’ltf

The parameters to the Q’ltf attribute must be constants or aggregates of scalar references. For example, given the following declarations:

entity lpf_1 is
generic ( fp : real := 1.0;
gain : real := 1.0 );
port ( quantity input : in real;
quantity output : out real);
end entity lpf_1;
library ieee;
use ieee.math_real.all;
architecture simple of lpf_1 is
constant wp : real := math_2_pi*fp;
constant wpGain : real := wp * gain;
constant num : real_vector := (0 => wp * gain);
constant den : real_vector := (wp, 1.0);
begin
...
end architecture simple;

Then the following ’ltf statements, when they appear in the body of the architecture, are valid or invalid as described in the comments:

output == input'ltf(num, den);  // Invalid, parameters are array references.
// The parameters must be aggregates.
output == input'ltf((0=>num[0]), (den[0], den[1]));
// Invalid, parameters are aggregates of
// array references, not scalar references.
output == input'ltf((0=>wp*gain), (wp, 1.0));
// Invalid, first parameter aggregates
// contains an expression.
output == input'ltf((0=>wpGain, (wp, 1.0));
// Valid, parameter aggregates are scalar
// references and constants.

Terminal

A terminal declaration declares a terminal, reference quantity, and contribution quantity of the terminal.

terminal_declaration ::=
    terminal identifier_list : subnature_indication ;

A terminal represents a physical connection point in the system.

Although Cadence VHDL-AMS does not support a general ability to create aliases, you can declare aliases to terminals used for GROUND connections.

Quantity

A quantity declaration declares a quantity.

quantity_declaration ::= 
    free_quantity_declaration | branch_quantity_declaration
free_quantity_declaration ::= 
    quantity identifier_list : subtype_indication [:= expression];

branch_quantity_declaration ::= 
    quantity [across_aspect] [through_aspect] terminal_aspect ;
across_aspect ::= 
    identifier_list [:= expression] across
through_aspect ::= 
    identifier_list [:= expression] through
terminal_aspect ::= 
    plus_terminal_name  [ to minus_terminal_name ] 

Across quantities specify the voltage across two terminals. Through quantities define the current through a terminal. Free quantity values are determined solely by the specified equations and are not constrained by any terminal.

Branch quantity arrays are supported, so you can declare branch quantities referencing bits, slices, or a whole terminal arrays and use the quantity arrays in VHDL-AMS behavioral statements.

Component

To instantiate a design entity within another design entity, the lower level design entity is declared in the form of a component. The component declaration is placed in the architecture declaration of the high level design entity, creating a socket into which a design entity is placed. The component declarations indicate that a lower-level design entity is used. They do not specify which entity/architecture pair is plugged into the socket.

Specifying an entity name and a corresponding architecture body name binds the instance. Different instances of a given component can be bound to different entity./architecture pairs. The keyword all can also be used if all instances of a particular component type have the same binding.

component_declaration ::=
    component identifier [ is ]      [ generic (generic_interface_list);]      [ port (port_interface_list); ]
    end component [identifier] ;

It is common practice to use the same name and ports for the component and the entity to which it is bound.

The component instantiation statement specifies how the component is used in the design.

component_instantiation_statement ::=
    instantiation_label:
     [component](component_name)      [generic map (generic_association_list)]      [port map (port_association_list)];

The generic map arguments are expressions that map a particular value to a particular constant or constant array for an instance. You can use positional or named associations or a combination of both to specify the mapping.

If you are using the Spectre or UltraSim solver with the simulation front end (SFE) parser, you can specify constant or generic arrays on the component instantiation:

i1 : entity work.bottom
generic map ((5.0, 2.0*g1), (2.0, g1-g2))
You must specify the entire array. You cannot specify an index or a slice.

A port map statement maps ports of an entity to terminals, signals, or quantities in an architecture body. You can provide a value for the expression or you can unassociate the port using the open keyword. You can use positional or named associations or a combination of both to specify the mapping.

If you are using the Spectre or UltraSim solver with the simulation front end (SFE) parser, you can specify constant or generic arrays in a port map statement as follows:

port map ( formalArg => actualArg ) 

where the formalArg and the actualArg can be an array name representing an entire array or a scalar value. You must not specify an index or slice expression for the formalArg, such as formalArg(0) or formalArg(0 to 1). The actualArg can also be any of the following:

You must not use VHDL predefined index attributes, ’left or ’right, in an index or slice expression for actualArg.

Interface Declarations (Ports)

The ports of a block are defined by a port interface list. Interface elements in the port interface list declare a formal port. A formal port can be a signal port, a quantity port, or a terminal port. Interface objects also include interface terminals and interface quantities that appear as ports of a design entity, component, or block.

interface_declaration ::=
    interface_terminal_declaration
    interface_quantity_declaration
    interface_signal_declaration

interface_terminal declaration ::=
    terminal identifier_list : subnature_indication

interface_quantity_declaration ::=
    quantity identifier_list : [in | out] subtype_indication [:= 
    static_expression]

interface_signal_declaration ::=
    signal identifier_list : [in | out] subtype_indication [:= 
    static_expression]

Subprograms

The subprogram facility allows for the division of complex behavioral models into self-contained sections. There are two kinds of subprograms: procedures and functions. A procedure summarizes a collection of sequential statements that are executed for their effect, and is therefore a generalization of a statement. A function summarizes a collection of sequential statements that are executed for their result, and is therefore a generalization of an expression.

Procedures

When using a procedure in a model, it must first be declared. Declarations can include types, subtypes, constants, variables, and nested subprogram declarations.

subprogram_body ::=
    procedure identifier [(parameter_inteface_list)] is
{subprogram_declarative_part}
begin      {sequential_statement}
end [procedure][indentifier]

To use a procedure, code a call statement.

procedure_call_statement ::= 
    [label:] procedure_name;

Functions

A function is a way of defining a new operation using an expression. A collection of sequential statements are written that calculate the result.

subprogram_body ::=
    [pure|impure]
function identifier [(parameter_inteface_list)] return type_mark is
{subprogram_declarative_item}
begin      {sequential_statement}
end [function][indentifier]

Unlike a procedure call, a function call is part of an expression, not a sequential statement on its own.

function_call ::= 
function_name [(parameter_association_list)]

Statements

The three types of statements are sequential, concurrent, and simultaneous:

Sequential Statements

Sequential statements define algorithms for the execution of a subprogram or process; they execute in the order they appear.

Sequential Break Statement

A sequential break statement is included in a process.

break_statement ::=
    [label:] break [break_element {, ...}][when boolean_expression];
break_element ::= 
    [for quantity_name use] quantity_name => expression

Signal Assignment

Assignment of a signal statement provides a new value of a signal. A delay mechanism can be specified that determines when a new value should be applied. An event occurs on a signal when a new value is different than the old value it replaces.

signal_assignment_statement ::=
    [label:] name <=[delay_menchanism] waveform;
waveform ::= 
    (value_expression [after time_empression])(,...)

Variable Assignment

The value of a variable can be modified once assigned by an assignment statement.

variable_assignment_statement ::= 
    [label :] name := expression ;

Concurrent Statements

Concurrent statements define interconnected blocks and processes that jointly with simultaneous statements describe the overall behavior or structure of a design. Concurrent statements execute asynchronously with respect to each other. The concurrent statement is declared using the syntax for architecture bodies:

achitecture_body ::=
    architecture identifier of entity_name is
{block_declarative_item}
begin
{concurrent_statement}
end [architecture][identifier];

Block Statement

The primary concurrent statements are the block statement, which groups together other architecture statements, and the process statement, which represents a single independent sequential process. A block statement defines an internal block representing a portion of a design. Blocks can be hierarchically nested to support design decomposition.

block_statement ::=
    block_label :
     block [ ( guard_expression ) ] [ is ]
block_header
block_declarative_part
begin
block_statement_part
end block [ block_label ] ;

Process

A process statement defines an independent sequential process representing the behavior of some portion of the design.

process_statement ::=
    [ process_label : ]
     [ postponed ] process [ ( sensitivity_list ) ] [ is ]
process_declarative_part
begin
process_statement_part
end [ postponed ] process [ process_label ] ;

Component Instantiation

A component instantiation is a concurrent statement for writing a structural implementation. The component instantiation performs direct instantiation of an entity.

component_instantiation_statement ::=
    instantiation_label:
     entity entity_name [(architecture_identifier)]
      [port map (port_association_list)];

Concurrent Break Statement

A concurrent break statement is used in mixed-signal systems when the operating conditions of an analog part are changed by the process representing a digital part. A discontinuity is indicated by using a break statement to signal the analog solver that a discontinuity has occurred at the current simulation time.

concurrent_break_statement ::=
    [label:] 
break [break_element {, ...}]      [on signal_name {, ...}]      [when boolean_expression];
break_element ::= 
    [for quantity_name use] quantity_name => expression

Procedure

The concurrent procedure call statement is a process whose body contains a sequential procedure call statement.

concurrent_procedure_call_statement ::=
    [label:] procedure_name [(parameter_association_list)];

Concurrent Assert

A concurrent assertion statement is used to represent a process whose body contains an ordinary sequential assertion statement.

concurrent_assertion_statement ::=
    [label:] 
    assert boolean_expression
     [report expression][severity expression]

Simultaneous Statements

Simultaneous statements describe the analog behavior of a model by expressing explicit differential and algebraic equations. Together with implicit equations, these explicit equations constrain the values of quantities in a model.

architecture_body ::=
    architecture identifier of entity_name is 
    {block_declarative_item}     begin
    {concurrent_statement | simultaneous_statement}     end [architecture][identifier]

See also “Simultaneous Statements”.

Simple

A simple simultaneous statement specifies zero or more characteristic expressions.

simple_simultaneous_statement ::=
    [label :] expression == expression ;` 

If

A simultaneous if statement selects for evaluation one of the enclosed simultaneous statement parts depending on the value of one or more conditions.

simultaneous_if_statement ::=
     [if_label :] 
     if condition use
simultaneous_statement_part
{elsif condition use
simultaneous_statement_part}
[else
simultaneous_statement_part]
end use  [if_label];

Case

A simultaneous case statement selects for evaluation one of a number of alternative simultaneous statement parts; the chosen alternative is defined by the value of an expression.

simultaneous_case_statement ::=
    [case_label:]
     case expression use
      simultaneous_alternative
{simultaneous_alternative}
end use [case_label];
simultaneous_alternative ::=
     when choices =>
     simultaneous_statement_part

Expressions

Predefined Operators and Operator Precedence

Operators belong to classes that have the same precedence level; in the following table the classes of operators are listed in order of increasing precedence.

logical_operator

::=

and

|

or

|

nand

|

nor

|

xor

|

xnor

relational_operator

::=

=

|

/=

|

<

|

<=

|

>

|

>=

shift_operator

::=

sll

|

srl

|

sla

|

sra

|

rol

|

ror

adding_operator

::=

+

|

|

&

sign

::=

+

|

multiplying_operator

::=

*

|

/

|

mod

|

rem

miscellaneous_operator

::=

**

|

abs

|

not

Operators of higher precedence are associated with their operands before operators of lower precedence. When a sequence of operators is allowed, operators with the same precedence level are associated with their operands in textual order, from left to right. The precedence of an operator is fixed and cannot be changed. Parentheses can be used to control the association of operators and operands.

Static and Non- Static Expressions

Locally static expressions are those expressions that can be determined when a design unit is compiled. A globally static expression can be determined at the time of elaboration. Non-static expressions can change during simulation.


Return to top
 ⠀
X