Hello I'm trying to implement a N-bit adder/subtractor in VHDL but I'm not getting it to work properly for some reason and I can't seem to find what the problem is..
The adder is working as it should but the subtractor isn't and I can't really see what the problem is since I've checked the expression and it is correct, but when I simulate it seems like the subtraction part isn't working at all…
Here's how my implementation with overflow detection and saturation control:
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
entity ripple_adder_subtracter_saturate is
generic (WIDTH : INTEGER := 8);
port (a : IN STD_LOGIC_VECTOR(WIDTH-1 downto 0);
b : IN STD_LOGIC_VECTOR(WIDTH-1 downto 0);
cin : IN STD_LOGIC := '0';
saturate : IN STD_LOGIC := '0';
add_sub : IN STD_LOGIC := '1';
y : OUT STD_LOGIC_VECTOR(WIDTH-1 downto 0);
cout : OUT STD_LOGIC;
overflow : OUT STD_LOGIC);
end ripple_adder_subtracter_saturate;
ARCHITECTURE behavior OF ripple_adder_subtracter_saturate is
component bitAdder is
port(a : IN STD_LOGIC;
b : IN STD_LOGIC;
cin : IN STD_LOGIC;
add_sub : IN STD_LOGIC;
y : OUT STD_LOGIC;
cout : OUT STD_LOGIC);
end component;
signal carry : STD_LOGIC_VECTOR (WIDTH-1 downto 0); -- hold the carry outs from the adders
signal temp_sum : STD_LOGIC_VECTOR (WIDTH-1 downto 0);
signal o_flow : STD_LOGIC; -- internal overflow signal so I can read it in the process
begin
cell_0: bitAdder port map(a(0), b(0), cin, add_sub, temp_sum(0), carry(0));
G: FOR i IN 1 TO WIDTH-1 GENERATE
cell_i: bitAdder port map(a(i), b(i), carry(i-1), add_sub, temp_sum(i), carry(i));
end GENERATE;
o_flow <= carry(WIDTH-1) XOR carry(WIDTH-2);
overflow <= o_flow;
cout <= carry(WIDTH-1);
process(saturate, temp_sum, carry, o_flow)
begin
if (saturate = '1' AND o_flow = '1') then
if (carry(WIDTH-1) = '0') then
y <= (WIDTH-1 => '0', others => '1');
else
y <= (WIDTH-1 => '1', others => '0');
end if;
else
y <= temp_sum;
end if;
end process;
end behavior;
When the signal add_sub = 0, it should subtract and when it's 1 it should do additon etc..
This is how the full adder/subtractor looks like:
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
ENTITY bitAdder IS
PORT (a: IN STD_LOGIC;
b: IN STD_LOGIC;
cin: IN STD_LOGIC;
add_sub : IN STD_LOGIC;
y: OUT STD_LOGIC;
cout: OUT STD_LOGIC);
END bitAdder;
ARCHITECTURE behavior OF bitAdder IS
signal b_sub : STD_LOGIC := '1';
BEGIN
process(a, b, cin, add_sub)
begin
if (add_sub = '0') then
b_sub <= (not b);
y <= (a XOR b_sub) XOR cin;
cout <= (a AND b_sub) OR (b_sub AND cin) OR (a AND cin);
else
y <= (a XOR b) XOR cin;
cout <= (a AND b) OR (b AND cin) or (a AND cin);
end if;
end process;
END behavior;
Can you see what I might've done wrong? I've been bashing my head towards the wall for multiple hours now without any success. So any kind of pointers would be of help!
Here's the testbench that it should pass through:
-----------------------------------
-- testbench type 3 for --
-- ripple carry adder/subtracter --
-- with overflow signal --
-- and saturation logic --
-- for generic vector --
-----------------------------------
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
USE ieee.numeric_std.ALL;
ENTITY ripple_adder_subtracter_saturate_tb3 IS
GENERIC (WIDTH:INTEGER:=8);
PORT(test_OK:OUT STD_LOGIC);
END ripple_adder_subtracter_saturate_tb3;
ARCHITECTURE arch_ripple_adder_subtracter_saturate_tb3 OF
ripple_adder_subtracter_saturate_tb3 IS
COMPONENT ripple_adder_subtracter_saturate IS
GENERIC (WIDTH:INTEGER:=8);
PORT(a:IN STD_LOGIC_VECTOR(WIDTH-1 DOWNTO 0);
b:IN STD_LOGIC_VECTOR(WIDTH-1 DOWNTO 0);
add_sub:IN STD_LOGIC;
saturate:IN STD_LOGIC;
y:OUT STD_LOGIC_VECTOR(WIDTH-1 DOWNTO 0);
overflow:OUT STD_LOGIC);
END COMPONENT ripple_adder_subtracter_saturate;
SIGNAL a_tb_signal:STD_LOGIC_VECTOR(WIDTH-1 DOWNTO 0);
SIGNAL b_tb_signal:STD_LOGIC_VECTOR(WIDTH-1 DOWNTO 0);
SIGNAL y_tb_signal:STD_LOGIC_VECTOR(WIDTH-1 DOWNTO 0);
SIGNAL add_sub_tb_signal:STD_LOGIC;
SIGNAL saturate_tb_signal:STD_LOGIC;
SIGNAL overflow_tb_signal:STD_LOGIC;
BEGIN
ripple_adder_subtracter_saturate_comp:
COMPONENT ripple_adder_subtracter_saturate
PORT MAP(a=>a_tb_signal,
b=>b_tb_signal,
add_sub=>add_sub_tb_signal,
saturate=>saturate_tb_signal,
y=>y_tb_signal,
overflow=>overflow_tb_signal);
saturate_tb_signal<='0', -- overflow
'1' AFTER 1400 ns; -- saturate
add_sub_tb_signal<='1', -- add
'0' AFTER 700 ns, -- sub
'1' AFTER 1400 ns, -- add
'0' AFTER 2100 ns; -- sub
a_tb_signal<="00000000", -- 0
"01010101" AFTER 100 ns, -- 85
"11100101" AFTER 300 ns, -- -27
"00000000" AFTER 700 ns, -- 0
"01010101" AFTER 800 ns, -- 85
"11100101" AFTER 1000 ns, -- -27
"00000000" AFTER 1400 ns, -- 0
"01010101" AFTER 1500 ns, -- 85
"11100101" AFTER 1700 ns, -- -27
"00000000" AFTER 2100 ns, -- 0
"01010101" AFTER 2200 ns, -- 85
"11100101" AFTER 2400 ns; -- -27
b_tb_signal<="00000000", -- 0
"00011101" AFTER 100 ns, -- 29
"00111000" AFTER 200 ns, -- 56
"00000110" AFTER 400 ns, -- 6
"11001000" AFTER 500 ns, -- -56
"10010111" AFTER 600 ns, -- -105
"00000000" AFTER 700 ns, -- 0
"00011101" AFTER 800 ns, -- 29
"11001000" AFTER 900 ns, -- -56
"00111000" AFTER 1000 ns, -- 56
"00000110" AFTER 1100 ns, -- 6
"11001000" AFTER 1200 ns, -- -56
"01101001" AFTER 1300 ns, -- 105
"00000000" AFTER 1400 ns, -- 0
"00011101" AFTER 1500 ns, -- 29
"00111000" AFTER 1600 ns, -- 56
"00000110" AFTER 1800 ns, -- 6
"11001000" AFTER 1900 ns, -- -56
"10010111" AFTER 2000 ns, -- -105
"00000000" AFTER 2100 ns, -- 0
"00011101" AFTER 2200 ns, -- 29
"11001000" AFTER 2300 ns, -- -56
"00111000" AFTER 2400 ns, -- 56
"00000110" AFTER 2500 ns, -- 6
"11001000" AFTER 2600 ns, -- -56
"01101001" AFTER 2700 ns; -- 105
test_proc:
PROCESS
BEGIN
--overflow
--addition
WAIT FOR 50 ns; -- 50 ns 0+0=0 (00000000)
ASSERT (y_tb_signal="00000000")
REPORT "Error for 0+0=0=00000000"
SEVERITY ERROR;
ASSERT (overflow_tb_signal='0')
REPORT "Error in overflow bit when 0+0=0=00000000"
SEVERITY ERROR;
WAIT FOR 100 ns; -- 150 ns 85+29=114 (01110010)
ASSERT (y_tb_signal="01110010")
REPORT "Error for 85+29=114=01110010"
SEVERITY ERROR;
ASSERT (overflow_tb_signal='0')
REPORT "Error in overflow bit when 85+29=114=01110010"
SEVERITY ERROR;
WAIT FOR 100 ns; -- 250 ns 85+56=141->-115 (10001101)
ASSERT (y_tb_signal="10001101")
REPORT "Error for 85+56=141->-115=10001101"
SEVERITY ERROR;
ASSERT (overflow_tb_signal='1')
REPORT "Error in overflow bit when 85+56=141->-115=10001101"
SEVERITY ERROR;
WAIT FOR 100 ns; -- 350 ns -27+56=29 (00011101)
ASSERT (y_tb_signal="00011101")
REPORT "Error for -27+56=29=00011101"
SEVERITY ERROR;
ASSERT (overflow_tb_signal='0')
REPORT "Error in overflow bit when -27+56=29=00011101"
SEVERITY ERROR;
WAIT FOR 100 ns; -- 450 ns -27+6=-21 (11101011)
ASSERT (y_tb_signal="11101011")
REPORT "Error for -27+6=-21=11101011"
SEVERITY ERROR;
ASSERT (overflow_tb_signal='0')
REPORT "Error in overflow bit when -27+6=-21=11101011"
SEVERITY ERROR;
WAIT FOR 100 ns; -- 550 ns -27-56=-83 (10101101)
ASSERT (y_tb_signal="10101101")
REPORT "Error for -27-56=-83=10101101"
SEVERITY ERROR;
ASSERT (overflow_tb_signal='0')
REPORT "Error in overflow bit when -27-56=-83=10101101"
SEVERITY ERROR;
WAIT FOR 100 ns; -- 650 ns -27-105=-132->124 (01111100)
ASSERT (y_tb_signal="01111100")
REPORT "Error for -27-105=-132->124=01111100"
SEVERITY ERROR;
ASSERT (overflow_tb_signal='1')
REPORT "Error in overflow bit when -27-105=-132->124=01111100"
SEVERITY ERROR;
--subtraction
WAIT FOR 100 ns; -- 750 ns 0-0=0 (00000000)
ASSERT (y_tb_signal="00000000")
REPORT "Error for 0-0=0=00000000"
SEVERITY ERROR;
ASSERT (overflow_tb_signal='0')
REPORT "Error in overflow bit when 0-0=0=00000000"
SEVERITY ERROR;
WAIT FOR 100 ns; -- 850 ns 85-29=56 (00111000)
ASSERT (y_tb_signal="00111000")
REPORT "Error for 85-29=56=00111000"
SEVERITY ERROR;
ASSERT (overflow_tb_signal='0')
REPORT "Error in overflow bit when 85-29=56=00111000"
SEVERITY ERROR;
WAIT FOR 100 ns; -- 950 ns 85-(-56)=141->-115 (10001101)
ASSERT (y_tb_signal="10001101")
REPORT "Error for 85-(-56)=141->-115=10001101"
SEVERITY ERROR;
ASSERT (overflow_tb_signal='1')
REPORT "Error in overflow bit when 85-(-56)=141->-115=10001101"
SEVERITY ERROR;
WAIT FOR 100 ns; -- 1050 ns -27-56=-83 (10101101)
ASSERT (y_tb_signal="10101101")
REPORT "Error for -27-56=-83=10101101"
SEVERITY ERROR;
ASSERT (overflow_tb_signal='0')
REPORT "Error in overflow bit when -27-56=-83=10101101"
SEVERITY ERROR;
WAIT FOR 100 ns; -- 1150 ns -27-6=-33 (11011111)
ASSERT (y_tb_signal="11011111")
REPORT "Error for -27-6=-33=11011111"
SEVERITY ERROR;
ASSERT (overflow_tb_signal='0')
REPORT "Error in overflow bit when -27-6=-33=11011111"
SEVERITY ERROR;
WAIT FOR 100 ns; -- 1250 ns -27-(-56)=29 (00011101)
ASSERT (y_tb_signal="00011101")
REPORT "Error for -27-(-56)=29=00011101"
SEVERITY ERROR;
ASSERT (overflow_tb_signal='0')
REPORT "Error in overflow bit when -27-(-56)=29=00011101"
SEVERITY ERROR;
WAIT FOR 100 ns; -- 1350 ns -27-105=-132->124 (01111100)
ASSERT (y_tb_signal="01111100")
REPORT "Error for -27-105=-132->124=01111100"
SEVERITY ERROR;
ASSERT (overflow_tb_signal='1')
REPORT "Error in overflow bit when -27-105=-132->124=01111100"
SEVERITY ERROR;
--saturate
--addition
WAIT FOR 100 ns; -- 1450 ns 0+0=0 (00000000)
ASSERT (y_tb_signal="00000000")
REPORT "Error for 0+0=0=00000000"
SEVERITY ERROR;
ASSERT (overflow_tb_signal='0')
REPORT "Error in overflow bit when 0+0=0=00000000"
SEVERITY ERROR;
WAIT FOR 100 ns; -- 1550 ns 85+29=114 (01110010)
ASSERT (y_tb_signal="01110010")
REPORT "Error for 85+29=114=01110010"
SEVERITY ERROR;
ASSERT (overflow_tb_signal='0')
REPORT "Error in overflow bit when 85+29=114=01110010"
SEVERITY ERROR;
WAIT FOR 100 ns; -- 1650 ns 85+56=141->127 (01111111)
ASSERT (y_tb_signal="01111111")
REPORT "Error for 85+56=141->127=10001101"
SEVERITY ERROR;
ASSERT (overflow_tb_signal='1')
REPORT "Error in overflow bit when 85+56=141->127=10001101"
SEVERITY ERROR;
WAIT FOR 100 ns; -- 1750 ns -27+56=29 (00011101)
ASSERT (y_tb_signal="00011101")
REPORT "Error for -27+56=29=00011101"
SEVERITY ERROR;
ASSERT (overflow_tb_signal='0')
REPORT "Error in overflow bit when -27+56=29=00011101"
SEVERITY ERROR;
WAIT FOR 100 ns; -- 1850 ns -27+6=-21 (11101011)
ASSERT (y_tb_signal="11101011")
REPORT "Error for -27+6=-21=11101011"
SEVERITY ERROR;
ASSERT (overflow_tb_signal='0')
REPORT "Error in overflow bit when -27+6=-21=11101011"
SEVERITY ERROR;
WAIT FOR 100 ns; -- 1950 ns -27-56=-83 (10101101)
ASSERT (y_tb_signal="10101101")
REPORT "Error for -27-56=-83=10101101"
SEVERITY ERROR;
ASSERT (overflow_tb_signal='0')
REPORT "Error in overflow bit when -27-56=-83=10101101"
SEVERITY ERROR;
WAIT FOR 100 ns; -- 2050 ns -27-105=-132->-128 (10000000)
ASSERT (y_tb_signal="10000000")
REPORT "Error for -27-105=-132->-128=01111100"
SEVERITY ERROR;
ASSERT (overflow_tb_signal='1')
REPORT "Error in overflow bit when -27-105=-132->-127=10000000"
SEVERITY ERROR;
--subtraction
WAIT FOR 100 ns; -- 2150 ns 0-0=0 (00000000)
ASSERT (y_tb_signal="00000000")
REPORT "Error for 0-0=0=00000000"
SEVERITY ERROR;
ASSERT (overflow_tb_signal='0')
REPORT "Error in overflow bit when 0-0=0=00000000"
SEVERITY ERROR;
WAIT FOR 100 ns; -- 2250 ns 85-29=56 (00111000)
ASSERT (y_tb_signal="00111000")
REPORT "Error for 85-29=56=00111000"
SEVERITY ERROR;
ASSERT (overflow_tb_signal='0')
REPORT "Error in overflow bit when 85-29=56=00111000"
SEVERITY ERROR;
WAIT FOR 100 ns; -- 2350 ns 85-(-56)=141->127 (01111111)
ASSERT (y_tb_signal="01111111")
REPORT "Error for 85-(-56)=141->127=01111111"
SEVERITY ERROR;
ASSERT (overflow_tb_signal='1')
REPORT "Error in overflow bit when 85-(-56)=141->127=01111111"
SEVERITY ERROR;
WAIT FOR 100 ns; -- 2450 ns -27-56=-83 (10101101)
ASSERT (y_tb_signal="10101101")
REPORT "Error for -27-56=-83=10101101"
SEVERITY ERROR;
ASSERT (overflow_tb_signal='0')
REPORT "Error in overflow bit when -27-56=-83=10101101"
SEVERITY ERROR;
WAIT FOR 100 ns; -- 2550 ns -27-6=-33 (11011111)
ASSERT (y_tb_signal="11011111")
REPORT "Error for -27-6=-33=11011111"
SEVERITY ERROR;
ASSERT (overflow_tb_signal='0')
REPORT "Error in overflow bit when -27-6=-33=11011111"
SEVERITY ERROR;
WAIT FOR 100 ns; -- 2650 ns -27-(-56)=29 (00011101)
ASSERT (y_tb_signal="00011101")
REPORT "Error for -27-(-56)=29=00011101"
SEVERITY ERROR;
ASSERT (overflow_tb_signal='0')
REPORT "Error in overflow bit when -27-(-56)=29=00011101"
SEVERITY ERROR;
WAIT FOR 100 ns; -- 2750 ns -27-105=-132->-128 (10000000)
ASSERT (y_tb_signal="10000000")
REPORT "Error for -27-105=-132->-128=10000000"
SEVERITY ERROR;
ASSERT (overflow_tb_signal='1')
REPORT "Error in overflow bit when -27-105=-132->-128=10000000"
SEVERITY ERROR;
END PROCESS test_proc;
END arch_ripple_adder_subtracter_saturate_tb3;
And the .do file:
-- ripple_adder_saturate_tb3.do
restart -f -nowave
view signals wave
add wave saturate_tb_signal a_tb_signal b_tb_signal y_tb_signal
add wave -radix signed a_tb_signal b_tb_signal y_tb_signal
add wave -radix unsigned y_tb_signal
add wave overflow_tb_signal
run 1380ns
Best Answer
Without running your testbench there are a couple of things that appear wrong in the unlabeled adder process.
Firs, in bitAdder the process sensitivity list is missing
b_sub
, which will have an event one delta cycle afterb
. You could end up operating on the lastb_sub
value, which also has an inferred latch should you want to synthesize this (b_sub
is not assigned under else).Also note that
add_sub
effectively one's complements the top levelb
, by inverting the bitAdderb
bits.To accomplish subtraction by adding the two's complement of the top level
b
you need a+ 1
accomplished by carry in. To preserve the ability to use your top levelcin
, you can simply invert the value ofcin
being delivered tocell_0
whenadd_sub = '0'
. This allows you to chain operations ofWIDTH
width operands.In
ripple_adder_subtracter_saturate
:And substituting
cin_add_sub
forcin
in thecell_0
instantiation:You could add a separate statement or process in bitAdder to invert
b
whenadd_sub = '0'
and eliminate the else in the if statement in the present process.Something like:
Likewise you could move the entire two's complement operation to the design top level.
I made the above changes and your design did not produce any assertion violations. (As long as you don't let it run long enough for the process with the assertion statements to wrap, it should be terminated by say
wait 49 ns; wait;
. The extra wait so you can display waveforms more or less uniformly for all tests.)Examining a waveform dump shows subtraction getting the right value. I didn't verify the rest of the assertions.