problem with unsigned vs std_logic_vector

Discussion in 'VHDL' started by jlodman, Feb 25, 2014.

  1. jlodman

    jlodman Guest

    I'm having a problem with a VHDL signal I hadn't expected. Simulator is Modelsim.

    When I declare a signal

    signal A : unsigned(31 downto 0);


    signal A : std_logic_vector(31 downto 0);

    I get unexpected results from the unsigned case specifically when I try to set the 31st bit. I don't expect there would be a difference but I could be wrong.

    I am using numeric_std

    Thanks for any insight.
    jlodman, Feb 25, 2014
    1. Advertisements

  2. jlodman

    Sean Durkin Guest

    Am 25.02.2014 19:14, schrieb :
    You need to be more specific. What "unexpected results"? What exactly
    are you trying to do, what are you expecting to happen, and what does
    actually happen?

    Sean Durkin, Feb 26, 2014
    1. Advertisements

  3. jlodman

    Daniel Kho Guest

    You need to be more specific. What "unexpected results"? What exactly

    Yes, also how did you assign your signal A? Did you try forcing A(31) to some hard-coded value and see what happens?

    regards, daniel
    Daniel Kho, Feb 27, 2014
  4. jlodman

    HT-Lab Guest

    I suspect the longest static prefix manage to trip another user ;-)

    HT-Lab, Feb 27, 2014
  5. Am 25.02.2014 19:14, schrieb :
    Probably your code breaks when you try to convert to integer.
    Integers are only + / - 2 Giga and you would also need sth. between
    +2Giga and slightly less than +4Giga for full 32 bit unsigneds.
    0x8000 0000 is also forbidden.

    That's not your fault, that's brain damage built into the language.
    It's fun testing a 64 bit design if you cannot formulate the numbers
    for your test cases in a readable way.

    I was thinking about a BCD arithmetic package that provides at least
    the equivalent of 256 bits. 4 bits stored per char. Should give fast
    conversion to/from int/string/signed/unsigned/fixed etc. and
    implementation could be an easy table-driven version of paper & pencil.

    Google summer of code?

    Still could not be used for long loops & synthesis.
    I really want int64 and int128.

    regards, Gerhard
    Gerhard Hoffmann, Feb 28, 2014
  6. jlodman

    jlodman Guest

    I did try and force it to a hardcoded value of '1' by "or" with x"8000_0000". It ended up as x"0000_0003"

    It's become clear that unsigned really can't handle a value large than 2^31-1, even when declaring a large range (I tried it). With everything else identical, when I changed the unsigned(31 downto 0) to std_logic_vector(31 downto 0) everything worked perfectly. I simply wasn't expecting this. Reading on-line it seems that even though the simulator/compiler accepts it, an unsigned bigger than an integer don't work right even when not using it to work with integers.

    As Gerhard indicates, this restriction on integers is becoming a Not Fun ifnot a serious problem in the language that should have been fixed in the last standard. Unsigned and signed should work regardless of the range specified, even if they would kick out now when trying to convert to a 32 bit integer.

    Since I have 36 bit addresses, I now have to do more work to get them out.
    jlodman, Feb 28, 2014
  7. jlodman

    Daniel Kho Guest

    Yes, (un)signed and any array types such as std_(u)logic_vector can handle any required range. Scalar types such as integer can't as mentioned by Brian.

    You should try with a simple testcase:

    architecture test of design is
    signal A : unsigned(31 downto 0);
    end architecture test;

    Try changing the value from x"8000_0000" to x"0", resimulate, and notice if there are any changes in the simulated waveform.

    Also, you could try with just driving a single bit to different values and resimulate to notice the difference:

    Yes, I'm a little-endian guy myself, though I have the (bad) habit of referring A(0) as the zeroth bit instead of the first bit. Sorry about that.
    Daniel Kho, Mar 2, 2014
  8. jlodman

    Daniel Kho Guest

    I meant to say change x"8000_0000" to x"0000_0000" or 32x"0".

    Daniel Kho, Mar 2, 2014
  9. jlodman

    Dio Gratia Guest

    You're statement that an unsigned can deal with greater than 31 bits is unfounded for VHDL in general. There's also not an arithmetic operator defined for std_logic_vector by default in VHDL unless you're also using synopsys's package std_logic_unsigned. You should consider it anathema to mix numeric_std (which provides unsigned) with synopsys's packages.

    library ieee;
    use ieee.std_logic_1164.all;
    use ieee.numeric_std.all;

    entity test is
    end entity;

    architecture foo of test is
    function unsigned_to_string (inp: unsigned) return string is
    variable tmp: string (1 to inp'LENGTH) := "";
    variable eval: character;
    variable index: positive;
    for i in inp'RANGE loop
    if inp(i) = 'U' then eval := 'U';
    elsif inp(i) = 'X' then eval := 'X';
    elsif inp(i) = '0' then eval := '0';
    elsif inp(i) = '1' then eval := '1';
    elsif inp(i) = 'Z' then eval := 'Z';
    elsif inp(i) = 'W' then eval := 'W';
    elsif inp(i) = 'L' then eval := 'L';
    elsif inp(i) = 'H' then eval := 'H';
    else eval := '-';
    end if ;
    tmp(index) := eval;
    index := index + 1;
    end loop;
    return tmp;
    end function;

    signal A: unsigned (31 downto 0);
    signal B: unsigned (35 downto 0);
    signal C: unsigned (35 downto 0);

    A <= x"80000000" after 1 ns;
    B <= x"800000000" after 1 ns;
    C <= A + B;

    assert C = x"FFFFFFFFF"
    report LF & "A = " & unsigned_to_string(A) & LF &
    "B = " & unsigned_to_string(B) & LF &
    "C = " & unsigned_to_string(C)
    severity NOTE;
    end architecture;

    %% ghdl -a unsigned.vhdl
    %% ghdl -e test
    %% ghdl -r test
    .../../../src/ieee/numeric_std-body.v93:1613:7:mad:0ms:(assertion warning): NUMERIC_STD."=": metavalue detected, returning FALSE
    unsigned.vhdl:40:1:mad:0ms:(assertion note):
    .../../../src/ieee/numeric_std-body.v93:1613:7:mad:0ms:(assertion warning): NUMERIC_STD."=": metavalue detected, returning FALSE
    unsigned.vhdl:40:1:mad:0ms:(assertion note):
    unsigned.vhdl:40:1:mad:1ns:(assertion note):
    A = 10000000000000000000000000000000
    B = 100000000000000000000000000000000000
    C = 100010000000000000000000000000000000

    All the 'U's are expected from the default assignment to the left most value of std_ulogic for each element of the unsigned arrays. The second reportis due to no delay in the assignment of C. You get all 'X's adding two arrays of 'U's. The third report shows the results of C <= A + B;

    unsigned is an array of std_logic which uses a nine value representation todescribe bit values ('U','X','0','1','Z','W','L','H','-'). The function "+" (an adding operator) is defined in package numeric_std.

    You could note I was too lazy to convert unsigned to string representationsin base 16, they are shown by std_logic element (i.e. bit by bit).

    There's also useful information derived from familiarity with the packages,for example the array length of the result for the function "+" (an operator) is derived from the MAX of the length of it's two arguments. C is a anarray of the std_ulogic nine level (MVL9 originally from Synopsys) representation of an array of bits that has a range of 35 downto 0 (36 bits).

    Perhaps you could show us an example VHDL description that exhibits your problem?
    Dio Gratia, Mar 2, 2014
  10. jlodman

    Andy Guest

    VHDL-2008 includes the package ieee.numeric_standard_unsigned, which defines arithmetic operators with std_logic_vector operands for unsigned arithmetic.
    Amen. If your synthesis/simulation vendor does not support VHDL-2008, tell them you need it, or switch tools.

    Even with the two ieee packages, I doubt there is an operator defined to add an SLV to an unsigned. Just don't go there...

    Andy, Mar 3, 2014
  11. jlodman

    Dio Gratia Guest

    Technically it's by inheritance. numeric_std_unsigned defines arithemetic and other operators for std_ulogic_vector which the 2008 std_logic_1164 package defines standard_logic_vector as a resolved subtype of.
    See the bit above about standard_logic_vector being a subtype of std_ulogic_vector. In 2008 unsigned is a resolved UN_RESOLVED_UNSIGNED which is an array type of STD_ULOGIC.

    They two array types (standard_logic_vector and UNSIGNED) aren't closely related. Their elements do have the same base type.
    And imagine how few religious arguments over types we'd have today if unsigned had been an alias for std_logic_vector originally. They're all just bags of bits (arrays) and the hardware (the 'H' in VHDL) really doesn't care.
    Dio Gratia, Mar 3, 2014
  12. jlodman

    Andy Guest

    This is not true. The BASE TYPES of std_logic_vector and unsigned are both arrays of std_ulogic. That makes them closely related.
    How do you specify that you want SLV to have an unsigned numeric representation? VHDL lets you (or other users before you) write packages that do thatfor you, or define the SLV representation as twos-complement, signed or unsigned fixed point, or floating point. When you want to mix them, VHDL wants to know explicitly how you want them mixed, so it can accurately model the behavior you want. From an accurate model, accurate hardware can be synthesized, rather than guessed at.

    If all you want to do is describe HW structure/implementation instead of behavior, use edif. It doesn't care either.

    Andy, Mar 4, 2014
    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.