--------------------------------------------------------------------------------
-- CERN BE-CO-HT
--
-- https://www.ohwr.org/projects/wr2rf-vme
--------------------------------------------------------------------------------
--
-- unit name:   wr2rf_ocxo
--
-- description: Provides wrapper for OCXO related code
--
--------------------------------------------------------------------------------
-- Copyright CERN 2020
--------------------------------------------------------------------------------
-- Copyright and related rights are licensed under the Solderpad Hardware
-- License, Version 2.0 (the "License"); you may not use this file except
-- in compliance with the License. You may obtain a copy of the License at
-- http://solderpad.org/licenses/SHL-2.0.
-- Unless required by applicable law or agreed to in writing, software,
-- hardware and materials distributed under this License is distributed on an
-- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
-- or implied. See the License for the specific language governing permissions
-- and limitations under the License.
--------------------------------------------------------------------------------

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

library unisim;
use unisim.vcomponents.all;

entity wr2rf_ocxo is

   port (
      clk_sys_i        : in  std_logic;

      ocxo_enabled_i   : in  std_logic;
      ocxo_uptime_o    : out std_logic_vector(15 downto 0) );

   attribute keep_hierarchy              : STRING;
   attribute keep_hierarchy of wr2rf_ocxo : entity is "yes";
   
end entity;

architecture rtl of wr2rf_ocxo is

   signal cyc_cnt    : unsigned(3  downto 0);
   signal usec_cnt   : unsigned(9  downto 0);
   signal msec_cnt   : unsigned(9  downto 0);
   signal sec_cnt    : unsigned(15 downto 0);   
   signal cyc_cnt_r  : unsigned(3  downto 0);
   signal usec_cnt_r : unsigned(9  downto 0);
   signal msec_cnt_r : unsigned(9  downto 0);
   signal sec_cnt_r  : unsigned(15 downto 0);
   signal sec_wrap   : std_logic;
   
begin

   -- rough calculation for 1 sec interval based on 62.5 MHz sys clock frequency
   cyc_cnt  <= cyc_cnt_r  + 1;
   usec_cnt <= usec_cnt_r + 1 when cyc_cnt_r(3)  = '1' and cyc_cnt(3)  = '0' else usec_cnt_r;
   msec_cnt <= msec_cnt_r + 1 when usec_cnt_r(9) = '1' and usec_cnt(9) = '0' else msec_cnt_r;
   sec_cnt  <= sec_cnt_r  + 1 when msec_cnt_r(9) = '1' and msec_cnt(9) = '0' else sec_cnt_r;

   -- counter saturates   
   sec_wrap <= '1'            when sec_cnt_r(15) = '1' and sec_cnt(15) = '0' else '0';
   
   process(clk_sys_i) is
   begin
      if rising_edge(clk_sys_i) then
         if ocxo_enabled_i = '0' then
            cyc_cnt_r  <= (others => '0');            
            usec_cnt_r <= (others => '0');                        
            msec_cnt_r <= (others => '0');            
            sec_cnt_r  <= (others => '0');
         else
            cyc_cnt_r  <= cyc_cnt;
            usec_cnt_r <= usec_cnt;
            msec_cnt_r <= msec_cnt;
            if sec_wrap = '0' then
               sec_cnt_r  <= sec_cnt;
            end if;
         end if;
      end if;
   end process;

   -- outputs
   ocxo_uptime_o <= std_logic_vector(sec_cnt_r);

end architecture;
