8

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

  • array is a reserved word in VHDL. –  Nov 30 '13 at 05:50
  • The comp.lang.vhdl FAQ may be useful here with respect to reduction operators: http://www.eda.org/comp.lang.vhdl/FAQ1.html#reduction The 'and reduction' example should yield something suitable for your purpose. – nall Nov 30 '13 at 04:25

3 Answers3

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.

VAP
  • 541
  • 3
  • 3
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);
Morten Zilmer
  • 15,586
  • 3
  • 30
  • 49
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".

Jim Lewis
  • 3,601
  • 10
  • 20
  • 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. –  Dec 01 '13 at 18:00
  • 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' –  Dec 01 '13 at 20:53
  • 1
    @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. – Jim Lewis Dec 15 '13 at 19:40
  • All those in the audience with a -2008 compliant tool set raise your hands. –  Dec 15 '13 at 22:41
  • Another way to get this for a std_logic_vector: `result <= '1' when not (unsigned(MyArray) = 0) else '0' ; ` – ferdepe Feb 21 '23 at 15:11