I am just trying to make a simple two's complement device in VHDL but it is throwing back this really annoying error and I'm unsure what I have done wrong. Probably something very silly...The error is
"Error (10327): VHDL error at twocompliment.vhd(21): can't determine definition of operator ""nand"" -- found 0 possible definitions"
The code is
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity twoscompliment is
generic
(
Nbits : positive := 8
);
port
(
--Inputs
A : in std_logic_vector (Nbits-1 downto 0);
--Outputs
Y : out std_logic_vector (Nbits downto 0)
);
end twoscompliment;
architecture twoscompliment_v1 of twoscompliment is
begin
Y <= std_logic_vector(unsigned(A NAND '1') + '1');
end twoscompliment_v1;
Any help would be awesome!
It seems to me you are trying to negate the input number... Maybe I'm missing something vital, but the other answers give a solution which, whilst achieving the goal, appear to be one step more obfuscated than they need to be.
Barring the ugly conversions, what's wrong with
y <= std_logic_vector(-signed(resize(unsigned(A)), y'length));
Of course, I would argue that if A and Y are supposed to be representing signed numbers (or unsigned numbers), they should be expressed as such:
library ieee;
use ieee.numeric_std.all;
entity twoscomplement is
generic
(
Nbits : positive := 8
);
port
(
A : in unsigned (Nbits-1 downto 0);
Y : out signed (Nbits downto 0)
);
end entity twoscomplement;
architecture a1 of twoscomplement is
begin
Y <= -signed(resize(A, Y'length));
end architecture;
Let's check the results:
entity test_twoscomplement is
end entity;
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
architecture test of test_twoscomplement is
signal A : unsigned (7 downto 0);
signal Y : signed(8 downto 0);
begin
dut : entity work.twoscomplement port map (A => A, Y=>Y);
process
begin
for i in 0 to 255 loop
A <= to_unsigned(i, A'length);
wait for 1 ns;
assert to_integer(Y) = -i severity error;
end loop;
report "tests done";
wait;
end process;
end architecture;
Running with GHDL:
$ ghdl -a twoscomp.vhd
$ ghdl --elab-run test_twoscomplement
twoscomp.vhd:40:8:#256ns:(report note): tests done
Success!
Try this:
architecture twoscompliment_v1 of twoscompliment is
signal temp : std_logic_vector(Nbits-1 downto 0);
begin
temp <= not A;
Y <= std_logic_vector(unsigned(temp + 1));
end twoscompliment_v1;
architecture twoscompliment_v1 of twoscompliment is
constant ONE: UNSIGNED(Y'RANGE) := (0 => '1', others => '0');
begin
Y <= std_logic_vector(unsigned (not A) + ONE);
end twoscompliment_v1;
Hi gentleman basically 2's complement is done by inverting the binary bits of a
given no. i.e changing ones to zeroes and zeroes to ones, after that add the
binary bit '1' to the Least significant bit of the given binary number. Now I
have a program
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity twoscomplementconversion is Port (
bin : in STD_LOGIC_VECTOR (3 downto 0);
twos : out STD_LOGIC_VECTOR (3 downto 0)
);
end twoscomplementconversion;
architecture Behavioral of twoscomplementconversion is
component fourbitadder45 Port (
a : in std_logic_vector (3 downto 0);
b : in std_logic_vector(3 downto 0);
cin : in std_logic;
cout : out std_logic;
sum : out std_logic_vector (3 downto 0)
);
end component;
signal onebit : std_logic_vector(3 downto 0):="0001";
signal cin1 : std_logic:='0';
signal notbin : std_logic_vector(3 downto 0);
signal cout1 : std_logic;
begin
notbin <= not(bin);
twos1: fourbitadder45 port map (
a => notbin,
b => onebit,
cin => cin1,
cout => cout1,
sum => twos
);
end Behavioral;
The four bit adder program is given below:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity fourbitadder45 is Port (
a : in std_logic_vector (3 downto 0);
b : in std_logic_vector(3 downto 0);
cin : in std_logic;
cout : out std_logic;
sum : out std_logic_vector (3 downto 0)
);
end fourbitadder45;
architecture Behavioral of fourbitadder45 is
component fulladder2 Port (
a : in std_logic;
b : in std_logic;
cin : in std_logic;
cout : out std_logic;
sum : out std_logic
);
end component;
signal c:std_logic_vector (3 downto 1);
begin
fa1 :fulladder2 port map (a => a(0), b => b(0), cin => cin, cout => c(1), sum => sum(0));
fa2 :fulladder2 port map (a => a(1), b => b(1), cin => c(1), cout => c(2), sum => sum(1));
fa3 :fulladder2 port map (a => a(2), b => b(2), cin => c(2), cout => c(3), sum => sum(2));
fa4 :fulladder2 port map (a => a(3), b => b(3), cin => c(3), cout => cout, sum => sum(3));
end Behavioral;
four bit adder contains 4 full adders so the full adder program is given below:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity fulladder2 is Port (
a : in std_logic;
b : in std_logic;
cin : in std_logic;
cout : out std_logic;
sum : out std_logic
);
end fulladder2;
architecture Behavioral of fulladder2 is
begin
sum <= a xor b xor cin;
cout <= ((a and b) or (b and cin) or (cin and a));
end Behavioral;
I hope that answers the question. This is a method there are many different methods
Related
Im new to VHDL and I'm doing some university exercises. It was all great until today when I got an error that I don't understand the reason of why it appears. Hope you could help me. (Software: Quartus Prime)
Code:
library IEEE;
use IEEE.STD_LOGIC_1164.all;
entity AddSub4 is
port(a, b : in std_logic_vector(3 downto 0);
sub : in std_logic;
s : out std_logic_vector(3 downto 0);
cout : out std_logic);
end AddSub4;
architecture Structural of AddSub4 is
signal s_b : std_logic_vector (3 downto 0);
begin
sub_mux: s_b <= b when (sub='0') else
not b;
final: entity work.Adder4(Structural)
port map(cin => sub,
a => a,
b => b,
cout => cout,
s => s);
end Structural;
architecture Behave of AddSub4 is
signal val1, val2, valFinal : unsigned(4 downto 0);
begin
val1 <= '0' & unsigned(a);
val2 <= '0' & unsigned(b);
valFinal <= (val1 + val2) when (sub = '0') else (val1 - val2);
s <= std_logic_vector(valFinal(3 downto 0));
cout <= std_logic(valFinal(4));
end Behave;
The error in the terminal:
Error (10482): VHDL error at AddSub4.vhd(30): object "unsigned" is used but not declared
you need to add a library you can either
use ieee.numeric_std.all ;
use ieee.std_logic_unsigned.all;
I'm currently building a n-bit subtractor, and it appears to be working fine, but my waveform has these anomalous lines that instantaneously come and go. I'm not sure what's causing them, and it's been bugging me for days. You can see the spikes happening for the "negative" signal - I suspect it's because of some concurrency issue but I have tried searching all kinds of keywords to find the root of this problem and haven't come up with anything:
Code:
One bit full adder
library ieee;
use ieee.std_logic_1164.all;
entity one_bit_full_adder is
port (
x, y, cin : in std_logic;
sum, cout: out std_logic);
end one_bit_full_adder;
architecture arch of one_bit_full_adder is
begin
sum <= x xor y xor cin;
cout <= (x and y) or (cin and (x xor y));
end arch;
N-bit subtractor
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity n_bit_subtractor is
generic(constant BIT_LENGTH : integer);
port (
a, b : in std_logic_vector(BIT_LENGTH - 1 downto 0);
negative: out std_logic;
difference: out std_logic_vector(BIT_LENGTH - 1 downto 0));
end n_bit_subtractor;
architecture arch of n_bit_subtractor is
component one_bit_full_adder port (x, y, cin: in std_logic; sum, cout: out std_logic); end component;
signal carry_ins: std_logic_vector(BIT_LENGTH downto 0) := (0 => '1', others => '0');
signal differences: std_logic_vector(BIT_LENGTH - 1 downto 0);
signal b_operand: std_logic_vector(BIT_LENGTH - 1 downto 0);
begin
b_operand <= not b;
difference <= differences;
negative <= differences(BIT_LENGTH - 1) and '1';
adders: for i in 0 to BIT_LENGTH-1 generate
H2: one_bit_full_adder port map(x=>a(i), y=>b_operand(i), cin=>carry_ins(i), sum=>differences(i), cout=>carry_ins(i+1));
end generate;
end arch;
Testbench:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity n_bit_subtractor_test is
end n_bit_subtractor_test;
architecture arch_test of n_bit_subtractor_test is
constant BIT_LEN : integer := 3;
component n_bit_subtractor is
generic(constant BIT_LENGTH : integer);
port (
a, b : in std_logic_vector(BIT_LENGTH - 1 downto 0);
negative: out std_logic;
difference: out std_logic_vector(BIT_LENGTH - 1 downto 0));
end component n_bit_subtractor;
signal p0, p1, difference: std_logic_vector(BIT_LEN-1 downto 0) := (others => '0');
signal negative: std_logic;
begin
uut: n_bit_subtractor
generic map (BIT_LENGTH => BIT_LEN)
port map (a => p0, b => p1, difference => difference, negative => negative);
process
variable difference_actual: std_logic_vector(BIT_LEN-1 downto 0) := (others => '0');
begin
for i in 0 to (2**BIT_LEN)-1 loop
for k in 0 to (2**BIT_LEN)-1 loop
wait for 200 ns;
p1 <= std_logic_vector(unsigned(p1) + 1);
end loop;
p0 <= std_logic_vector(unsigned(p0) + 1);
end loop;
report "No errors detected. Simulation successful." severity failure;
end process;
end arch_test;
Any help would be greatly appreciated. The ModelSim version is v10.1d
I am trying to create N-bits adder/subtractor using a ripple of full adders.
The input is N-bits A, N-bits B, and the result should be at length of 2N (it outputs ALU with 2 buses High and low of N-bits each, so I am trying to extend the signed bit).
The problem arises with carryout in subtraction. For example, when doing 3-2 (assume N=3 so that it's 011-010 and with two's compliment it's 011+110) I get 001 with carry 1. The problem is that this carry is garbage and can't be extended, but in other case it's necessary. For example, when trying do (-3)+(-3) (101+101, again N=3), then I get 010 with carry of 1. This time the carry really indicate the sign, so I would like to extend it.
Here is my code:
entity FullAdder is
Port (
A : in std_logic;
B : in std_logic;
Cin : in std_logic;
sum : out std_logic;
Cout : out std_logic
);
end FullAdder;
architecture gate of FullAdder is
begin
sum <= A xor B xor Cin ;
Cout <= (A and B) OR (Cin and A) OR (Cin and B) ;
end gate;
here is the N-bit Adder
entity NbitsAdder is
generic(N: integer := 8);
Port(
A : in std_logic_vector((N-1) downto 0);
B : in std_logic_vector((N-1) downto 0);
Cin: in std_logic;
SUM : out std_logic_vector((N-1) downto 0);
Cout : out std_logic
);
end NbitsAdder;
architecture NbitsAdderGate of NbitsAdder is
...
signal temp : std_logic_vector (N downto 0);
begin
temp (0) <= Cin;
arrrayOfFullAdders : for i in 0 to N-1 generate
adder_i: FullAdder port map ( A(i), B(i), temp(i), SUM(i), temp (i+1) );
end generate;
Cout <= temp(N); --which will be extend
end NbitsAdderGate;
And this is the ADDER or SUBTRACTOR
entity NbitsAddOrSub is
generic(N: integer := 8);
port(
A : in std_logic_vector ((N-1) downto 0);
B : in std_logic_vector ((N-1) downto 0);
addOrSub : in std_logic;
sumLo : out std_logic_vector ((N-1) downto 0);
sumHi : out std_logic_vector ((N-1) downto 0)
);
end NbitsAddOrSub;
architecture NbitsAddOrSubGate of NbitsAddOrSub is
signal tempB: std_logic_vector ( (N-1) downto 0);
signal CoutTemp: std_logic;
begin
loop1 : for i in 0 to N-1 generate
xor_i: xorGate port map ( B(i), addOrSub, tempB(i));
end generate;
theOperation : NbitsAdder generic map (N)
port map ( A => A, B => tempB, Cin => addOrSub, sum => sumLo, Cout => CoutTemp);
sumHi <= (N-1 downto 0 => CoutTemp); -- tring to extend the sign bit
end NbitsAddOrSubGate;
In signed addition the carry has no meaning. You get the sign bit from the MSB of the sum and not from the carry. In your second example there is an underflow because -3+-3 is smaller than 2^((N=3)-1), thus the result is incorrect.
To sign-extend the result you should first check the overflow/underflow conditions for signed addition. If no overflow/underflow has occured, you look at the MSB of the sum and extend that bit
I am looking at this example and below answer which is a nice solution to produce two's complement:
library ieee;
use ieee.numeric_std.all;
entity twoscomplement is
generic
(
Nbits : positive := 8
);
port
(
A : in unsigned (Nbits-1 downto 0);
Y : out signed (Nbits downto 0)
);
end entity twoscomplement;
architecture a1 of twoscomplement is
begin
Y <= -signed(resize(A, Y'length));
end architecture;
I want to use the said example to have two's complement and then make a "16-bit subtractor". The code will look like the following:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity subtractor_16bit is
Port ( a : in STD_LOGIC_VECTOR(15 downto 0);
b : in STD_LOGIC_VECTOR(15 downto 0);
cin : in STD_LOGIC;
sum : out STD_LOGIC_VECTOR(15 downto 0);
cout : out STD_LOGIC;
over : out STD_LOGIC
);
end subtractor_16bit;
architecture Behavioral of subtractor_16bit is
component fulladder_16bit is
Port (
a : in STD_LOGIC_VECTOR(15 downto 0);
b : in STD_LOGIC_VECTOR(15 downto 0);
cin : in STD_LOGIC;
sum : out STD_LOGIC_VECTOR(15 downto 0);
cout : out STD_LOGIC;
over : out STD_LOGIC
);
end component;
component twoscomplement is
Port (
A : in unsigned (15 downto 0);
C : out signed (15 downto 0)
);
end component;
signal n1 : STD_LOGIC_VECTOR(15 downto 0);
begin
twoscomplement_1: twoscomplement port map (a => a ,c => n1); --ERROR
fulladder_16bit_1: fulladder_16bit port map (a => a, b => n1, sum => sum , cin => cin, cout => cout, over => over);
end Behavioral;
However, I am receiving an error saying:
Error: type error near a; current type std_logic_vector; expected type unsigned.
Kindly help me to solve this problem.
As nobody is answering this and nobody is down voting it, I will answer.
Look at the error
Error: type error near a; current type std_logic_vector; expected type unsigned.
Now look at entity subtractor_16bit.
[...]
entity subtractor_16bit is
Port ( a : in STD_LOGIC_VECTOR(15 downto 0);
[...]
component twoscomplement is
Port (
A : in unsigned (15 downto 0);
[...]
twoscomplement_1: twoscomplement port map (a => a ,c => n1);
[...]
What do you see? twoscomplement expects an unsigned, while a is std_logic_vector! Just like the error says.
std_logic_vector and unsigned are two separate types. As VHDL is a strongly typed language, you cannot just put the data from one type to another. You need to use type conversion.
For unrelated types, you should implement a type conversion function. Or functions, if you want bidirectional conversion. E.g.
function (input : type_a) return type_b;
But in this case, std_logic_vector and unsigned have the same underlying type, std_logic. (std_ulogic actually since VHDL-2008 I believe.)
In that case you can convert from one type to another explicitly. E.g.
signal a_u : unsigned(y downto 0);
signal a_slv : std_logic_vector(y downto 0);
begin
a_u <= unsigned(a_slv);
Next, your not instantiating the twoscomplement component properly. The entity has a generic Nbits. By default you set it to 8. But in your architecture Behavioral of subtractor_16bit, you feed it with 16 bits, without changing the generic value. That doesn't work.
Also: twoscomplement has two ports: A and Y. But in subtractor_16bit you start using A and C. That's bad coding practice.
Finally, you can drop the component declarations. Just instantiate the entities from the library. E.g.
twoscomplement_1: entity work.twoscomplement [...]
So, subtractor_16bit should look something like this:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity subtractor_16bit is
Port (
a : in STD_LOGIC_VECTOR(15 downto 0);
b : in STD_LOGIC_VECTOR(15 downto 0);
cin : in STD_LOGIC;
sum : out STD_LOGIC_VECTOR(15 downto 0);
cout : out STD_LOGIC;
over : out STD_LOGIC
);
end entity;
architecture structural of subtractor_16bit is
use IEEE.NUMERIC_STD.ALL;
signal n1 : signed(a'range);
begin
twoscomplement_1: entity work.twoscomplement
generic map(
NBits => a'length
)
port map (
a => unsigned(a),
y => n1
);
fulladder_16bit_1: entity work.fulladder_16bit
port map (
a => a,
b => std_logic_vector(n1),
sum => sum,
cin => cin,
cout => cout,
over => over
);
end architecture;
...
HOWEVER this will still not work.
As you see on your entity twoscomplement, port A has a size of NBits, and port Y has a size of NBits+1. That is because you seem to want to keep 16-bit value precision. So when converting unsigned to signed, you need to add a 17th bit for the sign. As a result, the rest of you code will need to be modified!
.... But this can be fixed a different way. I will learn you something about two's complement: -a = not(a) + 1.
Proof (Take 4 bits signed precision):
0 = b'0000 => -0 is not(b'0000)+1 = b'1111'+1 = b'0000'
7 = b'0111 => -7 is not(b'0111)+1 = b'1000'+1 = b'1001'
-6 = b'1010' => 6 is not(b'1010)+1 = b'0101'+1 = b'0110'
See?
So now I will solve your puzzle for you:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity subtractor_16bit is
Port (
a : in STD_LOGIC_VECTOR(15 downto 0);
b : in STD_LOGIC_VECTOR(15 downto 0);
sum : out STD_LOGIC_VECTOR(15 downto 0);
cout : out STD_LOGIC;
over : out STD_LOGIC
);
end entity;
architecture structural of subtractor_16bit is
begin
fulladder_16bit_1: entity work.fulladder_16bit
port map (
a => a,
b => not(b),
sum => sum,
cin => '1',
cout => cout,
over => over
);
end architecture;
You will still need to change/fix the cout and over behavior...
I am very new to VHDL coding and I have been trying to debug my code for a 32-bit adder/subtractor. The N-bit adder/subtractor is composed multiple 1-bit adder/subtractor using a generate statement. I have been testing it for 6-bit inputs using simulation. The waveform is constantly incorrect and I have tried changing just about everything. Maybe, it is a problem with the delays and the generate statement not cycling through correctly. (I am just beginning to learn how to code in vhdl.)
My 1-bit adder/subtractor
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity addsub_1bit is
Port ( in_0 : in STD_LOGIC;
in_1 : in STD_LOGIC;
cin : in STD_LOGIC;
AddOrSub : in STD_LOGIC;
sum_sub : out STD_LOGIC;
cout_bout : out STD_LOGIC);
end addsub_1bit;
architecture data_flow_addsub_1bit of addsub_1bit is
begin
sum_sub <= (in_1 and (not in_0) and (not cin)) or ((not in_1) and in_0 and (not cin)) or ((not in_1) and (not in_0) and cin) or (in_1 and in_0 and cin) after 19 ns;
cout_bout <= (in_1 and in_0 and (not AddOrSub)) or ((not in_1)and in_1 and cin) or ((not in_1)and cin and AddOrSub) or (in_0 and cin) or (in_1 and cin and AddOrSub) after 19 ns;
end data_flow_addsub_1bit;
The N-bit adder/subtractor:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
ENTITY adder_sub32 is
GENERIC (BW : INTEGER :=32);
PORT ( a_32 : IN STD_LOGIC_VECTOR (BW -1 downto 0);
b_32 : IN STD_LOGIC_VECTOR (BW -1 downto 0);
cin : IN STD_LOGIC;
sub : IN STD_LOGIC;
sum_32 : out STD_LOGIC_VECTOR (BW -1 downto 0);
cout : INOUT STD_LOGIC ;
ov : OUT STD_LOGIC ); -- ov stands for overflow
END adder_sub32 ;
ARCHITECTURE adder_sub32_arch OF adder_sub32 IS
signal tmp : std_logic_vector (BW downto 0);
BEGIN
tmp(0) <= cin;
gen: for i IN 0 TO BW-1 GENERATE
as1: entity work.addsub_1bit
PORT MAP(
in_0 => a_32(i),
in_1 => b_32(i),
cin => tmp(i),
AddOrSub => sub,
sum_sub => sum_32(i),
cout_bout => tmp(i+1));
end GENERATE;
ov <= tmp(BW) after 95 ns;
END ARCHITECTURE;
My testbench:
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
ENTITY adder_sub32_TB_SHan_53967364 IS
END adder_sub32_TB_SHan_53967364;
ARCHITECTURE behavior OF adder_sub32_TB_SHan_53967364 IS
-- Component Declaration for the Unit Under Test (UUT)
COMPONENT adder_sub32 IS
GENERIC (BW : INTEGER :=32);
PORT ( a_32 : IN STD_LOGIC_VECTOR (BW -1 downto 0);
b_32 : IN STD_LOGIC_VECTOR (BW -1 downto 0);
cin : IN STD_LOGIC ;
sub : IN STD_LOGIC ;
sum_32 : out STD_LOGIC_VECTOR (BW -1 downto 0);
cout : INOUT STD_LOGIC ;
ov : OUT STD_LOGIC ); -- ov stands for overflow
END COMPONENT;
signal a : std_logic_vector(5 downto 0); --:= (others => '0');
signal b : std_logic_vector(5 downto 0); --:= (others => '0');
signal cin : std_logic;
signal sub : std_logic;
signal cout : std_logic;
signal sum_32 : std_logic_vector(5 downto 0);
signal ov : std_logic;
BEGIN
test1: adder_sub32
GENERIC MAP (6)
PORT MAP (a_32 => a,b_32 => b,cin => cin,sub => sub,sum_32 => sum_32,cout => cout,ov => ov);
sub <= '0';
cin <= '0';
a <= "101010";
b <= "110101";
END;
The waveform I got:
The final sum is correct ("101010" + "110101" = "011111") in this case, but not in all cases.
EDIT2: Let's take a closer look, why the carry is not rippling as expected in your addition. The bits 0 (LSB) to 5 of the operands together, request that the carry-in is propagated from bit 0 to the carry-in of bit 6. Bits 6 of the operands generate a carry, which is carry-out of the adder. As the cin of bit 0 is '0', all intermediate carry-ins will be '0' too, but it should ripple through the carry-chain.
Now lets, take a look at the one-bit adder. You are adding two numbers, so that, AddOrSub is '0'. With this, the equation of cout_bout can be simplified to:
cout_bout <= (in_1 and in_0) or (in_0 and cin);
This equation is definitly wrong, because the carry-in is not propagated when in_1 = '1' and in_0 = '0'. Thus, some of the intermediate carries will be computed to '0' just after 19 ns without waiting for the rippling carry. The corresponding sum bit will be valid after 38 ns as shown in your waveform. The final value of the sum is not affected because this shortcuted carry is identical to the expected rippling carry. Please consider here, that all the 1-bit adder (generated by the generate statement) work concurrently.
To fix the equation, I recommend to write a testbench for the 1-bit adder. This testbench would have to check all possible 16 input combinations of in_0, in_1, cin, and AddOrSub.
Another testcase would be to add the above two operands with an cin of '1'.
(End of EDIT2.)
The ov is correct too in this case, but not in all cases.
EDIT: You mixed up the overflow ov with the carry-out cout. The overflow flag indicates an overflow in the signed number space. For the addition, the overflow flag is '1' if and only if:
the addition of two positive numbers results in a negative sum, or
the addition of two negative numbers results in a positive sum.
For subtraction it is the other way round.
Because this is a homework question, I will not solve it completely. But I will give a you a testcase where your current logic fails: if you add 1 ("000001") plus -1 ("111111"), then the sum must be zero, the overflow '0' and the carry-out '1'. (End of Edit.)
The cout is 'U' because you haven't connected it in adder_sub32. The carry-out is the top-most bit in your carry-chain, and thus:
cout <= tmp(BW);
And you should fix the direction of cout in adder_sub32. The carry-out is just an output of this component. So declare it as out instead of inout.