-- clock_logic.vhd library IEEE; use IEEE.STD_LOGIC_1164.ALL; -- Uncomment the following library declaration if using -- arithmetic functions with Signed or Unsigned values --use IEEE.NUMERIC_STD.ALL; -- Uncomment the following library declaration if instantiating -- any Xilinx leaf cells in this code. --library UNISIM; --use UNISIM.VComponents.all; entity clock_logic is Port ( CLK : in STD_LOGIC; RST : in STD_LOGIC; CE_1HZ : in STD_LOGIC; -- Enable signal from the divider SW_DIN : in STD_LOGIC_VECTOR (3 downto 0); BTN_LOAD : in STD_LOGIC_VECTOR (3 downto 0); -- Outputs to the top module/display S_UNITS : out STD_LOGIC_VECTOR (3 downto 0); S_TENS : out STD_LOGIC_VECTOR (3 downto 0); M_UNITS : out STD_LOGIC_VECTOR (3 downto 0); M_TENS : out STD_LOGIC_VECTOR (3 downto 0); H_UNITS : out STD_LOGIC_VECTOR (3 downto 0); H_TENS : out STD_LOGIC_VECTOR (3 downto 0) ); end clock_logic; architecture Behavioral of clock_logic is -- TODO CHECK AGAINST COUNTER.VHD IF NEEDED component counter is Generic ( MAX_LIMIT : STD_LOGIC_VECTOR(3 downto 0) := "1001" ); -- Default to 9 Port ( CLK : in STD_LOGIC; CE : in STD_LOGIC; PE : in STD_LOGIC; DIN : in STD_LOGIC_VECTOR(3 downto 0); RST : in STD_LOGIC; TC : out STD_LOGIC; COUNT_OUT : out STD_LOGIC_VECTOR (3 downto 0)); end component; -- Internal signals to connect the counters signal sig_s_units, sig_s_tens : std_logic_vector(3 downto 0); signal sig_m_units, sig_m_tens : std_logic_vector(3 downto 0); signal sig_h_units, sig_h_tens : std_logic_vector(3 downto 0); -- Carry signals (TC) signal tc_su, tc_st, tc_mu, tc_mt, tc_hu : std_logic; -- Reset for hours (to handle the 24 reset) signal hour_reset : std_logic; -- Specific load enable signals that check for boundaries signal load_h_tens, load_h_units : std_logic; signal load_m_tens, load_m_units : std_logic; -- Internal signals for the "Safe" load triggers signal safe_load_su, safe_load_st : std_logic; signal safe_load_mu, safe_load_mt : std_logic; signal safe_load_hu, safe_load_ht : std_logic; begin -- MINUTES CONSTRAINTS (Max 59) load_m_units <= BTN_LOAD(0) when (SW_DIN <= "1001") else '0'; -- 0-9 load_m_tens <= BTN_LOAD(1) when (SW_DIN <= "0101") else '0'; -- 0-5 -- HOURS CONSTRAINTS (Max 23) -- Rule A: Cannot load Tens > 2. -- Rule B: If Tens is 2, cannot load Units > 3. -- Rule C: If Units is > 3, cannot load Tens into 2. load_h_tens <= BTN_LOAD(3) when ( SW_DIN < "0010" or (SW_DIN = "0010" and sig_h_units <= "0011") ) else '0'; load_h_units <= BTN_LOAD(2) when ( (sig_h_tens < "0010" and SW_DIN <= "1001") or (sig_h_tens = "0010" and SW_DIN <= "0011") ) else '0'; ------------------------------------------------------- -- SECONDS SECTION -- SECONDS UNITS (0-9) - Triggered by the 1Hz pulse U_CNT_SEC_UNITS : counter generic map ( MAX_LIMIT => "1001" ) -- do 9 port map ( CLK => CLK, RST => RST, CE => CE_1HZ, PE => '0', DIN => "0000", -- Seconds usually don't need manual load TC => tc_su, COUNT_OUT => sig_s_units ); -- SECONDS TENS (0-5) - Triggered when Sec Units reach 9 U_CNT_SEC_TENS : counter generic map ( MAX_LIMIT => "0101" ) -- do 5 port map ( CLK => CLK, RST => RST, CE => tc_su, PE => '0', DIN => "0000", TC => tc_st, COUNT_OUT => sig_s_tens ); ------------------------------------------------------- -- MINUTES SECTION -- MINUTES UNITS (0-9) - When Seconds reach 59 U_CNT_MIN_UNITS : counter generic map ( MAX_LIMIT => "1001" ) -- do 9 port map ( CLK => CLK, RST => RST, CE => tc_st, PE => load_m_units, DIN => SW_DIN, TC => tc_mu, COUNT_OUT => sig_m_units ); -- MINUTES TENS (0-5) U_CNT_MIN_TENS : counter generic map ( MAX_LIMIT => "0101" ) -- do 5 port map ( CLK => CLK, RST => RST, CE => tc_mu, PE => load_m_tens, DIN => SW_DIN, TC => tc_mt, COUNT_OUT => sig_m_tens ); ------------------------------------------------------- -- HOURS SECTION -- If we are at 23:59:59, the next tick should reset hours process(sig_h_tens, sig_h_units, tc_mt, RST) begin if RST = '1' then hour_reset <= '1'; -- TICK: If clock is at 23:59:59 and the minutes tick over elsif (sig_h_tens = "0010" and sig_h_units = "0011" and tc_mt = '1') then hour_reset <= '1'; -- LOAD PROTECTION: If current value is 24:XX or higher -- This part works even if tc_mt is '0' (for the alarm) elsif (sig_h_tens = "0010" and sig_h_units >= "0100") then hour_reset <= '1'; elsif (sig_h_tens > "0010") then hour_reset <= '1'; else hour_reset <= '0'; end if; end process; -- HOURS UNITS (0-9) U_CNT_HOR_UNITS : counter generic map ( MAX_LIMIT => "1001" ) -- To 9 port map ( CLK => CLK, RST => hour_reset, CE => tc_mt, PE => load_h_units, DIN => SW_DIN, TC => tc_hu, COUNT_OUT => sig_h_units ); -- HOURS TENS (0-2) U_CNT_HOR_TENS : counter generic map ( MAX_LIMIT => "0010" ) -- To 2 port map ( CLK => CLK, RST => hour_reset, CE => tc_hu, PE => load_h_tens, DIN => SW_DIN, TC => open, COUNT_OUT => sig_h_tens ); -- Drive output ports S_UNITS <= sig_s_units; S_TENS <= sig_s_tens; M_UNITS <= sig_m_units; M_TENS <= sig_m_tens; H_UNITS <= sig_h_units; H_TENS <= sig_h_tens; end Behavioral;