library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity watch is
port(
clk : in std_logic;
reset : in std_logic;
T0, T1, T2 : in std_logic;
fgo : in std_logic;
reg : in std_logic;
step : in std_logic;
sw0 : in std_logic;
led_alarm : out std_logic;
FND_out1 : out std_logic_vector(7 downto 0);
FND_out2 : out std_logic_vector(7 downto 0);
FND_out3 : out std_logic_vector(7 downto 0);
FND_sel1 : out std_logic_vector(1 downto 0);
FND_sel2 : out std_logic_vector(1 downto 0);
FND_sel3 : out std_logic_vector(1 downto 0)
);
function num_FND(num : integer) return std_logic_vector is
begin
case num is
when 0 => return "11111100";
when 1 => return "01100000";
when 2 => return "11011010";
when 3 => return "11110010";
when 4 => return "01100110";
when 5 => return "10110110";
when 6 => return "10111110";
when 7 => return "11100000";
when 8 => return "11111110";
when 9 => return "11110110";
when others => return "00000000";
end case;
end function num_FND;
function change_num(num : integer; change_mode : integer; time_plus_minus : std_logic) return integer is
begin
if time_plus_minus = '0' then
case change_mode is
when 0 => return num - 1;
when 1 => return num - 60;
when 2 => return num - 3600;
when others => return num;
end case;
else
case change_mode is
when 0 => return num + 1;
when 1 => return num + 60;
when 2 => return num + 3600;
when others => return num;
end case;
end if;
end function change_num;
end watch;
architecture Behavioral of watch is
signal clk_time, clk_fnd, clk_debouncing, clk_2hz : std_logic;
signal watch_mode : integer range 0 to 2 := 0;
signal change_mode : integer range 0 to 2 := 0;
signal time_cnt, alarm_cnt : integer range 0 to 86400 := 0;
signal alarm_out : std_logic;
signal h0, h1, m0, m1, s0, s1 : integer range 0 to 9;
begin
process(clk_fnd, clk_time, clk_debouncing, clk_2hz)
variable cnt : integer range 0 to 999999 := 0;
variable cnt2hz : integer range 0 to 249999:= 0;
variable cnt5hz : integer range 0 to 199999 := 0;
variable cnt50hz : integer range 0 to 9999 := 0;
begin
if rising_edge(clk) then
if cnt > 999999 then
cnt := 0;
clk_time <= '1';
else
clk_time <= '0';
cnt := cnt + 1;
end if;
if cnt2hz > 249999 then
cnt2hz := 0;
clk_2hz <= not clk_2hz;
else
cnt2hz := cnt2hz + 1;
end if;
if cnt5hz > 199999 then
cnt5hz := 0;
clk_debouncing <= '1';
else
clk_debouncing <= '0';
cnt5hz := cnt5hz + 1;
end if;
if cnt50hz >= 9999 then
cnt50hz := 0;
clk_fnd <= not clk_fnd;
else
cnt50hz := cnt50hz + 1;
end if;
end if;
end process;
process(watch_mode, change_mode)
begin
if rising_edge(clk) then
if T0 = '1' then
watch_mode <= 0;
change_mode <= 0;
end if;
if T1 = '1' then
watch_mode <= 1;
change_mode <= 0;
end if;
if T2 = '1' then
watch_mode <= 2;
change_mode <= 0;
end if;
if clk_time = '1' then
if fgo = '0' then
case change_mode is
when 0 => change_mode <= 1;
when 1 => change_mode <= 2;
when 2 => change_mode <= 0;
end case;
end if;
end if;
end if;
end process;
process(clk_time, clk_debouncing, time_cnt, alarm_cnt)
begin
if rising_edge(clk) then
if not (watch_mode = 1) then
if clk_time = '1' then
time_cnt <= time_cnt + 1;
end if;
end if;
if watch_mode = 1 then
if clk_debouncing = '1' then
if reg = '0' or step = '0' then
time_cnt <= change_num(time_cnt, change_mode, reg);
end if;
end if;
elsif watch_mode = 2 then
if clk_debouncing = '1' then
if reg = '0' or step = '0' then
alarm_cnt <= change_num(alarm_cnt, change_mode, reg);
end if;
end if;
end if;
if time_cnt >= 86400 or (watch_mode = 0 and reset = '0') then
time_cnt <= 0;
end if;
if alarm_cnt >= 86400 or (watch_mode = 2 and reset = '0') then
alarm_cnt <= 0;
end if;
end if;
end process;
process(alarm_out)
begin
if sw0 = '1' and watch_mode = 0 and time_cnt = alarm_cnt then
alarm_out <= '1';
end if;
if sw0 = '0' then
alarm_out <= '0';
end if;
end process;
process(alarm_out, clk_2hz)
begin
if alarm_out = '1' then
led_alarm <= clk_2hz;
else
led_alarm <= '0';
end if;
end process;
process(time_cnt, s0, s1, m0, m1, h0, h1)
begin
if rising_edge(clk) then
if watch_mode = 0 or watch_mode = 1 then
s0 <= (time_cnt mod 60) mod 10;
s1 <= (time_cnt mod 60) / 10;
m0 <= ((time_cnt mod 3600) / 60) mod 10;
m1 <= ((time_cnt mod 3600) / 60) / 10;
h0 <= (time_cnt / 3600) mod 10;
h1 <= (time_cnt / 3600) / 10;
else
s0 <= (alarm_cnt mod 60) mod 10;
s1 <= (alarm_cnt mod 60) / 10;
m0 <= ((alarm_cnt mod 3600) / 60) mod 10;
m1 <= ((alarm_cnt mod 3600) / 60) / 10;
h0 <= (alarm_cnt / 3600) mod 10;
h1 <= (alarm_cnt / 3600) / 10;
end if;
end if;
end process;
process(clk_fnd, h0, h1, m0, m1, s0, s1, change_mode)
begin
if rising_edge(clk) then
if clk_fnd = '1' then
FND_sel1 <= "10";
FND_sel2 <= "10";
FND_sel3 <= "10";
FND_out1 <= num_FND(h1);
FND_out2 <= num_FND(m1);
FND_out3 <= num_FND(s1);
else
FND_sel1 <= "01";
FND_sel2 <= "01";
FND_sel3 <= "01";
FND_out1 <= num_FND(h0);
FND_out2 <= num_FND(m0);
FND_out3 <= num_FND(s0);
end if;
if (not (watch_mode = 0)) and clk_2hz = '0' then
case change_mode is
when 0 =>
FND_sel3 <= "11";
when 1 =>
FND_sel2 <= "11";
when 2 =>
FND_sel1 <= "11";
when others => null;
end case;
end if;
end if;
end process;
end Behavioral;