Загрузка данных
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;