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