--=====================================================
-- Проект 25. Арифметико-логическое устройство
-- Восемь операций над двумя числами с флагами
-- нуля, переноса и знака.
--=====================================================
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity alu is
    generic (
        WIDTH : integer := 8
    );
    port (
        a, b   : in  std_logic_vector(WIDTH-1 downto 0);
        op     : in  std_logic_vector(2 downto 0);      -- код операции
        result : out std_logic_vector(WIDTH-1 downto 0);
        zero   : out std_logic;
        carry  : out std_logic;
        neg    : out std_logic
    );
end entity alu;

architecture rtl of alu is
    signal res_ext : unsigned(WIDTH downto 0);          -- на разряд шире для переноса
    signal res     : unsigned(WIDTH-1 downto 0);
begin
    process (a, b, op)
    begin
        case op is
            when "000" => res_ext <= ('0' & unsigned(a)) + ('0' & unsigned(b));  -- сложение
            when "001" => res_ext <= ('0' & unsigned(a)) - ('0' & unsigned(b));  -- вычитание
            when "010" => res_ext <= '0' & (unsigned(a) and unsigned(b));
            when "011" => res_ext <= '0' & (unsigned(a) or  unsigned(b));
            when "100" => res_ext <= '0' & (unsigned(a) xor unsigned(b));
            when "101" => res_ext <= '0' & (not unsigned(a));
            when "110" => res_ext <= '0' & (unsigned(a(WIDTH-2 downto 0)) & '0'); -- сдвиг влево
            when others=> res_ext <= '0' & ('0' & unsigned(a(WIDTH-1 downto 1))); -- сдвиг вправо
        end case;
    end process;

    res    <= res_ext(WIDTH-1 downto 0);
    result <= std_logic_vector(res);
    carry  <= res_ext(WIDTH);
    zero   <= '1' when res = 0 else '0';
    neg    <= res(WIDTH-1);
end architecture rtl;
