====== 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;