Implementing Overflow Checking in 4-bit Adder/Subtractor (VHDL) - vhdl

I am rather new (3 weeks) to VHDL, and I am having a problem in my latest assignment, which involves implementing overflow checking in a simple 4-bit adder:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity add_sub_4bit is
Port ( a : in STD_LOGIC_VECTOR(3 downto 0);
b : inout STD_LOGIC_VECTOR(3 downto 0);
sel: in STD_LOGIC );
--sum : inout STD_LOGIC_VECTOR(3 downto 0)
end add_sub_4bit;
architecture Behavioral of add_sub_4bit is
signal localflow : STD_LOGIC;
signal localsum : STD_LOGIC_VECTOR (3 downto 0);
begin
localsum <= a + b when sel = '1'
else
a - b;
process(a,b,localsum) begin
if a(3) = '0' AND b(3) = '0' AND localsum(3) = '1' then
localflow <= '1';
elsif a(3) = '1' AND b(3) = '1' AND localsum(3) = '0' then
localflow <='1';
else
localflow <='0';
end if;
end process;
end Behavioral;
Now, the test cases are as such:
A=5, B=-3, giving 0 to sel adds them, 1 subtracts.
A=6, B=2, working much the same.
Now, given that the numbers are signed, of course, they are two's complement numbers, so is the result. However, I can only detect overflow in a case of adding 6 (0110) and 2 (0010), giving out -8 (1000), which is obviously an overflow case in 4-bit. But, when doing 5 -(-3), the result is much the same, 1000, but since I have given numbers of two different signs, I cannot detect overflow using my method.
My teacher has suggested that we change the sign of B depending on the value of sel - I tried something like making b <= b+"1000" based on that but that didn't help, and I don't know of other ways, being very new to the language. What can I do to get a proper program? Thank you.

Firstly:
use IEEE.STD_LOGIC_UNSIGNED.ALL;
Don't do that. Especially if you want the numbers to be signed. Normal to use is:
use IEEE.numeric_std.all;
After that, you should cast the std_logic_vector to the wanted data type, e.g. 'signed', for the correct arithmetic.
Secondly, don't use inout. VHDL is not so good with bidirectional assignments. Either use in or out.
So combining the above, you could do (n.b. not the best code):
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.numeric_std.ALL;
entity add_sub_4bit is
Port (
a : in STD_LOGIC_VECTOR(3 downto 0);
b : in STD_LOGIC_VECTOR(3 downto 0);
sel: in STD_LOGIC;
sum : out STD_LOGIC_VECTOR(3 downto 0);
overflow : out std_logic
);
end add_sub_4bit;
architecture Behavioral of add_sub_4bit is
signal localflow : STD_LOGIC;
signal locala, localb, localsum : signed(4 downto 0); -- one bit more then input
signal sumout : std_logic_vector(4 downto 0);
begin
locala <= resize(signed(a), 5);
localb <= resize(signed(b), 5);
localsum <= locala + localb when sel = '1' else locala - localb;
-- overflow occurs when bit 3 is not equal to the sign bit(4)
localflow <= '1' when localsum(3) /= localsum(4) else '0';
-- convert outputs
sumout <= std_logic_vector(localsum);
--outputs
sum <= sumout(4)&sumout(2 downto 0);
overflow <= localflow;
end Behavioral;
You can test this using a testbench:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.numeric_std.ALL;
entity add_sub_4bit_tb is
end add_sub_4bit_tb;
architecture Behavioral of add_sub_4bit_tb is
signal sel : std_logic_vector(0 downto 0);
signal a, b, sum : std_logic_vector(3 downto 0);
begin
uut: entity work.add_sub_4bit
port map (a, b, sel(0), sum);
test: process
begin
for sel_o in 0 to 1 loop
sel <= std_logic_vector(to_signed(sel_o, 1));
for a_o in -8 to 7 loop
a <= std_logic_vector(to_signed(a_o, 4));
for b_o in -8 to 7 loop
b <= std_logic_vector(to_signed(b_o, 4));
wait for 1 ns;
end loop;
end loop;
end loop;
wait;
end process;
end Behavioral;

Related

10028 Can't solve multiple constant drivers for net "D[x]"

Hi pleople this is my code, and the only error is Error (10028): Can't resolve multiple constant drivers for net "D[22]" at bonus2.vhd(26). I<m new at this and I don't understant this error.
Here is my code
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity bonus2 is
port (
B,C : in unsigned(15 downto 0);
clear, clk : in std_logic;
Q : out unsigned(31 downto 0)
);
end entity bonus2;
architecture arch_bonus2 of bonus2 is
signal mult : unsigned(31 downto 0); --signal d'addition
signal D: unsigned(31 downto 0); --signal d'addition
begin
mult <= B * C;
process(clear)
begin
if clear = '1' then
D <= x"00000000";
end if;
end process;
process(clk)
begin
if rising_edge(clk) then
D <= mult + D;
end if;
end process;
Q <= D;
end architecture arch_bonus2;
Your code shows that you might be unfamiliar with some concepts of hardware design, so I suggest you catch up on combinational/sequential logic and how to describe them with VHDL. Also, a good rule of thumb is that you should be able to draw some parts of your design, and if you do you'll see that the D wire is driven by multiple nets.
What I believe you want to do, based on your code, is to be able to reset/initialize your output register. However, the way you have coded it suggests you want an asynchronous reset.
Please check here to know more about synch vs asynch logic and then I suggest you to explore further to understand the implications.
Here is a modified version of your code with an asynchronous reset, because it seems what you want.
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity bonus2 is
port (
B,C : in unsigned(15 downto 0);
clear, clk : in std_logic;
Q : out unsigned(31 downto 0)
);
end entity bonus2;
architecture arch_bonus2 of bonus2 is
signal mult : unsigned(31 downto 0); --signal d'addition
signal D: unsigned(31 downto 0); --signal d'addition
begin
mult <= B * C;
process(clk,clear)
if clear == '1' then
D <= x"00000000";
elsif rising_edge(clk) then
D <= mult + D;
end if;
end process;
Q <= D;
end architecture arch_bonus2;

Devision and Multiplication using SHIFTING in VHDL

How can I implement Division and Multiplication manually in VHDL? That is; using Left & Right Shift and without the need for numeric_std (If possible).
A possible soulution:
library ieee;
USE ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity Shifter is
generic(
num_length : integer := 32
);
port(
EN : in std_logic;
clk : in std_logic;
number : in std_logic_vector((num_length - 1) downto 0);
dir : in std_logic;
result : out std_logic_vector((num_length - 1) downto 0));
end Shifter;
architecture Beh of Shifter is
signal temp : std_logic_vector((num_length - 1) downto 0);
begin
result <= std_logic_vector(temp);
process(EN, clk) is
begin
if EN = '0' then
temp <= (OTHERS => '0');
elsif rising_edge(clk) then
case dir is
when '0' => temp <= '0' & number((num_length - 2) downto 0);
when '1' => temp <= number((num_length - 2) downto 0) & '0';
end case;
end if;
end process;
end Beh;
Every clk cycle the position increases/decreases (depends on dir setting)
It can also be released with loops so that the module can increase/decrease more than one bit at a cycle.
Important: It is only possible to increase/decrease by the power of 2 (2,4,8,16,32,...) with shifting

VHDL : Internal signals are undefined even when defined in the architecture declaration section

So I've been working on some homework for my VHDL course and I can't seem to understand this problem.
The point here is to create the adder/subtractor of an ALU that works both on 2's complement and unsigned 32-bit buses, which is why I have a condition called sub_mode ( A - B = A + !B + 1 ) which will also be the carry-in when activated.
The rest of the different inputs and outputs are pretty self-explanatory.
My problem is with the testbenching of such component where, even though carry_temp and r_temp have been initialized in declaration section of the architecture, end up showing up undefined. I have guessed that it is due to the for loop within the process screwing everything up. Would that be an accurate guess? And if yes, is it possible to proceed to add two bit buses together without having to fully create an n-bit adder made from n 1-bit adder components?
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity add_sub is
port(
a : in std_logic_vector(31 downto 0);
b : in std_logic_vector(31 downto 0);
sub_mode : in std_logic;
carry : out std_logic;
zero : out std_logic;
r : out std_logic_vector(31 downto 0)
);
end add_sub;
architecture synth of add_sub is
signal cond_inv : std_logic_vector(31 downto 0);
signal carry_temp : std_logic_vector(32 downto 0) := (others => '0');
signal r_temp : std_logic_vector(31 downto 0) := (others => '0');
begin
behave : process(a,b,sub_mode)
begin
if sub_mode = '1' then
cond_inv <= b xor x"ffffffff";
else
cond_inv <= b;
end if;
carry_temp(0) <= sub_mode;
for i in 0 to 31 loop
r_temp(i) <= a(i) xor cond_inv(i) xor carry_temp(i);
carry_temp(i+1) <=
(a(i) and cond_inv(i)) or
(a(i) and carry_temp(i)) or
(cond_inv(i)and carry_temp(i));
end loop;
if r_temp = x"00000000" then
zero <= '1';
else
zero <= '0';
end if;
r <= r_temp;
carry <= carry_temp(32);
end process behave;
end synth;

TestBench for Bitwise Operators

Can someone help me to create a TestBench Program for the below Program, please?
library ieee;
use ieee.std_logic_1164.all;
entity bitwise is
port( a,b : in std_logic_vector(4 downto 0);
result1, result2, result3, result4, result5, result6 : out std_logic_vector(4 downto 0));
end bitwise;
architecture arch of bitwise is
begin
result1 <= a and b;
result2 <= a or b;
result3 <= a xor b;
result4 <= not a;
result5 <= to_stdlogicvector(to_bitvector(a) sll 1);
result6 <= to_stdlogicvector(to_bitvector(a) srl 1);
end arch;
My Test Bench Program is below: I am stuck to in the Stimulus process where we have to test each and every possibility. It could be either a loop version or just testing possible numbers for each operator.
LIBRARY ieee;
USE ieee.std_logic_1164.all;
entity test_bitwise is
end test_bitwise;
architecture behavior of test_bitwise is
component bitwise;
port( a,b : in std_logic_vector(4 downto 0);
result1, result2, result3, result4 : out std_logic_vector(4 downto 0));
end component;
--INPUTS
signal tb_a : std_logic_vector(4 downto 0) := (others => '0');
`signal tb_b : std_logic_vector(4 downto 0) := (others => '0');
--OUTPUTS
signal tb_result1 : std_logic_vector(7 downto 0);
signal tb_result2 : std_logic_vector(7 downto 0);
signal tb_result3 : std_logic_vector(7 downto 0);
signal tb_result4 : std_logic_vector(7 downto 0);
begin
-- INSTANTIATE THE UNIT UNDER TEST (UUT)
U1_Test : entity work.test_bitwise(behavioral)
port map (a => tb_a,
b => tb_b,
result1 <= tb_result1,
result2 <= tb_result2,
result3 <= tb_result3,
result4 <= tb_result4);
--STIMULUS PROCESS
stim_proc : process
begin
-- CODE HERE
end process;
end behavior;
As others have stated in the comments, you should provide some input yourself. What have you tried and why didn't it succeed? If you have hard time to find out what to try and how to start, you could begin by doing the following. And if you don't succeed, you can then edit your question or post a new one so the other members can help you.
Use a for loop to iterate over each and every possibility. Writing all the possible values to test by hand would be exhausting.
Because you have two inputs, use two nested for loops inside your process. One iterates the values for input a and the other one for b. Check here how a for loop is written.
Inside the loops, assign values to your signals tb_a and tb_b. The loop indices are integers, so you have to convert them to std_logic_vector type before assigning. Check here for a short tutorial about VHDL conversions.
Add some delay after each iteration with wait.
Print the output values for example to simulator console with report, or you can even use assert statement.

how to check for any carry generated while adding std_logic_vector using operator overloading?

I am trying to add two std_logic_vectors using the notation given below:-
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
--use IEEE.NUMERIC_STD.ALL;
entity adder is
port( a:in std_logic_vector(31 downto 0);
b:in std_logic_vector(31 downto 0);
o:out std_logic_vector(31 downto 0));
end adder;
architecture Behavioral of adder is
begin
o<=a+b;
end Behavioral;
One possibility is to generate the result with carry, and then split that afterwards, like:
architecture Behavioral of adder is
signal c_o : std_logic_vector(o'length downto 0); -- Result with carry
signal c : std_logic; -- Carry only
begin
c_o <= ('0' & a) + b; -- Result with carry; extended with '0' to keep carry
o <= c_o(o'range); -- Result without carry
c <= c_o(c_o'left); -- Carry only
end Behavioral;
You can do this. The carry is not saved, but it's being reported that there was an overflow.
function "+" (Add1: std_logic_vector; Add2: std_logic_vector) return std_logic_vector is
variable big_sum: bit_vector(Add1'LENGTH downto 0);
begin
big_sum = Add1 + Add2;
assert big_sum(Add1'LENGTH) = 0
report "overflow"
severity warning;
return big_sum(Add1'LENGTH-1 downto 0);
Of course you'll need to define a new package and also include that package in your already existing file.
o<=std_logic_vector(unsigned(a)+unsigned(b))
Although I suggest you use unsigned/signed on your ports (and have a clock cycle of latency).
If you want the carry
o_with_carry <= std_logic_vector('0'&unsigned(a)+unsigned(b));
o_carry <= o_with_carry(o_with_carry'high);
o <= o_with_carry(o'range);

Resources