Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

problem with unsigned vs std_logic_vector

518 views
Skip to first unread message

jlo...@gmail.com

unread,
Feb 25, 2014, 1:14:23 PM2/25/14
to
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);

or

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.

Sean Durkin

unread,
Feb 26, 2014, 6:29:36 AM2/26/14
to
Am 25.02.2014 19:14, schrieb jlo...@gmail.com:
> 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);
>
> or
>
> 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.

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?

Greetings,
Sean

Daniel Kho

unread,
Feb 26, 2014, 11:30:21 PM2/26/14
to
> 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?
>
>
>
> Greetings,
>
> Sean


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

Brian Drummond

unread,
Feb 27, 2014, 6:21:57 AM2/27/14
to
Actually, the 31st bit would be either A(30) or A(1) depending on how the
OP counted; as a little-endian guy I would consider A(31) to be the 32nd
bit...

I agree the question as posted is hopelessly unclear.

- Brian

HT-Lab

unread,
Feb 27, 2014, 6:46:24 AM2/27/14
to
I suspect the longest static prefix manage to trip another user ;-)

Hans
www.ht-lab.com

Gerhard Hoffmann

unread,
Feb 28, 2014, 4:43:33 AM2/28/14
to
Am 25.02.2014 19:14, schrieb jlo...@gmail.com:
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

jlo...@gmail.com

unread,
Feb 28, 2014, 1:42:04 PM2/28/14
to
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 if not 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.

Brian Drummond

unread,
Mar 1, 2014, 8:12:28 AM3/1/14
to
On Fri, 28 Feb 2014 10:42:04 -0800, jlodman wrote:

> On Tuesday, February 25, 2014 10:14:23 AM UTC-8, jlo...@gmail.com wrote:
>> I'm having a problem with a VHDL signal I hadn't expected. Simulator is
>> Modelsim.

>> signal A : unsigned(31 downto 0);

> 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).

Unsigned can handle any required range. Integer (and Natural) can't.
Yes this does cause difficulty in current implementations of VHDL.
Fortunately you can create Unsigned literal values without using Integer.

- Brian

Brian Drummond

unread,
Mar 1, 2014, 8:12:58 AM3/1/14
to
On Fri, 28 Feb 2014 10:42:04 -0800, jlodman wrote:

> On Tuesday, February 25, 2014 10:14:23 AM UTC-8, jlo...@gmail.com wrote:
>> I'm having a problem with a VHDL signal I hadn't expected. Simulator is
>> Modelsim.

>> signal A : unsigned(31 downto 0);

> 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).

Daniel Kho

unread,
Mar 2, 2014, 12:37:18 AM3/2/14
to
>
> Unsigned can handle any required range. Integer (and Natural) can't.

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);
begin
A<=x"8000_0000";
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:
A(31)<='1';
A(31)<='0';


>
> Actually, the 31st bit would be either A(30) or A(1) depending on how the
> OP counted; as a little-endian guy I would consider A(31) to be the 32nd
> bit...

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

unread,
Mar 2, 2014, 9:35:55 AM3/2/14
to
>
> Try changing the value from x"8000_0000" to x"0", resimulate, and notice if there are any changes in the simulated waveform.

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

-daniel

Dio Gratia

unread,
Mar 2, 2014, 5:05:44 PM3/2/14
to
On Saturday, March 1, 2014 7:42:04 AM UTC+13, jlo...@gmail.com wrote:
>
> Since I have 36 bit addresses, I now have to do more work to get them out.

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;
begin
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);

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

MONITOR:
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:@0ms:(assertion warning): NUMERIC_STD."=": metavalue detected, returning FALSE
unsigned.vhdl:40:1:@0ms:(assertion note):
A = UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU
B = UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU
C = UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU
../../../src/ieee/numeric_std-body.v93:1613:7:@0ms:(assertion warning): NUMERIC_STD."=": metavalue detected, returning FALSE
unsigned.vhdl:40:1:@0ms:(assertion note):
A = UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU
B = UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU
C = XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
unsigned.vhdl:40:1:@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 report is 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 to describe 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 representations in 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 an array 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?

Andy

unread,
Mar 3, 2014, 11:39:28 AM3/3/14
to
On Sunday, March 2, 2014 4:05:44 PM UTC-6, Dio Gratia wrote:
> ...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.

VHDL-2008 includes the package ieee.numeric_standard_unsigned, which defines arithmetic operators with std_logic_vector operands for unsigned arithmetic.

> You should consider it anathema to mix numeric_std (which provides unsigned)
> with synopsys's packages.

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

Dio Gratia

unread,
Mar 3, 2014, 1:34:00 PM3/3/14
to
On Tuesday, March 4, 2014 5:39:28 AM UTC+13, Andy wrote:
> On Sunday, March 2, 2014 4:05:44 PM UTC-6, Dio Gratia wrote:
>
> > ...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.
>
>
>
> VHDL-2008 includes the package ieee.numeric_standard_unsigned, which defines arithmetic operators with std_logic_vector operands for unsigned arithmetic.

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.

>
> > You should consider it anathema to mix numeric_std (which provides unsigned)
>
> > with synopsys's packages.
>
>
>
> 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...

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.


Andy

unread,
Mar 4, 2014, 6:40:17 PM3/4/14
to
On Monday, March 3, 2014 12:34:00 PM UTC-6, Dio Gratia wrote:
> They two array types (standard_logic_vector and UNSIGNED) aren't closely
> related. Their elements do have the same base type.

This is not true. The BASE TYPES of std_logic_vector and unsigned are both arrays of std_ulogic. That makes them closely related.

> 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.

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 that for 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

0 new messages