library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity Calendar is
    Port (
         clk          :   in    STD_LOGIC; -- 1Hz clock
         reset        :   in    STD_LOGIC;
         set_sec      :   in    STD_LOGIC;
         set_minute   :   in    STD_LOGIC;
         set_hour     :   in    STD_LOGIC;
         set_day      :   in    STD_LOGIC;
         set_month    :   in    STD_LOGIC;
         set_year     :   in    STD_LOGIC;
         seg          :   out   STD_LOGIC_VECTOR(27 downto 0)   -- 6 x 7-segment outputs
(HHMMSS)
    );
end Calendar;
architecture Behavioral of Calendar is
    function bcd_to_7seg(bcd : STD_LOGIC_VECTOR(5 downto 0)) return
STD_LOGIC_VECTOR is
        variable seg : STD_LOGIC_VECTOR(6 downto 0);
    begin
        case bcd is
            when "000000" => seg := "1000000"; -- 0
            when "000001" => seg := "1111001"; -- 1
            when "000010" => seg := "0100100"; -- 2
            when "000011" => seg := "0110000"; -- 3
            when "000100" => seg := "0011001"; -- 4
            when "000101" => seg := "0010010"; -- 5
            when "000110" => seg := "0000010"; -- 6
            when "000111" => seg := "1111000"; -- 7
            when "001000" => seg := "0000000"; -- 8
            when "001001" => seg := "0010000"; -- 9
            when others => seg := "1111111"; -- blank
        end case;
        return seg;
    end function;
    function zile_luna(luna:STD_LOGIC_VECTOR(5 downto 0); an:STD_LOGIC_VECTOR(11
downto 0)) return STD_LOGIC_VECTOR is
       variable zi:STD_LOGIC_VECTOR(4 downto 0);
    begin
    case luna is
         when "000001" => zi :="11111";
         when "000010" => zi :="11100";
         when "000011" => zi :="11111";
         when "000100" => zi :="11110";
         when "000101" => zi :="11111";
         when "000110" => zi :="11110";
         when "000111" => zi :="11111";
         when "001000" => zi :="11111";
         when "001001" => zi :="11110";
         when "001010" => zi :="11111";
         when "001011" => zi :="11110";
         when "001100" => zi :="11111";
         when others => return "00000";
         end case;
         return zi;
        end function;
    signal   sec : STD_LOGIC_VECTOR(5 downto 0) := (others => '0'); -- 0–59
    signal   min : STD_LOGIC_VECTOR(5 downto 0) := (others => '0'); -- 0–59
    signal   hr : STD_LOGIC_VECTOR(5 downto 0) := (others => '0');
    signal   day : STD_LOGIC_VECTOR(5 downto 0) := (others => '0');
    signal   month: STD_LOGIC_VECTOR(5 downto 0) := (others => '0');
    signal   year: STD_LOGIC_VECTOR(11 downto 0) := (others => '0');
    signal sec_ones, sec_tens : STD_LOGIC_VECTOR(5 downto 0);
    signal min_ones, min_tens : STD_LOGIC_VECTOR(5 downto 0);
    signal hr_ones, hr_tens    : STD_LOGIC_VECTOR(5 downto 0);
    signal day_ones, day_tens : STD_LOGIC_VECTOR(5 downto 0);
    signal month_ones, month_tens : STD_LOGIC_VECTOR(5 downto 0);
    signal year_ones, year_tens, year_hundreds, year_thousands :
STD_LOGIC_VECTOR(11 downto 0);
    signal seg0, seg1, seg2, seg3 : STD_LOGIC_VECTOR(6 downto 0);
    signal   last_set_sec      :   STD_LOGIC   :=   '0';
    signal   last_set_minute   :   STD_LOGIC   :=   '0';
    signal   last_set_hour     :   STD_LOGIC   :=   '0';
    signal   last_set_day      :   STD_LOGIC   :=   '0';
    signal   last_set_month    :   STD_LOGIC   :=   '0';
    signal   last_set_year     :   STD_LOGIC   :=   '0';
begin
    process(clk, reset)
    begin
        if reset = '1' then
            sec <= (others => '0');
            min <= (others => '0');
            hr <= (others => '0');
            day <= (others => '1');
            month <= (others => '1');
            year <= (others => '1');
            last_set_sec    <= '0';
            last_set_minute <= '0';
            last_set_hour   <= '0';
            last_set_day    <= '1';
            last_set_month <= '1';
            last_set_year   <= '1';
        elsif rising_edge(clk) then
              -- Set second
              if set_sec = '1' and last_set_sec = '0' then
                  if sec = "111011" then
                       sec <= (others => '0');
                  else
                       sec <= std_logic_vector(unsigned(sec) + 1);
                  end if;
              -- Set minute
              elsif set_minute = '1' and last_set_minute = '0' then
                  if min = "111011" then
                    min <= (others => '0');
                else
                    min <= std_logic_vector(unsigned(min) + 1);
                end if;
            -- Set hour
            elsif set_hour = '1' and last_set_hour = '0' then
                if hr = "010111" then
                     hr <= (others => '0');
                else
                     hr <= std_logic_vector(unsigned(hr) + 1);
                end if;
            elsif set_day = '1' and last_set_day ='1' then
                  if unsigned(day) = unsigned(zile_luna(month, year)) then
                        day <= (others => '1');
                  else
                        day <=std_logic_vector(unsigned(day) + 1);
                  end if;
            elsif set_month = '1' and last_set_month = '1' then
                  if month="001100" then
                     month <= (others => '1');
                  else
                     month <= std_logic_vector(unsigned(month)+1);
                  end if;
            elsif set_year='1' and last_set_year = '1' then
            -- Normal clock tick
            else
                 if sec = "111011" then
                     sec <= (others => '0');
                     if min = "111011" then
                         min <= (others => '0');
                         if hr = "010111" then
                             hr <= (others => '0');
                               if unsigned(day) = unsigned(zile_luna(month, year))
then
                                       day <= (others =>'1');
                                             if month = "001100" then
                                                month <= (others => '1');
                                                  else
                                                  month <=
std_logic_vector(unsigned(month) + 1);
                                              end if;
                                       else
                                 day <= std_logic_vector(unsigned(day) + 1);
                               end if;
                          else
                               hr <= std_logic_vector(unsigned(hr) + 1);
                          end if;
                     else
                          min <= std_logic_vector(unsigned(min) + 1);
                     end if;
                else
                     sec <= std_logic_vector(unsigned(sec) + 1);
                end if;
            end if;
           -- Update last button states
           last_set_sec    <= set_sec;
           last_set_minute <= set_minute;
           last_set_hour   <= set_hour;
           last_set_day    <= set_day;
           last_set_month <= set_month;
       end if;
   end process;
   -- BCD Conversion
   sec_ones <= std_logic_vector(unsigned(sec) mod 10);
   sec_tens <= std_logic_vector(unsigned(sec) /10 mod 10);
   min_ones <= std_logic_vector(unsigned(min) mod 10);
   min_tens <= std_logic_vector(unsigned(min) / 10);
   hr_ones <= std_logic_vector(unsigned(hr) mod 10);
   hr_tens <= std_logic_vector(unsigned(hr) / 10);
   day_ones <= std_logic_vector(unsigned(day) mod 10);
   day_tens <= std_logic_vector(unsigned(day) / 10);
   month_ones <= std_logic_vector(unsigned(month) mod 10);
   month_tens <= std_logic_vector(unsigned(month) / 10);
   -- 7-segment encoding
   seg <= bcd_to_7seg(day_ones);
   seg2 <= bcd_to_7seg(day_tens);
   seg1 <= bcd_to_7seg(month_ones);
   seg0 <= bcd_to_7seg(month_tens);
   -- Final output order: HH MM SS (seg5..seg0)
   seg <=seg3 & seg2 & seg1 & seg0;
end Behavioral;