📄 statemachine.vhd
字号:
Library IEEE ;
USE IEEE.STD_LOGIC_1164.all;
USE IEEE.STD_LOGIC_ARITH.all;
ENTITY statemachine IS
PORT(clk : IN STD_LOGIC; --全局时钟
keyvalue : IN STD_LOGIC_VECTOR(3 DOWNTO 0); --按键值
keypressed : IN STD_LOGIC; --有按键来标志
functionkey : IN STD_LOGIC; --是否是功能键
buffertime : BUFFER STD_LOGIC_VECTOR(23 DOWNTO 0);--缓存时间
iscount : OUT STD_LOGIC; --状态机状态是否是计数态
alarmload : OUT STD_LOGIC; --闹钟时间加载信号
timeload : OUT STD_LOGIC); --计时器时间加载信号
END statemachine;
ARCHITECTURE rtl OF statemachine IS
--定义状态机状态类型
TYPE state IS (count,modifytime1,modifytime2,modifytime3,modifytime4,modifytime5,
modifytime6,modifytime7,loadtime,
setalarm1,setalarm2,setalarm3,setalarm4,setalarm5,setalarm6,
setalarm7,loadalarm);
--当前状态和次态
SIGNAL present_state : state :=count;
SIGNAL next_state : state :=count;
--缓存时间的信号表示
SIGNAL time_temp : STD_LOGIC_VECTOR(23 DOWNTO 0);
BEGIN
--状态更新
PROCESS(clk)
BEGIN
IF(clk'event AND clk='1')THEN
present_state <= next_state;
END IF;
END PROCESS;
--状态译码
PROCESS(keyvalue,keypressed,functionkey,present_state,clk)
BEGIN
IF(clk'event AND clk='0')THEN
CASE present_state IS
--计时状态
WHEN count =>
IF(keypressed='1' AND keyvalue="1110") THEN
next_state <= modifytime1; --返回计时状态
ELSIF(keypressed='1' AND keyvalue="1111") THEN
next_state <= setalarm1;
ELSE
next_state <= present_state;
END IF;
time_temp <= "000000000000000000000000";
--校时状态1,,等待输入小时的高位
WHEN modifytime1 =>
IF(keypressed='1' AND keyvalue="1011") THEN
next_state <= count; --返回计时状态
ELSIF(keypressed='1' AND keyvalue<="0010") THEN
--小时的高位可以输入0~2
next_state <= modifytime2;
time_temp(23 DOWNTO 20) <= keyvalue;
ELSE
next_state <= present_state;
time_temp <= time_temp;
END IF;
--校时状态2,等待输入小时的低位
WHEN modifytime2 =>
IF(keypressed='1' AND keyvalue="1011") THEN
next_state <= count;
ELSIF(keypressed='1' AND functionkey='0' AND time_temp(23 DOWNTO 20) <= "0001") THEN
--小时的高位为0和1时,可以输入0~9
next_state <= modifytime3;
time_temp(19 DOWNTO 16) <= keyvalue;
ELSIF(keypressed='1' AND time_temp(23 DOWNTO 20)="0010" AND keyvalue <= "0011") THEN
--小时的高位为2时,只可以输入0~3
next_state <= modifytime3;
time_temp(19 DOWNTO 16) <= keyvalue;
ELSE
next_state <= present_state;
time_temp <= time_temp;
END IF;
--校时状态2,等待输入分钟的高位
WHEN modifytime3 =>
IF(keypressed='1' AND keyvalue="1011") THEN
next_state <= count;
ELSIF(keypressed='1' AND keyvalue<="0101") THEN
--分钟的高位可以输入0~5
next_state <= modifytime4;
time_temp(15 DOWNTO 12) <= keyvalue;
ELSE
next_state <= present_state;
time_temp <= time_temp;
END IF;
--校时状态4,等待输入分钟的低位
WHEN modifytime4 =>
IF(keypressed='1' AND keyvalue="1011") THEN
next_state <= count;
ELSIF(keypressed='1' AND functionkey = '0') THEN
--分钟的低位可以输入0~9
next_state <= modifytime5;
time_temp(11 DOWNTO 8) <= keyvalue;
ELSE
next_state <= present_state;
time_temp <= time_temp;
END IF;
--校时状态5,等待输入秒的高位
WHEN modifytime5 =>
IF(keypressed='1' AND keyvalue="1011") THEN
next_state <= count;
ELSIF(keypressed='1' AND keyvalue<="0101") THEN
--秒的高位可以输入0~5
next_state <= modifytime6;
time_temp(7 DOWNTO 4) <= keyvalue;
ELSE
next_state <= present_state;
time_temp <= time_temp;
END IF;
--校时状态6,,等待输入秒的低位
WHEN modifytime6 =>
IF(keypressed='1' AND keyvalue="1011") THEN
next_state <= count;
ELSIF(keypressed='1' AND functionkey='0') THEN
--秒的低位可以输入0~9
next_state <= modifytime7;
time_temp(3 DOWNTO 0) <= keyvalue;
ELSE
next_state <= present_state;
time_temp <= time_temp;
END IF;
--校时状态7,等待输入确认键A
WHEN modifytime7 =>
IF(keypressed='1' AND keyvalue="1011") THEN
next_state <= count;
ELSIF(keypressed='1' AND keyvalue="1010") THEN
--输入确认键
next_state <= loadtime;
ELSE
next_state <= present_state;
END IF;
time_temp <= time_temp;
--计时器时间加载状态
WHEN loadtime =>
next_state <= count;
time_temp <= time_temp;
--设闹状态1,等待输入小时高位
WHEN setalarm1 =>
IF(keypressed='1' AND keyvalue="1011") THEN
next_state <= count;
ELSIF(keypressed='1' AND keyvalue<="0010") THEN
--小时高位可以0~2
next_state <= setalarm2;
time_temp(23 DOWNTO 20) <= keyvalue;
ELSE
next_state <= present_state;
time_temp <= time_temp;
END IF;
--设闹状态2,等待输入小时低位
WHEN setalarm2 =>
IF(keypressed='1' AND keyvalue="1011") THEN
next_state <= count;
ELSIF(keypressed='1' AND functionkey='0' AND time_temp(23 DOWNTO 20)<="0001") THEN
--小时的高位为0和1时,可以输入0~9
next_state <= setalarm3;
time_temp(19 DOWNTO 16) <= keyvalue;
ELSIF(keypressed='1' AND time_temp(23 DOWNTO 20)="0010" AND keyvalue<="0011") THEN
--小时的高位为2时,可以输入0~3
next_state <= setalarm3;
time_temp(19 DOWNTO 16) <= keyvalue;
ELSE
next_state <= present_state;
time_temp <= time_temp;
END IF;
--设闹状态3,等待输入分钟高位
WHEN setalarm3 =>
IF(keypressed='1' AND keyvalue="1011") THEN
next_state <= count;
ELSIF(keypressed='1' AND keyvalue<="0101") THEN
--分钟高位可以输入0~5
next_state <= setalarm4;
time_temp(15 DOWNTO 12) <= keyvalue;
ELSE
next_state <= present_state;
time_temp <= time_temp;
END IF;
--设闹状态4,等待输入分钟低位
WHEN setalarm4 =>
IF(keypressed='1' AND keyvalue="1011") THEN
next_state <= count;
ELSIF(keypressed='1' AND functionkey='0') THEN
--分钟低位可以输入0~9
next_state <= setalarm5;
time_temp(11 DOWNTO 8) <= keyvalue;
ELSE
next_state <= present_state;
time_temp <= time_temp;
END IF;
--设闹状态5,等待输入秒高位
WHEN setalarm5 =>
IF(keypressed='1' AND keyvalue="1011") THEN
next_state <= count;
ELSIF(keypressed='1' AND keyvalue<="0101") THEN
next_state <= setalarm6;
time_temp(7 DOWNTO 4) <= keyvalue;
ELSE
next_state <= present_state;
time_temp <= time_temp;
END IF;
--设闹状态6,等待输入秒低位
WHEN setalarm6 =>
IF(keypressed='1' AND keyvalue="1011") THEN
next_state <= count;
ELSIF(keypressed='1' AND functionkey='0') THEN
next_state <= setalarm7;
time_temp(3 DOWNTO 0) <= keyvalue;
ELSE
next_state <= present_state;
time_temp <= time_temp;
END IF;
--设闹状态7,等待输入确认键
WHEN setalarm7 =>
IF(keypressed='1' AND keyvalue="1011") THEN
next_state <= count;
ELSIF(keypressed='1' AND keyvalue="1010") THEN
next_state <= loadalarm;
ELSE
next_state <= present_state;
END IF;
time_temp <= time_temp;
--闹钟时间加载状态
WHEN loadalarm =>
next_state <= count;
time_temp <= time_temp;
--多于态处理
WHEN OTHERS =>
next_state <= count;
time_temp <= time_temp;
END CASE;
END IF;
END PROCESS;
--输出缓存时间
buffertime <= time_temp;
--输出译码
PROCESS(present_state)
BEGIN
--状态机是否在计数态
IF(present_state = count)THEN
iscount <= '1';
ELSE
iscount <= '0';
END IF;
--计时器时间加载信号
IF(present_state = loadtime)THEN
timeload <= '1';
ELSE
timeload <= '0';
END IF;
--闹钟时间加载信号
IF(present_state = loadalarm)THEN
alarmload <= '1';
ELSE
alarmload <= '0';
END IF;
END PROCESS;
END rtl;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -