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


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_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 show_clean   : std_logic;
    signal reset_clean  : std_logic;

    -- Сигналы от mult_controller
    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: Фильтр кнопки SHOW
    u_btn_show : entity work.button_debounce
        port map (
            clk       => clk,
            btn_in    => show_btn,
            btn_clean => show_clean
        );

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

    -- Блок 3: Контроллер умножения (IP-ядро + регистр)
    u_mult_ctrl : entity work.mult_controller
        port map (
            clk         => clk,
            show_btn    => show_clean,
            reset_btn   => reset_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
        );

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

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

    -- Сигналы IP-ядра
    signal mult_result : unsigned(15 downto 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

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

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

    -- Преобразование в BCD (5 цифр для числа до 65535)
    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_btn = '1' then
                bcd_reg_0 <= to_integer((mult_result / 10000) mod 10);
                bcd_reg_1 <= to_integer((mult_result / 1000) mod 10);
                bcd_reg_2 <= to_integer((mult_result / 100) mod 10);
                bcd_reg_3 <= to_integer((mult_result / 10) mod 10);
                bcd_reg_4 <= to_integer(mult_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 Гц)
    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";
                seg <= char_0;
            when 1 =>
                ind <= "11101";
                seg <= char_1;
            when 2 =>
                ind <= "11011";
                seg <= char_2;
            when 3 =>
                ind <= "10111";
                seg <= char_3;
            when 4 =>
                ind <= "01111";
                seg <= char_4;
            when others =>
                ind <= "11111";
                seg <= "11111111";
        end case;
    end process;

end rtl;