Chapter 9. Miscellaneous Changes

In this chapter, we describe various miscellaneous semantic and syntactic changes to constructs in VHDL-2008 not mentioned in earlier chapters. Many of the changes are relaxations to rules previously in VHDL, and will make some modeling tasks easier. Other changes are clarifications or corrections to minor inconsistencies in the language definition.

Referencing Generics in Generic Lists

In earlier versions of VHDL, a formal generic declared within a given generic list could not be used to declare other generics in that list. The same rule also applied to ports declared within a port list and to parameters declared in a subprogram’s parameter list. In VHDL-2008, the rule is relaxed for generics. Thus, we can use one generic to declare subsequent generics in the list. Among other possibilities, this means we can use the value of a generic constant to constrain the size of a subsequent generic of an array type. This was one of the motivations behind the change.

Example 9.1. Individual propagation delay generics for array port elements

Suppose we want to use generic constants to specify the propagation delays for an adder. The entity is declared with input and output ports that are arrays whose sizes are determined by a generic constant. We want to specify individual propagation delays for corresponding input and output port elements. The entity declaration is:

entity adder is
   generic ( width : positive;
               Tpd_ab_s : time_vector(width - 1 downto 0) );
   port    ( a, b : in bit_vector(width - 1 downto 0);
               c_in : in bit;
               s    : out bit_vector(width - 1 downto 0);
               c_out : out bit );
end entity adder;

The generic constant width is used in the declaration of the second generic constant, Tpd_ab_s, to ensure that there is a matching propagation delay for each element of the input and output ports. We can instantiate the entity in a design as follows:

subtype byte is  bit_vector(7 downto 0);
signal op1, op2, result : byte;
signal c_out : bit;
. . .

byte_adder : entity work.adder
  generic map ( width   => byte'length,
              Tpd_ab_s => (7 downto 1=> 120 ps,
                                       0                => 80 ps) )
  port map    ( a => op1, b => op2, c_in   => '0',
              s => result, c_out => c_out );

In this instance, an actual value is given for width, and that is used to determine the index range for Tpd_ab_s, as well as for the ports. Note that we don’t have to write the actual generics in this order. The values are determined for generics in the order of their occurrence in the generic list, not the generic map. Thus, we could have written the generic map as:

generic map ( Tpd_ab_s  => (7 downto 1=> 120 ps,
                           0                => 80 ps),
              width     => byte'length )

though to do so might look a bit strange.

We saw several other examples of generics being used in the declarations of other generics in our discussion of generic types, subprograms, and packages in Chapter 1. Supporting these features was another motivation for making the change.

Function Return Subtype

In earlier version of VHDL, the value returned by a function had to belong to the subtype defined as the function’s return type. For example, in the following function:

subtype byte is  bit_vector(7 downto  0);

function f ( x : byte ) return byte is
begin
  return '0' & x(6 downto 0);
end function f;

the result had to be a bit vector indexed from 7 down to 0. However, the result is a bit vector indexed from 0 to 7, due to the rules for determining the index range of a concatenation result. Thus, in earlier versions of VHDL, this function would have caused an error when executed.

In VHDL-2008, the rules for a function result returned by a return statement are relaxed. The value of the return expression is implicitly converted to the result subtype of the function. As a consequence, the above function does not produce an error. The conversion of the result value simply remaps the indices to the required range and direction.

Qualified Expression Subtype

In a change related to that described in Section 9.2, the rules for qualified expressions are relaxed. In earlier versions of VHDL, a type qualification stated the precise subtype of an expression. The value of the expression was required to be of that subtype. In VHDL-2008, the value is converted to the stated subtype. However, it still has to have the same base type as the stated subtype.

To illustrate the fine distinctions, suppose we declare a subtype, byte, as we did in Section 9.2, along with some variables:

subtype byte is  bit_vector(7 downto 0);
variable x : byte;
variable y : IEEE. numeric_bit.unsigned(7 downto 0);

If we wanted to write an expression of the subtype byte comprising a '0' bit concatenated with the low-order 7 bits of x, we would have written the following in earlier versions of VHDL:

byte(bit_vector' ('0' & x(6 downto 0)))

The qualified expression

byte'( '0' & x(6 downto 0) )

was illegal in earlier versions of VHDL, since the index range of the concatenation result is 0 to 7. A bit vector with that index range is not in the subtype of bit vectors with index ranges 7 down to 0. In VHDL-2008, the shorter qualified expression is legal, and converts the value to have an index range of 7 down to 0. Note that the following qualified expression is not legal:

byte' ( y )

The value of y is a vector whose base type is unsigned, which is different from the base type of byte, namely, bit_vector. It is not correct to state that an unsigned value is a bit_vector value. Hence, a qualified expression is not appropriate; we should use a type conversion instead.

Type Conversions

In VHDL-2008, the rules for type conversions of array types are relaxed. Previously, when converting an expression of an array type to some other target array type, the elements of the expression and the target type had to be the same. Moreover, the types of the indices of the expression and the target had to be the same or had to be integer types. Under the revised VHDL-2008 rules, an array can be converted to any other array type, provided the elements can be converted to the target element type. If the target type is in fact a subtype that specifies the index bounds, then the converted expression must have the required number of elements.

To illustrate, suppose we have array types and signals declared as follows:

type exception_type is  (int, ovf, div0, undef, trap);
type exception_vector is array (exception_type) of bit;
signal d_in, d_out: bit_vector(31 downto 0);
signal exception_reg : exception_vector;

In VHDL-2008, the type conversions:

exception_vector( d_in(4 downto 0) )

yields a vector of bits indexed from int to trap, with each element being the matching element of the slice of d_in, from left to right. Since the element types for the expression and the target type are both bit, conversion of the elements is trivial. In this example, the target type is also a subtype that specifies the index bounds, so the converted expression is required to have five elements.

We can also convert in the reverse direction:

bit_vector( exception_reg )

In this case, the target type is unconstrained, so the index range of the result comes from the index subtype defined for bit_vector, namely, natural. The subtype natural is declared to be an ascending range with a left bound of 0. This direction and left bound are used as the direction and left bound of the type-conversion result. The right bound comes from the number of elements. Thus, the result is a bit_vector value indexed from 0 to 4. We could assign that result to a slice of the d-out signal:

d_out(31 downto 27) <= bit_vector( exception_reg );

in which case matching elements are assigned left to right.

The rule that the element types of the converted expression and the target type must be convertible allows us to perform the following conversions:

variable i_vec : integer_vector(1 to 10);
variable r_vec : real_vector(1 to 10);
. . .

i_vec := integer_vector(r_vec);
r_vec := real_vector(i_vec);

Since we can convert between values of type integer and real, we can also convert between arrays with integer and real elements, respectively. Each element of the converted expression is converted to the element subtype of the target type.

Case Expression Subtype

VHDL allows the expression in a case statement to be of a one-dimensional character-array type, that is, a one-dimensional array whose elements include character literals. Examples of such types are bit_vector, std_logic_vector, and similar types. In earlier versions of VHDL, if we wrote such an expression in a case statement, the index range had to be locally static. In other words, we had to be able to determine the index bounds and direction at analysis time. The reason was that the case choices would be array aggregates or strings, and the analyzer needed to be able to check that they were all of the same correct length. An example showing where these rules are inconvenient is the following:

variable s : bit_vector (3 downto 0);
variable c : bit;
. . .

case c & s is
     . . .
end case;

This would be illegal in earlier versions of VHDL, since the index range of the expression is not locally static. Instead, we would have to rewrite the example as:

variable s : bit_vector(3 downto 0);
variable c : bit;
subtype bv5 is bit_vector(0 to 4);
. . .

case bv5'(c & s) is
     . . .
end case;

VHDL-2008 avoids this and other inconveniences by allowing the case expression not to have a locally static index range. All that is statically required is that the choices have the same length. When the case statement is executed, the value of the expression must have the same length as the choices. Thus, in VHDL-2008, we can complete the above example as follows:

variable s : bit_vector(3 downto 0);
variable c : bit;
. . .

case c & s is
  when "00000" => . . .
  when "10000" => . . .
  when  others => . . .
end case;

All of the choices are of length five, so that determines the required length for the result of the concatenation.

A related change in VHDL-2008 is that an array aggregate containing others is allowed as a choice in a case statement, provided the index range of the case expression is locally static. For example, we can write a case statement as follows:

variable s : bit_vector(3 downto 0);
. . .

case s is
  ('0', others => '1') => . . .
  ('1', others => '0') => . . .
  . . .
end case;

In this example, the index range of the expression s can be determined at analysis time as being 3 down to 0. That means the analyzer can use the index range for the choice values. If the analyzer cannot work out the index range for the case expression, it cannot determine the index values represented by others in the aggregates.

Subtypes for Port and Parameter Actuals

Earlier versions of VHDL required that, for a scalar port, the actual signal be of exactly the same subtype as the port, including having exactly the same bounds and direction. A similar restriction applied to signal parameters of subprograms. For example, given the following component declaration:

component counter is
  port ( count : out natural; . . .);
end component counter;

we could not use an integer signal as the actual signal:

signal count_int : integer;
. . .

my_counter : counter
  port map ( count => count_int, . . . );

This would appear to be a reasonable thing to do, since the counter output is always a non-negative integer, and the count_int signal can legally take on any integer value. However, the type integer has different bounds from the subtype natural, so the association was not allowed. The motivation for the restriction was to avoid subtype checks slowing down simulation. For example, consider the procedure:

procedure monitor_count ( signal count :   in natural;
                       max_val : in natural )is
begin
  loop
    assert count >= max_val;
    wait on count;
  end loop ;
end procedure monitor_count;

If we supplied an integer signal as an actual parameter, as follows:

signal count_int : integer ;
. . .

monitor_count ( count_int, 50 ); -- not legal

each time there was an event on the signal parameter within the procedure, we would need to check that the new value belonged to the subtype of the parameter.

VHDL-2008 changes the subtype rules for scalar ports and scalar signal parameters to partially relax the subtype requirements, in a way that makes reasonable cases legal but that avoids the need for runtime subtype checks. Under the new rules, a port of mode out, inout, or buffer can be connected to a signal of a different subtype, provided the signal’s subtype includes at least the values in the ports subtype. So, for example, the signal could be of type integer and the port of the subtype natural, since integer includes all of the values in natural. Similarly, a port of mode in or inout can be connected to a signal of a different subtype, provided the port’s subtype includes at least the values in the signal’s subtype. Since ports of mode inout are included in both conditions, the sub-types of an inout-mode port and the connected signal must have the same bounds, though they no longer need to have the same direction. The same rules apply to signal parameters of subprograms (though such parameters cannot be of mode buffer, of course).

Static Composite Expressions

VHDL requires expressions in a number of places to be locally static, meaning that they can be evaluated during analysis. An example is an expression used as a choice in a case statement. Earlier versions of VHDL limited the forms of locally static expressions producing composite results. For example, a concatenation of two strings was not locally static, even if the strings were locally static literals.

VHDL-2008 expands the kinds of expressions that are considered to be locally static. A locally static expression can be of a composite type, provided the subtype of each of the primaries in the expression is locally static and has a locally static subtype. The list of allowed primaries is expanded to include array and record aggregates, indexed array elements, array slices, and selected record elements. The operators in the expression can be any of the predefined operators or functions, or any of the operators or functions defined in the standard packages std_logic_1164, numeric_bit, numeric_std, numeric_bit_unsigned, and numeric_std_unsigned.

To illustrate a consequence of these changes, given the following declarations:

constant unsigned_const : unsigned(5 downto 0) := "000000";
type unsigned_ROM_array is array (0 to 255) of unsigned(7 downto 0);
constant unsigned_ROM : unsigned_ROM_array := (. . .);

it is now legal to write a case statement with the following choices:

case unsigned_value is
  "00" & unsigned_const    =>  . . .
  ("00" & unsigned_const)+ 1=>  . . .
  unsigned_ROM(128)             =>  . . .
  . . .
end case;

Static Ranges

In many modeling scenarios, we would like to use the index range of one object to declare another object. If the declaration requires the index range to be globally static, we can sometimes run into problems, as this example illustrates:

entity shifter is
  port ( d : in bit_vector; . . . );
end entity shift_in;

architecture rtl of shift_in is
begin
  ff_gen : for i in d'range generate
    . . .
  end generate ff_gen;
end architecture rtl;

In earlier versions of VHDL, this was illegal. The range used to define the for-generate parameter must be a globally static range; that is, it must be determined at elaboration time. The earlier rules for globally static ranges permitted use of an attribute, provided the prefix was of a globally static subtype. In this example, the subtype of d is bit_vector, which is not globally static.

VHDL-2008 addresses this and similar problems by recognizing that it is not the index range of the declared subtype of d that we are interested in. Rather, it is the index range of d itself, which is determined at elaboration time from the actual signal associated with the port. VHDL-2008 revises the rules for globally static expressions and ranges to allow use of attributes that provide information about the range of a prefix, provided the prefix is one of the following:

  • a signal or port

  • a constant or generic constant

  • a type or subtype

  • a globally static function call

  • a variable that is not of an access type, or a variable of an access type whose designated subtype is fully constrained

For these prefixes, we can use attributes such as 'range, 'left, 'right, 'length, and 'ascending, since they provide information about the range of the prefix that is determined at elaboration time.

Use Clauses, Types, and Operations

VHDL allows a name declared in a package to be made visible in another design unit with a use clause. We commonly write

use package_name. all ;

to make all of the names declared in the package visible. Alternatively, we can list individual names to identify which of the names declared in the package become visible, for example:

use package_name. identifier;

According to the rules of earlier versions of VHDL, strictly, if the name listed was the name of a type declared in the package, only the type name was made visible. None of the predefined operations for the type were also made visible. Moreover, for enumeration types, none of the enumeration literals were made visible, and for physical types, none of the unit names were made visible.

VHDL-2008 extends the rules for use clauses to make using type names more useful. If we write a type or subtype name in a use clause, then as well as that name becoming visible, the following additional items declared in the package become visible:

  • All of the predefined operations on the type, provided they are not hidden by overloaded version also declared in the package.

  • Overloaded versions of predefined operations on the type declared in the package.

  • For an enumeration type or subtype, all of the enumeration literals. This includes any character literals of the type.

  • For a physical type or subtype, all of the unit names for the type.

For example, suppose we declare the following package:

package stuff_pkg is

  type color_type is (red, orange, yellow, green, blue, violet);
  subtype warm_color is color_type range red to yellow;

  function ">" ( c1, c2 : color_type ) return boolean;
  function pretty ( c : color_type ) return boolean;

  type resistance is range 0 to 1E9 units
    Ohm;
    kOhm = 1000 Ohm;
    MOhm   = 1000 k0hm;
  end units ;

  subtype weak_logic is
    IEEE.std_logic_ll64.std_1ogic range 'W' to 'H';

end package stuff_pkg;

Then the use clause

use stuff_pkg. color_type;

makes not only the type color_type visible, but also the enumeration literals red through violet, the predefined operations on color-type other than "<", and the overloaded "<" operator declared in the package. It does not make the function pretty visible, since it is not an overloaded version of a predefined operation. If we write the use clause

use stuff_pkg. warm_color;

it makes the subtype warm_color visible, along with all of the enumeration literals for color_type (not just those in the subtype) and the operations for color-type.

If we write the use clause

use stuff_pkg. resistance;

it makes the type resistance visible, along with the unit names Ohm, kOhm, and MOhm, and the predefined operations on resistance.

Finally, if we write the use clause

use stuff_pkg.weak_logic;

all we get is the subtype name weak_logic made visible, since none of the enumeration literals or operations are declared in the package stuff_pkg.

Hiding of Implicit Operations

Earlier versions of VHDL had a subtle interaction between the rules for use clauses and the rules for overloading predefined operations. This interaction caused a problem during development of the numeric_bit_unsigned and numeric_std_unsigned packages. When we declare a type in a package, the predefined operators for the type are implicitly declared in that package. For example, the type std_logic_vector is declared in package std_logic_1164, and so the predefined operators such as "<" are also declared implicitly in std_logic_1164. If we were to declare an overloaded version of "<" for std_logic_vector in the same package, it would hide the predefined version. A use clause for the package with the overloaded operator would make the overloaded version visible, not the predefined version.

On the other hand, we can write a separate package that defines overloaded operators. The package numeric_std_unsigned does just that for the std_logic_vector type. It declared overloaded comparison operators that perform arithmetic comparisons, whereas the predefined comparison operators in std_logic_1164 perform lexicographic comparisons.

Now suppose we write a design unit that uses both std_logic_1164 and numeric_std_unsigned:

library IEEE;
use IEEE.std_logic_1164.all, IEEE.numeric_std_unsigned.all ;
. . .

The question is, which version of the "<" is visible in the design unit? Since the two versions are declared in different packages, under the old VHDL rules, the explicitly declared version did not hide the implicitly declared version. Since the use clauses made two version potentially visible, neither version was made visible. VHDL-2008 revises the rules for use clauses so that an overloaded version of a predefined operation explicitly declared in one package, when used by a use clause, hides the use of an implicitly declared version from another package. So in the above example, the "<" operator explicitly declared in numeric_std_unsigned is made visible, and the implicit version from std_logic_1164 remains hidden.

Multidimensional Array Alias

VHDL allows us to write an alias for an object, and to specify a subtype with which to view the object. For example, we can write:

signal s : bit_vector(l5 downto 0);
alias bigendian_s : bit_vector(0 to 15) is s;

In earlier versions of VHDL, the rules for aliases of arrays were unclear, and prohibited aliases of multidimensional array objects. Thus, the following was illegal in earlier versions of VHDL:

type bit_matrix is
  array (natural range <>, natural range <>) of bit;
signal s : bit_matrix(15 downto 0, 15 downto 0);
alias bigendian_s : bit_matrix(0 to 15, 0 to 15) is s;

VHDL-2008 clarifies the rules and removes the restriction, making the above example legal.

Others in Aggregates

VHDL allows an array aggregate to include an others choice, provided the index range of the array can be determined from the context. We need the index range in order to work out what index values are implied by the others choice. In earlier versions of VHDL, the rules identifying where an array aggregate could include others omitted a number of useful cases. VHDL-2008 rectifies the omissions.

One place where earlier versions of VHDL did not allow us to use others in an array aggregate was as a default value for a generic constant declared to be of a constrained array type. For example, the aggregate in the following declaration would be illegal in earlier versions of VHDL:

entity adder32 is
  generic ( Tpd : time_vector(31 downto 0)
                      := (others => 100 ps) );
  port    ( a, b : in bit_vector(31 downto 0);
               ( s    : out bit_vector(31 downto 0) );
end entity adder32;

While we could certainly write out an aggregate with 32 elements, or rewrite the aggregate as:

(31 downto 0 => 100 ps)

this would be less convenient. VHDL-2008 rectifies the omission, making the aggregate in the generic list above legal. Moreover, when combined with the change described in Section 9.1, the following becomes legal in VHDL-2008:

entity adder is
   generic ( width : positive;
                   Tpd : time_vector(width-1  downto 0)
                         := (others => 100 ps) );
   port     ( a, b : in bit_vector(width-1 downto 0);
                    ( S    : out bit_vector(width-1 downto 0) );
end entity adder;

Other places where aggregates with others were previously omitted but are now allowed are:

  • As an actual expression in a port map associated with a port (or an element of a port) that is of a fully constrained array subtype.

  • As an actual expression associated with a slice of a parameter in a subprogram call, or with a slice of a generic in a generic map, or with a slice of a port in a port map.

  • As the right-hand side of an assignment statement where the assignment target is an element of an object and the element is of a fully constrained array type.

  • As the right-hand side of an assignment statement where the assignment target is a slice of an object.

Attribute Specifications in Package Bodies

Earlier versions of VHDL did not allow attribute declarations or specification in package bodies. This omission is rectified in VHDL-2008. As a consequence, the following is now legal, whereas it was illegal in previous versions:

package utility_pkg is
  type lookup_ROM is array (0 to 15) of bit_vector(7 downto 0);
  constant lookup : lookup_ROM;
end package utility_pkg;

package body utility_pkg is

  function get_cpu_time return delay_length;
  attribute foreign of get_cpu_time : function is
     "VHPIDIRECT libutility get_cpu_time";
  . . .

  constant lookup : lookup_ROM := ( . . . );

  attribute logic_block : boolean;
  attribute logic_block of lookup : constant is true;

end package utilty_pkg;

The package declaration contains an attribute specification to decorate the function get_cpu_time with the 'foreign attribute. This allows the function, declared privately within the package body, to have a VHPI implementation. The package body also declares the synthesis attribute 'logic_block and decorates the deferred constant lookup with the attribute. These attribute declarations and specifications are all now legal in VHDL-2008.

Attribute Specification for Overloaded Subprograms

The way attribute specifications for overloaded subprograms were defined in earlier versions of VHDL led to some undesirable consequences in some cases. One of the rules was that, if we wrote an attribute specification for a name, and there were multiple overloaded subprograms of that name, then all of the overloaded versions were decorated. The problem arose if a given name was used for both procedures and functions. For example, suppose we declared the following subprograms and tried to decorate them:

procedure add  ( a, b : in integer; s : out integer );
procedure add  ( a, b : in real; s : out real );
function add   ( a, b : integer ) return integer;
function add   ( a, b : real ) return real;

attribute built_in : boolean;
atribute built_in of add : procedure is true;
attribute built_in of add : function is false;

The problem was that, in earlier versions of VHDL, the subprogram identified by the names did not take account of the subprogram kind in the attribute specification. That caused us to run foul of the rule that all of the items identified by the name had to be of the specified kind. Thus, in the example, the name add in both attribute specifications identifies all four overloaded versions. Even though two are not procedures for the first specification, and two are not functions for the second specification. We could avoid this problem by writing separate attribute specifications for each subprogram, using a signature to differentiate them, but that would require four attribute specifications instead of two:

atribute built_in of
  add[integer, integer, integer] : procedure is true;
atribute bui1t_in of
  add[real, real, real] : procedure is true;
attribute built_in of
  add[integer, integer return integer] : function is false;
attribute built_in of
  add[real, real return real] : function is false;

Clearly, this is more cumbersome. VHDL-2008 tidies up the rules for attribute specifications by taking account of the kind of item. If the name identifies multiple overloaded subprograms, only those of the specified kind are actually decorated. Thus, we can legally write the original two attribute specifications above. Only the two procedures are decorated with the attribute value true, and only the two functions are decorated with the attribute value false.

Integer Expressions in Range Bounds

In certain cases in earlier versions of VHDL, we could not use a numeric literal as one bound for a range and a more complex expression as the other bound. An example is a for loop written as follows:

for i in 0 to 2**N - 1 loop . . .

where N is a constant of type integer. A similar problem could arise in a for generate statement and in an index range for an array type definition.

The underlying reason, in earlier versions of VHDL, was that the bounds are both of the predefined type universal_integer, but VHDL only implicitly converted the bounds from universal-integer values to integer if both were simple expressions consisting just of a numeric literal or an attribute value. If that was not the case, the bounds were required to be of a type other than universal-integer. In the example above, the fact that the right bound is a more complex expression prevented the implicit conversion being performed, leaving both bounds of the type universal_integer, which was illegal.

VHDL-2008 rectifies the anomaly by removing the requirement that both bounds be simple expressions for the implicit conversion to integer to apply. Instead, the implicit conversion is done if both bounds are of type universal_integer, regardless of the complexity of the expressions. Thus, in the above example in VHDL-2008, the conversion is performed, leading to the loop parameter i being of type integer.

Action on Assertion Violations

Assertion statements and report statements allow specification of the severity level (note, warning, error, or failure) associated with a message. Earlier versions of VHDL did not specify the effect of different severity levels, beyond saying that it should be included in the message. Different simulators have taken different approaches. Most will stop execution on some given severity level or greater, but they differ in the threshold at which they stop. Some stop on error or failure, whereas others stop only on failure. This has caused portability problems for users writing simulation control scripts and for developers of packages that include assertions.

VHDL-2008 recommends that a simulator continue execution for an assertion or report statement with severity level of error or less. This should help reduce the portability problems, as tool implementers converge upon the recommendation.

’Path-Name and ’Instance_Name

VHDL includes two predefined attributes, 'path_name and 'instance_name, that give string values representing the path through the design hierarchy from the root to the prefix item. These attributes were introduced in VHDL-93.

One omission from the rules for forming the attribute values in earlier versions of VHDL was provision for overloaded operators. Both attributes included the name of a subprogram enclosing an item, but only allowed for an identifier to represent the subprogram name. An overloaded operator, on the other hand, has an operator symbol in quotation marks as its name. VHDL-2008 amends the rules to allow for this scenario. Thus, given the following design hierarchy:

entity e is
end entity e;

architecture a of e is
begin
  proc : process is
    type T is . . .
    function "+" ( a, b : T ) return T is
       variable s : integer;
    begin
       . . .
    end function "+";
  begin
    . . .
  end process proc;
end architecture a;

the value of s'pathname is the string

:e:proc: "+":s

and the value of s'instance name is the string

:e(a):proc: "+":s

In VHDL-2000, protected types for shared variables were introduced. A protected type encapsulates declarations and is instantiated when a shared variable is elaborated. Thus, a shared variable constitutes part of the hierarchy of a design. The path to an item declared within a protected type descends through a shared variable. Nonetheless, neither VHDL-2000 nor VHDL-2002 made provision for a shared variable’s name in rules for the 'path_name and 'instance_name attributes. VHDL-2008 rectifies this omission. To illustrate, suppose we declare a protected type in a package as follows:

package sharing_pkg is
  type int_mailbox is protected
      . . .
  end protected int_mailbox;
end package sharing_pkg;

package body sharing_pkg is
  type int_mailbox is protected body
     variable int : integer := 0;
     . . .
  end protected body int_mailbox;
end package body sharing_pkg;

We then declare a shared variable of this type within an architecture:

entity e is
end entity e;

architecture a of e is
  shared variable v : work.sharing_pkg.int_mailbox;
begin
  . . .
end architecture a;

The value of int'path-name for the encapsulated variable within the instance v is:

:e:v:int

Similarly, the value of int'instance_name for that encapsulated variable is:

:e(a):v:int

Note that in both cases, the path does not go through the package in which the protected type is declared. Rather, the path follows the instantiation hierarchy through the shared variable.

Non-Nesting of Architecture Region

In versions of VHDL prior to 2002, there were some anomalies relating to the way in which entity and architecture names were defined. A literal interpretation of the rules meant that entity and architecture names could not be referenced. Since this was clearly not intended, different implementations of VHDL made different interpretations, resulting in some incompatibilities between tools.

In those earlier versions, the declarative part of an architecture was intended to be an extension of the declarative part of the corresponding entity. However, it was not clear where the architecture name itself was declared. Problems became apparent when the architecture name was the same as the entity name, a common practice for many designers. Under some interpretations of the rules for scope and visibility of names, the architecture name hid the entity name, whereas under other interpretations, making the entity and architecture names the same was illegal.

VHDL-2002 sought to clarify the rules by specifying that an architecture was no longer to be considered as an extension of the entity’s declarative part. Instead, the architecture formed a nested declarative region, logically positioned within and at the end of the entity declarative part. Thus, the architecture name was officially declared within the entity, and could hide the entity name if it was the same. This approach very neatly solved the naming problems with minimal change to the scope and visibility rules. However, the nesting structure could become apparent in a number of ways, and turned out not to be what users wanted. In practice, VHDL implementers did not revise their tools to conform with the new rules, and so the old problems remained.

VHDL-2008 reverts the rules for architectures to specify that an architecture is logically an extension of the corresponding entity declarative part. Moreover, the scope and visibility rules are revised to clarify the issues that led to different interpretations in earlier versions of VHDL. In particular, an architecture name is no longer considered to be declared within the entity declaration. Rather, an architecture name is given special consideration, and the places where it makes sense to refer to it are explicitly listed. As implementations converge on the new rules, the inconsistencies and incompatibilities from earlier versions of VHDL should disappear.

Purity of Now

VHDL-93 introduced the distinction between pure and impure functions. Essentially, a pure function returns the same result when called with the same parameters, whereas an impure function, by virtue of being allowed to reference items outside its declaration, may return different results.

The standard function now, defined in package standard, has no parameters and returns the current simulation time. Clearly, since the simulation time can change from one call to another, the function should be impure, and in VHDL-93 it was. In VHDL 2002, its declaration was changed to pure in order to address some concerns in another standard related to VHDL. However, this caused more problems than it solved, particularly since that other standard was revised to avoid the concerns. VHDL-2008 rectifies the anomaly by changing the declaration of now back to an impure function.

Delimited Comments

Earlier versions of VHDL have single-line comments, starting with the characters "--" and extending to the end of the line. VHDL-2008 keeps this style of comment, but also adds delimited comments, starting with the characters "/*" and extending to the closing characters "*/". The opening and closing characters can be on different lines, or can be on the same line. Moreover, there can be further VHDL code on the line after the closing characters. Some examples are:

/* This is a comment header that describes
   the purpose of the design unit. It contains
   all you ever wanted to know, plus more.
*/

library IEEE; context IEEE.IEEE_STD_CONTEXT;
entity thingumy is
   port ( clk   : in std_logic; -- keeps it going
               reset : in std_logic /* start over */
               /* other ports to be added later */ );
end entity thingumy;

Since the text in comments is ignored, it may contain comment delimiters. Mixing comment styles can be quite useful. For example, if we use delimited comments in a section of code, and we want to “comment out” the section, we can use single-line comments:

-- This section commented out because it doesn't work
-- /* Process to do a complicated computation
- -   involving lots of digital signal processing.
-- */
-- dsp_stuff : process is
-- begin
- -     assert 2 + 2 = 4;   -- make sure we're in the right universe
--      . . .
-- end process dsp_stuff;

However, we should be aware that comments do not nest. For example, the following is ill-formed:

-- Here is the start of the comment: /* A comment extending
                                          over two lines */

The opening "/*" characters occur in a single-line comment, and so are ignored. Similarly, we cannot reliably use delimited comments to comment out a section of code, since the section might already contain a delimited comment:

/* Comment out the following code:
signal count : unsigned(5 downto 0); /* event counter */
* /

In this case, the occurrence of the characters "*/" on the second line closes the comment started on the first line, making the orphaned delimiter "*/" on the third line illegal. Provided we avoid pitfalls such as these, delimited comments are a useful addition to the language.

Tool Directives

In Section 2.5, we mentioned that protect directives for IP protection are a form of tool directives. VHDL-2008 adds tool directives as a way of embedding information for use by tools in a VHDL model. A tool directive takes the form:

identifier . . .

The grave accent character (sometimes called a “back-tick”) is followed by an identifier that determines the action to be performed or the kind of information provided. The rest of the text on the line, if any, provides any further information required. The directive finishes with the end of the line. VHDL-2008 defines protect directives, with the identifier protect, but does not define any other kinds of directives. Implementations may define their own kinds of directives and place requirements on the text that follows the identifier.

New Reserved Words

As new features are added to VHDL, new reserved words are usually required. In VHDL-2008, the new reserved words added are

context

Used in context declarations and context references (see Section 2.3).

default

Can be used in the generic map of a formal generic package (see Section 1.6).

force

Used in a simple forcing assignment (see Section 2.2) and in conditional and selected forcing assignments (see Section 5.1.2).

parameter

Optionally precedes the parameter list in a subprogram (see Section 1.4).

release

Used in a release assignment (see Section 2.2).

In addition, the following PSL reserved words are also VHDL-2008 reserved words

assert
assume
assume_guarantee
cover
default
fairness
property
restrict
restrict_guarantee
sequence
strong
vmode
VProP
vunit

Note that assert was previously a reserved word, but now gains another use. Also, default has two uses, one in a PSL default clock declaration, and the other in the generic map of a formal generic package.

Since a reserved word cannot be used as an identifier, there is potential for backward incompatibility. If a model written in an earlier version of VHDL uses one of the new reserved words as an identifier, it is not legal VHDL-2008. However, most tools provide options to analyze a model using the rules of earlier versions of the language and allow a design to be composed of design units written in a mixture of language versions. So, in practice, backward incompatibility is not an insurmountable problem.

Replacement Characters

Earlier versions of VHDL allowed certain characters in models to be replaced with others. Specifically,

  • A vertical bar ("I") could be replaced by an exclamation mark ("I")

  • The number-sign characters ("#") in a based numeric literal could be replaced by colon characters (":").

  • The double-quote characters ("″") in a string literal could be replaced by percent characters ("%I").

Most VHDL users are unaware that such replacements were permitted. Nonetheless, they were allowed in the initial version of the language, since at that time, some computers used the EBCDIC character code, which did not include the replaced characters. In VHDL-2002, replacement characters were included in a list of deprecated features. The axe falls in VHDL-2008.

 

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.136.26.20