0
\$\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\$
  • 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\$ – Brian Drummond Oct 19 '19 at 18:45
  • \$\begingroup\$ @BrianDrummond You need to add Cin, not concatenate it. So the total line is wrong. \$\endgroup\$ – user110971 Oct 19 '19 at 18:53
  • \$\begingroup\$ As @BrianDrummond says, Cout looks like it should be corrected to a std_logic output. \$\endgroup\$ – TonyM Oct 19 '19 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\$ – Brian Drummond Oct 19 '19 at 18:58
  • 1
    \$\begingroup\$ Re: your edit. You still have an error. Your output Sum doesn't take Cin into account. \$\endgroup\$ – Blair Fonville Oct 19 '19 at 21:06
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.

| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ Thanks, it seems to work now! \$\endgroup\$ – user234430 Oct 19 '19 at 21:31
  • \$\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 '19 at 8:11
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.

| improve this answer | |
\$\endgroup\$
  • 2
    \$\begingroup\$ You cannot add std_logic_vectors like that. You need to cast them to a numeric type first. \$\endgroup\$ – user110971 Oct 19 '19 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 '19 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 '19 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 '19 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 '19 at 21:34

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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