----------------------------------------------------------------------------------
-- Company:        CERN, BE-CO-HT
-- Engineer:       Carlos Gil Soriano
-- 
-- Create Date:    09:58:06 10/12/2011 
-- Design Name:    HDL trigger top
-- Module Name:    trigger - Behavioral 
-- Project Name:   CTDAH
-- Target Devices: Spartan 6
-- Tool versions: 
-- Description:    This is the wishbone trigger which receives a input
--                 and outputs a trigger signal for the pulse converter.
--                 It internally debounces the inputs and control the output
--                 driver.
--                 The registers it has can be modified via wishbone access.
-- Dependencies:   none
--
-- Revision: 
-- Revision 0.1
-- Additional Comments: 
--
----------------------------------------------------------------------------------
library IEEE;

use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;

entity basic_trigger_top is
   generic(g_NUMBER_OF_CHANNELS : NATURAL := 6);
   port (
      clk_i          : in  STD_LOGIC;

      led_pw_o       : out STD_LOGIC;
      led_err_o      : out STD_LOGIC;
      led_ttl_o      : out STD_LOGIC;

      fpga_o_en      : out STD_LOGIC;
      fpga_o_ttl_en  : out STD_LOGIC;
      fpga_o_inv_en  : out STD_LOGIC;
      fpga_o_blo_en  : out STD_LOGIC;

      level          : in  STD_LOGIC;
      switch_i       : in  STD_LOGIC;   --! General enable
      manual_rst_n_o : out STD_LOGIC;   --! It allows power sequencing of the
                                        --! 24V rail after a security given
                                        --! delay
      pulse_i_front  : in  STD_LOGIC_VECTOR(g_NUMBER_OF_CHANNELS downto 1);
      pulse_o_front  : out STD_LOGIC_VECTOR(g_NUMBER_OF_CHANNELS downto 1);

      pulse_i_rear   : in  STD_LOGIC_VECTOR(g_NUMBER_OF_CHANNELS downto 1);
      pulse_o_rear   : out STD_LOGIC_VECTOR(g_NUMBER_OF_CHANNELS downto 1);

      led_o_front    : out STD_LOGIC_VECTOR(g_NUMBER_OF_CHANNELS downto 1);
      led_o_rear     : out STD_LOGIC_VECTOR(g_NUMBER_OF_CHANNELS downto 1);

      --! WR LEDs not to let them ON
      led_link_up_o  : out STD_LOGIC;
      led_pps_o      : out STD_LOGIC;
      led_wr_ok_o    : out STD_LOGIC;

      inv_i          : in  STD_LOGIC_VECTOR(4 downto 1);
      inv_o          : out STD_LOGIC_VECTOR(4 downto 1));
end basic_trigger_top;


architecture Behavioral of basic_trigger_top is

   signal s_pulse_i          : STD_LOGIC_VECTOR(g_NUMBER_OF_CHANNELS downto 1); 
   signal s_pulse_i_rear     : STD_LOGIC_VECTOR(g_NUMBER_OF_CHANNELS downto 1); 
   signal s_pulse_i_front    : STD_LOGIC_VECTOR(g_NUMBER_OF_CHANNELS downto 1); 
   signal s_pulse_o_front    : STD_LOGIC_VECTOR(g_NUMBER_OF_CHANNELS downto 1); 
   signal s_pulse_o          : STD_LOGIC_VECTOR(g_NUMBER_OF_CHANNELS downto 1);
   signal s_pulse_n_o        : STD_LOGIC_VECTOR(g_NUMBER_OF_CHANNELS downto 1);
   signal s_led              : STD_LOGIC_VECTOR(g_NUMBER_OF_CHANNELS downto 1);

   signal s_crop             : STD_LOGIC_VECTOR(g_NUMBER_OF_CHANNELS downto 1);

   signal s_level            : STD_LOGIC;

   signal s_fpga_o_en        : STD_LOGIC;
   signal s_fpga_o_ttl_en    : STD_LOGIC;
   signal s_fpga_o_inv_en    : STD_LOGIC;
   signal s_fpga_o_blo_en    : STD_LOGIC;

   signal s_rst              : STD_LOGIC_VECTOR(7 downto 0) := (others => '1');

   type delay_array   is array (g_NUMBER_OF_CHANNELS downto 1)
                                               of STD_LOGIC_VECTOR(3 downto 0);

   signal s_pulse_i_reg : delay_array;

   component basic_trigger_core is
      port (wb_rst_i       : in  STD_LOGIC;
            wb_clk_i       : in  STD_LOGIC;

            pulse_i        : in  STD_LOGIC;
            pulse_o        : out STD_LOGIC;
            pulse_n_o      : out STD_LOGIC;

            crop_o         : out STD_LOGIC;

            led_o          : out STD_LOGIC);
   end component;

begin

   s_level         <= level;

   led_pw_o        <= '0';
   led_err_o       <= '1';
   led_ttl_o       <= not(s_level);

   led_link_up_o   <= '1';
   led_pps_o       <= '1'; 
   led_wr_ok_o     <= '1'; 

   --! s_level '1' means TTL input, as we have one inverter in the board we
   --! invert here.
   s_pulse_i_front <= not(pulse_i_front) when s_level = '1' else pulse_i_front;
   s_pulse_i       <= s_pulse_i_front or not(pulse_i_rear);

   fpga_o_en       <= s_fpga_o_en when switch_i = '1' else '0';

   fpga_o_ttl_en   <= s_fpga_o_ttl_en;
   fpga_o_inv_en   <= s_fpga_o_inv_en;
   fpga_o_blo_en   <= s_fpga_o_blo_en;

   led_o_front     <= not(s_led);--! No need of accurate sync, hence we place
   led_o_rear      <= not(s_led);--! some combinatorial here.

   pulse_o_front   <= s_pulse_o  when level = '1'
                                 else not(s_pulse_o);

   pulse_o_rear    <= s_pulse_o;

   inv_o           <= inv_i;
                            --! As we have one Schmitt inverter in the input,
                            --! and a buffer in the output, there's no need
                            --! of invert here.


   i_repetitors: for i in 1 to g_NUMBER_OF_CHANNELS generate
   begin
      trigger: basic_trigger_core
      port map ( 
         wb_rst_i  => s_rst(7), 
         wb_clk_i  => clk_i, 

         pulse_i   => s_pulse_i(i), 
         pulse_o   => s_pulse_o(i), 
         pulse_n_o => s_pulse_n_o(i), 

         crop_o    => s_crop(i),

         led_o          => s_led(i));
   end generate i_repetitors;


   p_reset_chain : process(clk_i) is
   begin
      if rising_edge(clk_i) then

         s_rst(0) <= '0';
         for i in 1 to 7 loop
            s_rst(i) <= s_rst(i-1);
         end loop;

         if s_rst(7) = '1' then
         --! First we reset the FPGA general output enable
         --! Then we let one clock delay for the rest of signals
            manual_rst_n_o   <= '0';
            s_fpga_o_en      <= '0';
            s_fpga_o_ttl_en  <= '0';
            s_fpga_o_inv_en  <= '0';
            s_fpga_o_blo_en  <= '0';

         else
            manual_rst_n_o   <= '1';
            s_fpga_o_en      <= '1';
            s_fpga_o_ttl_en  <= s_fpga_o_en;
            s_fpga_o_inv_en  <= s_fpga_o_en;
            s_fpga_o_blo_en  <= s_fpga_o_en;
         end if;
      end if;
   end process p_reset_chain;


end Behavioral;
