I know that I have googled this at least a hundred times throughout my career as an FPGA engineer; how to check if all bits in a `std_logic_vector`

signal are `'0'`

or `'1'`

. Of course, you know a few ways to do it already, but you want to find the most elegant code that will work with vectors of any length. Right?

Let’s have a look at the best methods for checking that all the bits in a vector are set or unset.

This is the vector that we’re going to use as a test case for all the code examples that are presented:

signal my_slv : std_logic_vector(7 downto 0);

## The RTL schematic of the circuit

The circuit for checking if all bits are zero is a NOR gate with all the bits of the vector as inputs. The output will be set to

`'1'`

only if all the input bits are interpreted as `'0'`

, that’s how a NOR gate works. The synthesis tool may choose to implement this differently, depending on the available resources on the target device, but the basic circuit consists of this single elementary logic gate.The simplest possible circuit for checking that all the bits in a vector are logical

`'1'`

values is to use an AND gate. The truth table for an AND gate states that it will output a *true*value if and only if all the input values evaluate to true. By anding together all the bits in the vector, we can check if all of them are

`'1'`

. ## Comparing with a hard-coded value

The most straightforward way to check if a vector contains *any* value, is to compare it with a hard-coded bit literal. The problem with this approach is that if we change the length of the vector, we have to change the length of the hard-coded literal as well. But for completeness, let’s have a look at how we can use static values to check if `my_slv`

is all zeros or ones.

Check if all zeros by comparing with the binary value:

my_slv = "00000000"

Check if all zeros by comparing with the hexadecimal value:

my_slv = x"00"

These statements yield a true value only if all bits contain the `'0'`

value:

**‘U’**

**‘X’**

**‘0’**

**‘1’**

**‘Z’**

**‘W’**

**‘L’**

**‘H’**

**‘-‘**

Check if all ones by comparing with the binary value:

my_slv = "11111111"

Check if all ones by comparing with the hexadecimal value:

my_slv = x"FF"

These statements yield a true value only if all bits contain the `'1'`

value:

**‘U’**

**‘X’**

**‘0’**

**‘1’**

**‘Z’**

**‘W’**

**‘L’**

**‘H’**

**‘-‘**

## Comparing with the unsigned or signed value

One way to check if a vector of any length is all zeros, is to convert it to an unsigned value and then compare it to its integer equivalent.

To check if the vector contains all zeros:

unsigned(my_slv) = 0

The statement above yields a true value if the vector contains only `'0'`

or `'L'`

:

**‘U’**

^{1}

**‘X’**

^{1}

**‘0’**

**‘1’**

**‘Z’**

^{1}

**‘W’**

^{1}

**‘L’**

**‘H’**

**‘-‘**

^{1}

ModelSim will produce the following warning message if any value marked with ^{1} are present in the vector:

# ** Warning: NUMERIC_STD.”=”: metavalue detected, returning FALSE

This warning means that `my_slv`

contains one or more bits that cannot be interpreted as neither `'0'`

nor `'1'`

.

**Click here to read about the 9 different metavalues that the std_logic can have**

A nice trick for finding out if a vector contains only ones is first to cast it to a signed type. You can then compare it to -1 cast to a signed type with the same length as the target vector:

signed(my_slv) = to_signed(-1, my_slv'length)

Because of how sign extension works in VHDL and in computers in general, the right-hand side value will be all ones. The statement above yields a true value if the vector contains only `'1'`

or `'H'`

:

**‘U’**

^{1}

**‘X’**

^{1}

**‘0’**

**‘1’**

**‘Z’**

^{1}

**‘W’**

^{1}

**‘L’**

**‘H’**

**‘-‘**

^{1}

ModelSim will produce the same metavalue warning if the vector contains any value marked with ^{1}.

## Comparing with the integer value

Converting the vector to an integer value before comparing is also an option. This method yields the same results as comparing with the unsigned values for vectors containing `'0'`

, `'1'`

, `'H'`

or `'L'`

, but it behaves differently for metavalues.

To check if a vector is all zeros:

to_integer(unsigned(my_slv)) = 0

The code above yields the following Boolean values for vectors where all bits are the same value:

**‘U’**

^{2}

**‘X’**

^{2}

**‘0’**

**‘1’**

**‘Z’**

^{2}

**‘W’**

^{2}

**‘L’**

**‘H’**

**‘-‘**

^{2}

ModelSim will produce this warning if the vector contains any value marked with ^{2}:

# ** Warning: NUMERIC_STD.TO_INTEGER: metavalue detected, returning 0

To check if a vector is all ones:

to_integer(unsigned(my_slv)) = 2 ** my_slv'length - 1

The code above yields the following Boolean values for vectors where all bits have the same value:

**‘U’**

^{2}

**‘X’**

^{2}

**‘0’**

**‘1’**

**‘Z’**

^{2}

**‘W’**

^{2}

**‘L’**

**‘H’**

**‘-‘**

^{2}

ModelSim will print the previously mentioned warning if the vector contains any value marked with ^{2}.

This method of checking for all ones is only accurate for vectors up to a maximum length of 30 bits due to integer overflow in the exponential calculation. Some compilers will print a warning message as ModelSim does:

# ** Warning: (vcom-1158) Integer exponentiation has overflowed; result is -2147483648.

## Comparing with a constant value

Declaring a dynamically sized constant vector with the same length as the target vector is another clever way to check if all bits are *any* value. Simply use an aggregate assignment to initialize the constant. Then, compare it with the target vector.

This is how to check if all bits of a vector are `'0'`

:

constant all_zeros : std_logic_vector(vec'range) := (others => '0'); ... my_slv = all_zeros

The comparison with the `all_zeros`

constant yields true only if the vector contains all zeros:

**‘U’**

**‘X’**

**‘0’**

**‘1’**

**‘Z’**

**‘W’**

**‘L’**

**‘H’**

**‘-‘**

This is how to check if all bits of a vector are `'1'`

:

constant all_ones : std_logic_vector(vec'range) := (others => '1'); ... my_slv = all_ones

The comparison with the `all_ones`

constant yields true only if the vector contains all ones:

**‘U’**

**‘X’**

**‘0’**

**‘1’**

**‘Z’**

**‘W’**

**‘L’**

**‘H’**

**‘-‘**

### Function for checking that all bits are some value

You can declare a function for checking that all bits of a vector are any value by using the constant method. We have created such a function below which takes two parameters. The first parameter is the vector to check, and the second one is the value to check if all bits contain exclusively.

function is_all(vec : std_logic_vector; val : std_logic) return boolean is constant all_bits : std_logic_vector(vec'range) := (others => val); begin return vec = all_bits; end function;

To check if all bits are `'0'`

by using the function:

is_all(my_slv,'0')

The function call above only returns true if all bits in the vector have the `'0'`

value:

**‘U’**

**‘X’**

**‘0’**

**‘1’**

**‘Z’**

**‘W’**

**‘L’**

**‘H’**

**‘-‘**

To check if all bits are `'1'`

by using the function:

is_all(my_slv,'1')

The function call above only returns true if all bits in the vector have the `'1'`

value:

**‘U’**

**‘X’**

**‘0’**

**‘1’**

**‘Z’**

**‘W’**

**‘L’**

**‘H’**

**‘-‘**

## Using a unary operator

This is the shortest possible code for checking if a vector contains only `'0'`

or `'L'`

values. We are using the unary OR operator for oring together all bits of the vector. The term “unary operator” simply means that the operator takes one operand, which is the vector.

To check if all bits are zero by using the unary OR operator:

or my_slv = '0'

An alternative is to use the unary NOR operator:

nor my_slv = '1'

*Thanks to Ralf from the comment section for the two code snippets above.*

This is the table of yielded values for the unary OR and NOR operators:

**‘U’**

**‘X’**

**‘0’**

**‘1’**

**‘Z’**

**‘W’**

**‘L’**

**‘H’**

**‘-‘**

To check if all bits are ones by using the unary AND operator:

and my_slv = '1'

This table shows what the code above yields for vectors containing different values:

**‘U’**

**‘X’**

**‘0’**

**‘1’**

**‘Z’**

**‘W’**

**‘L’**

**‘H’**

**‘-‘**

Unary operators are only supported in VHDL-2008 and above.

## Wrap-up

All the different methods yield the same result for the values `'0'`

and `'1'`

. On the other hand, the behavior differs for metavalues. Some statements consider the values `'L'`

and `'H'`

as logical high and low, while other treat them as valueless metavalues.

Except for the integer compare method that looks for zero value vectors, all methods yield `false`

for vectors containing `'U'`

, `'X'`

, `'Z'`

, `'W'`

, or `'-'`

. Additionally, ModelSim will produce runtime warnings for some of the methods if the vector contains any of those metavalues.

Go ahead and use the form above to download a printable cheat sheet with an overview of the statements that we talked about in this article. Then you will never again have to turn to Google for finding the best way to check if a vector contains only zeros or ones.

> There is no unary operator that is suitable for checking if all bits are zero.

What about this?

Assuming you’re using a the IEEE library that supports using the “or” on a vector like https://github.com/ghdl/ghdl/blob/master/libraries/ieee2008/std_logic_1164.vhdl

In this package the following functions are defined:

Which means that the following should work as well

Thanks Ralf!

I had overlooked those two methods. I must admit that I haven’t been using unary operators at all before. I’ve added your code snippets to the blog post as well as to the freebie PDF.

Anyone who already downloaded the PDF without the unary OR and NOR methods can send me a mail and I will reply with the updated version.

Very good article, I did not know the unary operator check. I personally I use this one:

Wow, that actually works too. I had to try it out in ModelSim myself ðŸ™‚

The only thing is that I had to change ‘range to ‘reverse_range because the my_slv vector is declared using a downto range.

Like this:

Otherwise, at least in ModelSim we get the compilation error:

(vcom-1514) Range choice direction (downto) does not determine aggregate index range direction (to).

For a vector declared using for example (0 to 7) your code will work.

This is interesting (especially for code portability), under Vivado 2018.1, you can either use â€˜range or â€˜reverse_range whatever your signal declaration (downto or to) is, it will work (both simulation and synthesis).

Additionally, the *_REDUCE functions of the IEEE.std_logic_misc library could be used.

Awesome! These methods are equivalent to those using the unary operators, but they work with older VHDL versions as well.

I have typed out the code suggested by Marian for clarity:

This is a great article with a lot of good ideas, thank you!

Do you think the different methods have different implications for how the synthesis tools will choose to implement the check? With a 32 bit wide bus, there could in theory be a hierarchy of 5 levels of 2-input NOR gates (less if the gates are 3 or 4 input), which might be bad news when it comes to meeting timing constraints. For example, if instantiating a comparitor using vendor IP might be better or worse for timing than just a series of gates in logic fabric?

The synthesis tool will create the same logic for all the different methods. I did try to synthesize every method I proposed in this article in Vivado, just to make sure, and they were all equivalent.

They are all equal for synthesis, but their behavior differ when it comes to metavalues and warnings produced during simulation.

The integer methods of checking for all ones will only work for vectors with a length up to 30 bits. Because with longer vectors, this expression will overflow:

I haven’t used vendor specific comparator IP, so I can’t really comment on that. It would be an interesting experiment to see if the inferred logic (created from the code) is different, and if it’s better for timing.