--_________________________________________________________________________________________________
--                                                                                                |
--                                           |TDC core|                                           |
--                                                                                                |
--                                         CERN,BE/CO-HT                                          |
--________________________________________________________________________________________________|

---------------------------------------------------------------------------------------------------
--                                                                                                |
--                                      fmc_masterFIP_core                                        |
--                                                                                                |
---------------------------------------------------------------------------------------------------
-- File         fmc_masterFIP_core.vhd                                                            |
--                                                                                                |
-- Description  The masterFIP core top level instantiates all the modules needed to provide
--                                                                                                |
-- Authors      Evangelia Gousiou (Evangelia.Gousiou@cern.ch)                                     |
-- Date         07/2014                                                                           |
-- Version      v1                                                                                |
-- Depends on                                                                                     |
--                                                                                                |
----------------                                                                                  |
-- Last changes                                                                                   |
--     07/2014  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;
use IEEE.numeric_std.all;
use work.masterFIP_pkg.all;
use work.gencores_pkg.all;
use work.wishbone_pkg.all;
use work.wrcore_pkg.all;
use work.genram_pkg.all;


--=================================================================================================
--                                Entity declaration for fmc_masterFIP_core
--=================================================================================================
entity fmc_masterFIP_core is
  generic
    (g_span           : integer := 32;                    -- address span in bus interfaces
     g_width          : integer := 32;                    -- data width in bus interfaces
     values_for_simul : boolean := FALSE);                -- this generic is set to TRUE
                                                          -- when instantiated in a test-bench
  port
    (-- Clock and reset
     clk_i       : in    std_logic;                       -- 
     rst_i       : in    std_logic;                       -- 

      -- FielDrive
     fd_rxcdn_i  : in    std_logic;
     fd_rxd_i    : in    std_logic;
     fd_txer_i   : in    std_logic;
     fd_wdgn_i   : in    std_logic;
     fd_rstn_o   : out   std_logic;
     fd_txck_o   : out   std_logic;
     fd_txd_o    : out   std_logic;
     fd_txena_o  : out   std_logic;

     -- Interrupts
     irq_p_o     : out   std_logic_vector(7 downto 0); -- vector that groups all sources if irqs

     -- Aux
     aux_o       : out std_logic_vector(7 downto 0);   -- group of 8 aux signals to pass to the higher levels

    -- WISHBONE bus interface with the GN4124/VME core for the configuration of the core
     wb_adr_i    : in    std_logic_vector(g_span-1 downto 0);   -- WISHBONE classic address
     wb_dat_i    : in    std_logic_vector(g_width-1 downto 0);  -- WISHBONE classic data in
     wb_stb_i    : in    std_logic;                             -- WISHBONE classic strobe
     wb_sel_i    : in    std_logic_vector(3 downto 0);          -- WISHBONE classic select
     wb_we_i     : in    std_logic;                             -- WISHBONE classic write enable
     wb_cyc_i    : in    std_logic;                             -- WISHBONE classic cycle
     wb_stall_o  : out   std_logic;                             -- WISHBONE classic stall
     wb_ack_o    : out   std_logic;                             -- WISHBONE classic acknowledge
     wb_dat_o    : out   std_logic_vector(g_width-1 downto 0)); -- WISHBONE classic data out

end fmc_masterFIP_core;


--=================================================================================================
--                                    architecture declaration
--=================================================================================================
architecture rtl of fmc_masterFIP_core is

  constant c_RST_UNLOCK_VALUE : std_logic_vector(15 downto 0) := x"cafe";
  
  signal rst_n, core_rst, rx_rst : std_logic;
  -- control unit
  signal tx_byte_index, rx_byte_index   : std_logic_vector (7 downto 0);
   -- masterfip_rx outputs
  signal rx_fss_received_p, rx_fss_crc_fes_ok_p             : std_logic;
  signal rx_crc_wrong_p, rx_byte_ready_p                    : std_logic;
  signal rx_byte                                            : std_logic_vector (7 downto 0);
  -- wf_production outputs
  signal  byte_to_tx                                        : std_logic_vector (7 downto 0);
  -- masterfip_tx outputs
  signal tx_completed_p    : std_logic;
  -- resets
  signal core_sw_rstn_tmp, fd_sw_rstn_tmp : std_logic;--_vector (0 downto 0);
  signal core_sw_rst, fd_sw_rst : std_logic;
  signal core_sw_rst_p, core_sw_rst_n, fd_sw_rst_n : std_logic;
  signal core_sw_rstn_lock : std_logic_vector (15 downto 0);
  -- counters
  signal macrocyc_lgth, turnar_lgth, silen_lgth : std_logic_vector (31 downto 0);
  signal macrocyc_cnt, turnar_cnt, silen_cnt : std_logic_vector (31 downto 0);
  signal macrocyc_cnt_zero_p, turnar_cnt_zero_p, silen_cnt_zero_p : std_logic; 
  -- tx
  signal tx_rst, tx_start, tx_start_p : std_logic;
  signal tx_bytes_num : std_logic_vector (8 downto 0);
  signal tx_frame : tx_frame_t;
  signal tx_ctrl_byte : std_logic_vector (7 downto 0);
  -- rx
  signal rx_pream_ok, rx_frame_ok_p : std_logic;
  signal rx_frame : rx_frame_t;
  signal rx_ctrl_byte : std_logic_vector (7 downto 0);
  
  -- Chipscope
  component chipscope_ila
    port (
      CONTROL : inout std_logic_vector(35 downto 0);
      CLK     : in    std_logic;
      TRIG0   : in    std_logic_vector(31 downto 0);
      TRIG1   : in    std_logic_vector(31 downto 0);
      TRIG2   : in    std_logic_vector(31 downto 0);
      TRIG3   : in    std_logic_vector(31 downto 0));
  end component;
  component chipscope_icon
    port (
      CONTROL0 : inout std_logic_vector (35 downto 0));
  end component;
  signal CONTROL : std_logic_vector(35 downto 0);
  signal CLK     : std_logic;
  signal TRIG0   : std_logic_vector(31 downto 0);
  signal TRIG1   : std_logic_vector(31 downto 0);
  signal TRIG2   : std_logic_vector(31 downto 0);
  signal TRIG3   : std_logic_vector(31 downto 0);

  
--=================================================================================================
--                                       architecture begin
--=================================================================================================
begin

  rst_n <= not rst_i;
---------------------------------------------------------------------------------------------------
--                                           REGISTERS                                           --
---------------------------------------------------------------------------------------------------
  reg_control_block: fmc_masterfip_csr
  port map(
    -- wishbone
    rst_n_i                              => rst_n,
    clk_sys_i                            => clk_i,
    wb_adr_i                             => wb_adr_i(6 downto 0),
    wb_dat_i                             => wb_dat_i,
    wb_dat_o                             => wb_dat_o,
    wb_cyc_i                             => wb_cyc_i,
    wb_sel_i                             => wb_sel_i,
    wb_stb_i                             => wb_stb_i,
    wb_we_i                              => wb_we_i,
    wb_ack_o                             => wb_ack_o,
    wb_stall_o                           => wb_stall_o,
    -- resets
    mf_rst_core_o                        => core_sw_rstn_tmp,
    mf_rst_fd_o                          => fd_sw_rstn_tmp,
    mf_rst_lock_o                        => core_sw_rstn_lock,
    mf_rst_lock_wr_o                     => core_sw_rst_p,
    -- config
    mf_config_host_bitrate_o             => open,
    mf_config_host_ext_sync_term_en_n_o  => open,
    mf_config_host_subs_o                => open,
    mf_config_fmc_bitrate_i              => "01",
    mf_config_fmc_bitrate_ok_i           => '1',
    -- counters
    mf_macrocyc_lgth_o                   => macrocyc_lgth,
    mf_turnar_lgth_o                     => turnar_lgth,
    mf_silen_lgth_o                      => silen_lgth,
    mf_macrocyc_time_cnt_i               => macrocyc_cnt,
    mf_turnar_time_cnt_i                 => turnar_cnt,
    mf_silen_time_cnt_i                  => silen_cnt,
    -- external sync pulse termination
    mf_ext_sync_tstamp_i                 => "00000000000000000000000000000000",
    -- tx control/status
    mf_tx_rst_o                          => tx_rst,         -- have to convert to pulse
    mf_tx_start_o                        => tx_start,       -- have to convert to pulse
    mf_tx_bytes_num_o                    => tx_bytes_num,
    mf_tx_stop_i                         => tx_completed_p, -- have to extend the pulse
    mf_fd_wdgn_i                         => fd_wdgn_i,
    mf_fd_txer_i                         => fd_txer_i,
    -- rx control/status
    mf_rx_rst_o                          => rx_rst,         -- note: this is not a pulse
    mf_rx_pream_ok_i                     => rx_pream_ok,    -- have to extend the pulse
    mf_rx_frame_ok_i                     => rx_frame_ok_p,    -- have to extend the pulse
    mf_rx_frame_err_i                    => '0',
    mf_rx_frame_err_code_i               => "000",
    mf_rx_bytes_num_i                    => '0' & rx_byte_index,
    -- rx data
    mf_rx_data_ctrl_i                    => rx_ctrl_byte,
    mf_rx_data_reg1_i                    => rx_frame(0),
    mf_rx_data_reg2_i                    => rx_frame(1),
    mf_rx_data_reg3_i                    => rx_frame(2),
    mf_rx_data_reg4_i                    => rx_frame(3),
    mf_rx_data_reg5_i                    => rx_frame(4),
    mf_rx_data_reg6_i                    => rx_frame(5),
    mf_rx_data_reg7_i                    => rx_frame(6),
    mf_rx_data_reg8_i                    => rx_frame(7),
    mf_rx_data_reg9_i                    => rx_frame(8),
    mf_rx_data_reg10_i                   => rx_frame(9),
    mf_rx_data_reg11_i                   => rx_frame(10),
    mf_rx_data_reg12_i                   => rx_frame(11),
    mf_rx_data_reg13_i                   => rx_frame(12),
    mf_rx_data_reg14_i                   => rx_frame(13),
    mf_rx_data_reg15_i                   => rx_frame(14),
    mf_rx_data_reg16_i                   => rx_frame(15),
    mf_rx_data_reg17_i                   => rx_frame(16),
    mf_rx_data_reg18_i                   => rx_frame(17),
    mf_rx_data_reg19_i                   => rx_frame(18),
    mf_rx_data_reg20_i                   => rx_frame(19),
    mf_rx_data_reg21_i                   => rx_frame(20),
    mf_rx_data_reg22_i                   => rx_frame(21),
    mf_rx_data_reg23_i                   => rx_frame(22),
    mf_rx_data_reg24_i                   => rx_frame(23),
    mf_rx_data_reg25_i                   => rx_frame(24),
    mf_rx_data_reg26_i                   => rx_frame(25),
    mf_rx_data_reg27_i                   => rx_frame(26),
    mf_rx_data_reg28_i                   => rx_frame(27),
    mf_rx_data_reg29_i                   => rx_frame(28),
    mf_rx_data_reg30_i                   => rx_frame(29),
    mf_rx_data_reg31_i                   => rx_frame(30),
    mf_rx_data_reg32_i                   => rx_frame(31),
    -- rx data
    mf_tx_data_ctrl_o                    => tx_ctrl_byte,
    mf_tx_data_reg1_o                    => tx_frame(0),
    mf_tx_data_reg2_o                    => tx_frame(1),
    mf_tx_data_reg3_o                    => tx_frame(2),
    mf_tx_data_reg4_o                    => tx_frame(3),
    mf_tx_data_reg5_o                    => tx_frame(4),
    mf_tx_data_reg6_o                    => tx_frame(5),
    mf_tx_data_reg7_o                    => tx_frame(6),
    mf_tx_data_reg8_o                    => tx_frame(7),
    mf_tx_data_reg9_o                    => tx_frame(8),
    mf_tx_data_reg10_o                   => tx_frame(9),
    mf_tx_data_reg11_o                   => tx_frame(10),
    mf_tx_data_reg12_o                   => tx_frame(11),
    mf_tx_data_reg13_o                   => tx_frame(12),
    mf_tx_data_reg14_o                   => tx_frame(13),
    mf_tx_data_reg15_o                   => tx_frame(14),
    mf_tx_data_reg16_o                   => tx_frame(15),
    mf_tx_data_reg17_o                   => tx_frame(16),
    mf_tx_data_reg18_o                   => tx_frame(17),
    mf_tx_data_reg19_o                   => tx_frame(18),
    mf_tx_data_reg20_o                   => tx_frame(19),
    mf_tx_data_reg21_o                   => tx_frame(20),
    mf_tx_data_reg22_o                   => tx_frame(21),
    mf_tx_data_reg23_o                   => tx_frame(22),
    mf_tx_data_reg24_o                   => tx_frame(23),
    mf_tx_data_reg25_o                   => tx_frame(24),
    mf_tx_data_reg26_o                   => tx_frame(25),
    mf_tx_data_reg27_o                   => tx_frame(26),
    mf_tx_data_reg28_o                   => tx_frame(27),
    mf_tx_data_reg29_o                   => tx_frame(28),
    mf_tx_data_reg30_o                   => tx_frame(29),
    mf_tx_data_reg31_o                   => tx_frame(30),
    mf_tx_data_reg32_o                   => tx_frame(31));


---------------------------------------------------------------------------------------------------
--                                             resets                                            --
---------------------------------------------------------------------------------------------------
  sw_reset : process(clk_i)
  begin
    if rising_edge(clk_i) then
      if(rst_n = '0') then
        core_sw_rst_n   <= '0';
        fd_sw_rst_n     <= '0';
      else
        -- protection against accidental write
        if(core_sw_rst_p = '1' and core_sw_rstn_lock = c_RST_UNLOCK_VALUE) then
          core_sw_rst_n <= core_sw_rstn_tmp;--(0);
          fd_sw_rst_n   <= fd_sw_rstn_tmp;--(0);
        end if;
      end if;
    end if;
  end process;

  core_sw_rst <= not core_sw_rst_n;
  fd_rstn_o   <= fd_sw_rst_n;
  core_rst    <= core_sw_rst or rst_i;
  
---------------------------------------------------------------------------------------------------
--                                       macrocycle counter                                      --
---------------------------------------------------------------------------------------------------
  macrocycle_cnt: decr_counter
  generic map(width   => 32)
  port map(
    clk_i             => clk_i,
    rst_i             => core_rst,
    counter_load_i    => macrocyc_cnt_zero_p,
    counter_top_i     => macrocyc_lgth,
    counter_o         => macrocyc_cnt,
    counter_is_zero_o => macrocyc_cnt_zero_p);

---------------------------------------------------------------------------------------------------
--                                       tournaround counter                                     --
---------------------------------------------------------------------------------------------------
  turnaround_cnt: decr_counter
  generic map(width   => 32)
  port map(
    clk_i             => clk_i,
    rst_i             => core_rst,
    counter_load_i    => tx_completed_p,
    counter_top_i     => turnar_lgth,
    counter_o         => turnar_cnt,
    counter_is_zero_o => turnar_cnt_zero_p);

--------------------------------------------------------------------------------------------------
--                                        silence counter                                       --
--------------------------------------------------------------------------------------------------
  silence_cnt: decr_counter
  generic map(width   => 32)
  port map(
    clk_i             => clk_i,
    rst_i             => core_rst,
    counter_load_i    => rx_fss_received_p,
    counter_top_i     => silen_lgth,
    counter_o         => silen_cnt,
    counter_is_zero_o => silen_cnt_zero_p);

--------------------------------------------------------------------------------------------------
--                                        signals for tx                                        --
--------------------------------------------------------------------------------------------------    
  tx_start_pulse_detect: gc_sync_ffs
  generic map(g_sync_edge => "positive")
  port map(
    clk_i    => clk_i,
    rst_n_i  => rst_n,
    data_i   => tx_start,
    ppulse_o => tx_start_p);


--------------------------------------------------------------------------------------------------
--                                        signals for rx                                        --
--------------------------------------------------------------------------------------------------    
  rx_extend_pulses : gc_extend_pulse
    generic map (
      g_width => 5000000)
    port map (
      clk_i      => clk_i,
      rst_n_i    => rst_n,
      pulse_i    => rx_fss_received_p,
      extended_o => rx_pream_ok);    


  -- rx_rst_pulse_detect: gc_sync_ffs
  -- generic map(g_sync_edge => "positive");
  -- port map(
    -- clk_i    => clk_i,
    -- rst_n_i  => rst_n_i,
    -- data_i   => rx_rst,
    -- ppulse_o => rx_rst_p);

      
---------------------------------------------------------------------------------------------------
--                                               rx                                              --
---------------------------------------------------------------------------------------------------
  FIELDRIVE_Receiver: masterfip_rx
  port map(
    uclk_i                => clk_i,
    core_rst_i            => core_rst,
    rate_i                => "01",
    fd_rxd_a_i            => fd_rxd_i,
    rx_rst_i              => rx_rst,
  -------------------------------------------------------------
    rx_byte_index_o       => rx_byte_index, -- should have the amount of bytes
    rx_ctrl_byte_o        => rx_ctrl_byte,
    rx_frame_o            => rx_frame,
    rx_tx_byte_o          => rx_byte,
    rx_byte_ready_p_o     => rx_byte_ready_p,
    rx_fss_crc_fes_ok_p_o => rx_frame_ok_p,
    rx_fss_received_p_o   => rx_fss_received_p,
    rx_crc_wrong_p_o      => rx_crc_wrong_p);
  -------------------------------------------------------------


---------------------------------------------------------------------------------------------------
--                                               tx                                              --
---------------------------------------------------------------------------------------------------

  FIELDRIVE_Transmitter: masterfip_tx
  port map(
    uclk_i                     => clk_i,
    core_rst_i                 => (core_rst or tx_rst),
    rate_i                     => "01",
    tx_bytes_num_i             => tx_bytes_num(7 downto 0),
    tx_start_p_i               => tx_start_p,
    tx_frame_i                 => tx_frame,
    tx_ctrl_byte_i             => tx_ctrl_byte,
  -------------------------------------------------------------
    tx_byte_index_o            => tx_byte_index,
    tx_completed_p_o           => tx_completed_p,
    tx_data_o                  => fd_txd_o,
    tx_enable_o                => fd_txena_o,
    tx_clk_o                   => fd_txck_o);
  -------------------------------------------------------------


---------------------------------------------------------------------------------------------------
--                                              irqs                                             --
---------------------------------------------------------------------------------------------------
  irq_p_o <= '0' & rx_crc_wrong_p & rx_frame_ok_p & rx_fss_received_p & tx_completed_p & turnar_cnt_zero_p & silen_cnt_zero_p & macrocyc_cnt_zero_p;
  

---------------------------------------------------------------------------------------------------
--                                              aux                                             --
---------------------------------------------------------------------------------------------------  
  
  aux_o <= "0000000" & tx_start_p;
---------------------------------------------------------------------------------------------------
--                                           CHIPSCOPE                                           --
---------------------------------------------------------------------------------------------------   
  
--   chipscope_ila_1 : chipscope_ila
--   port map (
--     CONTROL => CONTROL,
--     CLK     => clk_i,
--     TRIG0   => TRIG0,
--     TRIG1   => TRIG1,
--     TRIG2   => TRIG2,
--     TRIG3   => TRIG3);

--  chipscope_icon_1 : chipscope_icon
--   port map (
--     CONTROL0 => CONTROL);
 
--  TRIG0(7 downto 0)   <= rx_byte;
--  TRIG0(8)            <= rx_byte_ready_p;
--  TRIG0(16 downto 9)  <= byte_to_tx;
--  TRIG0(17)           <= tx_start_p;
--  TRIG0(18)           <= rx_fss_crc_fes_ok_p;
--  TRIG0(19)           <= start_tx_p;
--  TRIG0(20)           <= tx_completed_p;
--  TRIG0(21)           <= rx_fss_crc_fes_ok_p;
--  TRIG0(22)           <= rx_fss_received_p;
--  TRIG0(23)           <= rx_crc_wrong_p;

--  TRIG1(7 downto 0)   <= tx_byte_index;
--  TRIG1(15 downto 8)  <= rx_byte_index;
--  TRIG1(16)           <= irq_p;

--  TRIG0(16)           <= start_from_fpga;  
--  TRIG0(24 downto 17) <= retrig_nb_offset(7 downto 0);
--  TRIG0(31 downto 25) <= clk_i_cycles_offset(6 downto 0);  
--
--  TRIG1(30 downto 0)  <= acam_tstamp1(30 downto 0);
--  TRIG1(31)           <= acam_tstamp1_ok_p;
--
--  TRIG2(31 downto 0)  <= utc(31 downto 0); 
--  
--  TRIG3(0)            <= tdc_in_fpga_1_i;
--  TRIG3(1)            <= roll_over_incr_recent;
--  TRIG3(2)            <= wrabbit_tai_p_i;
--  TRIG3(31 downto 3)  <= current_retrig_nb(28 downto 0);
  
end rtl;
----------------------------------------------------------------------------------------------------
--  architecture ends
----------------------------------------------------------------------------------------------------