AND all elements of an n-bit array in VHDL
Asked Answered
C

3

9

lets say I have an n-bit array. I want to AND all elements in the array. Similar to wiring each element to an n-bit AND gate.

How do I achieve this in VHDL?

Note: I am trying to use re-usable VHDL code so I want to avoid hard coding something like

    result <= array(0) and array(1) and array(2)....and array(n); 

Thanks Oshara

Coolie answered 30/11, 2013 at 3:47 Comment(2)
The comp.lang.vhdl FAQ may be useful here with respect to reduction operators: eda.org/comp.lang.vhdl/FAQ1.html#reduction The 'and reduction' example should yield something suitable for your purpose.Siler
array is a reserved word in VHDL.Sligo
D
11

Solution 1: With unary operator

VHDL-2008 defines unary operators, like these:

outp <= and "11011";
outp <= xor "11011";
outp <= and inp; --this would be your case

However, they might not be supported yet by your compiler.

Solution 2: With pure combinational (and traditional) code

Because in concurrent code you cannot assign a value to a signal more than once, your can create a temp signal with an "extra" dimension. In your case, the output is one-bit, so the temp signal should be a 1D array, as shown below.

-------------------------------------------
entity unary_AND IS
    generic (N: positive := 8); --array size
    port (
        inp: in bit_vector(N-1 downto 0);
        outp: out bit);
end entity;
-------------------------------------------
architecture unary_AND of unary_AND is
    signal temp: bit_vector(N-1 downto 0);
begin
    temp(0) <= inp(0);
    gen: for i in 1 to N-1 generate
        temp(i) <= temp(i-1) and inp(i);
    end generate; 
    outp <= temp(N-1); 
end architecture;
-------------------------------------------

The inferred circuit is shown in the figure below. enter image description here

Solution 3: With sequential code

This is simpler than solution 2, though you are now using sequential code to solve a purely combinational problem (but the hardware will be the same). You can either write a code similar to that in solution 2, but with a process and loop (the latter, in place of generate) or using a function. Because in sequential code you are allowed to assign a value to a signal more than once, the temp signal of solution 2 is not needed here.

Damiondamita answered 30/11, 2013 at 13:40 Comment(1)
And if VHDL-2008 is not supported with your compiler, raise a bug... they've had 5 years to get it together!Benignity
M
10

If you have VHDL-2008 available, then reduction and is build into the language as David Koontz and Pedroni have explained.

If you only have VHDL-2003 and prior available, then you can use a function like:

function and_reduct(slv : in std_logic_vector) return std_logic is
  variable res_v : std_logic := '1';  -- Null slv vector will also return '1'
begin
  for i in slv'range loop
    res_v := res_v and slv(i);
  end loop;
  return res_v;
end function;

You can then use the function both inside and outside functions with:

signal arg : std_logic_vector(7 downto 0);
signal res : std_logic;
...
res <= and_reduct(arg);
Mural answered 30/11, 2013 at 16:28 Comment(0)
K
5

My favorite, non-VHDL-2008 solution is:

use ieee.std_logic_unsigned.all ;  -- assuming not VHDL-2008
. . . 
result <= '1' when not MyArray = 0 else '0' ; 

With VHDL-2008, I recommend that you use the "and" reduction built-in (see Pedroni's post) and use the IEEE standard package "ieee.numeric_std_unsigned.all" instead of the shareware package "std_logic_unsigned".

Kinship answered 30/11, 2013 at 16:40 Comment(5)
For the curious the example using std_logic_unsigned works because there's an equality operator that evaluates between a standard logic vector left argument and an integer right argument. This method depends on the non-standard package std_logic_arith as well and doesn't pass 'X's or 'Z' to result like the logical reduction AND, simply evaluating equality of each left and right elements of the std_logic_vector a conversion of 0 into an equivalent SIGNED array of STD_LOGIC elements. A whole lot of shaking going on behind the scenes for a simple expression.Sligo
You can get the same result with less work by declaring a constant std_logic_vector of '1's using the range constraint from MyArray and using the equality operator between two std_logic_vectors predefined for all one-dimensional array (discrete array) type. This simpler method also depends on not needing to pass 'X' or or 'Z'Sligo
@David. The language also allows the more readable expression "MyArray = (MyArray'range => '1')", however, while this is legal VHDL, the last I check with Synopsys DesignCompiler it did not work - so it is not a portable method. Thankfully we don't need to worry too much about these things as VHDL-2008 has created a preferred solution.Kinship
All those in the audience with a -2008 compliant tool set raise your hands.Sligo
Another way to get this for a std_logic_vector: result <= '1' when not (unsigned(MyArray) = 0) else '0' ; Flagstone

© 2022 - 2024 — McMap. All rights reserved.