Загрузка данных
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
constant NUM_A : unsigned(7 downto 0) := to_unsigned(12, 8);
constant NUM_B : unsigned(7 downto 0) := to_unsigned(15, 8);
-- Фильтр кнопок
signal show_ip_clean : std_logic;
signal show_logic_clean : std_logic;
signal reset_clean : std_logic;
-- Детекторы фронтов кнопок
signal show_ip_prev : std_logic := '0';
signal show_logic_prev : std_logic := '0';
-- Сигналы Slow (импульс 1 такт по фронту кнопки)
signal slow_ip : std_logic := '0';
signal slow_logic : std_logic := '0';
-- Детекторы спадов Slow (для захвата результата)
signal slow_ip_prev : std_logic := '0';
signal slow_logic_prev : std_logic := '0';
signal slow_ip_fall : std_logic;
signal slow_logic_fall : std_logic;
-- Выходы мультиплексоров для IP-ядра
signal mux_a_ip : std_logic_vector(7 downto 0);
signal mux_b_ip : std_logic_vector(7 downto 0);
-- Выходы мультиплексоров для логического умножителя
signal mux_a_logic : unsigned(7 downto 0);
signal mux_b_logic : unsigned(7 downto 0);
-- Результат IP-ядра
signal mult_ip_result : std_logic_vector(15 downto 0) := (others => '0');
-- Результат логического умножителя
signal mult_logic_result : unsigned(15 downto 0) := (others => '0');
-- Регистр результата 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 ip_counter : integer range 0 to 1000000 := 0;
variable logic_counter : integer range 0 to 1000000 := 0;
begin
if rising_edge(clk) then
-- Фильтр IP кнопки
if reset_btn = '0' then
if ip_counter < 1000000 then
ip_counter := ip_counter + 1;
show_ip_clean <= '0';
else
show_ip_clean <= '1';
end if;
else
ip_counter := 0;
show_ip_clean <= '0';
end if;
-- Фильтр Logic кнопки
if reset_btn = '0' then
if logic_counter < 1000000 then
logic_counter := logic_counter + 1;
show_logic_clean <= '0';
else
show_logic_clean <= '1';
end if;
else
logic_counter := 0;
show_logic_clean <= '0';
end if;
-- Сброс
if reset_btn = '1' then
reset_clean <= '1';
else
reset_clean <= '0';
end if;
end if;
end process;
-- ==========================================
-- 2. Детектор фронта кнопки IP → Slow (1 такт)
-- ==========================================
process(clk)
begin
if rising_edge(clk) then
if reset_clean = '1' then
show_ip_prev <= '0';
slow_ip <= '0';
else
show_ip_prev <= show_ip_clean;
-- Slow = 1 на 1 такт при переходе кнопки 0→1
if show_ip_clean = '1' and show_ip_prev = '0' then
slow_ip <= '1';
else
slow_ip <= '0';
end if;
end if;
end if;
end process;
-- ==========================================
-- 3. Детектор фронта кнопки Logic → Slow (1 такт)
-- ==========================================
process(clk)
begin
if rising_edge(clk) then
if reset_clean = '1' then
show_logic_prev <= '0';
slow_logic <= '0';
else
show_logic_prev <= show_logic_clean;
if show_logic_clean = '1' and show_logic_prev = '0' then
slow_logic <= '1';
else
slow_logic <= '0';
end if;
end if;
end if;
end process;
-- ==========================================
-- 4. Детектор спадов Slow (для захвата результата)
-- ==========================================
process(clk)
begin
if rising_edge(clk) then
if reset_clean = '1' then
slow_ip_prev <= '0';
slow_logic_prev <= '0';
else
slow_ip_prev <= slow_ip;
slow_logic_prev <= slow_logic;
end if;
end if;
end process;
-- Спад = переход 1→0
slow_ip_fall <= slow_ip_prev and not slow_ip;
slow_logic_fall <= slow_logic_prev and not slow_logic;
-- ==========================================
-- 5. Мультиплексоры для IP-ядра (переключаются по Slow)
-- ==========================================
-- ОДНОВРЕМЕННО: Slow=1 → MUX пропускают A и B
mux_a_ip <= std_logic_vector(NUM_A) when slow_ip = '1' else (others => '0');
mux_b_ip <= std_logic_vector(NUM_B) when slow_ip = '1' else (others => '0');
-- ==========================================
-- 6. IP-ядро умножителя
-- ==========================================
u_mult_ip : entity work.mult_ip
port map (
dataa => mux_a_ip,
datab => mux_b_ip,
result => mult_ip_result
);
-- ==========================================
-- 7. Мультиплексоры для логического умножителя (переключаются по Slow)
-- ==========================================
mux_a_logic <= NUM_A when slow_logic = '1' else (others => '0');
mux_b_logic <= NUM_B when slow_logic = '1' else (others => '0');
-- ==========================================
-- 8. Логический умножитель (Shift-and-Add)
-- ==========================================
process(mux_a_logic, mux_b_logic)
variable temp_result : unsigned(15 downto 0);
begin
temp_result := (others => '0');
for i in 0 to 7 loop
if mux_b_logic(i) = '1' then
temp_result := temp_result + (mux_a_logic sll i);
end if;
end loop;
mult_logic_result <= temp_result;
end process;
-- ==========================================
-- 9. Регистр C (захват результата ПО СПАДУ Slow)
-- ==========================================
process(clk)
begin
if rising_edge(clk) then
if reset_clean = '1' then
result_reg <= (others => '0');
enable_reg <= '0';
elsif slow_ip_fall = '1' then
-- ПО СПАДУ Slow_IP сохраняем результат
result_reg <= unsigned(mult_ip_result);
enable_reg <= '1';
elsif slow_logic_fall = '1' then
-- ПО СПАДУ Slow_Logic сохраняем результат
result_reg <= mult_logic_result;
enable_reg <= '1';
end if;
end if;
end process;
-- ==========================================
-- 10. Преобразование в BCD
-- ==========================================
process(clk)
begin
if rising_edge(clk) then
if reset_clean = '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;