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


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 ip_valid    : std_logic;
    signal logic_valid : std_logic;
    
    signal ip_bcd_0    : integer range 0 to 9;
    signal ip_bcd_1    : integer range 0 to 9;
    signal ip_bcd_2    : integer range 0 to 9;
    signal ip_bcd_3    : integer range 0 to 9;
    signal ip_bcd_4    : integer range 0 to 9;
    
    signal logic_bcd_0 : integer range 0 to 9;
    signal logic_bcd_1 : integer range 0 to 9;
    signal logic_bcd_2 : integer range 0 to 9;
    signal logic_bcd_3 : integer range 0 to 9;
    signal logic_bcd_4 : integer range 0 to 9;
    
    signal final_valid : std_logic;
    signal final_bcd_0 : integer range 0 to 9;
    signal final_bcd_1 : integer range 0 to 9;
    signal final_bcd_2 : integer range 0 to 9;
    signal final_bcd_3 : integer range 0 to 9;
    signal final_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: IP умножитель (НЕЗАВИСИМАЯ СХЕМА)
    u_ip_mult : entity work.ip_multiplier
        port map (
            clk          => clk,
            reset_btn    => reset_btn,
            show_btn     => show_ip_btn,
            result_valid => ip_valid,
            bcd_0        => ip_bcd_0,
            bcd_1        => ip_bcd_1,
            bcd_2        => ip_bcd_2,
            bcd_3        => ip_bcd_3,
            bcd_4        => ip_bcd_4
        );

    -- Модуль 2: Логический умножитель (НЕЗАВИСИМАЯ СХЕМА)
    u_logic_mult : entity work.logic_multiplier
        port map (
            clk          => clk,
            reset_btn    => reset_btn,
            show_btn     => show_logic_btn,
            result_valid => logic_valid,
            bcd_0        => logic_bcd_0,
            bcd_1        => logic_bcd_1,
            bcd_2        => logic_bcd_2,
            bcd_3        => logic_bcd_3,
            bcd_4        => logic_bcd_4
        );

    -- Выбор результата (какой модуль активен)
    final_valid <= ip_valid or logic_valid;
    
    process(ip_valid, logic_valid, ip_bcd_0, ip_bcd_1, ip_bcd_2, ip_bcd_3, ip_bcd_4,
            logic_bcd_0, logic_bcd_1, logic_bcd_2, logic_bcd_3, logic_bcd_4)
    begin
        if ip_valid = '1' then
            final_bcd_0 <= ip_bcd_0;
            final_bcd_1 <= ip_bcd_1;
            final_bcd_2 <= ip_bcd_2;
            final_bcd_3 <= ip_bcd_3;
            final_bcd_4 <= ip_bcd_4;
        else
            final_bcd_0 <= logic_bcd_0;
            final_bcd_1 <= logic_bcd_1;
            final_bcd_2 <= logic_bcd_2;
            final_bcd_3 <= logic_bcd_3;
            final_bcd_4 <= logic_bcd_4;
        end if;
    end process;

    -- BCD конвертер
    u_bcd_conv : entity work.bcd_converter
        port map (
            result_valid => final_valid,
            bcd_0        => final_bcd_0,
            bcd_1        => final_bcd_1,
            bcd_2        => final_bcd_2,
            bcd_3        => final_bcd_3,
            bcd_4        => final_bcd_4,
            char_0       => char_0,
            char_1       => char_1,
            char_2       => char_2,
            char_3       => char_3,
            char_4       => char_4
        );

    -- Дисплей
    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 ip_multiplier is
    port (
        clk          : in  std_logic;
        reset_btn    : in  std_logic;
        show_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 ip_multiplier;

architecture rtl of ip_multiplier 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_clean : std_logic;
    
    -- Детектор фронта кнопки
    signal show_prev : std_logic := '0';
    
    -- Сигнал Slow (1 такт после нажатия)
    signal slow : std_logic := '0';
    
    -- Детектор спада Slow
    signal slow_prev : std_logic := '0';
    signal slow_fall : std_logic;

    -- Мультиплексоры
    signal mux_a : std_logic_vector(7 downto 0);
    signal mux_b : std_logic_vector(7 downto 0);

    -- IP-ядро умножителя
    signal mult_result : std_logic_vector(15 downto 0);

    -- D-триггер (регистр 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 counter : integer range 0 to 1000000 := 0;
    begin
        if rising_edge(clk) then
            if reset_btn = '0' then
                if counter < 1000000 then
                    counter := counter + 1;
                else
                    show_clean <= '1';
                end if;
            else
                counter := 0;
                show_clean <= '0';
            end if;
        end if;
    end process;

    -- ==========================================
    -- 2. Детектор фронта кнопки → Slow (1 такт)
    -- ==========================================
    process(clk)
    begin
        if rising_edge(clk) then
            if reset_btn = '1' then
                show_prev <= '0';
                slow <= '0';
            else
                show_prev <= show_clean;
                if show_clean = '1' and show_prev = '0' then
                    slow <= '1';
                else
                    slow <= '0';
                end if;
            end if;
        end if;
    end process;

    -- ==========================================
    -- 3. Детектор спада Slow
    -- ==========================================
    process(clk)
    begin
        if rising_edge(clk) then
            if reset_btn = '1' then
                slow_prev <= '0';
            else
                slow_prev <= slow;
            end if;
        end if;
    end process;
    
    slow_fall <= slow_prev and not slow;

    -- ==========================================
    -- 4. Мультиплексоры (A и B)
    -- ==========================================
    -- MUX A: если Slow=1 → A, иначе → 0
    mux_a <= std_logic_vector(NUM_A) when slow = '1' else (others => '0');
    
    -- MUX B: если Slow=1 → B, иначе → 0
    mux_b <= std_logic_vector(NUM_B) when slow = '1' else (others => '0');

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

    -- ==========================================
    -- 6. D-триггер (захват по спаду Slow)
    -- ==========================================
    process(clk)
    begin
        if rising_edge(clk) then
            if reset_btn = '1' then
                result_reg <= (others => '0');
                enable_reg <= '0';
            elsif slow_fall = '1' then
                -- По спаду Slow сохраняем результат
                result_reg <= unsigned(mult_result);
                enable_reg <= '1';
            end if;
        end if;
    end process;

    -- ==========================================
    -- 7. Преобразование в BCD
    -- ==========================================
    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 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;

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

entity logic_multiplier is
    port (
        clk          : in  std_logic;
        reset_btn    : in  std_logic;
        show_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 logic_multiplier;

architecture rtl of logic_multiplier 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_clean : std_logic;
    
    -- Детектор фронта кнопки
    signal show_prev : std_logic := '0';
    
    -- Сигнал Slow (1 такт после нажатия)
    signal slow : std_logic := '0';
    
    -- Детектор спада Slow
    signal slow_prev : std_logic := '0';
    signal slow_fall : std_logic;

    -- Мультиплексоры
    signal mux_a : unsigned(7 downto 0);
    signal mux_b : unsigned(7 downto 0);

    -- Логический умножитель (Shift-and-Add)
    signal mult_result : unsigned(15 downto 0);

    -- D-триггер (регистр 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 counter : integer range 0 to 1000000 := 0;
    begin
        if rising_edge(clk) then
            if reset_btn = '0' then
                if counter < 1000000 then
                    counter := counter + 1;
                else
                    show_clean <= '1';
                end if;
            else
                counter := 0;
                show_clean <= '0';
            end if;
        end if;
    end process;

    -- ==========================================
    -- 2. Детектор фронта кнопки → Slow (1 такт)
    -- ==========================================
    process(clk)
    begin
        if rising_edge(clk) then
            if reset_btn = '1' then
                show_prev <= '0';
                slow <= '0';
            else
                show_prev <= show_clean;
                if show_clean = '1' and show_prev = '0' then
                    slow <= '1';
                else
                    slow <= '0';
                end if;
            end if;
        end if;
    end process;

    -- ==========================================
    -- 3. Детектор спада Slow
    -- ==========================================
    process(clk)
    begin
        if rising_edge(clk) then
            if reset_btn = '1' then
                slow_prev <= '0';
            else
                slow_prev <= slow;
            end if;
        end if;
    end process;
    
    slow_fall <= slow_prev and not slow;

    -- ==========================================
    -- 4. Мультиплексоры (A и B)
    -- ==========================================
    mux_a <= NUM_A when slow = '1' else (others => '0');
    mux_b <= NUM_B when slow = '1' else (others => '0');

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

    -- ==========================================
    -- 6. D-триггер (захват по спаду Slow)
    -- ==========================================
    process(clk)
    begin
        if rising_edge(clk) then
            if reset_btn = '1' then
                result_reg <= (others => '0');
                enable_reg <= '0';
            elsif slow_fall = '1' then
                result_reg <= mult_result;
                enable_reg <= '1';
            end if;
        end if;
    end process;

    -- ==========================================
    -- 7. Преобразование в BCD
    -- ==========================================
    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 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;