I'm trying to implement a serial adder/subtractor in VHDL, I've done it the ripple carry way before but now I'm supposed to implement the same functionality by just using one full adder cell instead of N-amount of cells so I have to shift the bits from the vectors in to the full adder/subtractor and store the result in another vector which I just shift the index for as well... The logic behind it is very easily understood, you just have a counter for the index and so on. But I obviously encounter problems since I'm probably still thinking a bit too much software programming I guess...
The problem I have is that the counter increases to 1 right away when it enters the process so that when I try to add the vectors a = 0101 0101 and b = 1010 1010 I get y = 1111 111X and the carrys = 0000 000X. I've tried to start storing the result at index_counter - 1 since the index jumps to 1 on the first clock cycle, but then I get a fatal error in the simulation...
I've been trying to solve this problem for a few hours now and can't seem to figure out how to do it, so could you please take a look and see what I can do to fix it? Would be very much appreciated!
I do have signals for saturation and overflow that I am going to implement later on but they aren't really used at the moment so don't worry about them.
The design shouldn't update the final result before the addition/subtraction is finished if you're wondering why I have done it the way I have..
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
entity serial_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);
saturate : IN STD_LOGIC := '0';
add_sub : IN STD_LOGIC := '1';
clk : IN STD_LOGIC;
start : IN STD_LOGIC;
reset : IN STD_LOGIC;
y : OUT STD_LOGIC_VECTOR(WIDTH-1 downto 0);
overflow : OUT STD_LOGIC;
finished : OUT STD_LOGIC);
end serial_adder_subtracter_saturate;
ARCHITECTURE behavior OF serial_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
signal a_temp : STD_LOGIC;
signal b_temp : STD_LOGIC;
signal y_temp : STD_LOGIC;
signal cin_temp : STD_LOGIC;
signal cout_temp : STD_LOGIC;
begin
AddSub: bitAdder
port map(a => a_temp,
b => b_temp,
cin => cin_temp,
add_sub => add_sub,
y => y_temp,
cout => cout_temp);
o_flow <= carry(WIDTH-1) XOR carry(WIDTH-2);
test: process(clk)
variable index_counter : integer range 0 to (WIDTH) := 0;
begin
if rising_edge(clk) then
if reset = '1' then
index_counter := 0;
carry <= (others => '0');
temp_sum <= (others => '0');
finished <= '0';
elsif reset = '0' AND start = '1' then
if index_counter = (WIDTH) then
finished <= '1';
y <= temp_sum;
else
if index_counter = 0 then
cin_temp <= NOT add_sub;
else
cin_temp <= carry(index_counter);
end if;
a_temp <= a(index_counter);
b_temp <= b(index_counter);
carry(index_counter) <= cout_temp;
temp_sum(index_counter) <= y_temp;
index_counter := index_counter + 1;
end if;
end if;
end if;
end process;
end behavior;
Here's how the full adder/subtractor looks if that's of interest:
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
USE ieee.std_logic_unsigned.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_sig : STD_LOGIC := '1';
BEGIN
b_sig <= not b when add_sub = '0' else
b; -- b_sig <= add_sub XOR b;
y <= a XOR b_sig XOR cin;
cout <= (a AND b_sig) OR
(b_sig AND cin) OR
(a AND cin);
END behavior;