====== ALUS library ====== The ALUS library consists of the following 4 generic components : * [[.:alus#addN]]: N-bit adder * [[.:alus#subN]]: N-bit subtractor * [[.:alus#adsbN]]: N-bit adder / subtractor * [[.:alus#aluNf]]: N-bit general purpose ALU with flags The ALUS library can be verified with this testbench: [[.:alus#testbench|test_alus]] These particular components implements all the logical and arithmetic operations, such as addition and substraction, with a variable word length of the operands. In the next two tables, the general's ALU operations encoding is shown. Arithmetic operations: ^ Operation ^ Expression ^ Mnemonic ^ Op Code ^ | Add | A + B + CIN | ADD | 1001111 | | Subtract | A + B~ + CIN | SUB | 1000111 | | Reverse Subtract | B - A - CIN~ | SBR | 1001101 | | Negate A | A~ + CIN | NEGA | 1000001 | | Negate B | B~ + CIN | NEGB | 1000100 | | Increment A | A + CIN | INCA | 1000011 | | Increment B | B + CIN | INCB | 1001100 | | Decrement A | A - CIN~ | DECA | 1001011 | | Decrement B | B - CIN~ | DECB | 1001110 | | Negated Add | A~ + B~ + CIN | NADD | 1000101 | | Decrement Not A | A~ + CIN~ | NDECA | 1001001 | | Decrement Not B | B~ + CIN~ | NDECB | 1000110 | Logical Operations: ^ Operation ^ Expression ^ Mnemonic ^ Op Code ^ | Ones | -1 | ONES | 0100000 | | Zeros | 0 | ZEROS | 0100010 | | Pass A | A | EQUA | 0100011 | | Pass B | B | EQUB | 0101100 | | Not A | A~ | NOTA | 0100001 | | Not B | B~ | NOTB | 0100100 | | And | A * B | AND | 1010101 | | And Complement A | A~ * B | ANDCA | 1010111 | | And Complement B | A * B~ | ANDCB | 1011110 | | Nand | (A * B)~ | NAND | 0010101 | | Or | A + B | OR | 0011111 | | Or Complement A | A~ + B | ORCA | 0011101 | | Or Complement b | A + B~ | ORCB | 0010111 | | Nor | (A + B)~ | NOR | 1011111 | | Exclusive Or | A ^ B | XOR | 0101111 | | Exclusive Nor | (A ^ B)~ | XNOR | 1101111 | ===== addN ===== -- ############################################################################ -- # Project : Leonardo CBT-Kernel # -- # # -- # Filename : alus.vhd # -- # # -- # Component : addN : N-Bit Adder # -- # # -- # Model : rtl # -- # # -- # Designer : S. Theoharis,N. Zervas # -- # Institute : VLSI Design Lab., University of Patras # -- # Date : 01.05.1999 # -- ############################################################################ library IEEE; use IEEE.std_logic_1164.all; use IEEE.std_logic_arith.all; -- addN Entity Description entity addN is generic(N: INTEGER := 4); port( A: in std_ulogic_vector(N-1 downto 0); B: in std_ulogic_vector(N-1 downto 0); D: out std_ulogic_vector(N-1 downto 0); CIN: in std_ulogic; COUT: out std_ulogic ); end addN; -- addN Architecture Description architecture rtl of addN is signal pre_D : std_ulogic_vector(N downto 0); signal pre_OV : std_ulogic; begin ARITHMETIC_Process: process(A,B,CIN) variable fct_out : std_ulogic_vector(N downto 0); variable a_ext,b_ext : std_ulogic_vector(N downto 0); variable carry_ext : std_ulogic_vector(1 downto 0); variable msb : integer; begin -- zero extend inputs to include carry bit a_ext := '0' & A; b_ext := '0' & B; carry_ext := '0' & CIN; -- ADD fct_out := a_ext + b_ext + carry_ext; -- Assign to signal for use outside process pre_D <= fct_out; -- Calculate overflow bit if (a_ext(N-1) = b_ext(N-1) and fct_out(N-1) = not a_ext(N-1)) then pre_OV <= '1'; else pre_OV <= '0'; end if; end process ARITHMETIC_Process; -- Assign the outputs D <= pre_D(N-1 downto 0); -- Assign flags COUT <= pre_D(N); end rtl; ===== subN ===== -- ############################################################################ -- # Project : Leonardo CBT-Kernel # -- # # -- # Filename : alus.vhd # -- # # -- # Component : subN : N-Bit Subtractor # -- # # -- # Model : rtl # -- # # -- # Designer : S. Theoharis,N. Zervas # -- # Institute : VLSI Design Lab., University of Patras # -- # Date : 01.05.1999 # -- ############################################################################ library IEEE; use IEEE.std_logic_1164.all; use IEEE.std_logic_arith.all; -- subN Entity Description entity subN is generic(N: INTEGER := 4); port( A: in std_ulogic_vector(N-1 downto 0); B: in std_ulogic_vector(N-1 downto 0); D: out std_ulogic_vector(N-1 downto 0); CIN: in std_ulogic; COUT: out std_ulogic ); end subN; -- subN Architecture Description architecture rtl of subN is signal pre_D : std_ulogic_vector(N downto 0); signal pre_OV : std_ulogic; begin ARITHMETIC_Process: process(A,B,CIN) variable fct_out : std_ulogic_vector(N downto 0); variable a_ext,b_ext : std_ulogic_vector(N downto 0); variable carry_ext : std_ulogic_vector(1 downto 0); variable msb : integer; begin -- zero extend inputs to include carry bit a_ext := '0' & A; b_ext := '0' & not B; carry_ext := '0' & CIN; -- SUB fct_out := a_ext + b_ext + carry_ext; -- Assign to signal for use outside process pre_D <= fct_out; -- Calculate overflow bit if (a_ext(N-1) = b_ext(N-1) and fct_out(N-1) = not a_ext(N-1)) then pre_OV <= '1'; else pre_OV <= '0'; end if; end process ARITHMETIC_Process; -- Assign the outputs D <= pre_D(N-1 downto 0); -- Assign flags COUT <= pre_D(N); end rtl; ===== adsbN ===== -- ############################################################################ -- # Project : Leonardo CBT-Kernel # -- # # -- # Filename : alus.vhd # -- # # -- # Component : adsbN : N-Bit Adder/Subtractor # -- # # -- # Model : rtl # -- # # -- # Designer : S. Theoharis,N. Zervas # -- # Institute : VLSI Design Lab., University of Patras # -- # Date : 01.05.1999 # -- ############################################################################ library IEEE; use IEEE.std_logic_1164.all; use IEEE.std_logic_arith.all; -- adsbN Entity Description entity adsbN is generic(N: INTEGER := 4); port( A: in std_ulogic_vector(N-1 downto 0); B: in std_ulogic_vector(N-1 downto 0); D: out std_ulogic_vector(N-1 downto 0); CIN,SUB: in std_ulogic; COUT: out std_ulogic ); end adsbN; -- adsbN Architecture Description architecture rtl of adsbN is signal pre_D : std_ulogic_vector(N downto 0); signal pre_OV : std_ulogic; begin ARITHMETIC_Process: process(A,B,CIN,SUB) variable fct_out : std_ulogic_vector(N downto 0); variable a_ext,b_ext : std_ulogic_vector(N downto 0); variable carry_ext : std_ulogic_vector(1 downto 0); variable msb : integer; begin -- zero extend inputs to include carry bit a_ext := '0' & A; if (SUB = '1') then b_ext := '0' & not B; else b_ext := '0' & B; end if; carry_ext := '0' & CIN; -- ADDSUB fct_out := a_ext + b_ext + carry_ext; -- Assign to signal for use outside process pre_D <= fct_out; -- Calculate overflow bit if (a_ext(N-1) = b_ext(N-1) and fct_out(N-1) = not a_ext(N-1)) then pre_OV <= '1'; else pre_OV <= '0'; end if; end process ARITHMETIC_Process; -- Assign the outputs D <= pre_D(N-1 downto 0); -- Assign flags COUT <= pre_D(N); end rtl; ===== aluNf ===== -- ############################################################################ -- # Project : Leonardo CBT-Kernel # -- # # -- # Filename : alus.vhd # -- # # -- # Component : aluNf : N-Bit ALU with Flags # -- # # -- # Model : rtl # -- # # -- # Designer : S. Theoharis,N. Zervas # -- # Institute : VLSI Design Lab., University of Patras # -- # Date : 01.05.1999 # -- ############################################################################ library IEEE; use IEEE.std_logic_1164.all; use IEEE.std_logic_arith.all; -- aluNf Entity Description entity aluNf is generic(N: INTEGER := 4); port( A: in std_ulogic_vector(N-1 downto 0); B: in std_ulogic_vector(N-1 downto 0); OP: in std_ulogic_vector(6 downto 0); D: out std_ulogic_vector(N-1 downto 0); CIN: in std_ulogic; COUT,EQ,GT,LT,OV: out std_ulogic ); end aluNf; -- aluNf Architecture Description architecture rtl of aluNf is signal pre_D : std_ulogic_vector(N downto 0); signal pre_OV : std_ulogic; signal pre_EQ : std_ulogic; signal pre_LT : std_ulogic; constant minus_one: std_ulogic_vector(N-1 downto 0) := (OTHERS => '1'); FUNCTION vector_eq_zero (vect : std_ulogic_vector ) RETURN BOOLEAN IS VARIABLE len : integer := vect'LENGTH; VARIABLE vector : std_ulogic_vector(len-1 downto 0); VARIABLE equal_zero : BOOLEAN; BEGIN -- Check zero equality equal_zero := true; for i in len-1 DOWNTO 0 loop if vector(i) /= '0' then equal_zero := false; exit; end if; end loop; RETURN equal_zero; END vector_eq_zero; begin ARITHMETIC_Process: process(A,B,CIN,OP) variable fct_out : std_ulogic_vector(N downto 0); variable a_ext,b_ext : std_ulogic_vector(N downto 0); variable minus_one_ext : std_ulogic_vector(N downto 0); variable not_a_ext,not_b_ext : std_ulogic_vector(N downto 0); variable carry_ext : std_ulogic_vector(1 downto 0); variable is_logical : integer range 0 to 1; variable msb : integer; begin -- zero extend inputs to include carry bit a_ext := '0' & A; b_ext := '0' & B; not_a_ext := '0' & not A; not_b_ext := '0' & not B; minus_one_ext := '0' & minus_one; is_logical := 0; carry_ext := '0' & CIN; -- ALU case OP is ----------------------- -- Logical Functions -- ----------------------- -- Output constants when "0100010" => is_logical := 1; fct_out := (OTHERS => '1'); when "0100000" => is_logical := 1; fct_out := (OTHERS => '0'); -- Pass throughs and complements when "0100011" => is_logical := 1; fct_out := a_ext; when "0101100" => is_logical := 1; fct_out := b_ext; when "0100001" => is_logical := 1; fct_out := not a_ext; when "0100100" => is_logical := 1; fct_out := not b_ext; -- AND functions when "1010101" => is_logical := 1; fct_out := a_ext and b_ext; when "1010111" => is_logical := 1; fct_out := (not a_ext) and b_ext; when "1011110" => is_logical := 1; fct_out := a_ext and (not b_ext); when "0010101" => is_logical := 1; fct_out := not (a_ext and b_ext); -- OR functions when "0011111" => is_logical := 1; fct_out := a_ext or b_ext; when "0011101" => is_logical := 1; fct_out := (not a_ext) or b_ext; when "0010111" => is_logical := 1; fct_out := a_ext or (not b_ext); when "1011111" => is_logical := 1; fct_out := not (a_ext or b_ext); -- XOR functions when "0101111" => is_logical := 1; fct_out := a_ext xor b_ext; when "1101111" => is_logical := 1; fct_out := not (a_ext xor b_ext); -------------------------- -- Arithmetic Functions -- -------------------------- -- Add/Subtract functions when "1001111" => fct_out := a_ext + b_ext + carry_ext; when "1000111" => fct_out := a_ext + not_b_ext + carry_ext; when "1001101" => fct_out := b_ext + not_a_ext + carry_ext; when "1000101" => fct_out := not_a_ext + not_b_ext + carry_ext; -- Negate functions when "1000001" => fct_out := not_a_ext + carry_ext; when "1000100" => fct_out := not_b_ext + carry_ext; -- Increment functions when "1000011" => fct_out := a_ext + carry_ext; when "1001100" => fct_out := b_ext + carry_ext; -- Decrement functions when "1001011" => fct_out := a_ext + minus_one_ext + carry_ext; when "1001110" => fct_out := b_ext + minus_one_ext + carry_ext; when "1001001" => fct_out := not_a_ext + minus_one_ext + carry_ext; when "1000110" => fct_out := not_b_ext + minus_one_ext + carry_ext; -- Unknown input when others => fct_out := (OTHERS => 'X'); end case; if (is_logical = 0) then COUT <= fct_out(N); else COUT <= 'X'; end if; -- Assign to signal for use outside process pre_D <= fct_out; -- Calculate overflow bit if (a_ext(N-1) = b_ext(N-1) and fct_out(N-1) = not a_ext(N-1)) then pre_OV <= '1'; else pre_OV <= '0'; end if; end process ARITHMETIC_Process; -- Assign the outputs D <= pre_D(N-1 downto 0); -- Assign flags pre_EQ <= '1' when vector_eq_zero(pre_D(N-1 downto 0)) else '0'; pre_LT <= (pre_OV xor pre_D(N-1)); GT <= not pre_EQ and not pre_LT; LT <= pre_LT; EQ <= pre_EQ; OV <= pre_OV; end rtl; ===== Testbench ===== -- ############################################################################ -- # Project : Leonardo CBT-Kernel # -- # # -- # Filename : test_alus.vhd # -- # # -- # Component : test_alus : Test Bench for various arithmetic components.# -- # # -- # Model : rtl # -- # # -- # Designer : S. Theoharis,N. Zervas # -- # Institute : VLSI Design Lab., University of Patras # -- # Date : 01.05.1999 # -- ############################################################################ library IEEE; use IEEE.std_logic_1164.all; use IEEE.std_logic_arith.all; entity test_alus IS END test_alus; ARCHITECTURE rtl OF test_alus IS COMPONENT addN generic(N: INTEGER := 4); port( A: in std_ulogic_vector(N-1 downto 0); B: in std_ulogic_vector(N-1 downto 0); D: out std_ulogic_vector(N-1 downto 0); CIN: in std_ulogic; COUT: out std_ulogic ); end COMPONENT; COMPONENT subN is generic(N: INTEGER := 4); port( A: in std_ulogic_vector(N-1 downto 0); B: in std_ulogic_vector(N-1 downto 0); D: out std_ulogic_vector(N-1 downto 0); CIN: in std_ulogic; COUT: out std_ulogic ); end COMPONENT; COMPONENT adsbN is generic(N: INTEGER := 4); port( A: in std_ulogic_vector(N-1 downto 0); B: in std_ulogic_vector(N-1 downto 0); D: out std_ulogic_vector(N-1 downto 0); CIN,SUB: in std_ulogic; COUT: out std_ulogic ); END COMPONENT; COMPONENT aluNf is generic(N: INTEGER := 4); port( A: in std_ulogic_vector(N-1 downto 0); B: in std_ulogic_vector(N-1 downto 0); OP: in std_ulogic_vector(6 downto 0); D: out std_ulogic_vector(N-1 downto 0); CIN: in std_ulogic; COUT,EQ,GT,LT,OV: out std_ulogic ); END COMPONENT; FOR ALL : addN USE ENTITY WORK.addN(rtl); FOR ALL : subN USE ENTITY WORK.subN(rtl); FOR ALL : adsbN USE ENTITY WORK.adsbN(rtl); FOR ALL : aluNf USE ENTITY WORK.aluNf(rtl); CONSTANT N : integer := 8; SIGNAL A,B,D1,D2,D3,D4 : std_ulogic_vector(N-1 downto 0); SIGNAL OP : std_ulogic_vector(6 downto 0); SIGNAL CIN,EQ,GT,LT,OV,SUB : std_ulogic; BEGIN Adder : addN GENERIC MAP ( N=>N ) PORT MAP ( A=>A, B=>B, CIN=>CIN, D=>D1, COUT=>OPEN ); Subtractor : subN GENERIC MAP ( N=>N ) PORT MAP ( A=>A, B=>B, CIN=>CIN, D=>D2, COUT=>OPEN ); Adder_Subtractor : adsbN GENERIC MAP ( N=>N ) PORT MAP ( A=>A, B=>B, CIN=>CIN, D=>D3, SUB=>SUB, COUT=>OPEN ); ALU : aluNf GENERIC MAP ( N=>N ) PORT MAP ( A=>A, B=>B, CIN=>CIN, OP=>OP, D=>D4, COUT=>OPEN, EQ=>EQ, GT=>GT, LT=>LT, OV=>OV ); SUB <= '0','1' AFTER 200 ns; CIN <= '0'; A <= "10101000", "01011001" AFTER 100 ns, "11011011" AFTER 200 ns, "01101001" AFTER 300 ns; B <= "00111000", "01001011" AFTER 100 ns, "01010001" AFTER 200 ns, "11001001" AFTER 300 ns; OP <= "1010101", "0011111" AFTER 100 ns, "0101111" AFTER 200 ns, "1000001" AFTER 300 ns; END rtl;