-------------------------------------------------------------------------------
-- Title      : WR Switch 18-ports top level
-- Project    : White Rabbit Switch
-------------------------------------------------------------------------------
-- File       : scb_top_synthesis.vhd
-- Author     : Tomasz Wlostowski, Maciej Lipinski, Grzegorz Daniluk
-- Company    : CERN BE-CO-HT
-- Created    : 2012-02-21
-- Last update: 2014-03-20
-- Platform   : FPGA-generic
-- Standard   : VHDL
-------------------------------------------------------------------------------
-- Description:
-- WR Switch 18-port version top synthesis level.
-------------------------------------------------------------------------------
--
-- Copyright (c) 2012 - 2014 CERN / BE-CO-HT
--
-- 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
--
-------------------------------------------------------------------------------

library ieee;
use ieee.STD_LOGIC_1164.all;
use ieee.numeric_std.all;
use ieee.std_logic_misc.all;

use work.wishbone_pkg.all;
use work.gencores_pkg.all;
use work.wr_fabric_pkg.all;
use work.endpoint_pkg.all;
use work.wr_txtsu_pkg.all;
use work.wrsw_top_pkg.all;


library UNISIM;
use UNISIM.vcomponents.all;


entity scb_top_synthesis is
  generic(
    g_cpu_addr_width : integer := 19;
    g_simulation     : boolean := false
    );
  port (
    sys_rst_n_i : in std_logic;         -- global reset

    -- Startup 25 MHz clock (from onboard 25 MHz oscillator)
    fpga_clk_25mhz_p_i : in std_logic;
    fpga_clk_25mhz_n_i : in std_logic;

    -- 125 MHz timing reference (from the AD9516 PLL output QDRII_CLK)
    fpga_clk_ref_p_i : in std_logic;
    fpga_clk_ref_n_i : in std_logic;

    -- 125+ MHz DMTD offset clock (from the CDCM62001 PLL output DMTDCLK_MAIN)
    fpga_clk_dmtd_p_i : in std_logic;
    fpga_clk_dmtd_n_i : in std_logic;

    -- 10MHz out clock generated from oserdes
    clk_aux_p_o  : out std_logic;
    clk_aux_n_o  : out std_logic;

    -------------------------------------------------------------------------------
    -- Atmel EBI bus
    -------------------------------------------------------------------------------
    cpu_clk_i   : in    std_logic;      -- clock (not used now)
    -- async chip select, active LOW
    cpu_cs_n_i  : in    std_logic;
    -- async write, active LOW
    cpu_wr_n_i  : in    std_logic;
    -- async read, active LOW
    cpu_rd_n_i  : in    std_logic;
    -- byte select, active  LOW (not used due to weird CPU pin layout - NBS2 line is
    -- shared with 100 Mbps Ethernet PHY)
    cpu_bs_n_i  : in    std_logic_vector(3 downto 0);
    -- address input
    cpu_addr_i  : in    std_logic_vector(g_cpu_addr_width-1 downto 0);
    -- data bus (bidirectional)
    cpu_data_b  : inout std_logic_vector(31 downto 0);
    -- async wait, active LOW
    cpu_nwait_o : out   std_logic;

    cpu_irq_n_o : out std_logic;

    -------------------------------------------------------------------------------
    -- Timing I/O
    -------------------------------------------------------------------------------    

    pps_i        : in  std_logic;
    ppsin_term_o : out std_logic;  -- 50Ohm termination enable for 1-PPS in
    pps_o        : out std_logic;

    -- DAC Drive
    dac_helper_sync_n_o : out std_logic;
    dac_helper_sclk_o   : out std_logic;
    dac_helper_data_o   : out std_logic;

    dac_main_sync_n_o : out std_logic;
    dac_main_sclk_o   : out std_logic;
    dac_main_data_o   : out std_logic;


    -------------------------------------------------------------------------------
    -- AD9516 PLL Control signals
    -------------------------------------------------------------------------------    

    pll_status_i  : in  std_logic;
    pll_mosi_o    : out std_logic;
    pll_miso_i    : in  std_logic;
    pll_sck_o     : out std_logic;
    pll_cs_n_o    : out std_logic;
    pll_sync_n_o  : out std_logic;
    pll_reset_n_o : out std_logic;

    uart_txd_o : out std_logic;
    uart_rxd_i : in  std_logic;

    -------------------------------------------------------------------------------
    -- Clock fanout control
    -------------------------------------------------------------------------------
    clk_en_o  : out std_logic;
    clk_sel_o : out std_logic;

    -- DMTD clock divider selection (0 = 125 MHz, 1 = 62.5 MHz)
    clk_dmtd_divsel_o : out std_logic;

    -- UART source selection (FPGA/DBGU)
    -- uart_sel_o : out std_logic;

    ---------------------------------------------------------------------------
    -- GTX ports
    ---------------------------------------------------------------------------

    gtx_clk_n_i : in std_logic_vector(4 downto 0);
    gtx_clk_p_i : in std_logic_vector(4 downto 0);

    gtx_rxp_i : in std_logic_vector(17 downto 0);
    gtx_rxn_i : in std_logic_vector(17 downto 0);

    gtx_txp_o : out std_logic_vector(17 downto 0);
    gtx_txn_o : out std_logic_vector(17 downto 0);

    ---------------------------------------------------------------------------
    -- Mini-Backplane signals
    ---------------------------------------------------------------------------

    led_act_o : out std_logic_vector(17 downto 0);

    mbl_scl_b : inout std_logic_vector(1 downto 0);
    mbl_sda_b : inout std_logic_vector(1 downto 0);

    sensors_scl_b: inout std_logic;
    sensors_sda_b: inout std_logic;

    mb_fan1_pwm_o : out std_logic;
    mb_fan2_pwm_o : out std_logic

  );

end scb_top_synthesis;

architecture Behavioral of scb_top_synthesis is

  component swcore_pll is
   port
   (-- Clock in ports
    clk_sys_i           : in     std_logic;
    -- Clock out ports
    clk_aux_o          : out    std_logic
   );
  end component;

  component ext_pll_10_to_100 is
  port (
    clk_ext_i     : in  std_logic;
    clk_ext_100_o : out std_logic;
    rst_a_i       : in  std_logic;
    locked_o      : out std_logic);
  end component;

  component ext_pll_100_to_62m is
  port(
    clk_ext_100_i : in  std_logic;
    clk_ext_mul_o : out std_logic;
    rst_a_i       : in  std_logic;
    locked_o      : out std_logic);
  end component;


  constant c_NUM_PHYS  : integer := 18;
  constant c_NUM_PORTS : integer := 18;

  function f_bool2int(x : boolean) return integer is
  begin
    if(x) then
      return 1;
    else
      return 0;
    end if;
  end f_bool2int;


  -------------------------------------------------------------------------------
  -- Clocks
  -------------------------------------------------------------------------------



  signal clk_sys_startup                        : std_logic;
  signal clk_sys, clk_ref, clk_25mhz , clk_dmtd : std_logic;
  signal pllout_clk_fb                          : std_logic;

  attribute maxskew: string;
  attribute maxskew of clk_dmtd : signal is "1.0ns";
  -----------------------------------------------------------------------------
  -- Component declarations
  -----------------------------------------------------------------------------

  component IBUFGDS
    generic (
      DIFF_TERM  : boolean := true;
      IOSTANDARD : string  := "DEFAULT")  ;
    port (
      O  : out std_ulogic;
      I  : in  std_ulogic;
      IB : in  std_ulogic);
  end component;

  component BUFGMUX
    generic (
      CLK_SEL_TYPE : string := "SYNC");
    port (
      O  : out std_ulogic := '0';
      I0 : in  std_ulogic := '0';
      I1 : in  std_ulogic := '0';
      S  : in  std_ulogic := '0');
  end component;


  signal to_phys   : t_phyif_output_array(c_NUM_PHYS-1 downto 0);
  signal from_phys : t_phyif_input_array(c_NUM_PHYS-1 downto 0);

  signal clk_aux      : std_logic;

  signal clk_gtx_ibuf : std_logic_vector(5-1 downto 0);
  signal clk_gtx : std_logic_vector(c_NUM_PHYS-1 downto 0);

  signal cpu_nwait_int : std_logic;

  signal top_master_in, bridge_master_in   : t_wishbone_master_in;
  signal top_master_out, bridge_master_out : t_wishbone_master_out;

  signal i2c_scl_oen : std_logic_vector(2 downto 0);
  signal i2c_scl_out : std_logic_vector(2 downto 0);
  signal i2c_sda_oen : std_logic_vector(2 downto 0);
  signal i2c_sda_out : std_logic_vector(2 downto 0);
  signal i2c_sda_in : std_logic_vector(2 downto 0);
  signal i2c_scl_in : std_logic_vector(2 downto 0);

  attribute buffer_type             : string;
  attribute buffer_type of clk_dmtd : signal is "BUFG";
  attribute buffer_type of clk_ref  : signal is "BUFG";
  attribute buffer_type of clk_aux  : signal is "BUFG";
  attribute buffer_type of clk_sys  : signal is "BUFG";

	signal local_reset, ext_pll_reset : std_logic;
	signal clk_ext, clk_ext_mul	:	 std_logic;
  signal clk_ext_100 : std_logic;
  signal ext_pll_100_locked, ext_pll_62_locked : std_logic;
  signal clk_ext_mul_locked : std_logic;

  component scb_top_bare
    generic (
      g_num_ports       : integer;
      g_simulation      : boolean;
      g_without_network : boolean;
      g_with_TRU        : boolean;
      g_with_TATSU      : boolean;
      g_with_HWIU       : boolean;
      g_with_PSTATS     : boolean;
      g_with_muxed_CS   : boolean;
      g_with_watchdog   : boolean;
      g_inj_per_EP      : std_logic_vector(17 downto 0));
    port (
      sys_rst_n_i         : in  std_logic;
      clk_startup_i       : in  std_logic;
      clk_ref_i           : in  std_logic;
      clk_dmtd_i          : in  std_logic;
      clk_aux_i           : in  std_logic;
			clk_ext_mul_i				:	in	std_logic;
			clk_ext_mul_locked_i:	in	std_logic;
      clk_aux_p_o         : out std_logic;
      clk_aux_n_o         : out std_logic;
      clk_sys_o           : out std_logic;
      cpu_wb_i            : in  t_wishbone_slave_in;
      cpu_wb_o            : out t_wishbone_slave_out;
      cpu_irq_n_o         : out std_logic;
      pps_i               : in  std_logic;
      ppsin_term_o        : out std_logic;
      pps_o               : out std_logic;
      dac_helper_sync_n_o : out std_logic;
      dac_helper_sclk_o   : out std_logic;
      dac_helper_data_o   : out std_logic;
      dac_main_sync_n_o   : out std_logic;
      dac_main_sclk_o     : out std_logic;
      dac_main_data_o     : out std_logic;
      pll_status_i        : in  std_logic;
      pll_mosi_o          : out std_logic;
      pll_miso_i          : in  std_logic;
      pll_sck_o           : out std_logic;
      pll_cs_n_o          : out std_logic;
      pll_sync_n_o        : out std_logic;
      pll_reset_n_o       : out std_logic;
      uart_txd_o          : out std_logic;
      uart_rxd_i          : in  std_logic;
      clk_en_o            : out std_logic;
      clk_sel_o           : out std_logic;
      uart_sel_o          : out std_logic;
      clk_dmtd_divsel_o   : out std_logic;
      phys_o              : out t_phyif_output_array(g_num_ports-1 downto 0);
      phys_i              : in  t_phyif_input_array(g_num_ports-1 downto 0);
      led_link_o          : out std_logic_vector(g_num_ports-1 downto 0);
      led_act_o           : out std_logic_vector(g_num_ports-1 downto 0);
      gpio_o              : out std_logic_vector(31 downto 0);
      gpio_i              : in  std_logic_vector(31 downto 0);
      i2c_scl_oen_o   : out std_logic_vector(2 downto 0);
      i2c_scl_o       : out std_logic_vector(2 downto 0);
      i2c_scl_i       : in  std_logic_vector(2 downto 0) := "111";
      i2c_sda_oen_o   : out std_logic_vector(2 downto 0);
      i2c_sda_o       : out std_logic_vector(2 downto 0);
      i2c_sda_i       : in  std_logic_vector(2 downto 0) := "111";
      mb_fan1_pwm_o   : out std_logic;
      mb_fan2_pwm_o   : out std_logic;
      spll_dbg_o    : out std_logic_vector(5 downto 0)
      );
  end component;

  component chipscope_icon
    port (
      CONTROL0 : inout std_logic_vector(35 downto 0));
  end component;

  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;

  signal CONTROL : std_logic_vector(35 downto 0);
  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);
begin


  --chipscope_icon_1 : chipscope_icon
  --  port map (
  --    CONTROL0 => CONTROL);

  --chipscope_ila_1 : chipscope_ila
  --  port map (
  --    CONTROL => CONTROL,
  --    CLK     => clk_25mhz,
  --    TRIG0   => TRIG0,
  --    TRIG1   => TRIG1,
  --    TRIG2   => TRIG2,
  --    TRIG3   => TRIG3);

  --TRIG0(0) <= mbl_scl_b(0);
  --TRIG0(1) <= mbl_sda_b(0);
  --TRIG0(2) <= mbl_scl_b(1);
  --TRIG0(3) <= mbl_sda_b(1);
  --TRIG1                              <= cpu_data_b;
  --TRIG2(0)                           <= cpu_cs_n_i;
  --TRIG2(1)                           <= cpu_rd_n_i;
  --TRIG2(2)                           <= cpu_wr_n_i;
  --TRIG2(3) <= sys_rst_n_i;

  gtx_clk_buf_gen : for i in 0 to 4 generate
    u_gtx_clk_buf : IBUFDS_GTE4
    port map (
      O     => clk_gtx_ibuf(i),
      ODIV2 => open,
      CEB   => '0',     -- clock enable (active LOW)
      I     => gtx_clk_p_i(i),
      IB    => gtx_clk_n_i(i)
    );
  
  end generate;
  
  U_Buf_CLK_Startup : IBUFDS
    generic map (
      DIFF_TERM  => true,
      IOSTANDARD => "LVDS_25")
    port map (
      O  => clk_25mhz,
      I  => fpga_clk_25mhz_p_i,
      IB => fpga_clk_25mhz_n_i);

  U_Buf_CLK_Ref : IBUFDS
    generic map (
      DIFF_TERM  => true,
      IOSTANDARD => "LVDS_25")
    port map (
      O  => clk_ref,
      I  => fpga_clk_ref_p_i,
      IB => fpga_clk_ref_n_i);

  U_Buf_CLK_DMTD : IBUFDS
    generic map (
      DIFF_TERM  => true,
      IOSTANDARD => "LVDS_25")
    port map (
      O  => clk_dmtd,
      I  => fpga_clk_dmtd_p_i,
      IB => fpga_clk_dmtd_n_i);

  U_swcore_pll: swcore_pll port map  ( clk_sys_i => clk_ref, clk_aux_o => clk_aux); 
 
  U_SYS_PLL : PLL_BASE
    generic map (
      BANDWIDTH          => "OPTIMIZED",
      CLK_FEEDBACK       => "CLKFBOUT",
      COMPENSATION       => "INTERNAL",
      DIVCLK_DIVIDE      => 1,
      CLKFBOUT_MULT      => 40,
      CLKFBOUT_PHASE     => 0.000,
      CLKOUT0_DIVIDE     => 16,         -- 62.5 MHz
      CLKOUT0_PHASE      => 0.000,
      CLKOUT0_DUTY_CYCLE => 0.500,
      CLKOUT1_DIVIDE     => 16,         -- 62.5 MHz
      CLKOUT1_PHASE      => 0.000,
      CLKOUT1_DUTY_CYCLE => 0.500,
      CLKOUT2_DIVIDE     => 8,
      CLKOUT2_PHASE      => 0.000,
      CLKOUT2_DUTY_CYCLE => 0.500,
      CLKIN_PERIOD       => 40.0,
      REF_JITTER         => 0.016)
    port map (
      CLKFBOUT => pllout_clk_fb,
      CLKOUT0  => clk_sys_startup,
      CLKOUT1  => open,
      CLKOUT2  => open,
      CLKOUT3  => open,
      CLKOUT4  => open,
      CLKOUT5  => open,
      LOCKED   => open,
      RST      => '0',
      CLKFBIN  => pllout_clk_fb,
      CLKIN    => clk_25mhz);


	-- Make 62.5MHz from 10MHz for locking ext clock in new SoftPLL
	U_CLKEXT_BUF: IBUFG
		port map (
			I => pll_status_i,
			O => clk_ext);

  U_Ext_PLL1: ext_pll_10_to_100
    port map(
      clk_ext_i     => clk_ext,
      clk_ext_100_o => clk_ext_100,
      rst_a_i       => ext_pll_reset,
      locked_o      => ext_pll_100_locked);

  U_Ext_PLL2: ext_pll_100_to_62m
    port map(
      clk_ext_100_i => clk_ext_100,
      clk_ext_mul_o => clk_ext_mul,
      rst_a_i       => ext_pll_reset,
      locked_o      => ext_pll_62_locked);

  clk_ext_mul_locked <= ext_pll_100_locked and ext_pll_62_locked;

	local_reset <= not sys_rst_n_i;
	U_Extend_EXT_Reset: gc_extend_pulse
		generic map (
			g_width => 1000)
		port map(
			clk_i 		 => clk_sys,
			rst_n_i 	 => sys_rst_n_i,
			pulse_i		 => local_reset,
			extended_o => ext_pll_reset);

  ------------------------------------------------    
  cmp_wb_cpu_bridge : wb_cpu_bridge
    --generic map(
    --)
    port map(
      sys_rst_n_i => sys_rst_n_i,

      -- Atmel EBI bus
      cpu_clk_i   => cpu_clk_i,
      cpu_cs_n_i  => cpu_cs_n_i,
      cpu_wr_n_i  => cpu_wr_n_i,
      cpu_rd_n_i  => cpu_rd_n_i,
      cpu_bs_n_i  => "1111",
      cpu_addr_i  => cpu_addr_i,
      cpu_data_b  => cpu_data_b,
      cpu_nwait_o => cpu_nwait_int,

      wb_clk_i  => clk_sys,
      wb_addr_o => bridge_master_out.adr(18 downto 0),
      wb_data_o => bridge_master_out.dat,
      wb_stb_o  => bridge_master_out.stb,
      wb_we_o   => bridge_master_out.we,
      wb_sel_o  => bridge_master_out.sel,
      wb_cyc_o  => bridge_master_out.cyc,
      wb_data_i => bridge_master_in.dat,
      wb_ack_i  => bridge_master_in.ack
      );

  bridge_master_out.adr(31 downto 19) <= (others => '0');

  U_Bridge_to_pipelined : wb_slave_adapter
    generic map (
      g_master_use_struct  => true,
      g_master_mode        => PIPELINED,
      g_master_granularity => BYTE,
      g_slave_use_struct   => true,
      g_slave_mode         => CLASSIC,
      g_slave_granularity  => WORD)
    port map (
      clk_sys_i => clk_sys,
      rst_n_i   => sys_rst_n_i,
      slave_i   => bridge_master_out,
      slave_o   => bridge_master_in,
      master_i  => top_master_in,
      master_o  => top_master_out);

  cpu_nwait_o <= cpu_nwait_int;


-------------------------------------------------------------------------------
-- GTX PHYs
-------------------------------------------------------------------------------  

  clk_gtx(3 downto 0)   <= (others => clk_gtx_ibuf(0));
  clk_gtx(7 downto 4)   <= (others => clk_gtx_ibuf(1));
  clk_gtx(11 downto 8)  <= (others => clk_gtx_ibuf(2));
  clk_gtx(15 downto 12) <= (others => clk_gtx_ibuf(3));
  clk_gtx(17 downto 16) <= (others => clk_gtx_ibuf(4));

phy_block: block

  signal to_phys_tx_data    : STD_LOGIC_VECTOR(287 DOWNTO 0);
  signal to_phys_tx_k       : STD_LOGIC_VECTOR(143 DOWNTO 0);
  signal to_phys_rst        : STD_LOGIC;

  signal from_phys_rx_data  : STD_LOGIC_VECTOR(287 DOWNTO 0);
  signal from_phys_rx_k     : STD_LOGIC_VECTOR(287 DOWNTO 0);
  signal from_phys_disp_err : STD_LOGIC_VECTOR(287 DOWNTO 0);
  signal from_phys_rx_comma : STD_LOGIC_VECTOR(143 DOWNTO 0);
  signal from_phys_enc_err  : STD_LOGIC_VECTOR(143 DOWNTO 0);

  signal c25m_to_phys_rst   : STD_LOGIC;
  signal from_phys_tx_enc_err_common   : STD_LOGIC;
  
  signal tx_active          : STD_LOGIC;
  signal rx_active          : STD_LOGIC;
  signal phy_rdy            : STD_LOGIC_VECTOR(c_NUM_PHYS-1 DOWNTO 0);

  signal rxoutclks          : STD_LOGIC_VECTOR(c_NUM_PHYS-1 DOWNTO 0);
  signal rxusrclk2          : STD_LOGIC_VECTOR(c_NUM_PHYS-1 DOWNTO 0);
  
  signal txoutclks          : STD_LOGIC_VECTOR(c_NUM_PHYS-1 DOWNTO 0);
  signal txusrclk2          : STD_LOGIC_VECTOR(c_NUM_PHYS-1 DOWNTO 0);
  
  signal phy_rst_tx         : STD_LOGIC_VECTOR(c_NUM_PHYS-1 DOWNTO 0);

begin
  

  --reset of one channels resets all of them...
  or_reduce_manual : process (to_phys)
    variable to_phys_rst_v  : std_logic;
  begin
    
    to_phys_rst_v := '0';
    for i in 0 to c_NUM_PHYS-1 loop
      to_phys_rst_v := to_phys_rst_v or to_phys(i).rst;
    end loop;
    to_phys_rst <= to_phys_rst_v;

  end process or_reduce_manual;

  --sychronize to free running clock domain 
  --frequency must be below 50 MHz (set to 25 MHz) so can't use WRCLK/2 
  sync_rst : process (clk_25mhz)
  begin
    if (rising_edge(clk_25mhz)) then
      c25m_to_phys_rst  <= to_phys_rst;
    end if;
  end process sync_rst;

  --change from long vectors to records
  concatenate_gen : for i in 0 to c_NUM_PHYS-1 generate
    to_phys_tx_data(16*(i+1)-1 downto 16*i) 
                          <= to_phys(i).tx_data;
    
    --not sure if it shouldn't be swapped
    to_phys_tx_k(8*i)     <= to_phys(i).tx_k(0);
    to_phys_tx_k(8*i+1)   <= to_phys(i).tx_k(1);
    to_phys_tx_k(8*(i+1)-1 downto 8*i+2)   <= (others=>'0');

    
    from_phys(i).rx_clk       <= rxusrclk2(i);
    from_phys(i).rx_data      <= from_phys_rx_data(16*(i+1)-1 downto 16*i);
    
    -- actually only bits 0 and 1 out out 16 assigned to each channels are used
    from_phys(i).tx_disparity <= or_reduce( from_phys_disp_err(16*(i+1)-1 downto 16*i ) );
    
    -- ip sigals enc error for all channels combined
    from_phys(i).tx_enc_err   <= from_phys_tx_enc_err_common;
    
    -- actually only bits 0 and 1 out out 16 assigned to each channels are used
    from_phys(i).rx_k         <= from_phys_rx_comma(8*(i+1)-7 downto 8*i );
    
    -- actually only bits 0 and 1 out out 16 assigned to each channels are used
    from_phys(i).rx_enc_err   <= or_reduce( from_phys_enc_err(8*(i+1)-1 downto 8*i ) );
    
    -- bitslide is done automatically inside core
    -- (incompatible with WR)
    from_phys(i).rx_bitslide  <= (others => '0');

    -- phy_rdy is asserted when tx and rx are active 
    -- (incompatible with WR)
    from_phys(i).rdy          <= phy_rdy(i);

    -- reset sync
    sync_tx_rst_sp : process (txusrclk2(i))
    begin
      if (rising_edge(txusrclk2(i))) then
        phy_rst_tx(i)  <= c25m_to_phys_rst;
      end if;
    end process sync_tx_rst_sp;

    -- phy ready sync
    sync_phy_rdy_sp : process (rxusrclk2(i))
    begin
      if (rising_edge(rxusrclk2(i))) then
        phy_rdy(i)  <= tx_active and rx_active;
      end if;
    end process sync_phy_rdy_sp;
  end generate;

  --clock buffers for rx clock
  genbufg : for i in 0 to c_NUM_PHYS-1 generate
    U_RX_Clock_Buffer : BUFG_GT port map
    (
      CE      => '1',
      CEMASK  => '0',
      CLR     => '0',
      CLRMASK => '0',
      DIV     => "000",
      I       => rxoutclks(i),
      O       => rxusrclk2(i)
      );


    --clock buffers for tx clock
    U_TX_Clock_Buffer : BUFG_GT port map
    (
      CE      => '1',
      CEMASK  => '0',
      CLR     => '0',
      CLRMASK => '0',
      DIV     => "000",
      I       => txoutclks(i),
      O       => txusrclk2(i)
      );
  end generate;


phys: entity work.gtwizard_ultrascale_1
  port map(
    gtwiz_userclk_tx_reset_in(0)           => c25m_to_phys_rst,
    gtwiz_userclk_tx_active_in(0)          => '1',
    gtwiz_userclk_rx_active_in(0)          => '1',
    gtwiz_buffbypass_tx_reset_in           => (others => c25m_to_phys_rst), 
    gtwiz_buffbypass_tx_start_user_in      => (others => '0'),
    gtwiz_buffbypass_tx_done_out           => open, 
    gtwiz_buffbypass_tx_error_out(0)       => from_phys_tx_enc_err_common,
    
    gtwiz_buffbypass_rx_reset_in           => (others => c25m_to_phys_rst),
    gtwiz_buffbypass_rx_start_user_in      => (others => '0'),
    gtwiz_buffbypass_rx_done_out           => open,
    gtwiz_buffbypass_rx_error_out          => open,

    gtwiz_reset_clk_freerun_in             => (others => clk_25mhz),
    gtwiz_reset_all_in                     => (others => c25m_to_phys_rst),
    gtwiz_reset_tx_pll_and_datapath_in     => (others => '0'),
    gtwiz_reset_tx_datapath_in             => (others => '0'),
    gtwiz_reset_rx_pll_and_datapath_in     => (others => '0'),
    gtwiz_reset_rx_datapath_in             => (others => '0'),
    
    gtwiz_reset_rx_cdr_stable_out          => open,
    gtwiz_reset_tx_done_out => open,
    gtwiz_reset_rx_done_out => open,
    
    gtwiz_userdata_tx_in    => to_phys_tx_data,
    gtwiz_userdata_rx_out   => from_phys_rx_data,
    
    drpclk_in     => (others => clk_25mhz ),
    
    gthrxn_in     => gtx_rxn_i,
    gthrxp_in     => gtx_rxp_i,
    gtrefclk0_in  => clk_gtx,
    
    rx8b10ben_in => (others => '1'),
    rxusrclk_in   => rxusrclk2,
    rxusrclk2_in  => rxusrclk2,
    
    tx8b10ben_in => (others => '1'),
    -- Set High (on TXCTRL1) to work with TXCTRL0 to force running disparity negative or positive when encoding TXDATA. 
    -- Set Low to use normal running disparity. 
    txctrl0_in    => (others => '0'),
    txctrl1_in    => (others => '0'),
    
    txctrl2_in        => to_phys_tx_k,
    txusrclk_in       => txusrclk2,
    txusrclk2_in      => txusrclk2,

    gthtxn_out        => gtx_txn_o,
    gthtxp_out        => gtx_txp_o,
    gtpowergood_out   => open,
    --pg182: table 2-25
    --ug576: table 4-27
    rxctrl0_out             => from_phys_rx_k,
    rxctrl1_out             => from_phys_disp_err,
    rxctrl2_out             => from_phys_rx_comma,
    rxctrl3_out             => from_phys_enc_err,
    
    rxoutclk_out            => rxoutclks, 
    rxpmaresetdone_out      => open,
    
    txoutclk_out            => txoutclks,
    txpmaresetdone_out      => open,
    txprgdivresetdone_out   => open
  );

  end block phy_block;

  gen_terminate_unused_phys : for i in c_NUM_PORTS to c_NUM_PHYS-1 generate
    to_phys(i).tx_data <= (others => '0');
    to_phys(i).tx_k    <= (others => '0');
    to_phys(i).rst     <= '1';
    to_phys(i).loopen  <= '0';
    led_act_o(i)       <= '0';
  end generate gen_terminate_unused_phys;



  -----------------------------------------------------------------------------
  -- "Bare" top module instantiation
  -----------------------------------------------------------------------------

  U_Real_Top : scb_top_bare
    generic map (
      g_num_ports       => c_NUM_PORTS,
      g_simulation      => g_simulation,
      g_without_network => false,
      g_with_TRU        => false,
      g_with_TATSU      => false,
      g_with_HWIU       => true,
      g_with_PSTATS     => true,
      g_with_muxed_CS   => false,
      g_with_watchdog   => true,
      g_inj_per_EP      => "00" & x"0000")
    port map (
      sys_rst_n_i         => sys_rst_n_i,
      clk_startup_i       => clk_sys_startup,
      clk_ref_i           => clk_ref,
      clk_dmtd_i          => clk_dmtd,
      clk_sys_o           => clk_sys,
      clk_aux_i           => clk_aux,
			clk_ext_mul_i				=> clk_ext_mul,
      clk_ext_mul_locked_i=> clk_ext_mul_locked,
      clk_aux_p_o         => clk_aux_p_o,
      clk_aux_n_o         => clk_aux_n_o,
      cpu_wb_i            => top_master_out,
      cpu_wb_o            => top_master_in,
      cpu_irq_n_o         => cpu_irq_n_o,
      pps_i               => pps_i,
      ppsin_term_o        => ppsin_term_o,
      pps_o               => pps_o,
      dac_helper_sync_n_o => dac_helper_sync_n_o,
      dac_helper_sclk_o   => dac_helper_sclk_o,
      dac_helper_data_o   => dac_helper_data_o,
      dac_main_sync_n_o   => dac_main_sync_n_o,
      dac_main_sclk_o     => dac_main_sclk_o,
      dac_main_data_o     => dac_main_data_o,
      pll_status_i        => clk_ext,
      pll_mosi_o          => pll_mosi_o,
      pll_miso_i          => pll_miso_i,
      pll_sck_o           => pll_sck_o,
      pll_cs_n_o          => pll_cs_n_o,
      pll_sync_n_o        => pll_sync_n_o,
      pll_reset_n_o       => pll_reset_n_o,
      uart_txd_o          => uart_txd_o,
      uart_rxd_i          => uart_rxd_i,
      clk_en_o            => clk_en_o,
      clk_sel_o           => clk_sel_o,
--    uart_sel_o          => uart_sel_o,
      clk_dmtd_divsel_o   => clk_dmtd_divsel_o,
      gpio_i              => x"00000000",
      phys_o              => to_phys(c_NUM_PORTS-1 downto 0),
      phys_i              => from_phys(c_NUM_PORTS-1 downto 0),
--      led_link_o          => led_link_o,
      led_act_o           => led_act_o(c_NUM_PORTS-1 downto 0),
      i2c_scl_oen_o   => i2c_scl_oen,
      i2c_scl_o       => i2c_scl_out,
      i2c_scl_i       => i2c_scl_in,
      i2c_sda_oen_o   => i2c_sda_oen,
      i2c_sda_o       => i2c_sda_out,
      i2c_sda_i       => i2c_sda_in,
      mb_fan1_pwm_o   => mb_fan1_pwm_o,
      mb_fan2_pwm_o   => mb_fan2_pwm_o,
      spll_dbg_o      => open);

  i2c_scl_in(1 downto 0) <= mbl_scl_b(1 downto 0);
  i2c_sda_in(1 downto 0) <= mbl_sda_b(1 downto 0);

  i2c_scl_in(2) <= sensors_scl_b;
  i2c_sda_in(2) <= sensors_sda_b;
  
  gen_i2c_tribufs : for i in 0 to 1 generate
    mbl_scl_b(i) <= i2c_scl_out(i) when i2c_scl_oen(i) = '0' else 'Z';
    mbl_sda_b(i) <= i2c_sda_out(i) when i2c_sda_oen(i) = '0' else 'Z';
  end generate gen_i2c_tribufs;

  sensors_scl_b <= i2c_scl_out(2) when i2c_scl_oen(2) = '0' else 'Z';
  sensors_sda_b <= i2c_sda_out(2) when i2c_sda_oen(2) = '0' else 'Z';


end Behavioral;


