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.
-
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– user163242019年10月19日 18:45:40 +00:00Commented Oct 19, 2019 at 18:45
-
\$\begingroup\$ @BrianDrummond You need to add Cin, not concatenate it. So the total line is wrong. \$\endgroup\$user110971– user1109712019年10月19日 18:53:46 +00:00Commented Oct 19, 2019 at 18:53
-
\$\begingroup\$ As @BrianDrummond says, Cout looks like it should be corrected to a std_logic output. \$\endgroup\$TonyM– TonyM2019年10月19日 18:54:53 +00:00Commented 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– user163242019年10月19日 18:58:18 +00:00Commented 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\$Blair Fonville– Blair Fonville2019年10月19日 21:06:21 +00:00Commented Oct 19, 2019 at 21:06
3 Answers 3
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.
-
\$\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– scary_jeff2019年10月23日 08:11:43 +00:00Commented Oct 23, 2019 at 8:11
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);
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.
-
2\$\begingroup\$ You cannot add std_logic_vectors like that. You need to cast them to a numeric type first. \$\endgroup\$user110971– user1109712019年10月19日 18:56:08 +00:00Commented 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– user1109712019年10月19日 19:08:48 +00:00Commented 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– ks0ze2019年10月19日 20:51:56 +00:00Commented 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– user1109712019年10月19日 21:30:14 +00:00Commented 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– user1109712019年10月19日 21:34:35 +00:00Commented Oct 19, 2019 at 21:34