Search code examples
vhdladditionalu

Carry/Borrow in VHDL ALU


I am making a generic N-bit ALU in VHDL. I am having trouble assigning the value for the carry for addition, or borrow for subtraction. I have tried the following:

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL; 

entity alu is
    generic(n: integer :=1); --Default to 1
    port (
        a : in std_logic_vector(n-1 downto 0);
        b : in std_logic_vector(n-1 downto 0);
        op : in std_logic_vector(1 downto 0);
        output : out std_logic_vector(n-1 downto 0);
        carryborrow: out std_logic 
    );
end alu;

architecture Behavioral of alu is
    signal result: std_logic_vector(n downto 0); 
begin
process( a, b, op )
begin
    case op is
    when "00" => 
        result(n) <= '0'; 
        result(n-1 downto 0) <= a and b; --and gate 
        output <= result(n-1 downto 0); 
        carryborrow <= '0'; 
    when "01" => 
        result(n) <= '0'; 
        result(n-1 downto 0) <= a or b; --or gate 
        output <= result(n-1 downto 0); 
        carryborrow <= '0'; 
    when "10" => 
        result(n) <= '0'; 
        result(n-1 downto 0) <= std_logic_vector(signed(a) + signed(b)); --addition
        output <= result(n-1 downto 0); 
        carryborrow <= result(n); 
    when "11" => 
        result(n) <= '0';
        result(n-1 downto 0) <= std_logic_vector(signed(a) - signed(b)); --subtraction
        output <= result(n-1 downto 0); 
        carryborrow <= result(n); 
    when others => 
        NULL; 
    end case; 

end process;

end Behavioral;

This seems to set the carryborrow bit to always be 0. How can I assign it to what it should be without type errors?


Solution

  • There are bugs in your code:

    i) You have not taken into account the fact that signals are not updated immediately. Consequently, the following lines will not do as I think you are expecting:

        result(n) <= '0'; 
        result(n-1 downto 0) <= a and b; --and gate 
        output <= result(n-1 downto 0); 
    

    Instead, you need to take the lines driving output and carryborrow outside the combinational process, as you can see below. ii) Assuming you wish this code to be synthesisable, simply putting NULL in your always branch will result in latches being inferred. You need to drive result in the others branch, too.

    So, making an assumption about how your carry output is to behave with the and and or operations, this is how I would have written your code:

    architecture Behavioral of alu is
        signal result: std_logic_vector(n downto 0); 
    begin
    process( a, b, op )
    begin
        case op is
        when "00" => 
            result <= '0' & (a and b); --and gate 
        when "01" => 
            result <= '0' & (a or b); --or gate 
        when "10" => 
            result <= std_logic_vector(resize(signed(a), n+1) + resize(signed(b), n+1)); --addition
        when "11" => 
            result <= std_logic_vector(resize(signed(a), n+1) - resize(signed(b), n+1)); --subtraction
        when others => 
            result <= (others => 'X');
        end case; 
      end process;
    
      output <= result(n-1 downto 0); 
      carryborrow <= result(n); 
    
    end Behavioral;