bit_vector comparison

A

Amal

In a design done by someone else I encountered a problem that I did
not expect. I don't usually compare vectors of different length, but
he was comparing a 10-bit vector with a bit string literal that is a
bit_vector. The base was hexadecimal and apparently he was comparing
the 10 bit vector (std_logic_vector). And did not get the correct
functionality. I am not sure if this is an inherent problem with VHDL
or it is Modelsim simulator problem.

In the following code, even if you change the comparison operator from
'<' (less than) to '<=' (less than or equal), you would get the same
result, which is very weird.

Please give me your input and tell me how VHDL treats bit-string
literals and bit_vector constants.

entity test is
end entity test;

architecture behav of test is
signal v : bit_vector(9 downto 0);
signal x1, x2, x3 : boolean;
begin
x1 <= (v < X"010");
x2 <= (v < b"0000_0001_0000");
x3 <= (v < "000000010000");

z1 <= (v < b"00_0001_0000");
z2 <= (v < "0000010000");

process
begin
v <= (others=>'0');

-- for i in 0 to 31 loop
-- v <= conv_std_logic_vector( i, v'length );
-- wait for 10 ns;
-- end loop;

wait for 10 ns;
v <= "0000000001";
wait for 10 ns;
v <= "0000000010";
wait for 10 ns;
v <= "0000000011";
wait for 10 ns;
v <= "0000000100";
wait for 10 ns;
v <= "0000000101";
wait for 10 ns;
v <= "0000000110";
wait for 10 ns;
v <= "0000000111";
wait for 10 ns;
v <= "0000001000";
wait for 10 ns;
v <= "0000001001";
wait for 10 ns;
v <= "0000001010";
wait for 10 ns;
v <= "0000001011";
wait for 10 ns;
v <= "0000001100";
wait for 10 ns;
v <= "0000001101";
wait for 10 ns;
v <= "0000001110";
wait for 10 ns;
v <= "0000001111";
wait for 10 ns;
v <= "0000010000";
wait for 10 ns;
v <= "0000010001";

wait for 50 ns;
wait;
end process;
end architecture behav;

-- Amal
 
M

Mike Treseler

Amal said:
Please give me your input and tell me how VHDL treats bit-string
literals and bit_vector constants.


If I want numeric comparison functions
to work correctly, I use numeric types.
See below.
This should make everything flip on
the v transition from x"0F" to x"10"

-- Mike Treseler
_____________________________________
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity uns_compare is
end entity uns_compare;

architecture behav of uns_compare is
signal v : unsigned(9 downto 0);
signal x1, x2, x3, z1, z2 : boolean;
begin
x1 <= (v < X"010");
x2 <= (v < b"0000_0001_0000");
x3 <= (v < "000000010000");

z1 <= (v < b"00_0001_0000");
z2 <= (v < "0000010000");
....

____________________________________________
 
A

Amal

If I want numeric comparison functions
to work correctly, I use numeric types.
See below.
This should make everything flip on
the v transition from x"0F" to x"10"

-- Mike Treseler
_____________________________________
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity uns_compare is
end entity uns_compare;

architecture behav of uns_compare is
signal v : unsigned(9 downto 0);
signal x1, x2, x3, z1, z2 : boolean;
begin
x1 <= (v < X"010");
x2 <= (v < b"0000_0001_0000");
x3 <= (v < "000000010000");

z1 <= (v < b"00_0001_0000");
z2 <= (v < "0000010000");
...

____________________________________________


Yes, Mike, I understand that if you include numeric_std package, you
are overriding built-in comparison operators, but what happens here
when you don't? Why should the compiler not give you a warning and
you get wrong functionality.

The result is:

a 00 01 02 03 4 5 6 7 8 9 10 11 12 13 14 15 16 17
x1 --------------\________________________________
x2 --------------\________________________________
x3 --------------\________________________________
z1 ---------------------------------------\_______
z1 ---------------------------------------\_______

Why the change at 5? And why when you do:
x1 <= (v >= X"010");

you get the same result as:
x1 <= (v < X"010");

-- Amal
 
D

Duane Clark

Amal said:
In a design done by someone else I encountered a problem that I did
not expect. I don't usually compare vectors of different length, but
he was comparing a 10-bit vector with a bit string literal that is a
bit_vector. The base was hexadecimal and apparently he was comparing
the 10 bit vector (std_logic_vector). And did not get the correct
functionality. I am not sure if this is an inherent problem with VHDL
or it is Modelsim simulator problem.

In the following code, even if you change the comparison operator from
'<' (less than) to '<=' (less than or equal), you would get the same
result, which is very weird.

Please give me your input and tell me how VHDL treats bit-string
literals and bit_vector constants.

entity test is
end entity test;

architecture behav of test is
signal v : bit_vector(9 downto 0);
signal x1, x2, x3 : boolean;
begin
x1 <= (v < X"010");
x2 <= (v < b"0000_0001_0000");
x3 <= (v < "000000010000");

You are comparing a 10 bit signal against a 12 bit literal. So the
comparison is being done against the left most 10 bits of the literal.
 
A

Amal

If it is the 10 left bits, then why x1 is false when v 5? If you take
the 10 most significant bits, you get 4 and x1 should go false when v
is 4, not 5?!

And also both '<' and '<=' result in the same behavior? Give it a try
yourself.

-- Amal
 
M

Mike Treseler

Amal said:
If it is the 10 left bits, then why x1 is false when v 5? If you take
the 10 most significant bits, you get 4 and x1 should go false when v
is 4, not 5?!

If I don't use a numeric library, I will pick up
non-numeric string functions for =, < , <= etc.
String ranges are (1 to n) not (n downto 0).

You have found the bug.
I would fix it rather than analyze it.

Drop in numeric_bit or numeric_std
and declare unsigned vectors.

-- Mike Treseler
 
J

Jim Lewis

Amal,
The current comparison operators are implicitly defined
if you do not explicitly overload them. For an enumerated
type, implicitly left-most values are smaller than right-most
values. Hence, U < X < 0 < 1 < Z < W < L < H < -. For arrays,
comparisons start with the left-most element (like
a dictionary). As a result, comparisons using bit_vector
and std_logic_vector do not work numerically when the
array lengths are not the same. Also for std_logic,
L /= 0 and H /= 1 as it would numerically.

This means you must take caution:
1) Use numeric_std and either signed and unsigned types
or convert to signed and unsigned
2) Make sure arrays are equal length and you
only have driving values (use ieee.std_logic_1164.TO_X01).
3) Use an unsigned package that understands std_logic_vector
to be unsigned - of course expect many to object

In the next revision of the language, new ordering operators
are being added (?>, ?>=, ?<, ?<=) that return std_logic/bit
and are not implicitly defined As a result, it will be an error
if an appropriate package is not referenced. They are also
handy for other use cases such as:

RamSel <= MemSel and Addr > X"1FFF" ;

Cheers,
Jim
 
D

Duane Clark

Amal said:
If it is the 10 left bits, then why x1 is false when v 5? If you take
the 10 most significant bits, you get 4 and x1 should go false when v
is 4, not 5?!

I find the spec to be rather cryptic on this point. It implies that the
full 12 bits are considered starting from the left. How they are
supposed to be compared is not clear to me. I suspect Modelsim is correct.
And also both '<' and '<=' result in the same behavior?

This is explained in the spec. The values are never equal because they
are different sizes. Modelsim is definitely correct, and indeed if you
set say:
x2 <= (v = b"0000_0001_0000");
Modelsim will print a warning that the comparison is always false.
 

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. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,744
Messages
2,569,483
Members
44,902
Latest member
Elena68X5

Latest Threads

Top