Attributes for Enumerated Types

Proposal Editing Information

  • Who Updates: JimLewis, PatrickLehmann, <Add YourName>, ...
  • Date Proposed: 2012-08-17
  • Date Last Updated: 2015-06-26
  • Priority:
  • Complexity:
  • Focus: Testbench and Synthesis

Requirement Summary

Additional attributes for enumerated types

Related and/or Competing Issues: none

Proposal

T'LENGTH

Kind: function.
Prefix: A VHDL assert statement with the static label A.
Result type: Type integer. 
Result: T'LENGTH = T'POS(T'RIGHT) + 1
Alternative name(s): T'COUNT -- Main.PatrickLehmann - 2015-06-26

T'RANGE

Kind: range.
Prefix: A VHDL assert statement with the static label A.
Result type: Type integer. 
Result: 0 to T'POS(T'RIGHT) 

<Brent Hayhoe> 2015-06-30 - Prefixes should be 'any enumerated type or subtype T' </Brent Hayhoe>

T'SERIALIZE(value : T)

Kind: function.
Prefix: Converts an enum value into a commonly exchangeable binary representation.
Parameter 'value': Value that is to be serialized.
Result type: Type STD_LOGIC_VECTOR.
Result: Binary representation of value

T'DESERIALIZE(value : STD_LOGIC_VECTOR)

Kind: function.
Prefix: Converts a binary representation of an enum value into a concrete enum member.
Parameter 'value': Value that is to be deserialized.
Result type: Type T. 
Result: Enum member of it's binary representation

Use Models

Serialization and de-serialization of enumerated types into binary representations is a common use case in simulation and synthesis of HDL code. While VHDL does not support type generics to describe generic RAMs, FIFOs or cross-clock synchronizers. A 'serialization' functionality is needed to convert enum values into a common binary representation. Such converted values (e.g. of type STD_LOGIC_VECTOR) can be passed to a FIFO. Later it's also possible to convert the STD_LOGIC_VECTOR value back to an enum value.

The knowledge of the required bit count in the resulting bit vector, is a major step in enum value serialization into binary representations. Currently the count of declared enum members can only be retrieved by T'POS(T'RIGHT)+1 or T'POS(T'HIGH)+1. An initial step towards serialization is a VHDL attribute to get the count of enum members. Such an attribute could be named 'LENGTH - as known from array types - or 'COUNT to state the difference between array types and scalar types.

Some code snippets, which are used by the next examples:

type T_STATUS is (
  STATUS_IDLE,
  STATUS_TRANSMITTING,
  STATUS_COMPLETE,
  STATUS_ERROR
);

function log2(value : NATURAL) return POSITIVE;     -- returns log2 of value
function str_len(value : STRING) return NATURAL;    -- returns the length of a NUL terminated string
function str_trim(value : STRING) return STRING;    -- returns a trimmed string without trailing NUL characters

Use Case 1 - Serializing enum values to STD_LOGIC_VECTOR and vice versa for using with generic VHDL components

At the moment it's not possible to store enum vales in a generic FIFO or RAM. Here are several solutions for this scenario:

  • give up on using enums
  • implement a FIFO or RAM for each enum type
  • convert enum values to STD_LOGIC_VECTOR and vice versa

The latter solution needs one conversion function per type and direction.

function serializeStatus(value : T_STATUS) return STD_LOGIC_VECTOR is
begin
  return std_logic_vector(to_unsigned(T_STATUS'pos(value), log2(T_STATUS'pos(T_STATUS'high) + 1)));
end function;

function deserializeStatus(slv : STD_LOGIC_VECTOR) return T_STATUS is
begin
  if (to_integer(unsigned(slv)) <= T_STATUS'pos(T_STATUS'high)) then
    return T_STATUS'val(to_integer(unsigned(slv)));
  else
    return STATUS_ERROR;
  end if;
end function;

This could be shortened to this, if enum types support 'COUNT:

function serializeStatus(value : T_STATUS) return STD_LOGIC_VECTOR is
begin
  return std_logic_vector(to_unsigned(T_STATUS'pos(value), log2(T_STATUS'count)));
end function;

function deserializeStatus(slv : STD_LOGIC_VECTOR) return T_STATUS is
begin
  if (to_integer(unsigned(slv)) < T_STATUS'count) then
    return T_STATUS'val(to_integer(unsigned(slv)));
  else
    return STATUS_ERROR;
  end if;
end function;

All these function could be spared if enum types support a 'SERIALZE and a 'DESERIALZE attribute:

signal Status                : T_STATUS;
signal Debugger_Data : STD_LOGIC_VECTOR(15 downto 0);

Debugger_Data(1 downto 0) <= serializeStatus(Status)

Or shorter with support for 'serialize:

Debugger_Data(1 downto 0) <= T_STATUS'serialize(Status);

Use Case 2 - Exporting/writing enum values and member names into files for external tools

Some simulation and synthesis tools support I/O functions to read and write files from the host's file system. While this feature is massively used in simulation environments it's rarely used in synthesis environments. Synthesis tools generate large reports, which include state encodings for enum based FSMs. But it's not common to report other encodings for e.g. enum based signals. There are several solutions to this scenario:

  • give up on using enums
  • force a specific enum encoding by using a vendor specific encoding attribute
  • export enum values and it's internal value (position) into a string representation

These string representations can be read back by external tools like waveform viewers or debuggers to show captured signals with it's member name instead of it's binary representation.

A simple export format could be:

  • one member per line
  • separated by semi-colons

Example of a simple format:

STATUS_IDLE;STATUS_TRANSMITTING;STATUS_COMPLETE;STATUS_ERROR;

procedure str_append(StringBuffer : inout STRING; value : STRING) is
  constant BufferEnd : POSITIVE := str_len(StringBuffer);
begin
  StringBuffer(BufferEnd + 1 to BufferEnd + str_len(value))   := value;
end procedure;
   
function encodeStatus return string is
  variable StringBuffer      : STRING(1 to (64 * T_STATUS'count))      := (others => NUL);
begin
  for member in T_STATUS loop
    str_append(StringBuffer, (T_STATUS'image(member) & ';');
  end loop;
  return  str_trim(StringBuffer);
end function;

A external script can transform this enum member list into other file formats like ChipScope's token files (*.tok) or GTKwaves data format filter files. It's even possible to export these file formats directly. An advantage is to generate up-to-date encoding files for external tools without complex synthesis report parsing.

Questions

  • <Brent Hayhoe> 2015-06-30 - Do we really want T'RANGE to return an integer range? Should it not return the enumerated range T'LEFT to T'RIGHT? For example, in Std_logic_1164 we already use the range keyword to define subtypes:

  -------------------------------------------------------------------    
  -- common subtypes
  -------------------------------------------------------------------    
  subtype X01 is resolved STD_ULOGIC range 'X' to '1';    -- ('X','0','1') 
  subtype X01Z is resolved STD_ULOGIC range 'X' to 'Z';   -- ('X','0','1','Z') 
  subtype UX01 is resolved STD_ULOGIC range 'U' to '1';   -- ('U','X','0','1') 
  subtype UX01Z is resolved STD_ULOGIC range 'U' to 'Z';  -- ('U','X','0','1','Z') 

I think that we should match T'range to return the base type range, in the same manner as it is used in defining a subtype. </Brent Hayhoe>

  • The extension is trivial, but where and how would this be used? -- ErnstChristen - 2015-01-27

  • <Brent Hayhoe> 2015-06-30 - I think 'serialize' and 'deserialize' are application specific and should remain as functions in an (open source?) package. The problem here is not so much language design deficiency as a limitation in synthesis. We could build a FIFO model to handle enumerated types and would work in simulation, but would a synthesis tool be able to map it to Std_Logic. My guess is that it will complain at the compilation stage? </Brent Hayhoe>

General Comments

Supporters

-- Brent Hayhoe - 2015-06-30 (with the provisos of range based on base enumerated type and that serialize and deserialize attributes are not approved.

-- PatrickLehmann - 2015-06-26

Add your signature here to indicate your support for the proposal

Topic revision: r15 - 2015-07-01 - 03:46:08 - KevinJennings
 
Copyright © 2008-2019 by the contributing authors. All material on this collaboration platform is the property of the contributing authors.
Ideas, requests, problems regarding TWiki? Send feedback