---------------------------------------------------------------------------------
-- Company:        CERN, BE-CO-HT
-- Engineer:       Carlos Gil Soriano
-- 
-- Create Date:    15:27:55 02/08/2012 
-- Design Name:    CONV_TTL_BLO image 1
-- Module Name:    image1_top - Behavioral 
-- Project Name:   CONV_TTL_BLO
-- Target Devices: Spartan 6 SLX45T
-- Tool versions: 
-- Description:    image1_top.vhd comprises the integration of four vhdl modules:
--                 1.- Trigger
--                 2.- i2c_slave_wb_master 
--                 3.- multiboot
--                 4.- wb_addr_decoder
-- Dependencies: 
--
-- Revision: 
-- Revision 0.01 - File Created
-- Additional Comments: 
--
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity image1_top is
   generic(
             g_NUMBER_OF_CHANNELS : INTEGER := 6
          );
   port(

          LED_SYS_PW        : out STD_LOGIC;
          LED_SYS_ERROR     : out STD_LOGIC;
          LED_TTL           : out STD_LOGIC;

          LED_LINK_UP       : out STD_LOGIC; 
          LED_PPS           : out STD_LOGIC; 
          LED_WR_OK         : out STD_LOGIC; 

          ---------------------------------------
          --  EXTRA_SWITCH
          --   
          --   1            rst 
          --   2            general OE and TTL
          --   3            OE blocking
          --------------------------------------

          EXTRA_SWITCH      : in  STD_LOGIC_VECTOR(3  downto 1);
          TTL               : in  STD_LOGIC;
          CLK20_VCXO        : in  STD_LOGIC;

          FPGA_OE           : out STD_LOGIC; 
          FPGA_BLO_OE       : out STD_LOGIC;  
          FPGA_TRIG_TTL_OE  : out STD_LOGIC; 
          FPGA_INV_OE       : out STD_LOGIC;

          FPGA_BLO_IN       : in  STD_LOGIC_VECTOR(g_NUMBER_OF_CHANNELS downto 1); 
          FPGA_TRIG_BLO     : out STD_LOGIC_VECTOR(g_NUMBER_OF_CHANNELS downto 1);
          PULSE_REAR_LED    : out STD_LOGIC_VECTOR(g_NUMBER_OF_CHANNELS downto 1);

          FPGA_INPUT_TTL    : in  STD_LOGIC_VECTOR(g_NUMBER_OF_CHANNELS downto 1);
          FPGA_OUT_TTL      : out STD_LOGIC_VECTOR(g_NUMBER_OF_CHANNELS downto 1);
          PULSE_FRONT_LED   : out STD_LOGIC_VECTOR(g_NUMBER_OF_CHANNELS downto 1);

          INV_OUT           : out STD_LOGIC_VECTOR(4  downto 1);

          FPGA_HEADER_OUT   : out STD_LOGIC_VECTOR(6  downto 1);

          FPGA_GA           : in  STD_LOGIC_VECTOR(4  downto 0);
          FPGA_GAP          : in  STD_LOGIC;

          SCL_I             : in  STD_LOGIC;
          SCL_O             : out STD_LOGIC;
          SCL_OE            : out STD_LOGIC;
          SDA_I             : in  STD_LOGIC;
          SDA_O             : out STD_LOGIC;
          SDA_OE            : out STD_LOGIC
       );
end image1_top;

architecture Behavioral of image1_top is

   -------------------------------------------------------------------------------
   -- MODULE MAPPING: wishbone slaves 
   -------------------------------------------------------------------------------
   --  ID       Device          Wishbone wiring
   --   0       I2C             wb_slave_*[0]
   --   1       Ch1             wb_slave_*[1]  
   --   2       Ch2             wb_slave_*[2]  
   --   3       Ch3             wb_slave_*[3]    
   --   4       Ch4             wb_slave_*[4]   
   --   5       Ch5             wb_slave_*[5]    
   --   6       Ch6             wb_slave_*[6]     
   --   7       Multiboot       wb_slave_*[7]    
   --   8       EEPROM          wb_slave_*[8] 
   --   9       White Rabbit    wb_slave_*[9]  
   -------------------------------------------------------------------------------

   constant c_WISHBONE_MODULES    : INTEGER := 10;
   constant c_WISHBONE_MEMWIDTH   : INTEGER := 32;
   constant c_WISHBONE_ADDRWIDTH  : INTEGER := 16;
   constant c_SLAVE_I2C           : INTEGER := 0;
   constant c_SLAVE_CH1           : INTEGER := 1;
   constant c_SLAVE_CH2           : INTEGER := 2;
   constant c_SLAVE_CH3           : INTEGER := 3;
   constant c_SLAVE_CH4           : INTEGER := 4;
   constant c_SLAVE_CH5           : INTEGER := 5;
   constant c_SLAVE_CH6           : INTEGER := 6;
   constant c_SLAVE_MULTIBOOT     : INTEGER := 7;
   constant c_SLAVE_EEPROM        : INTEGER := 8;
   constant c_SLAVE_WR            : INTEGER := 9;


   component trigger_top is
      port (
              pulse_i          : in  STD_LOGIC;
              pulse_o          : out STD_LOGIC;
              led_o            : out STD_LOGIC;
              utc_i            : in  STD_LOGIC_VECTOR(95 downto 0);
              wb_rst_i         : in  STD_LOGIC;               
              wb_clk           : in  STD_LOGIC;               
              wb_stb_i         : in  STD_LOGIC;
              wb_cyc_i         : in  STD_LOGIC;
              wb_ack_o         : out STD_LOGIC;
              wb_err_o         : out STD_LOGIC;
              wb_rty_o         : out STD_LOGIC;
              wb_we_i          : in  STD_LOGIC;               
              wb_sel_i         : in  STD_LOGIC_VECTOR(3  downto 0);
              wb_data_i        : in  STD_LOGIC_VECTOR(31 downto 0);
              wb_data_o        : out STD_LOGIC_VECTOR(31 downto 0);
              wb_addr_i        : in  STD_LOGIC_VECTOR(2  downto 0)
           );
   end component;

   component i2c_slave_top is
      port (
              sda_oen          : out STD_LOGIC;
              sda_i            : in  STD_LOGIC;
              sda_o            : out STD_LOGIC;
              scl_oen          : out STD_LOGIC;
              scl_i            : in  STD_LOGIC;
              scl_o            : out STD_LOGIC;
              wb_clk           : in  STD_LOGIC;
              wb_rst_i         : in  STD_LOGIC;
              wb_master_stb_o  : out STD_LOGIC;
              wb_master_cyc_o  : out STD_LOGIC;
              wb_master_sel_o  : out STD_LOGIC_VECTOR(3  downto 0);
              wb_master_we_o   : out STD_LOGIC;
              wb_master_data_i : in  STD_LOGIC_VECTOR(31 downto 0);
              wb_master_data_o : out STD_LOGIC_VECTOR(31 downto 0);
              wb_master_addr_o : out STD_LOGIC_VECTOR(15 downto 0);
              wb_master_ack_i  : in  STD_LOGIC;
              wb_master_rty_i  : in  STD_LOGIC;
              wb_master_err_i  : in  STD_LOGIC;
              wb_slave_stb_i   : in  STD_LOGIC;
              wb_slave_cyc_i   : in  STD_LOGIC;
              wb_slave_sel_i   : in  STD_LOGIC_VECTOR(3  downto 0);
              wb_slave_we_i    : in  STD_LOGIC;
              wb_slave_data_i  : in  STD_LOGIC_VECTOR(31 downto 0);
              wb_slave_data_o  : out STD_LOGIC_VECTOR(31 downto 0);
              wb_slave_addr_i  : in  STD_LOGIC_VECTOR(3  downto 0);
              wb_slave_ack_o   : out STD_LOGIC;
              wb_slave_rty_o   : out STD_LOGIC;
              wb_slave_err_o   : out STD_LOGIC;
              pf_wb_addr_o     : out STD_LOGIC;
              rd_done_o        : out STD_LOGIC;
              wr_done_o        : out STD_LOGIC;
              i2c_addr         : in  STD_LOGIC_VECTOR(6  downto 0)
           );
   end component;

   component multiboot_top is
      port(
             wb_rst_i   : in   STD_LOGIC;
             wb_clk     : in   STD_LOGIC;
             wb_we_i    : in   STD_LOGIC;
             wb_stb_i   : in   STD_LOGIC;
             wb_cyc_i   : in   STD_LOGIC;
             wb_sel_i   : in   STD_LOGIC_VECTOR(3  downto 0);
             wb_data_i  : in   STD_LOGIC_VECTOR(31 downto 0);
             wb_data_o  : out  STD_LOGIC_VECTOR(31 downto 0);
             wb_addr_i  : in   STD_LOGIC_VECTOR(3  downto 0);
             wb_ack_o   : out  STD_LOGIC;
             wb_rty_o   : out  STD_LOGIC;
             wb_err_o   : out  STD_LOGIC);
   end component;


   component wb_addr_decoder is
      generic
      (
         g_WINDOW_SIZE  : INTEGER := c_WISHBONE_ADDRWIDTH;
         g_WB_SLAVES_NB : INTEGER := c_WISHBONE_MODULES
      );
      port
      (
         clk_i       : in  STD_LOGIC;
         rst_n_i     : in  STD_LOGIC;
         wbm_adr_i   : in  STD_LOGIC_VECTOR(31 downto 0);
         wbm_dat_i   : in  STD_LOGIC_VECTOR(31 downto 0);
         wbm_sel_i   : in  STD_LOGIC_VECTOR(3  downto 0); 
         wbm_stb_i   : in  STD_LOGIC;
         wbm_we_i    : in  STD_LOGIC;
         wbm_cyc_i   : in  STD_LOGIC;
         wbm_dat_o   : out STD_LOGIC_VECTOR(31 downto 0);
         wbm_ack_o   : out STD_LOGIC;
         wbm_stall_o : out STD_LOGIC;
         wb_adr_o    : out STD_LOGIC_VECTOR(31 downto 0); 
         wb_dat_o    : out STD_LOGIC_VECTOR(31 downto 0); 
         wb_sel_o    : out STD_LOGIC_VECTOR(3  downto 0);                    
         wb_stb_o    : out STD_LOGIC;
         wb_we_o     : out STD_LOGIC;
         wb_cyc_o    : out STD_LOGIC_VECTOR(g_WB_SLAVES_NB - 1      downto 0);     
         wb_dat_i    : in  STD_LOGIC_VECTOR((32*g_WB_SLAVES_NB) - 1 downto 0);
         wb_ack_i    : in  STD_LOGIC_VECTOR(g_WB_SLAVES_NB - 1      downto 0);     
         wb_stall_i  : in  STD_LOGIC_VECTOR(g_WB_SLAVES_NB - 1      downto 0)      
      );
   end component;

   signal s_pulse_i              : STD_LOGIC_VECTOR(6  downto 1);
   signal s_pulse_o              : STD_LOGIC_VECTOR(6  downto 1);
   signal s_led_o                : STD_LOGIC_VECTOR(6  downto 1);

   signal s_led_sys_error_o      : STD_LOGIC;

   signal s_wb_i2c_master_stb_o  : STD_LOGIC; 
   signal s_wb_i2c_master_cyc_o  : STD_LOGIC; 
   signal s_wb_i2c_master_sel_o  : STD_LOGIC_VECTOR(3  downto 0); 
   signal s_wb_i2c_master_we_o   : STD_LOGIC; 
   signal s_wb_i2c_master_dat_i  : STD_LOGIC_VECTOR(c_WISHBONE_MEMWIDTH  - 1 downto 0); 
   signal s_wb_i2c_master_dat_o  : STD_LOGIC_VECTOR(c_WISHBONE_MEMWIDTH  - 1 downto 0); 
   signal s_wb_i2c_master_adr_o  : STD_LOGIC_VECTOR(c_WISHBONE_ADDRWIDTH - 1 downto 0); 
   signal s_wb_i2c_master_ack_i  : STD_LOGIC; 
   signal s_wb_i2c_master_rty_i  : STD_LOGIC; 
   signal s_wb_i2c_master_err_i  : STD_LOGIC; 
   signal s_wb_i2c_master_stall_o: STD_LOGIC;

   signal s_pf_wb_adr_o          : STD_LOGIC; 
   signal s_rd_done_o            : STD_LOGIC;
   signal s_wr_done_o            : STD_LOGIC; 

   signal s_wb_slave_stb_i    : STD_LOGIC;  
   signal s_wb_slave_cyc_i    : STD_LOGIC_VECTOR(c_WISHBONE_MODULES - 1  downto 0);  
   signal s_wb_slave_ack_o    : STD_LOGIC_VECTOR(c_WISHBONE_MODULES - 1  downto 0);  
   --   signal s_wb_slave_err_o    : STD_LOGIC_VECTOR(c_WISHBONE_MODULES - 1  downto 0);      -- Commented as wb_decoder is
   --   signal s_wb_slave_rty_o    : STD_LOGIC_VECTOR(c_WISHBONE_MODULES - 1  downto 0);      --  not providing that signals 
   signal s_wb_slave_we_i     : STD_LOGIC; 
   signal s_wb_slave_sel_i    : STD_LOGIC_VECTOR(3 downto 0); 
   signal s_wb_slave_dat_i    : STD_LOGIC_VECTOR(c_WISHBONE_MEMWIDTH - 1  downto 0); 
   signal s_wb_slave_dat_o    : STD_LOGIC_VECTOR(c_WISHBONE_MODULES*c_WISHBONE_MEMWIDTH - 1  downto 0); 
   signal s_wb_slave_adr_i    : STD_LOGIC_VECTOR(c_WISHBONE_ADDRWIDTH - 1 downto 0); 

   -- This is added because a splitted assignation within a port cannot be put to
   -- OPEN thanks to the so intuitive VHDL'93 syntax
   signal s_wb_slave_adr_AUX93_i : STD_LOGIC_VECTOR(31 downto c_WISHBONE_ADDRWIDTH);

begin


   LED_SYS_PW       <= '0' ; 
   LED_SYS_ERROR    <= s_led_sys_error_o; 
   LED_TTL          <= '0' ; 

   LED_LINK_UP      <= '1' ;
   LED_PPS          <= '1' ;
   LED_WR_OK        <= '1' ;

   FPGA_INV_OE      <= '0';

   s_pulse_i        <= not(FPGA_BLO_IN) or not(FPGA_INPUT_TTL);
   FPGA_OUT_TTL     <= s_pulse_o;
   FPGA_TRIG_BLO    <= s_pulse_o;
   PULSE_REAR_LED   <= not(s_led_o);
   PULSE_FRONT_LED  <= not(s_led_o);

   INV_OUT(4 downto 1) <= (others => '1');
   FPGA_HEADER_OUT     <= (others => '1');

   trigger_channels_loop: for i in 1 to g_NUMBER_OF_CHANNELS generate
   begin
      trigger_inst: trigger_top
      port map(
                 pulse_i         => s_pulse_i(i), 
                 pulse_o         => s_pulse_o(i), 
                 led_o           => s_led_o  (i), 
                 utc_i           => (others => '0'), 
                 wb_rst_i        => EXTRA_SWITCH(1), 
                 wb_clk          => CLK20_VCXO, 
                 wb_stb_i        => s_wb_slave_stb_i, 
                 wb_cyc_i        => s_wb_slave_cyc_i ( i), 
                 wb_ack_o        => s_wb_slave_ack_o ( i), 
                 wb_err_o        => open, 
                 wb_rty_o        => open,
                 --                 wb_err_o        => s_wb_slave_err_o ( i), 
                 --                 wb_rty_o        => s_wb_slave_rty_o ( i), 
                 wb_we_i         => s_wb_slave_we_i, 
                 wb_sel_i        => s_wb_slave_sel_i, 
                 wb_data_i       => s_wb_slave_dat_i, 
                 wb_data_o       => s_wb_slave_dat_o (c_WISHBONE_MEMWIDTH*(i+1) - 1 downto c_WISHBONE_MEMWIDTH*(i)), 
                 wb_addr_i       => s_wb_slave_adr_i(2 downto 0)
              );
   end generate trigger_channels_loop;

   i2c_slave_wb_master_inst: i2c_slave_top
   port map(
              sda_oen          => SDA_OE, 
              sda_i            => SDA_I, 
              sda_o            => SDA_O, 
              scl_oen          => SCL_OE, 
              scl_i            => SCL_I, 
              scl_o            => SCL_O, 
              wb_clk           => CLK20_VCXO, 
              wb_rst_i         => EXTRA_SWITCH(1), 
              wb_master_stb_o  => s_wb_i2c_master_stb_o,
              wb_master_cyc_o  => s_wb_i2c_master_cyc_o,
              wb_master_sel_o  => s_wb_i2c_master_sel_o,
              wb_master_we_o   => s_wb_i2c_master_we_o,
              wb_master_data_i => s_wb_i2c_master_dat_i,
              wb_master_data_o => s_wb_i2c_master_dat_o,
              wb_master_addr_o => s_wb_i2c_master_adr_o,
              wb_master_ack_i  => s_wb_i2c_master_ack_i,
              wb_master_rty_i  => s_wb_i2c_master_rty_i,
              wb_master_err_i  => s_wb_i2c_master_err_i,
              wb_slave_stb_i   => s_wb_slave_stb_i, 
              wb_slave_cyc_i   => s_wb_slave_cyc_i ( c_SLAVE_I2C), 
              wb_slave_sel_i   => s_wb_slave_sel_i, 
              wb_slave_we_i    => s_wb_slave_we_i, 
              wb_slave_data_i  => s_wb_slave_dat_i((c_SLAVE_I2C+1)*c_WISHBONE_MEMWIDTH  - 1 downto c_SLAVE_I2C*c_WISHBONE_MEMWIDTH),
              wb_slave_data_o  => s_wb_slave_dat_o((c_SLAVE_I2C+1)*c_WISHBONE_MEMWIDTH  - 1 downto c_SLAVE_I2C*c_WISHBONE_MEMWIDTH), 
              wb_slave_addr_i  => s_wb_slave_adr_i((c_SLAVE_I2C)*c_WISHBONE_ADDRWIDTH + 3 downto c_SLAVE_I2C*c_WISHBONE_ADDRWIDTH), 
              wb_slave_ack_o   => s_wb_slave_ack_o ( c_SLAVE_I2C), 
              wb_slave_rty_o   => open, 
              wb_slave_err_o   => open, 
              pf_wb_addr_o     => s_pf_wb_adr_o, 
              rd_done_o        => s_rd_done_o, 
              wr_done_o        => s_wr_done_o, 
              i2c_addr(4 downto 0)         => FPGA_GA,
              i2c_addr(6 downto 5)         => (others => '0')
           );


   multiboot_inst: multiboot_top
   port map(
              wb_rst_i  => EXTRA_SWITCH(1),
              wb_clk    => CLK20_VCXO, 
              wb_we_i   => s_wb_slave_we_i, 
              wb_stb_i  => s_wb_slave_stb_i, 
              wb_cyc_i  => s_wb_slave_cyc_i(c_SLAVE_MULTIBOOT), 
              wb_sel_i  => s_wb_slave_sel_i,
              wb_data_i => s_wb_slave_dat_i,
              wb_data_o => s_wb_slave_dat_o((c_SLAVE_MULTIBOOT+1)*c_WISHBONE_MEMWIDTH - 1  downto c_SLAVE_MULTIBOOT*c_WISHBONE_MEMWIDTH),
              wb_addr_i => s_wb_slave_adr_i(3 downto 0),
              wb_ack_o  => s_wb_slave_ack_o(c_SLAVE_MULTIBOOT), 
              wb_rty_o  => open, 
              wb_err_o  => open
           );


   wb_addr_decoder_inst: wb_addr_decoder
   port map(
              clk_i       => CLK20_VCXO, 
              rst_n_i     => EXTRA_SWITCH(1), 
              wbm_stb_i   => s_wb_i2c_master_stb_o, 
              wbm_cyc_i   => s_wb_i2c_master_cyc_o, 
              wbm_sel_i   => s_wb_i2c_master_sel_o, 
              wbm_we_i    => s_wb_i2c_master_we_o, 
              wbm_dat_o   => s_wb_i2c_master_dat_i, 
              wbm_dat_i   => s_wb_i2c_master_dat_o, 
              wbm_adr_i(c_WISHBONE_ADDRWIDTH - 1 downto 0) => s_wb_i2c_master_adr_o,
              wbm_adr_i(31 downto c_WISHBONE_ADDRWIDTH)    => (others => '0'),
              wbm_ack_o   => s_wb_i2c_master_ack_i, 
              wbm_stall_o => s_wb_i2c_master_stall_o,

              wb_stb_o    => s_wb_slave_stb_i, 
              wb_cyc_o    => s_wb_slave_cyc_i, 
              wb_sel_o    => s_wb_slave_sel_i, 
              wb_we_o     => s_wb_slave_we_i ,
              wb_dat_i(c_SLAVE_EEPROM*c_WISHBONE_MEMWIDTH - 1 downto c_SLAVE_I2C*c_WISHBONE_MEMWIDTH)    => s_wb_slave_dat_o(c_SLAVE_EEPROM*c_WISHBONE_MEMWIDTH - 1 downto c_SLAVE_I2C*c_WISHBONE_MEMWIDTH),
              wb_dat_i((c_SLAVE_WR + 1)*c_WISHBONE_MEMWIDTH - 1 downto c_SLAVE_EEPROM*c_WISHBONE_MEMWIDTH) => (others => '0'),--open,
              wb_dat_o    => s_wb_slave_dat_i, 
              wb_adr_o(c_WISHBONE_ADDRWIDTH - 1 downto 0)  => s_wb_slave_adr_i,
              wb_adr_o(31    downto c_WISHBONE_ADDRWIDTH)  => s_wb_slave_adr_AUX93_i, 
              wb_ack_i    => s_wb_slave_ack_o, 

              wb_stall_i  => (others => '0')
           );

   ttl_out: process (CLK20_VCXO)
   begin
      if rising_edge (CLK20_VCXO) then
         if EXTRA_SWITCH(2) = '1' then
            FPGA_OE          <= '0'; 
            FPGA_TRIG_TTL_OE <= '0'; 
         else
            FPGA_OE          <= '1'; 
            FPGA_TRIG_TTL_OE <= '1'; 
         end if;
      else

      end if;
   end process;

   blo_out: process(CLK20_VCXO)
   begin
      if rising_edge (CLK20_VCXO) then
         if EXTRA_SWITCH(3) = '1'  then
            FPGA_BLO_OE      <= '1';
         else
            FPGA_BLO_OE      <= '0';
         end if;
      else
      end if;
   end process;

   gap_check: process(CLK20_VCXO)
      variable parity : STD_LOGIC;
   begin
      if rising_edge (CLK20_VCXO) then
         parity := FPGA_GA(0) XOR FPGA_GA(1) XOR FPGA_GA(2) XOR FPGA_GA(3) XOR FPGA_GA(4);
         if (parity = FPGA_GAP) then
            s_led_sys_error_o <= '0';
         else
            s_led_sys_error_o <= '1';
         end if;
      else
      end if;
   end process;

end Behavioral;
