--=====================================================
-- Проект 24. Последовательный умножитель
-- Умножение сдвигами и сложениями: экономит ресурсы
-- там, где скорость не критична.
--=====================================================
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity shift_multiplier is
    generic (
        WIDTH : integer := 8
    );
    port (
        clk    : in  std_logic;
        rst    : in  std_logic;
        start  : in  std_logic;
        a, b   : in  std_logic_vector(WIDTH-1 downto 0);
        result : out std_logic_vector(2*WIDTH-1 downto 0);
        done   : out std_logic
    );
end entity shift_multiplier;

architecture rtl of shift_multiplier is
    type state_t is (IDLE, CALC);
    signal state : state_t := IDLE;
    signal acc   : unsigned(2*WIDTH-1 downto 0) := (others => '0');
    signal mcand : unsigned(2*WIDTH-1 downto 0) := (others => '0');
    signal mplier: unsigned(WIDTH-1 downto 0) := (others => '0');
    signal cnt   : integer range 0 to WIDTH := 0;
begin
    process (clk, rst)
    begin
        if rst = '1' then
            state <= IDLE;
            done  <= '0';
        elsif rising_edge(clk) then
            done <= '0';
            case state is
                when IDLE =>
                    if start = '1' then
                        acc    <= (others => '0');
                        mcand  <= resize(unsigned(a), 2*WIDTH);
                        mplier <= unsigned(b);
                        cnt    <= 0;
                        state  <= CALC;
                    end if;

                when CALC =>
                    -- если младший бит множителя единица — прибавляем
                    if mplier(0) = '1' then
                        acc <= acc + mcand;
                    end if;
                    mcand  <= mcand(2*WIDTH-2 downto 0) & '0';      -- сдвиг влево
                    mplier <= '0' & mplier(WIDTH-1 downto 1);       -- сдвиг вправо

                    if cnt = WIDTH - 1 then
                        state <= IDLE;
                        done  <= '1';
                    else
                        cnt <= cnt + 1;
                    end if;
            end case;
        end if;
    end process;

    result <= std_logic_vector(acc);
end architecture rtl;
