Загрузка данных


library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity mult_controller is
    port (
        clk            : in  std_logic;
        reset_btn      : in  std_logic;
        show_ip_btn    : in  std_logic;
        show_logic_btn : in  std_logic;
        result_valid   : out std_logic;
        bcd_0          : out integer range 0 to 9;
        bcd_1          : out integer range 0 to 9;
        bcd_2          : out integer range 0 to 9;
        bcd_3          : out integer range 0 to 9;
        bcd_4          : out integer range 0 to 9
    );
end mult_controller;

architecture rtl of mult_controller is

    constant NUM_A : unsigned(7 downto 0) := to_unsigned(12, 8);
    constant NUM_B : unsigned(7 downto 0) := to_unsigned(15, 8);

    -- Фильтр кнопок
    signal show_ip_clean    : std_logic;
    signal show_logic_clean : std_logic;
    signal reset_clean      : std_logic;

    -- Детекторы фронтов кнопок
    signal show_ip_prev    : std_logic := '0';
    signal show_logic_prev : std_logic := '0';
    
    -- Сигналы Slow (импульс 1 такт по фронту кнопки)
    signal slow_ip    : std_logic := '0';
    signal slow_logic : std_logic := '0';

    -- Детекторы спадов Slow (для захвата результата)
    signal slow_ip_prev    : std_logic := '0';
    signal slow_logic_prev : std_logic := '0';
    signal slow_ip_fall    : std_logic;
    signal slow_logic_fall : std_logic;

    -- Выходы мультиплексоров для IP-ядра
    signal mux_a_ip : std_logic_vector(7 downto 0);
    signal mux_b_ip : std_logic_vector(7 downto 0);

    -- Выходы мультиплексоров для логического умножителя
    signal mux_a_logic : unsigned(7 downto 0);
    signal mux_b_logic : unsigned(7 downto 0);

    -- Результат IP-ядра
    signal mult_ip_result : std_logic_vector(15 downto 0) := (others => '0');

    -- Результат логического умножителя
    signal mult_logic_result : unsigned(15 downto 0) := (others => '0');

    -- Регистр результата C
    signal result_reg : unsigned(15 downto 0) := (others => '0');
    signal enable_reg : std_logic := '0';

    -- BCD цифры
    signal bcd_reg_0 : integer range 0 to 9 := 0;
    signal bcd_reg_1 : integer range 0 to 9 := 0;
    signal bcd_reg_2 : integer range 0 to 9 := 0;
    signal bcd_reg_3 : integer range 0 to 9 := 0;
    signal bcd_reg_4 : integer range 0 to 9 := 0;

begin

    -- ==========================================
    -- 1. Фильтр кнопок
    -- ==========================================
    process(clk)
        variable ip_counter    : integer range 0 to 1000000 := 0;
        variable logic_counter : integer range 0 to 1000000 := 0;
    begin
        if rising_edge(clk) then
            -- Фильтр IP кнопки
            if reset_btn = '0' then
                if ip_counter < 1000000 then
                    ip_counter := ip_counter + 1;
                    show_ip_clean <= '0';
                else
                    show_ip_clean <= '1';
                end if;
            else
                ip_counter := 0;
                show_ip_clean <= '0';
            end if;
            
            -- Фильтр Logic кнопки
            if reset_btn = '0' then
                if logic_counter < 1000000 then
                    logic_counter := logic_counter + 1;
                    show_logic_clean <= '0';
                else
                    show_logic_clean <= '1';
                end if;
            else
                logic_counter := 0;
                show_logic_clean <= '0';
            end if;
            
            -- Сброс
            if reset_btn = '1' then
                reset_clean <= '1';
            else
                reset_clean <= '0';
            end if;
        end if;
    end process;

    -- ==========================================
    -- 2. Детектор фронта кнопки IP → Slow (1 такт)
    -- ==========================================
    process(clk)
    begin
        if rising_edge(clk) then
            if reset_clean = '1' then
                show_ip_prev <= '0';
                slow_ip <= '0';
            else
                show_ip_prev <= show_ip_clean;
                -- Slow = 1 на 1 такт при переходе кнопки 0→1
                if show_ip_clean = '1' and show_ip_prev = '0' then
                    slow_ip <= '1';
                else
                    slow_ip <= '0';
                end if;
            end if;
        end if;
    end process;

    -- ==========================================
    -- 3. Детектор фронта кнопки Logic → Slow (1 такт)
    -- ==========================================
    process(clk)
    begin
        if rising_edge(clk) then
            if reset_clean = '1' then
                show_logic_prev <= '0';
                slow_logic <= '0';
            else
                show_logic_prev <= show_logic_clean;
                if show_logic_clean = '1' and show_logic_prev = '0' then
                    slow_logic <= '1';
                else
                    slow_logic <= '0';
                end if;
            end if;
        end if;
    end process;

    -- ==========================================
    -- 4. Детектор спадов Slow (для захвата результата)
    -- ==========================================
    process(clk)
    begin
        if rising_edge(clk) then
            if reset_clean = '1' then
                slow_ip_prev <= '0';
                slow_logic_prev <= '0';
            else
                slow_ip_prev <= slow_ip;
                slow_logic_prev <= slow_logic;
            end if;
        end if;
    end process;
    
    -- Спад = переход 1→0
    slow_ip_fall <= slow_ip_prev and not slow_ip;
    slow_logic_fall <= slow_logic_prev and not slow_logic;

    -- ==========================================
    -- 5. Мультиплексоры для IP-ядра (переключаются по Slow)
    -- ==========================================
    -- ОДНОВРЕМЕННО: Slow=1 → MUX пропускают A и B
    mux_a_ip <= std_logic_vector(NUM_A) when slow_ip = '1' else (others => '0');
    mux_b_ip <= std_logic_vector(NUM_B) when slow_ip = '1' else (others => '0');

    -- ==========================================
    -- 6. IP-ядро умножителя
    -- ==========================================
    u_mult_ip : entity work.mult_ip
        port map (
            dataa  => mux_a_ip,
            datab  => mux_b_ip,
            result => mult_ip_result
        );

    -- ==========================================
    -- 7. Мультиплексоры для логического умножителя (переключаются по Slow)
    -- ==========================================
    mux_a_logic <= NUM_A when slow_logic = '1' else (others => '0');
    mux_b_logic <= NUM_B when slow_logic = '1' else (others => '0');

    -- ==========================================
    -- 8. Логический умножитель (Shift-and-Add)
    -- ==========================================
    process(mux_a_logic, mux_b_logic)
        variable temp_result : unsigned(15 downto 0);
    begin
        temp_result := (others => '0');
        
        for i in 0 to 7 loop
            if mux_b_logic(i) = '1' then
                temp_result := temp_result + (mux_a_logic sll i);
            end if;
        end loop;
        
        mult_logic_result <= temp_result;
    end process;

    -- ==========================================
    -- 9. Регистр C (захват результата ПО СПАДУ Slow)
    -- ==========================================
    process(clk)
    begin
        if rising_edge(clk) then
            if reset_clean = '1' then
                result_reg <= (others => '0');
                enable_reg <= '0';
            elsif slow_ip_fall = '1' then
                -- ПО СПАДУ Slow_IP сохраняем результат
                result_reg <= unsigned(mult_ip_result);
                enable_reg <= '1';
            elsif slow_logic_fall = '1' then
                -- ПО СПАДУ Slow_Logic сохраняем результат
                result_reg <= mult_logic_result;
                enable_reg <= '1';
            end if;
        end if;
    end process;

    -- ==========================================
    -- 10. Преобразование в BCD
    -- ==========================================
    process(clk)
    begin
        if rising_edge(clk) then
            if reset_clean = '1' then
                bcd_reg_0 <= 0; bcd_reg_1 <= 0; bcd_reg_2 <= 0;
                bcd_reg_3 <= 0; bcd_reg_4 <= 0;
            elsif enable_reg = '1' then
                bcd_reg_0 <= to_integer((result_reg / 10000) mod 10);
                bcd_reg_1 <= to_integer((result_reg / 1000) mod 10);
                bcd_reg_2 <= to_integer((result_reg / 100) mod 10);
                bcd_reg_3 <= to_integer((result_reg / 10) mod 10);
                bcd_reg_4 <= to_integer(result_reg mod 10);
            end if;
        end if;
    end process;

    result_valid <= enable_reg;
    bcd_0 <= bcd_reg_0;
    bcd_1 <= bcd_reg_1;
    bcd_2 <= bcd_reg_2;
    bcd_3 <= bcd_reg_3;
    bcd_4 <= bcd_reg_4;

end rtl;