x The Subtleties of Attributes


Question: I've been trying to use the function POS from the back of the VHDL LRM to compare enumerated values, but I cannot get it to work. I've used enumerations rather than vectors, and I need to compare the values to see which has the highest position. My code looks like this:

  -- Definitions in architecture body:
  type LIST is (MODE0, MODE1, MODE2, MODE3);
  signal CURRENT_MODE, NEXT_MODE: LIST;

  -- Statement in architecture body:
  if CURRENT_MODE'POS < NEXT_MODE'POS then
    CURRENT_MODE <= NEXT_MODE;

The compiler does not allow the test. Are the functions at the back of the LRM not generally available, or do I have to use STD_LOGIC_VECTORS?

Answer: There are a few points to make here. Let's kick off with the most straightforward one: the syntax.

You can indeed make use of POS as defined at the back of the VHDL Language Reference Manual, but the proper syntax is a little different to yours. In VHDL tech-speak, POS is a predefined attribute. The prefix of the attribute must be the name of an enumeration, integer or physical type, and the attribute itself is a function with one parameter. The correct syntax would look like this:

  if LIST'POS(CURRENT_MODE) < LIST'POS(NEXT_MODE) then
    CURRENT_MODE <= NEXT_MODE;

To clarify this, the attribute LIST'POS(NEXT_MODE) returns the position number of the value NEXT_MODE within the type LIST. The position number refers to the order of the values in the enumeration type definition. The first value in any enumeration type has a position number of 0 (not 1!), or in VHDL syntax:

  LIST'POS(MODE0) = 0
  LIST'POS(MODE1) = 1

And so on. More generally, for any suitable type T:

  T'POS(T'LEFT) = 0

So now you know the syntax to compare the order of values in an enumeration type, or even convert them to integers if you want to. But is this a good idea? Returning to your example, we could simplify the code by comparing the values of the enumeration type directly, like so:

  if CURRENT_MODE < NEXT_MODE then
    CURRENT_MODE <= NEXT_MODE;

There is no need to convert the values to their position numbers; the operator "<" is implicitly defined on all enumeration types tocompare the values using the order in the type definition. So is this a good idea?

Well, now we get on to the subtle stuff. Everything we've seen is kosher 1076 standard VHDL, but that doesn't always mean you can use it reliably! For a start, many synthesis tools simply do not support the POS attribute, so if you intend to synthesize your design, you must find a different solution.

How about the second version with the comparison CURRENT_MODE < NEXT_MODE? There is a potential problem here as well, because although the POS attribute is not used, the comparison implicitly relies on the position number within the type. So what? Well, there is a VHDL style issue here. It would be better not to rely on the order of the values in the type, because that order could be inadvertently changed by someone diligently tidying up the source code. There is also a synthesis issue, because if the enumeration type is used to define the state vector of a finite state machine, then state machine optimization could reorder the list of states, and thus break the design!

This last point deserves some clarification. In your example, the values of LIST satisfy the following relations:

  MODE0 < MODE1 < MODE2 < MODE3

This is the order of the values during VHDL simulation. But after finite state machine optimization has scrambled the states, there will be a new relationship between the values, say:

  MODE2 < MODE0 < MODE3 < MODE1

This is the order in the hardware implementation. Although many synthesis tools modify the states, some do not redefine the meaning of the ""<" operator on the enumeration type to retain the original order! To be safe, we must rewrite the VHDL to be independent of
the order. For example:

  case NEXT_MODE is
  when MODE0 => 
    null;
  when MODE1 => 
    if CURRENT_MODE = MODE0 then
      CURRENT_MODE <= MODE1;
    end if;
  when MODE2 => 
    if CURRENT_MODE = MODE0 or CURRENT_MODE = MODE1 then
      CURRENT_MODE <= MODE2;
    end if;
  when MODE3 => 
    if CURRENT_MODE /= MODE3 then
      CURRENT_MODE <= MODE3;
    end if;
  end case;

This final solution is very clumsy, but is independent of the order of the states. Such is life!


xVHDL FAQ
xDoulos Training Courses
author iconBack to “Your VHDL Problems Answered” Index


river sceneDoulos Home Page

Copyright 1995-1996 Doulos
This page was last updated 9th February 1996.

mail iconWe welcome your e-mail comments. Please contact us at: webmaster@doulos.co.uk