--_________________________________________________________________________________________________
--                                                                                                |
--                                           |SVEC PTS|                                           |
--                                                                                                |
--                                         CERN,BE/CO-HT                                          |
--________________________________________________________________________________________________|

---------------------------------------------------------------------------------------------------
--                                                                                                |
--                                       clk_info_wb_slave                                        |
--                                                                                                |
---------------------------------------------------------------------------------------------------
-- File         clk_info_wb_slave.vhd                                                             |
--                                                                                                |
-- Description  Wishbone slave that receives and transmits information for a clock counter.       |
--              It is Used at test svec_pts_04_05_06 for the evaluation of si570 VCXO and         |
--              at svec_pts_08 for the evaluation of the VCXO and PLLREF clocks                   |
--              Five 32 bits long registers are used:                                             |
--                Register in address x0 (reg 0) can only be read by the VME interface:           |
--                  reg 0 bit 0 indicates that a clock counter is full                            |
--                Register in address x1 (reg 1) can only be read by the VME interface:           |
--                  reg 1 bit 0 indicates a clock error:clock output disabled & clock counter full|
--                Register in address x2 (reg 2) can be written and read by the VME interface:    |
--                  reg 2 bit 0 enables the output of a clcok (oe_clk)                            |
--                Register in address x3 (reg 3) can be written and read by the VME interface:    |
--                  reg 3 bits 32..0 indicate the amount of cycles to be counted by the clock     |
--                Register in address x4 (reg 4) can only be read by the VME interface:           |
--                  reg 4 bits 32..0 indicate the amount of cycles counted so far                 |
--                Register in address x5 (reg 5) can be written and read by the VME interface:    |
--                  reg 5 bit 0 resets the counter                                                |
--                Register in address x6 (reg 6) can be written and read by the VME interface:    |
--                  reg 6 bit 0 enables the counting                                              |
--                                                                                                |
-- Authors      Samuel Iglesias Gonsalvez                                                         |
--              Evangelia Gousiou (Evangelia.Gousiou@cern.ch)                                     |
-- Date         07/2012                                                                           |
-- Version      v1                                                                                |
-- Depends on                                                                                     |
--                                                                                                |
----------------                                                                                  |
-- Last changes                                                                                   |
--     07/2012  v1  EG  First version                                                             |
---------------------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------------------
--                               GNU LESSER GENERAL PUBLIC LICENSE                                |
--                              ------------------------------------                              |
-- This source file is free software; you can redistribute it and/or modify it under the terms of |
-- the GNU Lesser General Public License as published by the Free Software Foundation; either     |
-- version 2.1 of the License, or (at your option) any later version.                             |
-- This source is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;       |
-- without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.      |
-- See the GNU Lesser General Public License for more details.                                    |
-- You should have received a copy of the GNU Lesser General Public License along with this       |
-- source; if not, download it from http://www.gnu.org/licenses/lgpl-2.1.html                     |
---------------------------------------------------------------------------------------------------


--=================================================================================================
--                                       Libraries & Packages
--=================================================================================================
library IEEE;
use IEEE.STD_LOGIC_1164.all;

--=================================================================================================
--                              Entity declaration for clk_info_wb_slave
--=================================================================================================
entity clk_info_wb_slave is
  port
    -- WISHBONE slave signals
    (wb_clk_i          : in  std_logic;
     rst_i             : in  std_logic;
     wb_cyc_i          : in  std_logic;
     wb_stb_i          : in  std_logic;
     wb_addr_i         : in  std_logic_vector( 2 downto 0);
     wb_data_i         : in  std_logic_vector(31 downto 0);
     wb_we_i           : in  std_logic;
     wb_data_o         : out std_logic_vector(31 downto 0);
     wb_ack_o          : out std_logic;
    -- Clock info signals
     counter_is_full_i : in std_logic;
     counter_now_i     : in std_logic_vector (31 downto 0);
     counter_top_o     : out std_logic_vector (31 downto 0);
     counter_rst_o     : out std_logic;
     counter_en_o      : out std_logic;
	 oe_clk_o          : out std_logic);
end clk_info_wb_slave;


--=================================================================================================
--                                    architecture declaration
--=================================================================================================
architecture behavioral of clk_info_wb_slave is

  signal clk_ok_synch, clk_err_synch : std_logic_vector(1 downto 0);
  signal reg2, reg5, reg6            : std_logic_vector(31 downto 0);
  signal reg3                        : std_logic_vector(31 downto 0) := x"FFFFFFFF"; -- initial value
  signal clk_err, oe_clk             : std_logic;
  
--=================================================================================================
--                                       architecture begin
--=================================================================================================
begin

---------------------------------------------------------------------------------------------------
--                                     INPUTS SYNCHRONIZATION                                    --
---------------------------------------------------------------------------------------------------
  clk_err_clk_ok_synchronizer: process (wb_clk_i)
  begin
    if rising_edge (wb_clk_i) then
      if rst_i = '1' then
        clk_ok_synch  <= (others => '0');
        clk_err_synch <= (others => '0');
      else
        clk_ok_synch  <= clk_ok_synch(0) & (counter_is_full_i);
        clk_err_synch <= clk_err_synch(0) & (clk_err);
		end if;
    end if;
  end process;

  clk_err <= '1' when counter_is_full_i = '1' and oe_clk = '0';

---------------------------------------------------------------------------------------------------
--                                         DATA IN/ OUT                                          --
---------------------------------------------------------------------------------------------------
  data_out: process (wb_clk_i)
  begin
    if rising_edge(wb_clk_i) then   
      if rst_i = '1' then
        wb_data_o        <= (others => '0');
        reg2             <= (others => '0');
        reg3             <= x"FFFFFFFF";
        reg5             <= (others => '0');
        reg6             <= (others => '0');
      else

        if (wb_cyc_i = '1') and (wb_stb_i = '1') and (wb_we_i = '0') then   -- WISHBONE reads

          if (wb_addr_i = "000") then                                 -- reg 0 read only, clk ok
            wb_data_o(0) <= clk_ok_synch(1);

          elsif (wb_addr_i = "001") then                              -- reg 1 read only, clk error
	        wb_data_o(0) <= clk_err_synch(1);

          elsif (wb_addr_i = "010") then                              -- reg 2 read write, oe_clk
            wb_data_o    <= reg2;

          elsif (wb_addr_i = "011") then                              -- reg 3 read write, counter top
            wb_data_o    <= reg3;

          elsif (wb_addr_i = "100") then                              -- reg 4 read only, counter current value
            wb_data_o    <= counter_now_i;

          elsif (wb_addr_i = "101") then                              -- reg 5 read write, counter reset
            wb_data_o    <= reg5;

          elsif (wb_addr_i = "110") then                              -- reg 6 read write, counter enable
            wb_data_o    <= reg6;

          elsif (wb_addr_i = "111") then                              -- dummy
            wb_data_o    <= x"C000FFEE";
          else
            wb_data_o    <= x"00000000";                         
          end if;


	     elsif (wb_cyc_i = '1') and (wb_stb_i = '1') and (wb_we_i = '1') then-- WISHBONE writes

          if (wb_addr_i = "010") then                                  -- reg 1 read write, oe_clk
            reg2         <= wb_data_i;
          elsif (wb_addr_i = "011") then                               -- reg 3 read write, counter top
            reg3         <= wb_data_i;
          elsif (wb_addr_i = "101") then                               -- reg 5 read write, counter reset
            reg5         <= wb_data_i;
          elsif (wb_addr_i = "110") then                               -- reg 6 read write, counter enable
            reg6         <= wb_data_i;
          end if;

        end if;
      end if;
    end if;
  end process;

  oe_clk        <= reg2(0);
  oe_clk_o      <= reg2(0);
  counter_top_o <= reg3;
  counter_rst_o <= reg5(0);
  counter_en_o  <= reg6(0);



---------------------------------------------------------------------------------------------------
--                                        ACK generation                                         --
---------------------------------------------------------------------------------------------------
  ack_generator: process (wb_clk_i)
  begin
    if rising_edge (wb_clk_i) then
      if rst_i = '1' then
        wb_ack_o <= '0';
      else
        wb_ack_o <= wb_stb_i and wb_cyc_i;
      end if;
    end if;
  end process;

end behavioral;
