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


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

entity calculator is
port (
    clk      : in std_logic;
    reset    : in std_logic;
    key      : in std_logic_vector(1 downto 0);
    result   : out integer;
    -- Сигналы для Signal Tap
    s_a      : out std_logic_vector(7 downto 0);
    s_b      : out std_logic_vector(7 downto 0);
    s_mux_a  : out std_logic_vector(7 downto 0);
    s_mux_b  : out std_logic_vector(7 downto 0);
    s_result : out integer;
    s_state  : out std_logic_vector(1 downto 0)
);
end calculator;

architecture rtl of calculator is
    
    -- Константы умножения
    constant A_VAL : integer := 5;
    constant B_VAL : integer := 7;
    
    -- Компоненты
    component mult_5 is
    port (
        dataa  : in std_logic_vector(7 downto 0);
        datab  : in std_logic_vector(7 downto 0);
        result : out std_logic_vector(15 downto 0)
    );
    end component;
    
    component logic is
    port (
        a : in integer;
        b : in integer;
        result : out integer
    );
    end component;
    
    -- Сигналы
    signal mux_a    : std_logic_vector(7 downto 0);
    signal mux_b    : std_logic_vector(7 downto 0);
    signal reg_a    : std_logic_vector(7 downto 0) := (others => '0');
    signal reg_b    : std_logic_vector(7 downto 0) := (others => '0');
    
    signal dsp_result_vec : std_logic_vector(15 downto 0);
    signal dsp_result_int : integer;
    signal logic_result   : integer;
    
    signal capture_en : std_logic := '0';
    signal mode       : std_logic := '0';
    
    -- Таймер 1 секунда
    signal counter    : integer range 0 to 49999999 := 0;
    constant ONE_SEC  : integer := 50000000;
    
    -- Состояния автомата
    type state_type is (IDLE, CAPTURE, MULTIPLY, HOLD);
    signal state : state_type := IDLE;
    
begin
    
    -- Мультиплексоры
    mux_a <= std_logic_vector(to_unsigned(A_VAL, 8)) when capture_en = '1' else (others => '0');
    mux_b <= std_logic_vector(to_unsigned(B_VAL, 8)) when capture_en = '1' else (others => '0');
    
    -- Регистры захвата
    process(clk, reset)
    begin
        if reset = '1' then
            reg_a <= (others => '0');
            reg_b <= (others => '0');
        elsif rising_edge(clk) then
            if capture_en = '1' then
                reg_a <= mux_a;
                reg_b <= mux_b;
            end if;
        end if;
    end process;
    
    -- Управляющий автомат
    process(clk, reset)
    begin
        if reset = '1' then
            state <= IDLE;
            counter <= 0;
            capture_en <= '0';
        elsif rising_edge(clk) then
            case state is
                when IDLE =>
                    capture_en <= '0';
                    if counter >= ONE_SEC - 1 then
                        counter <= 0;
                        state <= CAPTURE;
                    else
                        counter <= counter + 1;
                    end if;
                
                when CAPTURE =>
                    capture_en <= '1';
                    state <= MULTIPLY;
                
                when MULTIPLY =>
                    capture_en <= '0';
                    state <= HOLD;
                
                when HOLD =>
                    capture_en <= '0';
                    if counter >= ONE_SEC - 1 then
                        counter <= 0;
                        state <= CAPTURE;
                    else
                        counter <= counter + 1;
                    end if;
            end case;
        end if;
    end process;
    
    -- Умножители
    mult_inst: mult_5
    port map (
        dataa  => reg_a,
        datab  => reg_b,
        result => dsp_result_vec
    );
    
    dsp_result_int <= to_integer(unsigned(dsp_result_vec));
    
    logic_inst: logic
    port map (
        a      => to_integer(unsigned(reg_a)),
        b      => to_integer(unsigned(reg_b)),
        result => logic_result
    );
    
    -- Выбор режима кнопкой
    process(clk, reset)
    begin
        if reset = '1' then
            mode <= '0';
        elsif rising_edge(clk) then
            if key(1) = '0' then
                mode <= not mode;
            end if;
        end if;
    end process;
    
    -- Выходы
    result <= logic_result when mode = '0' else dsp_result_int;
    
    -- Сигналы для Signal Tap
    s_a <= reg_a;
    s_b <= reg_b;
    s_mux_a <= mux_a;
    s_mux_b <= mux_b;
    s_result <= logic_result when mode = '0' else dsp_result_int;
    
    with state select
        s_state <= "00" when IDLE,
                   "01" when CAPTURE,
                   "10" when MULTIPLY,
                   "11" when HOLD;

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

entity calculator_top is
port (
    clk   : in std_logic;
    reset : in std_logic;
    key   : in std_logic_vector(3 downto 0);
    dig   : out std_logic_vector(3 downto 0);
    seg   : out std_logic_vector(7 downto 0)
);
end calculator_top;

architecture struct of calculator_top is
    
    component calculator is
    port (
        clk      : in std_logic;
        reset    : in std_logic;
        key      : in std_logic_vector(1 downto 0);
        result   : out integer;
        s_a      : out std_logic_vector(7 downto 0);
        s_b      : out std_logic_vector(7 downto 0);
        s_mux_a  : out std_logic_vector(7 downto 0);
        s_mux_b  : out std_logic_vector(7 downto 0);
        s_result : out integer;
        s_state  : out std_logic_vector(1 downto 0)
    );
    end component;
    
    component display_control is
    port (
        clk   : in std_logic;
        reset : in std_logic;
        dig   : out std_logic_vector(3 downto 0);
        seg   : out std_logic_vector(7 downto 0);
        dig0  : in std_logic_vector(7 downto 0);
        dig1  : in std_logic_vector(7 downto 0);
        dig2  : in std_logic_vector(7 downto 0);
        dig3  : in std_logic_vector(7 downto 0)
    );
    end component;
    
    signal calc_result : integer;
    signal s_a, s_b    : std_logic_vector(7 downto 0);
    signal s_mux_a, s_mux_b : std_logic_vector(7 downto 0);
    signal s_result    : integer;
    signal s_state     : std_logic_vector(1 downto 0);
    
    signal dig0, dig1, dig2, dig3 : std_logic_vector(7 downto 0);
    
    -- Функция преобразования числа в сегменты (общий катод)
    function num_to_seg(num : integer) return std_logic_vector is
    begin
        case num is
            when 0 => return "11000000";  -- 0
            when 1 => return "11111001";  -- 1
            when 2 => return "10100100";  -- 2
            when 3 => return "10110000";  -- 3
            when 4 => return "10011001";  -- 4
            when 5 => return "10010010";  -- 5
            when 6 => return "10000010";  -- 6
            when 7 => return "11111000";  -- 7
            when 8 => return "10000000";  -- 8
            when 9 => return "10010000";  -- 9
            when others => return "11111111";  -- Пусто
        end case;
    end function;
    
begin
    
    calc_inst: calculator
    port map (
        clk      => clk,
        reset    => reset,
        key      => key(1 downto 0),
        result   => calc_result,
        s_a      => s_a,
        s_b      => s_b,
        s_mux_a  => s_mux_a,
        s_mux_b  => s_mux_b,
        s_result => s_result,
        s_state  => s_state
    );
    
    -- Преобразование результата для дисплея
    process(calc_result)
        variable thousands, hundreds, tens, ones : integer;
        variable temp : integer;
    begin
        temp := calc_result;
        
        if temp > 9999 then
            temp := 9999;  -- Ограничение 4 разряда
        end if;
        
        thousands := temp / 1000;
        temp := temp mod 1000;
        hundreds := temp / 100;
        temp := temp mod 100;
        tens := temp / 10;
        ones := temp mod 10;
        
        dig3 <= num_to_seg(thousands);
        dig2 <= num_to_seg(hundreds);
        dig1 <= num_to_seg(tens);
        dig0 <= num_to_seg(ones);
    end process;
    
    display_inst: display_control
    port map (
        clk   => clk,
        reset => reset,
        dig   => dig,
        seg   => seg,
        dig0  => dig0,
        dig1  => dig1,
        dig2  => dig2,
        dig3  => dig3
    );
    
end struct;