1
\$\begingroup\$

I'm trying to make a 4 bit adder with carry in & out, but I am having trouble converting Cin (Carry-in) to the type std_logic_vector when summing Sum and Cin together below in the architecture. Do you have any idea how i can make these types fit so that I can perform arithmetic on them together?

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

entity four_bit_adder_simple is
        port(
                A, B : in std_logic_vector(3 downto 0);
                Cin : in std_logic;
                Sum : out std_logic_vector(3 downto 0);
                Cout : out std_logic);
end four_bit_adder_simple;

architecture unsigned_impl of four_bit_adder_simple is
    signal total : std_logic_vector(4 downto 0);
begin
        Sum <= std_logic_vector(resize(unsigned(A),5) + resize(unsigned(B),5));
        total <= Sum + Cin;
        Cout <= total(4);
end unsigned_impl;

EDIT: It was an error that I made Cout a 2 bit std_logic_vector. It should just have been a simple std_logic.

\$\endgroup\$
5
  • 1
    \$\begingroup\$ Cout is 2 bits wide, which is odd... You are possibly missitg the fact that an array aggregate with one member can't use positional association. So use named association. (0 => Cin) is a 1 bit SLV. \$\endgroup\$
    – user16324
    Oct 19, 2019 at 18:45
  • \$\begingroup\$ @BrianDrummond You need to add Cin, not concatenate it. So the total line is wrong. \$\endgroup\$
    – user110971
    Oct 19, 2019 at 18:53
  • \$\begingroup\$ As @BrianDrummond says, Cout looks like it should be corrected to a std_logic output. \$\endgroup\$
    – TonyM
    Oct 19, 2019 at 18:54
  • \$\begingroup\$ If Cout should be an SLV, it should be a 1 bit SLV, e.g. (0 downto 0). And I was merely converting Cin to a SLV. Who mentioned concatenation? \$\endgroup\$
    – user16324
    Oct 19, 2019 at 18:58
  • 1
    \$\begingroup\$ Re: your edit. You still have an error. Your output Sum doesn't take Cin into account. \$\endgroup\$ Oct 19, 2019 at 21:06

3 Answers 3

1
\$\begingroup\$

You need to cast cin to an unsigned, then add it in.

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

entity four_bit_adder_simple is
    Port ( a    : in  std_logic_vector(3 downto 0);
           b    : in  std_logic_vector(3 downto 0);
           cin  : in  std_logic;
           sum  : out std_logic_vector (3 downto 0);
           cout : out std_logic );
end four_bit_adder_simple;

architecture Behavioral of four_bit_adder_simple is
    signal total : std_logic_vector(4 downto 0);
begin

    total <= std_logic_vector(resize(unsigned(a),5) + resize(unsigned(b),5) + unsigned'('0'&cin));
    sum   <= total(3 downto 0);
    cout  <= total(4);

end Behavioral;

You'll end up with this: adder

Note that resize returns an unsigned here.

\$\endgroup\$
1
  • \$\begingroup\$ To simplify the code above, most type conversion/casting can be avoided by simply giving signals and ports the appropriate numeric type in the first place. \$\endgroup\$
    – scary_jeff
    Oct 23, 2019 at 8:11
2
\$\begingroup\$

Seeing as to how the question was not actually answered:

signal s_vector: std_logic_vector(0 downto 0);
signal s_bit   : std_logic : = '1';
...
s_vector <= (0 => s_bit);
\$\endgroup\$
0
\$\begingroup\$

The following is a simplification of your design that meets all the requirements and compiles in VHDL-93 onwards. It uses std_logic_unsigned rather than numeric_std. (Forgive the style changes, automatic when I typed and tested it.)

library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;


entity FOUR_BIT_ADDER_SIMPLE is
  port(
    A                             : in  std_logic_vector( 3 downto  0);
    B                             : in  std_logic_vector( 3 downto  0);
    C_IN                          : in  std_logic;
    SUM                           : out std_logic_vector( 3 downto  0);
    C_OUT                         : out std_logic
  );
end FOUR_BIT_ADDER_SIMPLE;


architecture RTL of FOUR_BIT_ADDER_SIMPLE is

  signal total                    : std_logic_vector( 4 downto  0);

begin

  total  <=  ('0' & A) + ('0' & B) + ("0000" & C_IN);

  SUM    <=  total( 3 downto  0);
  C_OUT  <=  total( 4);

end architecture RTL;

The 5-bit addition is done in one line by first padding each element with leading zeroes.

\$\endgroup\$
12
  • 2
    \$\begingroup\$ You cannot add std_logic_vectors like that. You need to cast them to a numeric type first. \$\endgroup\$
    – user110971
    Oct 19, 2019 at 18:56
  • 1
    \$\begingroup\$ It doesn’t work. It is only supported in VHDL-2008, but you must use ieee.numeric_std_unsigned. \$\endgroup\$
    – user110971
    Oct 19, 2019 at 19:08
  • \$\begingroup\$ @user110971 this does work but uses std_logic_unsigned, which is a non-standard package. You are correct that in VHDL-2008 the same functionality has been included in the standard library numeric_std_unsigned. \$\endgroup\$
    – ks0ze
    Oct 19, 2019 at 20:51
  • 1
    \$\begingroup\$ @ks0ze My above comment was a reply to a now deleted comment, so it seems confusing. Indeed the edited answer now works, but uses non-standard libraries, which is just bad practice. If you want to avoid excessive casting, you should just use Verilog. VHDL is a strongly typed language, which can be really annoying at times. In fact, I do prefer Verilog. See the original answer for the full context of my comment. \$\endgroup\$
    – user110971
    Oct 19, 2019 at 21:30
  • 1
    \$\begingroup\$ @TonyM Well I know about a case wherein the change of an FPGA vendor almost resulted in someone’s death due to the use of non-standard libraries. Avoid good practice at your own peril. \$\endgroup\$
    – user110971
    Oct 19, 2019 at 21:34

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.