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


library ieee;
use ieee.std_logic_1164.all;

entity control_pulse_gen is
    port (
        clk       : in  std_logic;
        btn_ip    : in  std_logic;  -- очищенный от дребезга
        btn_logic : in  std_logic;  -- очищенный от дребезга
        slow      : out std_logic;  -- импульс 1 такт
        use_ip    : out std_logic   -- '1' = IP, '0' = логический
    );
end control_pulse_gen;

architecture rtl of control_pulse_gen is
    -- Регистры для детектора фронта
    signal btn_ip_d1, btn_ip_d2 : std_logic := '0';
    signal btn_logic_d1, btn_logic_d2 : std_logic := '0';
    
    -- Сигналы фронтов
    signal slow_ip, slow_logic : std_logic;
begin

    -- Синхронизация кнопок и детектор восходящего фронта (0 -> 1)
    process(clk)
    begin
        if rising_edge(clk) then
            btn_ip_d1 <= btn_ip;
            btn_ip_d2 <= btn_ip_d1;
            
            btn_logic_d1 <= btn_logic;
            btn_logic_d2 <= btn_logic_d1;
        end if;
    end process;

    -- Формирование импульсов нажатия (длительностью 1 такт)
    slow_ip <= btn_ip_d1 and not btn_ip_d2;
    slow_logic <= btn_logic_d1 and not btn_logic_d2;

    -- Логика формирования slow и use_ip
    process(clk)
    begin
        if rising_edge(clk) then
            -- Если нажаты обе кнопки одновременно — игнорируем
            if slow_ip = '1' and slow_logic = '1' then
                slow <= '0';
                use_ip <= '0';
            elsif slow_ip = '1' then
                slow <= '1';
                use_ip <= '1';
            elsif slow_logic = '1' then
                slow <= '1';
                use_ip <= '0';
            else
                slow <= '0';
                -- use_ip сохраняет предыдущее значение, но это не важно, так как slow='0'
            end if;
        end if;
    end process;

end rtl;


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;
        slow           : in  std_logic;
        use_ip         : 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 mux_a_out : unsigned(7 downto 0);
    signal mux_b_out : unsigned(7 downto 0);

    -- Регистры на входах умножителей
    signal reg_a : unsigned(7 downto 0);
    signal reg_b : unsigned(7 downto 0);

    -- Выходы умножителей
    signal mult_ip_result : std_logic_vector(15 downto 0);
    signal mult_logic_result : unsigned(15 downto 0);
    signal selected_result : unsigned(15 downto 0);

    -- Выходной регистр и сигнал валидности
    signal reg_c : unsigned(15 downto 0);
    signal res_valid_reg : std_logic;

    -- Задержка сигнала slow для корректного захвата результата
    signal slow_d1 : std_logic;

    -- BCD регистры
    signal bcd_reg_0, bcd_reg_1, bcd_reg_2, bcd_reg_3, bcd_reg_4 : integer range 0 to 9;

begin

    -- 1. Мультиплексоры (комбинационные)
    mux_a_out <= NUM_A when slow = '1' else (others => '0');
    mux_b_out <= NUM_B when slow = '1' else (others => '0');

    -- 2. Регистры после мультиплексоров (входы умножителей)
    process(clk)
    begin
        if rising_edge(clk) then
            if reset_btn = '1' then
                reg_a <= (others => '0');
                reg_b <= (others => '0');
            else
                reg_a <= mux_a_out;
                reg_b <= mux_b_out;
            end if;
        end if;
    end process;

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

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

    -- 5. Выбор результата (IP или логический)
    selected_result <= unsigned(mult_ip_result) when use_ip = '1' else mult_logic_result;

    -- 6. Задержка slow на 1 такт (чтобы регистры reg_a/reg_b успели защёлкнуть операнды)
    process(clk)
    begin
        if rising_edge(clk) then
            slow_d1 <= slow;
        end if;
    end process;

    -- 7. Выходной регистр (reg_c) и result_valid
    process(clk)
    begin
        if rising_edge(clk) then
            if reset_btn = '1' then
                reg_c <= (others => '0');
                res_valid_reg <= '0';
            elsif slow_d1 = '1' then
                -- Такт N+1: reg_a и reg_b уже равны A и B, умножители посчитали результат
                reg_c <= selected_result;
                res_valid_reg <= '1';
            else
                -- Такт N+2: обнуляем регистр и сбрасываем valid (Вариант B)
                reg_c <= (others => '0');
                res_valid_reg <= '0';
            end if;
        end if;
    end process;

    -- 8. Преобразование в BCD (синхронно с result_valid)
    process(clk)
    begin
        if rising_edge(clk) then
            if reset_btn = '1' or slow_d1 = '0' then
                bcd_reg_0 <= 0; bcd_reg_1 <= 0; bcd_reg_2 <= 0;
                bcd_reg_3 <= 0; bcd_reg_4 <= 0;
            else
                bcd_reg_0 <= to_integer((reg_c / 10000) mod 10);
                bcd_reg_1 <= to_integer((reg_c / 1000) mod 10);
                bcd_reg_2 <= to_integer((reg_c / 100) mod 10);
                bcd_reg_3 <= to_integer((reg_c / 10) mod 10);
                bcd_reg_4 <= to_integer(reg_c mod 10);
            end if;
        end if;
    end process;

    -- Выходы модуля
    result_valid <= res_valid_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;


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

entity sem_mult_top is
    port (
        clk            : in  std_logic;
        reset_btn      : in  std_logic;
        show_ip_btn    : in  std_logic;
        show_logic_btn : in  std_logic;
        ind            : out std_logic_vector(4 downto 0);
        seg            : out std_logic_vector(7 downto 0)
    );
end sem_mult_top;

architecture rtl of sem_mult_top is

    -- Сигналы после фильтрации кнопок
    signal reset_clean      : std_logic;
    signal show_ip_clean    : std_logic;
    signal show_logic_clean : std_logic;

    -- Сигналы от генератора импульсов
    signal slow             : std_logic;
    signal use_ip           : std_logic;

    -- Сигналы между модулями
    signal result_valid     : std_logic;
    signal bcd_0, bcd_1, bcd_2, bcd_3, bcd_4 : integer range 0 to 9;

    signal char_0, char_1, char_2, char_3, char_4 : std_logic_vector(7 downto 0);

begin

    -- Блок 1-3: Фильтры кнопок
    u_btn_reset : entity work.button_debounce
        port map (clk => clk, btn_in => reset_btn, btn_clean => reset_clean);

    u_btn_show_ip : entity work.button_debounce
        port map (clk => clk, btn_in => show_ip_btn, btn_clean => show_ip_clean);

    u_btn_show_logic : entity work.button_debounce
        port map (clk => clk, btn_in => show_logic_btn, btn_clean => show_logic_clean);

    -- Блок 4: Генератор управляющего импульса slow
    u_pulse_gen : entity work.control_pulse_gen
        port map (
            clk       => clk,
            btn_ip    => show_ip_clean,
            btn_logic => show_logic_clean,
            slow      => slow,
            use_ip    => use_ip
        );

    -- Блок 5: Контроллер умножения
    u_mult_ctrl : entity work.mult_controller
        port map (
            clk            => clk,
            reset_btn      => reset_clean,
            slow           => slow,
            use_ip         => use_ip,
            result_valid   => result_valid,
            bcd_0          => bcd_0,
            bcd_1          => bcd_1,
            bcd_2          => bcd_2,
            bcd_3          => bcd_3,
            bcd_4          => bcd_4
        );

    -- Блок 6: Преобразование BCD в коды сегментов
    u_bcd_conv : entity work.bcd_converter
        port map (
            result_valid => result_valid,
            bcd_0        => bcd_0,
            bcd_1        => bcd_1,
            bcd_2        => bcd_2,
            bcd_3        => bcd_3,
            bcd_4        => bcd_4,
            char_0       => char_0,
            char_1       => char_1,
            char_2       => char_2,
            char_3       => char_3,
            char_4       => char_4
        );

    -- Блок 7: Вывод на дисплей (мультиплексирование)
    u_display : entity work.display_output
        port map (
            clk       => clk,
            char_0    => char_0,
            char_1    => char_1,
            char_2    => char_2,
            char_3    => char_3,
            char_4    => char_4,
            ind       => ind,
            seg       => seg
        );

end rtl;