0
votes

I am practising some basic vhdl programs.Now i came across arithmetic operations.I used bit_vector and multiplied the input signals directly but it errors "No feasible entries for infix operator".The program is below:

   entity multiplier is
   port(a,b : in bit_vector(3 downto 0);
   c: out bit_vector(7 downto 0));
   end  multiplier;

   architecture ar of multiplier is

   begin

   c<=(a*b);

   end ar;

But i came across this program which works fine with std_logic_vector

   library IEEE;
   use IEEE.STD_LOGIC_1164.ALL;
   use IEEE.NUMERIC_STD.ALL;
   entity Multiplier_VHDL is
   port(
  Nibble1, Nibble2: in std_logic_vector(3 downto 0);
  Result: out std_logic_vector(7 downto 0)
  );
  end entity Multiplier_VHDL;

 architecture Behavioral of Multiplier_VHDL is
 begin

 Result <= std_logic_vector(unsigned(Nibble1) * unsigned(Nibble2));

 end ;

My questions are:

1.cant we simply add 2 signal bits c<=a+b as we do in verilog?

2.should a signal be signed/unsigned to perform arithmetic operations?

3.like c which is signed by default,what about vhdl/verilog?

4.are signed & unsigned present in use ieee.std_logic_arith.all and use IEEE.NUMERIC_STD.ALL same?

2

2 Answers

1
votes

1. Cant we simply add 2 signal bits c <= a + b as we do in verilog?

VHDL is a strongly typed language, which means it is strict when it comes to assigning things of different types to each other. Verilog might let you multiply a simple bit vector; you know what the types of the operands are and the format of the result, and that's fine for your design process. In VHDL, it's not good enough that you as the designer know what formats the numbers are in, the compiler wants to know this as well. In your example, the compiler doesn't know if your vectors represent an unsigned number, signed, fixed point, etc. By casting them to unsigned, you are explicitly telling it what the number format is. An even better solution would be to have these as type unsigned throughout, to avoid the type casts.

Another advantage of VHDL strongly typed is that this can help to catch bugs caused by errors in number format storage at the compilation stage instead of under simulation or on an FPGA device. In general it saves time to catch bugs earlier in the design cycle. If you search online for "strongly typed" you will find more discussion on this topic.

2. Should a signal be signed/unsigned to perform arithmetic operations?

As above, if you want to stick to standard libraries, then yes it is a good idea to give your signals a meaningful type. Think about the guy trying to understand your code in 10 years time (it might even be you), if it's clear what the number formats are, their life will be made easier.

3. Like c which is signed by default, what about vhdl/verilog?

c in your example code is not signed by default in VHDL, it has whatever type you declared it as. If you are multiplying using unsigned, the result would also be unsigned, so this would be the type that I would use for the result. If the type of the result signal does not match the return type of the operation, this will be a compiler error.

4. Are signed & unsigned present in use ieee.std_logic_arith.all and use IEEE.NUMERIC_STD.ALL same?

No, it is not recommended to use std_logic_arith, as this library is not part of the VHDL standard. If you familiarise yourself with the number formats in numeric_std, you should not need to use any other libraries for integer arithmetic.

0
votes

The usual vector type to use in VHDL is std_logic_vector from the package ieee.std_logic_1164, instead of bit_vector.

However, this vector type is just a collection of std_logic elements, without defined arithmetic operations. So the standard VHDL package that can be used to get arithmetic operations is numeric_std.

Using these for VHDL-2002 compatible code for unsigned arithmetic, it will look:

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity multiplier is
  port(a, b : in  std_logic_vector(3 downto 0);
       c    : out std_logic_vector(7 downto 0));
end multiplier;

architecture ar of multiplier is
begin
  c <= std_logic_vector(unsigned(a) * unsigned(b));
end ar;

However, you could choose to define a, ´b´, and ´c´ as unsigned to simplify the code like:

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity multiplier is
  port(a, b : in  unsigned(3 downto 0);
       c    : out unsigned(7 downto 0));
end multiplier;

architecture ar of multiplier is
begin
  c <= a * b;
end ar;

There are also signed types defined in the numeric_std package.

In VHDL-2008, a numeric_std_unsigned package is provided, which provides arithmetic operations for the std_logic_vector type, thus the code can be like:

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std_unsigned.all;

entity multiplier is
  port(a, b : in  std_logic_vector(3 downto 0);
       c    : out std_logic_vector(7 downto 0));
end multiplier;

architecture ar of multiplier is
begin
  c <= a * b;
end ar;

To answer the 4 questions:

  1. Arithmetic operations must be defined for the operands, and this can be done either through use of conversion to unsigned type in numeric_std package, or through use of operators in numeric_std_unsigned package.

  2. For VHDL-2002 yes, and for VHDL-2008 the numeric_std_unsigned package can be used.

  3. See above.

  4. The std_logic_arith package is a Synopsys package, so use numeric_std and numeric_std_unsigned instead.