This project implements a 4-bit Arithmetic Logic Unit (ALU) using VHDL. The ALU performs both arithmetic (addition, subtraction, etc.) and logical (AND, OR, XOR, etc.) operations based on a control signal. The inputs and operation mode are controlled via switches, and the output is displayed using LEDs on an FPGA.
An Arithmetic Logic Unit (ALU) is a fundamental building block of any computing system. It performs arithmetic and logical operations based on the given control signals. The ALU is part of the CPU and executes calculations required for program execution.
The ALU takes two 4-bit inputs (A and B) and a 3-bit control signal (Sel) to perform the following operations:
Sel (Control Signal) | Operation | Expression |
---|---|---|
000 | Addition | A + B |
001 | Subtraction | A - B |
010 | Bitwise AND | A AND B |
011 | Bitwise OR | A OR B |
100 | Bitwise XOR | A XOR B |
101 | Bitwise NOT (A) | NOT A |
110 | Left Shift (A) | A « 1 |
111 | Right Shift (A) | A » 1 |
The control signals determine which operation will be executed. These are typically provided by a control unit in a processor.
----------------------------------------------------------------------------------
-- Company:
-- Engineer:
--
-- Create Date: 03/20/2025 07:11:43 PM
-- Design Name:
-- Module Name: ALU - Behavioral
-- Project Name:
-- Target Devices:
-- Tool Versions:
-- Description: 8-bit ALU supporting basic arithmetic and logical operations
--
-- Dependencies: None
--
-- Revision:
-- Revision 0.01 - File Created
-- Additional Comments:
--
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL; -- Always use numeric_std for arithmetic operations
entity ALU is
Port (
A : in STD_LOGIC_VECTOR(7 downto 0); -- 8-bit input A
B : in STD_LOGIC_VECTOR(7 downto 0); -- 8-bit input B
ALU_op : in STD_LOGIC_VECTOR(2 downto 0); -- 3-bit operation selector
Result : out STD_LOGIC_VECTOR(7 downto 0); -- 8-bit result
Zero : out STD_LOGIC -- Zero flag
);
end ALU;
architecture Behavioral of ALU is
begin
process(A, B, ALU_op)
variable temp_result : STD_LOGIC_VECTOR(7 downto 0);
begin
-- Default assignment
temp_result := (others => '0');
case ALU_op is
-- Addition (A + B)
when "000" =>
temp_result := std_logic_vector(unsigned(A) + unsigned(B));
-- Subtraction (A - B) [Using Signed to handle underflow correctly]
when "001" =>
temp_result := std_logic_vector(signed(A) - signed(B));
-- AND operation (A AND B)
when "010" =>
temp_result := A and B;
-- OR operation (A OR B)
when "011" =>
temp_result := A or B;
-- XOR operation (A XOR B)
when "100" =>
temp_result := A xor B;
-- NOT operation (NOT A)
when "101" =>
temp_result := not A;
-- Default case for invalid ALU operations
when others =>
temp_result := (others => '0'); -- Set result to zero for undefined operations
end case;
-- Assign result
Result <= temp_result;
-- Set Zero flag: if result is all zeros, Zero flag is set to '1'
if temp_result = "00000000" then
Zero <= '1';
else
Zero <= '0';
end if;
end process;
end Behavioral;
A testbench was written to verify ALU operations for different inputs and control signals.
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity ALU_TB is
end ALU_TB;
architecture Behavioral of ALU_TB is
component ALU
Port (
A : in STD_LOGIC_VECTOR(7 downto 0);
B : in STD_LOGIC_VECTOR(7 downto 0);
ALU_op : in STD_LOGIC_VECTOR(2 downto 0);
Result : out STD_LOGIC_VECTOR(7 downto 0);
Zero : out STD_LOGIC
);
end component;
signal A : STD_LOGIC_VECTOR(7 downto 0) := (others => '0');
signal B : STD_LOGIC_VECTOR(7 downto 0) := (others => '0');
signal ALU_op : STD_LOGIC_VECTOR(2 downto 0) := "000";
signal Result : STD_LOGIC_VECTOR(7 downto 0);
signal Zero : STD_LOGIC;
begin
uut: ALU port map (
A => A,
B => B,
ALU_op => ALU_op,
Result => Result,
Zero => Zero
);
process
begin
-- Addition (A = 5, B = 10)
A <= "00000101";
B <= "00001010";
ALU_op <= "000";
wait for 10 ns;
-- Subtraction (A = 15, B = 5)
A <= "00001111";
B <= "00000101";
ALU_op <= "001";
wait for 10 ns;
-- AND operation
A <= "11001100";
B <= "10101010";
ALU_op <= "010";
wait for 10 ns;
-- OR operation
A <= "11001100";
B <= "10101010";
ALU_op <= "011";
wait for 10 ns;
-- XOR operation
A <= "11001100";
B <= "10101010";
ALU_op <= "100";
wait for 10 ns;
-- NOT operation (B is don't care)
A <= "00001111";
B <= "--------"; -- B is not used in NOT operation
ALU_op <= "101";
wait for 10 ns;
-- Zero Flag Check (A = B = 0)
A <= "00000000";
B <= "00000000";
ALU_op <= "001"; -- Subtraction (0 - 0 = 0)
wait for 10 ns;
-- Extra wait before stopping simulation
wait for 10 ns;
wait;
end process;
end Behavioral;
The simulation results confirm that the ALU correctly performs arithmetic and logical operations as per the control signal.
Sel | Operation | A (Input 1) | B (Input 2) | Output Y | Carry |
---|---|---|---|---|---|
000 | Addition | 0011 (3) | 0101 (5) | 1000 (8) | 0 |
001 | Subtraction | 1010 (10) | 0011 (3) | 0111 (7) | 0 |
010 | AND | 1100 (12) | 1010 (10) | 1000 (8) | 0 |
011 | OR | 1100 (12) | 1010 (10) | 1110 (14) | 0 |
100 | XOR | 1100 (12) | 1010 (10) | 0110 (6) | 0 |
101 | NOT A | 1100 (12) | N/A | 0011 (3) | 0 |
110 | Left Shift | 1010 (10) | N/A | 0100 (4) | 1 |
111 | Right Shift | 1010 (10) | N/A | 0101 (5) | 0 |
set_property -dict {PACKAGE_PIN J15 IOSTANDARD LVCMOS33} [get_ports {A[0]}]
set_property -dict {PACKAGE_PIN L16 IOSTANDARD LVCMOS33} [get_ports {A[1]}]
set_property -dict {PACKAGE_PIN M13 IOSTANDARD LVCMOS33} [get_ports {A[2]}]
set_property -dict {PACKAGE_PIN R15 IOSTANDARD LVCMOS33} [get_ports {A[3]}]
set_property -dict {PACKAGE_PIN R17 IOSTANDARD LVCMOS33} [get_ports {A[4]}]
set_property -dict {PACKAGE_PIN T18 IOSTANDARD LVCMOS33} [get_ports {A[5]}]
set_property -dict {PACKAGE_PIN U18 IOSTANDARD LVCMOS33} [get_ports {A[6]}]
set_property -dict {PACKAGE_PIN R13 IOSTANDARD LVCMOS33} [get_ports {A[7]}]
set_property -dict {PACKAGE_PIN T8 IOSTANDARD LVCMOS33} [get_ports {B[0]}]
set_property -dict {PACKAGE_PIN U8 IOSTANDARD LVCMOS33} [get_ports {B[1]}]
set_property -dict {PACKAGE_PIN R16 IOSTANDARD LVCMOS33} [get_ports {B[2]}]
set_property -dict {PACKAGE_PIN T13 IOSTANDARD LVCMOS33} [get_ports {B[3]}]
set_property -dict {PACKAGE_PIN H6 IOSTANDARD LVCMOS33} [get_ports {B[4]}]
set_property -dict {PACKAGE_PIN U12 IOSTANDARD LVCMOS33} [get_ports {B[5]}]
set_property -dict {PACKAGE_PIN U11 IOSTANDARD LVCMOS33} [get_ports {B[6]}]
set_property -dict {PACKAGE_PIN V10 IOSTANDARD LVCMOS33} [get_ports {B[7]}]
set_property -dict {PACKAGE_PIN P17 IOSTANDARD LVCMOS33} [get_ports {ALU_op[0]}]
set_property -dict {PACKAGE_PIN M17 IOSTANDARD LVCMOS33} [get_ports {ALU_op[1]}]
set_property -dict {PACKAGE_PIN M18 IOSTANDARD LVCMOS33} [get_ports {ALU_op[2]}]
set_property -dict {PACKAGE_PIN H17 IOSTANDARD LVCMOS33} [get_ports {Result[0]}]
set_property -dict {PACKAGE_PIN K15 IOSTANDARD LVCMOS33} [get_ports {Result[1]}]
set_property -dict {PACKAGE_PIN J13 IOSTANDARD LVCMOS33} [get_ports {Result[2]}]
set_property -dict {PACKAGE_PIN N14 IOSTANDARD LVCMOS33} [get_ports {Result[3]}]
set_property -dict {PACKAGE_PIN R18 IOSTANDARD LVCMOS33} [get_ports {Result[4]}]
set_property -dict {PACKAGE_PIN V17 IOSTANDARD LVCMOS33} [get_ports {Result[5]}]
set_property -dict {PACKAGE_PIN U17 IOSTANDARD LVCMOS33} [get_ports {Result[6]}]
set_property -dict {PACKAGE_PIN U16 IOSTANDARD LVCMOS33} [get_ports {Result[7]}]
set_property -dict {PACKAGE_PIN V11 IOSTANDARD LVCMOS33} [get_ports Zero]
Below are the simulation waveform results and FPGA output images showcasing ALU operations.
Made by Swaroop Kumar Yadav