我刚刚开始使用VHDL,似乎在我从状态NTIME
进行初始更改到SET_TIME
后,我无法返回{{1} }以便能够更改回NTIME
。
我已经检查了SET_ALARM
- 块之前的信号,它似乎已正确创建并收到。但我似乎只是陷入case
。当收到带有编码SET_TIME
的按钮时,会发生从NTIME
到SET_TIME
的更改。当第二次接收到该信号时,该状态应该返回到原始状态'0001'
。状态NTIME
的输入'0010'
也会出现类似的情况。
这是我到目前为止所做的:
SET_ALARM
我不确定这只是对VHDL的基本误解,也可能只是一个错字。
这是我的测试台:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity controller is
port(
btn : in std_logic_vector(3 downto 0);
sw : in std_logic_vector(0 downto 0);
o_mins, o_secs, o_wmins : out integer range 0 to 59;
o_hours, o_whours : out integer range 0 to 23;
alarm : out std_logic;
state : out std_logic_vector(1 downto 0);
clk : in std_logic;
reset : in std_logic
);
end controller;
architecture Behavioral of controller is
component trigger_gen is
generic(Delta : integer);
port(
clk : in std_logic;
reset : in std_logic;
trigger : out std_logic
);
end component trigger_gen;
-- pro Viertelsekunde einen Takt lang '1'
signal fasttrigger : std_logic;
-- fasttrigger wird zurueckgesetzt, wenn BTN2 oder BTN3 gedrueckt werden
signal fasttimer_reset : std_logic;
-- pro Sekunde einen Takt lang '1'
signal sectrigger : std_logic;
signal hours, whours : integer range 0 to 23;
signal secs, mins, wmins : integer range 0 to 59;
-- fuer Flankenerkennung der Taster
signal btn_shift : std_logic_vector(3 downto 0);
signal btn_triggered : std_logic_vector(3 downto 0);
type state_type is (NTIME, SET_TIME, SET_ALARM, error);
signal current_state : state_type;
begin
fasttimer_reset <= reset or
btn_triggered(2) or btn_triggered(3);
fasttimer : trigger_gen
generic map(11)
port map(clk, fasttimer_reset, fasttrigger);
sectimer : trigger_gen
generic map(13)
port map(clk, reset, sectrigger);
FSM : process(clk, reset)
variable next_state : state_type;
begin
if reset = '1' then
hours <= 0;
mins <= 0;
secs <= 0;
whours <= 0;
wmins <= 0;
alarm <= '0';
current_state <= NTIME;
elsif clk'event and clk = '1' then
for i in 0 to 3 loop
btn_shift(i) <= btn(i);
btn_triggered(i) <= not btn_shift(i) and btn(i);
end loop;
-- TODO: Zaehle Uhr hoch
IF secs <= 58 THEN
secs <= secs + 1;
ELSE
secs <= 0;
IF mins <= 58 THEN
mins <= mins + 1;
ELSE
mins <= 0;
IF hours <= 22 THEN
hours <= hours + 1;
ELSE
hours <= 0;
END IF;
END IF;
END IF;
-- TODO: Pruefe, ob Alarm ausgeloest werden muss
IF hours = whours AND mins = wmins AND sw(0) = '1' THEN
alarm <= '1';
END IF;
case current_state is
-- Zustand Time
when NTIME =>
IF btn_triggered(0) = '1' THEN
REPORT "Going to set time";
next_state := SET_TIME;
ELSIF btn_triggered(1) = '1' THEN
REPORT "Going to set Alarm";
next_state := SET_ALARM;
END IF;
-- Zustand SetTime
when SET_TIME =>
IF btn_triggered(0) = '1' THEN
next_state := NTIME;
END IF;
IF btn_triggered(2) = '1' THEN
REPORT "SETTING MINUTES IN TIME";
IF mins <= 58 THEN
mins <= mins + 1;
ELSE
mins <= 0;
END IF;
ELSIF btn_triggered(3) = '1' THEN
REPORT "SETTING HOURS IN TIME";
IF hours <= 22 THEN
hours <= hours + 1;
ELSE
hours <= 0;
END IF;
END IF;
-- Zustand SetAlarm
when SET_ALARM =>
IF btn_triggered(1) = '1' THEN
next_state := NTIME;
END IF;
IF btn_triggered(2) = '1' THEN
REPORT "SETTING MINUTES IN ALARM";
IF wmins <= 58 THEN
wmins <= wmins + 1;
ELSE
wmins <= 0;
END IF;
ELSIF btn_triggered(3) = '1' THEN
REPORT "SETTING HOURS IN ALARM";
IF whours <= 22 THEN
whours <= whours + 1;
ELSE
whours <= 0;
END IF;
END IF;
next_state := NTIME;
-- Illegale Zustaende
when others =>
next_state := NTIME;
end case;
current_state <= next_state;
end if;
end process FSM;
o_hours <= hours;
o_mins <= mins;
o_secs <= secs;
o_whours <= whours;
o_wmins <= wmins;
with current_state select
state <= "00" when NTIME,
"01" when SET_TIME,
"10" when SET_ALARM,
"11" when others;
end architecture Behavioral;