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


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;      -- Кнопка 1: Сброс
        show_ip_btn    : in  std_logic;      -- Кнопка 2: Показать IP-результат
        show_logic_btn : in  std_logic;      -- Кнопка 3: Показать логический результат
        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 result_valid : std_logic;
    signal bcd_0        : integer range 0 to 9;
    signal bcd_1        : integer range 0 to 9;
    signal bcd_2        : integer range 0 to 9;
    signal bcd_3        : integer range 0 to 9;
    signal bcd_4        : integer range 0 to 9;

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

begin

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

    -- Блок 2: Фильтр кнопки SHOW IP
    u_btn_show_ip : entity work.button_debounce
        port map (
            clk       => clk,
            btn_in    => show_ip_btn,
            btn_clean => show_ip_clean
        );

    -- Блок 3: Фильтр кнопки SHOW LOGIC
    u_btn_show_logic : entity work.button_debounce
        port map (
            clk       => clk,
            btn_in    => show_logic_btn,
            btn_clean => show_logic_clean
        );

    -- Блок 4: Контроллер умножения (IP-ядро + логический умножитель)
    u_mult_ctrl : entity work.mult_controller
        port map (
            clk            => clk,
            reset_btn      => reset_clean,
            show_ip_btn    => show_ip_clean,
            show_logic_btn => show_logic_clean,
            result_valid   => result_valid,
            bcd_0          => bcd_0,
            bcd_1          => bcd_1,
            bcd_2          => bcd_2,
            bcd_3          => bcd_3,
            bcd_4          => bcd_4
        );

    -- Блок 5: Преобразование 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
        );

    -- Блок 6: Вывод на дисплей (мультиплексирование)
    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;


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

entity button_debounce is
    port (
        clk       : in  std_logic;
        btn_in    : in  std_logic;
        btn_clean : out std_logic
    );
end button_debounce;

architecture rtl of button_debounce is
    signal counter    : integer range 0 to 1000000 := 0;  -- ~20 мс при 50 МГц
    signal btn_stable : std_logic := '0';
begin
    process(clk)
    begin
        if rising_edge(clk) then
            if btn_in = '0' then  -- Кнопка нажата (активный низкий уровень)
                if counter < 1000000 then
                    counter <= counter + 1;
                else
                    btn_stable <= '1';
                end if;
            else
                counter <= 0;
                btn_stable <= '0';
            end if;
        end if;
    end process;
    
    btn_clean <= btn_stable;
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;
        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

    -- Задаваемые числа (8 бит, максимум 255)
    constant NUM_A : unsigned(7 downto 0) := to_unsigned(12, 8);
    constant NUM_B : unsigned(7 downto 0) := to_unsigned(15, 8);

    -- Сигнал результата IP-ядра (std_logic_vector для port map)
    signal mult_ip_result : std_logic_vector(15 downto 0) := (others => '0');

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

    -- Выбранный результат
    signal selected_result : unsigned(15 downto 0) := (others => '0');

    -- Регистр результата
    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. IP-ядро умножителя (Арифметическое)
    -- ==========================================
    u_mult_ip : entity work.mult_ip
        port map (
            dataa  => std_logic_vector(NUM_A),
            datab  => std_logic_vector(NUM_B),
            result => mult_ip_result
        );

    -- ==========================================
    -- 2. Логический умножитель (Shift-and-Add)
    -- Реализация на логических элементах (LUT)
    -- ==========================================
    process(NUM_A, NUM_B)
        variable temp_result : unsigned(15 downto 0);
    begin
        temp_result := (others => '0');
        
        -- Алгоритм: для каждого бита B
        -- если бит = 1, добавляем A со сдвигом влево на i
        for i in 0 to 7 loop
            if NUM_B(i) = '1' then
                temp_result := temp_result + (NUM_A sll i);
            end if;
        end loop;
        
        mult_logic_result <= temp_result;
    end process;

    -- ==========================================
    -- 3. Выбор результата по кнопкам
    -- ==========================================
    process(clk)
    begin
        if rising_edge(clk) then
            if reset_btn = '1' then
                selected_result <= (others => '0');
            elsif show_ip_btn = '1' then
                selected_result <= unsigned(mult_ip_result);
            elsif show_logic_btn = '1' then
                selected_result <= mult_logic_result;
            end if;
        end if;
    end process;

    -- ==========================================
    -- 4. Регистр результата (фиксация по кнопке)
    -- ==========================================
    process(clk)
    begin
        if rising_edge(clk) then
            if reset_btn = '1' then
                result_reg <= (others => '0');
                enable_reg <= '0';
            elsif show_ip_btn = '1' or show_logic_btn = '1' then
                result_reg <= selected_result;
                enable_reg <= '1';
            end if;
        end if;
    end process;

    -- ==========================================
    -- 5. Преобразование в BCD (5 цифр)
    -- ==========================================
    process(clk)
    begin
        if rising_edge(clk) then
            if reset_btn = '1' then
                bcd_reg_0 <= 0; bcd_reg_1 <= 0; bcd_reg_2 <= 0;
                bcd_reg_3 <= 0; bcd_reg_4 <= 0;
            elsif show_ip_btn = '1' or show_logic_btn = '1' then
                bcd_reg_0 <= to_integer((selected_result / 10000) mod 10);
                bcd_reg_1 <= to_integer((selected_result / 1000) mod 10);
                bcd_reg_2 <= to_integer((selected_result / 100) mod 10);
                bcd_reg_3 <= to_integer((selected_result / 10) mod 10);
                bcd_reg_4 <= to_integer(selected_result 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;


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

entity bcd_converter is
    port (
        result_valid : in  std_logic;
        bcd_0        : in  integer range 0 to 9;
        bcd_1        : in  integer range 0 to 9;
        bcd_2        : in  integer range 0 to 9;
        bcd_3        : in  integer range 0 to 9;
        bcd_4        : in  integer range 0 to 9;
        char_0       : out std_logic_vector(7 downto 0);
        char_1       : out std_logic_vector(7 downto 0);
        char_2       : out std_logic_vector(7 downto 0);
        char_3       : out std_logic_vector(7 downto 0);
        char_4       : out std_logic_vector(7 downto 0)
    );
end bcd_converter;

architecture rtl of bcd_converter is

    type hex_array is array (0 to 9) of std_logic_vector(7 downto 0);
    
    constant hex_codes : hex_array := (
        "10000001",  -- 0
        "11110011",  -- 1
        "01001001",  -- 2
        "01100001",  -- 3
        "00110011",  -- 4
        "00100101",  -- 5
        "00000101",  -- 6
        "11110001",  -- 7
        "00000001",  -- 8
        "00100001"   -- 9
    );

begin

    process(result_valid, bcd_0, bcd_1, bcd_2, bcd_3, bcd_4)
    begin
        if result_valid = '0' then
            -- Нет результата: все сегменты выключены
            char_0 <= "11111111";
            char_1 <= "11111111";
            char_2 <= "11111111";
            char_3 <= "11111111";
            char_4 <= "11111111";
        else
            -- Преобразуем BCD-цифры в коды сегментов
            char_0 <= hex_codes(bcd_0);
            char_1 <= hex_codes(bcd_1);
            char_2 <= hex_codes(bcd_2);
            char_3 <= hex_codes(bcd_3);
            char_4 <= hex_codes(bcd_4);
        end if;
    end process;

end rtl;


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

entity display_output is
    port (
        clk       : in  std_logic;
        char_0    : in  std_logic_vector(7 downto 0);
        char_1    : in  std_logic_vector(7 downto 0);
        char_2    : in  std_logic_vector(7 downto 0);
        char_3    : in  std_logic_vector(7 downto 0);
        char_4    : in  std_logic_vector(7 downto 0);
        ind       : out std_logic_vector(4 downto 0);
        seg       : out std_logic_vector(7 downto 0)
    );
end display_output;

architecture rtl of display_output is
    signal sel_dig     : integer range 0 to 4 := 0;
    signal mux_counter : integer range 0 to 100000 := 0;
begin

    -- Счётчик разрядов (мультиплексирование ~500 Гц при 50 МГц)
    process(clk)
    begin
        if rising_edge(clk) then
            if mux_counter = 100000 - 1 then
                mux_counter <= 0;
                if sel_dig = 4 then 
                    sel_dig <= 0;
                else 
                    sel_dig <= sel_dig + 1;
                end if;
            else
                mux_counter <= mux_counter + 1;
            end if;
        end if;
    end process;

    -- Вывод на дисплей (выбор разряда)
    process(sel_dig, char_0, char_1, char_2, char_3, char_4)
    begin
        case sel_dig is
            when 0 =>
                ind <= "11110";  -- Активен 0-й разряд (левый)
                seg <= char_0;
            when 1 =>
                ind <= "11101";  -- Активен 1-й разряд
                seg <= char_1;
            when 2 =>
                ind <= "11011";  -- Активен 2-й разряд
                seg <= char_2;
            when 3 =>
                ind <= "10111";  -- Активен 3-й разряд
                seg <= char_3;
            when 4 =>
                ind <= "01111";  -- Активен 4-й разряд (правый)
                seg <= char_4;
            when others =>
                ind <= "11111";
                seg <= "11111111";
        end case;
    end process;

end rtl;