compare std_logic_vector to a constant using std_logic_vecto

K

KM23

Guest
Hi,
I use the following package only in my vhdl file:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

In the code, i compare an std_logic_vector signal : A with a constant value, e.g

....if A<="00001011" then

yet the code was checked correctly by Xilinx ISE. My understanding is that STD_LOGIC_1164 package does not include an implementation of inequalities having as an operand std_logic_vector so why the above code statement was accepted and will the above comparison treat A as signed or unsigned number?

Cheers
 
On Tue, 13 Jan 2015 16:57:14 -0800, KM23 wrote:

Hi,
I use the following package only in my vhdl file:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

In the code, i compare an std_logic_vector signal : A with a constant
value, e.g

...if A<="00001011" then

yet the code was checked correctly by Xilinx ISE. My understanding is
that STD_LOGIC_1164 package does not include an implementation of
inequalities having as an operand std_logic_vector so why the above code
statement was accepted and will the above comparison treat A as signed
or unsigned number?

Cheers

The question is ... accepted by what?

I'm guessing you mean, accepted by some synthesis tool. And that's your
problem.

Synthesis tools are notoriously lax about accepting incorrect VHDL, and
notoriously loose about translating VHDL, whether it is correct or not.

This has long been regarded as an acceptable situation, on the grounds
that it is reasonable to assume (in the minds of the synth tool
designers) that by the time a design reaches synthesis, it has been
thoroughly verified in simulation and shown to be essentially correct,
thus repeating that level of strictness is redundant.

Unfortunately, unwary users are often bypassing the simulation stage and
proceeding directly to synthesis, building probable time-bombs into their
designs.

Like the above.

For example, will it do what you expect when the MSB A(A'High) is set?
That depends on what you expect ... to some people, when A = "10000001"
this should obviously return True, to others it should equally obviously
be False.

SIMULATE FIRST.

(and if you're using ISIM, remember to turn on its overflow checking in
"Process Properties!)

Sometimes worth simulating or at least compiling with more than one
simulator (not synthesis). The free and open-source ghdl is also one of
the more thorough and accurate interpretors of VHDL source code.

https://sourceforge.net/projects/ghdl-updates/

The problem is compounded by frankly terrible education in how to use a
type system - is this no longer taught at all?

For example, if A had been declared as ieee.numeric_std.signed, the
expression would be completely unambiguous, and the behaviour would
always be in line with expectations.

Furthermore, the much more readable
....if A <= 11 then
-- OK. it's safe to turn up the volume
would be permitted.

-- Brian
 
Am Mittwoch, 14. Januar 2015 01:57:16 UTC+1 schrieb KM23:
use IEEE.STD_LOGIC_1164.ALL;
[..]
...if A<="00001011" then

Std_ulogic_vector means your signal A is an arbitrary collection of single bits without further meaning, than beeing a collection of 8 bits (eg. the status signals of 8 one bit inputs collected).
If you like to compare a collection of bits with an string containing bits the operation "=" is well defined. The operation ">" and "<" can only mean has more or less bits.

If you want to compare if A <= "101" you need to define if "101" is a collection of bits and you like to know if A has no more than 3 bits, or if you like to see if A<=5 or A<=-3. This can only be achieved by declaring explicite, that A is signed or unsigned instead of arbitrary bit collection. This is usually done with numeric_std package.
 
> ...if A<="00001011" then

All enumerated types and arrays of enumerated types implicitly define the regular ordering relational operators (>, >=, <, <=). Unfortunately it is not numerically ordered, so the results may not be as expected. Instead it is dictionary ordered.

First you have to look at the element type, which is std_logic whose base type is std_ulogic. For an enumerated type, such as std_ulogic, left values are less than right values, hence, for std_ulogic (and std_logic):
'U' < 'X' < '0' < '1' < 'Z' < 'W' < 'L' < 'H' < '-'

For equal length arrays whose element base type is std_ulogic (such as std_logic_vector or std_ulogic_vector) whose values are only 0 or 1, things work out fine:
"1010" > "0101"

Note that dictionary comparisons always compare the left element first. Hence, for string, something that starts with 'S' is always less than something that starts with 'T' independent of length. This is great for sorting strings into a dictionary and is the only practical default - if we are going to provide such as thing.

OTOH, this is not so great if you are thinking things are numeric. For example, if the arrays are not equal length, then the following is true because the leading '1'on the left parameter is > the leading '0' of the right parameter.
"100" > "0111"

Hence, with only "use ieee.std_logic_1164.all", you have potential exposure to bad coding practices that mistakenly think of std_logic_vector as numeric (such as unsigned).

Many will argue, never use std_logic_vector for math and ">" is math. I generally agree.

So what do I do? How do I protect my design and design team from this. First you have to decide a policy and how to implement it.

1) Forbid use of regular ordering relational operators (>, >=, <, <=) with std_logic_vector and enforce it with a lint tool. However this means you have to buy and require the use of a lint tool.

2) Forbid use of regular ordering relational operators (>, >=, <, <=) with std_logic_vector and enforce it by using the both of the following package references. Note that this generates errors by referencing two definitions for each of the operators, and hence, when used the expression becomes ambiguous. Note this may be problematic since numeric_std_unsigned was introduced in 1076-2008 and it may not yet be supported by your synthesis tools.
library ieee ;
use ieee.numeric_std_unsigned.all ;
use ieee.std_logic_unsigned.all ;

3) Relax the rules some. Our biggest concern is design correctness. Allow std_logic_vector to be interpreted as an unsigned value and either reference numeric_std_unsigned (preferred, but it is VHDL-2008 and may not be implemented by your synthesis tool yet - but if it is not be sure to submit a bug report) or std_logic_unsigned (not preferred - this is an old shareware package that is not an IEEE standard and perhaps does not belong in the IEEE library - OTOH, it is well supported and it plays nice with other packages - such as numeric_std).

The nice result of this is that it also allows comparisons that include integers:
if A <= 11 then

Note, some suggest that the overloading of ">" and friends in numeric_std_unsigned/std_logic_unsigned is illegal. This was a very conservative interpretation of 1076 prior to VHDL-2008. It was fixed for all revisions of VHDL with an ISAC resolution prior to VHDL-2008 that determined that explicitly defined operators always overload implicitly defined operators without creating any ambiguity. I note that even the VHDL FAQ is out of date on this issue.

4) Be formal, but practical. Never use std_logic_vector. Only use numeric types, such as unsigned and signed from package ieee.numeric_std. Types signed and unsigned also support comparisons with integers.

There are probably a few strategies I left out.

Note that VHDL-2008 introduces matching operators which also address this issue by not defining them for types that do not have a numeric interpretation. These operators are: ?=, ?/=, ?>, ?>=, ?<, ?<
Best Regards,
Jim Lewis
IEEE 1076 WG Member (among other things)
 

Welcome to EDABoard.com

Sponsor

Back
Top