Assigning Values to Enumerated Types

Discussion in 'VHDL' started by Kevin Neilson, May 7, 2008.

  1. This seems simple, but I've been unable to find the answer. I have an
    enumerated type like this:

    type opmode_type is (m, p_plus_m, p_minus_m, m_plus_c...);
    signal opmode : opmode_type;

    As I understand it, the synthesizer will assign sequential values to
    these (i.e., m=1, p_plus_m=2). But I need to assign particular (3-bit
    signed) values to these: e.g., m="101", p_plus_m="110". Is there a way
    to do this?

    Perhaps I need to do something else entirely. I supposed I could use
    aliases to assign names to the constants. I could make a constant array
    and somehow index it (maybe with the enumerated type?). Or maybe I
    could make a record?

    type opmode_type is record m, p_plus_m, ... : unsigned(2 downto 0);
    signal opmode : opmode_type := ("101","110",...);

    and then access the opmode with a field, as in: opmode.p_plus_m

    I just wondered what is most stylistically proper way to do this.
    Kevin Neilson, May 7, 2008
    1. Advertisements

  2. Kevin Neilson

    KJ Guest

    Not really. By using the enumerated type you're in a sense divorcing
    yourself from particular encodings...but read on.
    Typically I would create a to_std_logic_vector and from_std_logic_vector
    function pair to convert between enumerated types and particular bit
    encodings (or records...very useful for bits in a read/write port). In your
    case, maybe you want a to_unsigned/from_unsigned pair. In any case, with
    the to/from functions in hand, you are basically free to use whatever form
    is appropriate.

    Sample conversion function:

    to_unsigned(L: opmode_type) return unsigned is
    variable RetVal: unsigned(2 downto 0);
    case L is
    when m => RetVal := "101";
    when p_plus_m => ...
    end case;
    end function to_unsigned;

    Sample usage:

    opmode <= from_unsigned("101");

    The conversion functions synthesize quite nicely, there is no 'overhead' in
    the final hardware to using it. The appearance and maintainability of the
    code is greatly enhanced by converting to/from required bit patterns in this

    Kevin Jennings
    KJ, May 7, 2008
    1. Advertisements

  3. Kevin Neilson

    Tricky Guest

    As KJ said, using an ennumerated type is letting the synthesizer chose
    the encoding for you. By default, this is usually done one hot, but I
    think there are options to change the encoding, maybe even force it
    yourself (I have never done this), but this would be a bit convoluted.

    Personally, I would just define opmode_type as a subtype of
    std_logic_vector so you have a fixed bit width, and then define
    constants for all of the states you want. When using the opmode,
    remember to have an "OTHERS" case to catch opmode in any states you
    havent defined (although it should never happen).
    Tricky, May 7, 2008

  4. in a similar vein:

    type op_t is (run, pause, idle, test, stop, etc)
    constant adr_len_c : natural := 3;
    subtype adr_t is std_logic_vector(adr_len_c-1 downto 0);
    function vec2mode (arg : adr_t)
    return op_t is
    variable index : natural := to_integer(unsigned(arg));
    return op_t'val(index);
    end function vec2mode;
    variable op_v : op_t; -- address register enum
    -- ...
    op_v := vec2mode(my_port_adr);
    case op_v is
    when run =>
    when etc =>

    -- Mike Treseler
    Mike Treseler, May 7, 2008
  5. Thanks to all for the answers. I'll probably use the scheme described
    above. I can't really just convert the enumerated signal directly to a
    value because I only have opmodes for a subset of the numbers, so the
    above scheme probably works the best. It also seems reasonably clear.
    Kevin Neilson, May 7, 2008
  6. But (if you're using it) remember that XST doesn't support 'val
    David R Brooks, May 7, 2008
  7. That is unfortunate.
    (I'm not).

    -- Mike Treseler
    Mike Treseler, May 7, 2008
  8. I also found an old post from Mike T where he shows how to initialize
    the constant array by name instead of order. Here is my implementation:

    type opmode_type is (m, minus_m, p_plus_m, p_minus_m, c_plus_m,
    type opmode_array is array(opmode_type) of std_logic_vector(6 downto 0);
    constant conv_dsp48e_opmode : opmode_array :=
    (m => "0000101",
    minus_m => "0000101",
    p_plus_m => "0100101",
    p_minus_m => "0100101",
    c_plus_m => "0110101",
    c_minus_m => "0110101",
    others => (others=>'0'));

    Kevin Neilson, May 7, 2008
  9. Yes, I like enumeration arrays as a register type.
    Looping through a name range is a nice way
    to match up groups of register array elements
    for assignments.

    However, I agree with KJ and leave state encoding to synthesis.
    If I care about a state value, then I must
    be using it as an output rather than a mode.

    The example above is a good demonstration of one downside.
    There is no compile time check that the state values
    are unique. That is a tough bug to find.

    -- Mike Treseler
    Mike Treseler, May 8, 2008
  10. That's correct. The enumerated type is a DSP48 "generic" opmode which
    gets resolved to a specific opmode depending upon the Xilinx family.
    This is defined by the silicon. And the duplicates are correct--the
    generic opmode is converted into a specific opmode, alumode, and
    subtract flag, and the combination of these is unique for each generic
    opmode. -Kevin
    Kevin Neilson, May 9, 2008
    1. Advertisements

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments (here). After that, you can post your question and our members will help you out.