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:
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:
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'
:
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'
:
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:
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:
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:
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:
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:
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:
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:
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:
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.
how can i count from rom data of numbers from 0 to 255 and put the count value in ram
thank you for your help
Hello Derni,
Since your question isn’t related to this blog post, I kindly ask that you post it in the VHDLwhiz private Facebook group:
https://www.facebook.com/groups/vhdlwhiz/
Also, make sure to include any additional information like VHDL code from your own attempt to solve the problem.