--------------------------------------------------------------------------------
-- CERN (BE-CO-HT)
-- Top level entity for Simple PCIe FMC Carrier
-- http://www.ohwr.org/projects/spec
--------------------------------------------------------------------------------
--
-- unit name: spec_pts_usb (spec_pts_usb.vhd)
--
-- author: INCAA Computers BV (info@incaacomputers.com)
--
-- date: 13-06-2013
--
-- version: see sdb_meta_pkg.vhd
--
-- description: Top entity of PTS design for SPEC board.
--   Testing of the "USB to UART" chip IC17. For this test a USB cable needs to be
--   plugged between a USB port of the PC and the USB connector of the SPEC under test.
--
--   This test reads the alphabet that has been written to the USB tty.
--   Note that the firmware loaded to the FPGA implements the loop between
--   the transmitter and the receiver of the USB to UART chip.
--
-- dependencies:
--
--------------------------------------------------------------------------------
-- 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
--------------------------------------------------------------------------------
-- last changes: see git log.
--------------------------------------------------------------------------------
-- TODO: - 
--------------------------------------------------------------------------------

library IEEE;
use IEEE.STD_LOGIC_1164.all;
use IEEE.NUMERIC_STD.all;

library UNISIM;
use UNISIM.vcomponents.all;

library work;
use work.gn4124_core_pkg.all;
use work.gencores_pkg.all;
use work.wishbone_pkg.all;
use work.sdb_meta_pkg.all;
use work.spec_pts_pkg.all;

entity spec_pts_usb is
  generic(
    g_SIMULATION          : string := "FALSE";
    g_CALIB_SOFT_IP       : string := "TRUE");
  port
    (
      -- Local oscillator
      clk20_vcxo_i : in std_logic;      -- 20MHz VCXO clock

      clk_125m_pllref_p_i : in std_logic;  -- 125 MHz PLL reference
      clk_125m_pllref_n_i : in std_logic;

      fpga_pll_ref_clk_101_p_i : in std_logic;  -- Dedicated clock for Xilinx GTP transceiver
      fpga_pll_ref_clk_101_n_i : in std_logic;      

      fpga_pll_ref_clk0_123_p_i : in std_logic;  -- Dedicated clock for Xilinx GTP transceiver
      fpga_pll_ref_clk0_123_n_i : in std_logic;      

      -- Carrier font panel LEDs
      led_red_o   : out std_logic;
      led_green_o : out std_logic;

      -- Auxiliary pins
      aux_leds_o    : out std_logic_vector(3 downto 0);
      aux_buttons_i : in  std_logic_vector(1 downto 0);

      -- PCB version
      pcb_ver_i : in std_logic_vector(3 downto 0);

      -- Carrier 1-wire interface (DS18B20 thermometer + unique ID)
      carrier_one_wire_b : inout std_logic;

      -- GN4124 interface
      L_CLKp       : in    std_logic;                      -- Local bus clock (frequency set in GN4124 config registers)
      L_CLKn       : in    std_logic;                      -- Local bus clock (frequency set in GN4124 config registers)
      L_RST_N      : in    std_logic;                      -- Reset from GN4124 (RSTOUT18_N)
      P2L_RDY      : out   std_logic;                      -- Rx Buffer Full Flag
      P2L_CLKn     : in    std_logic;                      -- Receiver Source Synchronous Clock-
      P2L_CLKp     : in    std_logic;                      -- Receiver Source Synchronous Clock+
      P2L_DATA     : in    std_logic_vector(15 downto 0);  -- Parallel receive data
      P2L_DFRAME   : in    std_logic;                      -- Receive Frame
      P2L_VALID    : in    std_logic;                      -- Receive Data Valid
      P_WR_REQ     : in    std_logic_vector(1 downto 0);   -- PCIe Write Request
      P_WR_RDY     : out   std_logic_vector(1 downto 0);   -- PCIe Write Ready
      RX_ERROR     : out   std_logic;                      -- Receive Error
      L2P_DATA     : out   std_logic_vector(15 downto 0);  -- Parallel transmit data
      L2P_DFRAME   : out   std_logic;                      -- Transmit Data Frame
      L2P_VALID    : out   std_logic;                      -- Transmit Data Valid
      L2P_CLKn     : out   std_logic;                      -- Transmitter Source Synchronous Clock-
      L2P_CLKp     : out   std_logic;                      -- Transmitter Source Synchronous Clock+
      L2P_EDB      : out   std_logic;                      -- Packet termination and discard
      L2P_RDY      : in    std_logic;                      -- Tx Buffer Full Flag
      L_WR_RDY     : in    std_logic_vector(1 downto 0);   -- Local-to-PCIe Write
      P_RD_D_RDY   : in    std_logic_vector(1 downto 0);   -- PCIe-to-Local Read Response Data Ready
      TX_ERROR     : in    std_logic;                      -- Transmit Error
      VC_RDY       : in    std_logic_vector(1 downto 0);   -- Channel ready
      GPIO         : inout std_logic_vector(1 downto 0);   -- GPIO[0] -> GN4124 GPIO8
                                                           -- GPIO[1] -> GN4124 GPIO9
      -- DDR3 interface
      DDR3_CAS_N   : out   std_logic;
      DDR3_CK_N    : out   std_logic;
      DDR3_CK_P    : out   std_logic;
      DDR3_CKE     : out   std_logic;
      DDR3_LDM     : out   std_logic;
      DDR3_LDQS_N  : inout std_logic;
      DDR3_LDQS_P  : inout std_logic;
      DDR3_ODT     : out   std_logic;
      DDR3_RAS_N   : out   std_logic;
      DDR3_RESET_N : out   std_logic;
      DDR3_UDM     : out   std_logic;
      DDR3_UDQS_N  : inout std_logic;
      DDR3_UDQS_P  : inout std_logic;
      DDR3_WE_N    : out   std_logic;
      DDR3_DQ      : inout std_logic_vector(15 downto 0);
      DDR3_A       : out   std_logic_vector(13 downto 0);
      DDR3_BA      : out   std_logic_vector(2 downto 0);
      DDR3_ZIO     : inout std_logic;
      DDR3_RZQ     : inout std_logic;

      -- Si57x
      si570_scl_b   : inout std_logic;    -- I2C bus clock (Si570)
      si570_sda_b   : inout std_logic;    -- I2C bus data (Si570)
      si570_clk_p_i : in std_logic;  
      si570_clk_n_i : in std_logic;  
      si570_oe      : out std_logic;
     
      -- Clock displining DAC pins
      dac_sclk_o  : out std_logic;
      dac_din_o   : out std_logic;
      dac_cs1_n_o : out std_logic;
      dac_cs2_n_o : out std_logic;
      
      -- UART
      uart_rxd_i : in  std_logic;
      uart_txd_o : out std_logic;

      -- SFP pins
      sfp_mod_def0_b    : in    std_logic;  -- sfp detect
      sfp_mod_def1_b    : inout std_logic;  -- scl
      sfp_mod_def2_b    : inout std_logic;  -- sda
      sfp_rate_select_b : inout std_logic;
      sfp_tx_fault_i    : in    std_logic;
      sfp_tx_disable_o  : out   std_logic;
      sfp_los_i         : in    std_logic;

      -- SFP interface (MGT123, channel 1)
      sfp_rxp_i : in std_logic;
      sfp_rxn_i : in std_logic;
      sfp_txp_o : out std_logic;
      sfp_txn_o : out std_logic;

      -- SATA0 interface (straight - MGT101, channel 1)
      sata0_rxp_i : in  std_logic;
      sata0_rxn_i : in  std_logic;
      sata0_txp_o : out std_logic;
      sata0_txn_o : out std_logic;

      -- SATA1 interface (crossover - MGT123, channel 0)
      sata1_rxp_i : in  std_logic;
      sata1_rxn_i : in  std_logic;
      sata1_txp_o : out std_logic;
      sata1_txn_o : out std_logic;

      -- FMC High Speed pins (MGT101, channel 0)
      fmc_dp0_rxp_i : in  std_logic;
      fmc_dp0_rxn_i : in  std_logic;
      fmc_dp0_txp_o : out std_logic;
      fmc_dp0_txn_o : out std_logic;
      
      -- FMC GBT clock
      fmc_gbtclk0_m2c_n_i : in std_logic;
      fmc_gbtclk0_m2c_p_i : in std_logic;

      -- FMC slot IOs connected to the Expanders
      -- Expanders 0x27 & 0x24
      fmc_la17n_i        : inout std_logic; -- FPGA pin AB13 ---> connected to fmc expander 0x24 GPB0
      fmc_la19n_i        : inout std_logic; -- FPGA pin AB15
      fmc_la19p_i        : inout std_logic; -- FPGA pin Y15
      fmc_la20p_i        : inout std_logic; -- FPGA pin R11
      fmc_la20n_i        : inout std_logic; -- FPGA pin T11
      fmc_la14n_i        : inout std_logic; -- FPGA pin AB4
      fmc_la14p_i        : inout std_logic; -- FPGA pin AA4
      fmc_la17p_i        : inout std_logic; -- FPGA pin Y13
      fmc_la13n_i        : inout std_logic; -- FPGA pin AB9 ---> connected to fmc expander 0x24 GPA0
      fmc_la13p_i        : inout std_logic; -- FPGA pin Y9
      fmc_la15p_i        : inout std_logic; -- FPGA pin V11
      fmc_la15n_i        : inout std_logic; -- FPGA pin W11
      fmc_la16p_i        : inout std_logic; -- FPGA pin W12
      fmc_la32n_i        : inout std_logic; -- FPGA pin A20
      fmc_la33p_i        : inout std_logic; -- FPGA pin C19
      fmc_la33n_i        : inout std_logic; -- FPGA pin A19
      fmc_la07p_i        : inout std_logic; -- FPGA pin U9 ---> connected to fmc expander 0x27 GPB0
      fmc_la05p_i        : inout std_logic; -- FPGA pin AA6
      fmc_la07n_i        : inout std_logic; -- FPGA pin V9
      fmc_la08n_i        : inout std_logic; -- FPGA pin R8
      fmc_la08p_i        : inout std_logic; -- FPGA pin R9
      fmc_la06n_i        : inout std_logic; -- FPGA pin AB5
      fmc_la12p_i        : inout std_logic; -- FPGA pin T10
      fmc_la09n_i        : inout std_logic; -- FPGA pin AB7
      fmc_la16n_i        : inout std_logic; -- FPGA pin Y12 ---> connected to fmc expander 0x27 GPA0
      fmc_la12n_i        : inout std_logic; -- FPGA pin U10
      fmc_la11p_i        : inout std_logic; -- FPGA pin W10
      fmc_la10n_i        : inout std_logic; -- FPGA pin AB8
      fmc_la11n_i        : inout std_logic; -- FPGA pin Y10
      fmc_la10p_i        : inout std_logic; -- FPGA pin AA8
      fmc_la09p_i        : inout std_logic; -- FPGA pin Y7
      fmc_la05n_i        : inout std_logic; -- FPGA pin AB6
      -- Expanders 0x22 & 0x26
      fmc_la27p_i        : inout std_logic; -- FPGA pin AA18 ---> connected to fmc expander 0x26 GPB0
      fmc_la23n_i        : inout std_logic; -- FPGA pin AB16
      fmc_la22p_i        : inout std_logic; -- FPGA pin R13
      fmc_la22n_i        : inout std_logic; -- FPGA pin T14
      fmc_la18n_i        : inout std_logic; -- FPGA pin U12
      fmc_la18p_i        : inout std_logic; -- FPGA pin T12
      fmc_la23p_i        : inout std_logic; -- FPGA pin AA16
      fmc_la21p_i        : inout std_logic; -- FPGA pin V13
      fmc_la24p_i        : inout std_logic; -- FPGA pin W14 ---> connected to fmc expander 0x26 GPA0
      fmc_la25n_i        : inout std_logic; -- FPGA pin U15
      fmc_tck_i          : inout std_logic; -- FPGA pin G8
      fmc_la25p_i        : inout std_logic; -- FPGA pin T15
      fmc_la27n_i        : inout std_logic; -- FPGA pin AB18
      fmc_la26p_i        : inout std_logic; -- FPGA pin Y17
      fmc_la21n_i        : inout std_logic; -- FPGA pin W13
      fmc_la26n_i        : inout std_logic; -- FPGA pin AB17
      fmc_la32p_i        : inout std_logic; -- FPGA pin B20 ---> connected to fmc expander 0x22 GPB0
      fmc_la30n_i        : inout std_logic; -- FPGA pin W18
      --fmc_ga1          : in std_logic; -- GROUND
      fmc_la31n_i        : inout std_logic; -- FPGA pin C18
      fmc_la30p_i        : inout std_logic; -- FPGA pin V17
      --fmc_ga0          : in std_logic; -- GROUND
      --fmc_trst         : in std_logic; -- P3V3
      fmc_tms_i          : inout std_logic; -- FPGA pin H10
      fmc_la29p_i        : inout std_logic; -- FPGA pin W17 ---> connected to fmc expander 0x22 GPA0
      fmc_la29n_i        : inout std_logic; -- FPGA pin Y18
      fmc_tdo_i          : inout std_logic; -- FPGA pin F9
      fmc_la31p_i        : inout std_logic; -- FPGA pin D17
      fmc_la28n_i        : inout std_logic; -- FPGA pin W15
      fmc_la28p_i        : inout std_logic; -- FPGA pin Y16
      fmc_tdi_i          : inout std_logic; -- FPGA pin H11
      fmc_la24n_i        : inout std_logic; -- FPGA pin Y14
      -- Expanders 0x21 & 0x25
      fmc_clk0_m2c_n_i   : in std_logic; -- FPGA pin F16 ---> connected to fmc expander 0x25 GPB0
      fmc_clk0_m2c_p_i   : in std_logic; -- FPGA pin E16
      fmc_prsnt_m2c_l_i  : inout std_logic; -- FPGA pin AB14

      --remaining 13 pins of 0x25 expander not used
      --M2C_DIR on high pin count not used
      fmc_pg_c2m_i       : inout std_logic; -- FPGA pin AA14 ---> connected to fmc expander 0x21 GPB1
      fmc_la01p_i        : inout std_logic; -- FPGA pin AA12
      fmc_la06p_i        : inout std_logic; -- FPGA pin Y5
      fmc_la01n_i        : inout std_logic; -- FPGA pin AB12
      fmc_la03n_i        : inout std_logic; -- FPGA pin W8
      fmc_la04p_i        : inout std_logic; -- FPGA pin T8
      fmc_la03p_i        : inout std_logic; -- FPGA pin V7
      fmc_vrefam2c_D3_i  : inout std_logic; -- FPGA pin D3 ---> connected to fmc expander 0x21 GPB7
      fmc_vrefam2c_A5_i  : in std_logic; -- FPGA pin A5  //FPGA pins D3, A5, G13,D19,V15, U13, AB10 and Y8 are interconnected
      fmc_vrefam2c_G13_i : in std_logic; -- FPGA pin G13
      fmc_vrefam2c_D19_i : in std_logic; -- FPGA pin D19
      fmc_vrefam2c_V15_i : in std_logic; -- FPGA pin V15
      fmc_vrefam2c_U13_i : in std_logic; -- FPGA pin U13
      fmc_vrefam2c_AB10_i : in std_logic; -- FPGA pin AB10
      fmc_vrefam2c_Y8_i  : in std_logic; -- FPGA pin Y8
      fmc_clk1_m2c_n_i   : in std_logic; -- FPGA pin L22 ---> connected to fmc expander 0x21 GPA1
      fmc_clk1_m2c_p_i   : in std_logic; -- FPGA pin L20
      fmc_la00p_i        : inout std_logic; -- FPGA pin Y11
      fmc_io_scl_b       : inout std_logic; -- FPGA pin W6 -- FMC IO Expanders I2C clock
      fmc_la00n_i        : inout std_logic; -- FPGA pin AB11
      fmc_io_sda_b       : inout std_logic; -- FPGA pin Y6 -- FMC IO Expanders I2C data
      fmc_la04n_i        : inout std_logic; -- FPGA pin U8

      fmc_scl_b : inout std_logic;      -- FMC system I2C clock (EEPROM)
      fmc_sda_b : inout std_logic       -- FMC system I2C data (EEPROM)
      );
end spec_pts_usb;


architecture rtl of spec_pts_usb is

  ------------------------------------------------------------------------------
  -- SDB crossbar constants declaration
  --
  -- WARNING: All address in sdb and crossbar are BYTE addresses!
  ------------------------------------------------------------------------------

  -- Number of master port(s) on the wishbone crossbar
  constant c_NUM_WB_MASTERS : integer := 1;

  -- Number of slave port(s) on the wishbone crossbar
  constant c_NUM_WB_SLAVES : integer := 3;

  -- Wishbone master(s)
  constant c_MASTER_GENNUM : integer := 0;

  -- Wishbone slave(s)
  constant c_SLAVE_DMA         : integer := 0;  -- DMA controller in the Gennum core
  constant c_SLAVE_SPEC_CSR    : integer := 1;  -- SPEC control and status registers
  constant c_SLAVE_UART        : integer := 2;  -- Carrier UART controller

  -- sdb header address
  constant c_SDB_ADDRESS : t_wishbone_address := x"000F0000";

  -- Wishbone crossbar layout
  constant c_INTERCONNECT_LAYOUT : t_sdb_record_array(c_NUM_WB_SLAVES+2 downto 0) :=
    (
      c_SLAVE_DMA         => f_sdb_embed_device(c_DMA_SDB_DEVICE, x"00000000"),
      --
      c_SLAVE_SPEC_CSR    => f_sdb_embed_device(c_CARRIER_CSR_SDB_DEVICE, x"00010000"),
      c_SLAVE_UART        => f_sdb_embed_device(c_UART_SDB_DEVICE, x"00040000"),
      --
      c_NUM_WB_SLAVES     => f_sdb_embed_repo_url(c_SDB_REPO_URL),
      c_NUM_WB_SLAVES+1   => f_sdb_embed_synthesis(c_SDB_SYNTHESIS),
      c_NUM_WB_SLAVES+2   => f_sdb_embed_integration(c_SDB_INTEGRATION)
      );

  ------------------------------------------------------------------------------
  -- Signals declaration
  ------------------------------------------------------------------------------

  -- System clocks
  signal sys_clk_in         : std_logic;
  signal sys_clk_50m_buf    : std_logic;
  signal sys_clk_250_buf    : std_logic;
  signal sys_clk_50m        : std_logic;
  signal sys_clk_250        : std_logic;
  signal sys_clk_fb         : std_logic;
  signal sys_clk_pll_locked : std_logic;
  
  signal clk_125m_pllref    : std_logic;
  signal fmc_gbtclk0_m2c    : std_logic;
  signal si570_clk          : std_logic;  

  -- DDR3 clock
  signal ddr_clk     : std_logic;
  signal ddr_clk_buf : std_logic;

  -- LCLK from GN4124
  signal l_clk : std_logic;

  -- GBT clock
  signal clk_gtp101 : std_logic;
  signal clk_gtp123 : std_logic;

  -- Reset
  signal rst       : std_logic;
  signal sys_rst   : std_logic;
  signal sys_rst_n : std_logic;
  
  -- Wishbone buse(s) from crossbar master port(s)
  signal cnx_master_out : t_wishbone_master_out_array(c_NUM_WB_SLAVES-1 downto 0);
  signal cnx_master_in  : t_wishbone_master_in_array(c_NUM_WB_SLAVES-1 downto 0);

  -- Wishbone buse(s) to crossbar slave port(s)
  signal cnx_slave_out : t_wishbone_slave_out_array(c_NUM_WB_MASTERS-1 downto 0);
  signal cnx_slave_in  : t_wishbone_slave_in_array(c_NUM_WB_MASTERS-1 downto 0);

  -- Wishbone address from GN4124 core (32-bit word address)
  signal gn_wb_adr : std_logic_vector(31 downto 0);

  -- Wishbone address from to DMA controller (32-bit word address)
  signal dma_ctrl_wb_adr : std_logic_vector(31 downto 0);

  -- GN4124 core DMA port to DDR wishbone bus
  signal wb_dma_adr   : std_logic_vector(31 downto 0);
  signal wb_dma_dat_i : std_logic_vector(31 downto 0);
  signal wb_dma_dat_o : std_logic_vector(31 downto 0);
  signal wb_dma_sel   : std_logic_vector(3 downto 0);
  signal wb_dma_cyc   : std_logic;
  signal wb_dma_stb   : std_logic;
  signal wb_dma_we    : std_logic;
  signal wb_dma_ack   : std_logic;
  signal wb_dma_stall : std_logic;

  -- Interrupts stuff
  signal irq_sources    : std_logic_vector(1 downto 0);
  signal irq_to_gn4124  : std_logic;
  signal gn4124_gpio    : std_logic;

  -- Carrier I2C for Si570
  signal si570_scl_in   : std_logic;
  signal si570_scl_out  : std_logic;
  signal si570_scl_oe_n : std_logic;
  signal si570_sda_in   : std_logic;
  signal si570_sda_out  : std_logic;
  signal si570_sda_oe_n : std_logic;

  -- Carrier UART
  signal uart_rxd     : std_logic;
  signal uart_txd     : std_logic;

  -- Carrier I2C for SFP
  signal sfp_scl_in   : std_logic;
  signal sfp_scl_out  : std_logic;
  signal sfp_scl_oe_n : std_logic;
  signal sfp_sda_in   : std_logic;
  signal sfp_sda_out  : std_logic;
  signal sfp_sda_oe_n : std_logic;

  -- FMC system I2C for EEPROM
  signal fmc_scl_in   : std_logic;
  signal fmc_scl_out  : std_logic;
  signal fmc_scl_oe_n : std_logic;
  signal fmc_sda_in   : std_logic;
  signal fmc_sda_out  : std_logic;
  signal fmc_sda_oe_n : std_logic;

  -- FMC IO Expanders I2C
  signal fmc_io_scl_in   : std_logic;
  signal fmc_io_scl_out  : std_logic;
  signal fmc_io_scl_oe_n : std_logic;
  signal fmc_io_sda_in   : std_logic;
  signal fmc_io_sda_out  : std_logic;
  signal fmc_io_sda_oe_n : std_logic;
  
  signal fmc_i           : std_logic_vector(95 downto 0);
  signal fmc_o           : std_logic_vector(95 downto 0);
  signal fmc_oen_o       : std_logic_vector(95 downto 0);

  constant c_fmc_TRST    : std_logic := '1';
  constant c_fmc_GA1     : std_logic := '0';
  constant c_fmc_GA0     : std_logic := '0';
  
  -- LED control from carrier CSR register
  signal led_red   : std_logic;
  signal led_green : std_logic;

  -- CSR wishbone slaves for test
  signal gpio_stat     : std_logic_vector(31 downto 0);
  signal gpio_ctrl_1   : std_logic_vector(31 downto 0);
  signal gpio_ctrl_2   : std_logic_vector(31 downto 0);
  signal gpio_ctrl_3   : std_logic_vector(31 downto 0);
  signal gpio_led_ctrl : std_logic_vector(31 downto 0);

  -- GN4124
  signal gn4124_status  : std_logic_vector(31 downto 0);
  signal p2l_pll_locked : std_logic;

  -- DDR3
  signal ddr3_status     : std_logic_vector(31 downto 0);
  signal ddr3_calib_done : std_logic;

  -- SPI
  signal spi_din_t : std_logic_vector(3 downto 0);
  signal spi_ss_t  : std_logic_vector(7 downto 0);

  -- Carrier 1-wire
  signal carrier_owr_pwren : std_logic_vector(0 downto 0);
  signal carrier_owr_en    : std_logic_vector(0 downto 0);
  signal carrier_owr_i     : std_logic_vector(0 downto 0);
  
  -- led pwm
  signal led_pwm_update_cnt : unsigned(9 downto 0);
  signal led_pwm_update     : std_logic;
  signal led_pwm_val        : unsigned(16 downto 0);
  signal led_pwm_val_down   : std_logic;
  signal led_pwm_cnt        : unsigned(16 downto 0);
  signal led_pwm            : std_logic;

begin

  ------------------------------------------------------------------------------
  -- Clocks distribution from 20MHz TCXO
  -- 50.000 MHz system clock
  -- 250.000 MHz fast system clock
  -- 333.333 MHz DDR3 clock
  ------------------------------------------------------------------------------
  cmp_sys_clk_buf : IBUFG
    port map (
      I => clk20_vcxo_i,
      O => sys_clk_in);

  cmp_sys_clk_pll : PLL_BASE
    generic map (
      BANDWIDTH          => "OPTIMIZED",
      CLK_FEEDBACK       => "CLKFBOUT",
      COMPENSATION       => "INTERNAL",
      DIVCLK_DIVIDE      => 1,
      CLKFBOUT_MULT      => 50,
      CLKFBOUT_PHASE     => 0.000,
      CLKOUT0_DIVIDE     => 20, -- 50.000 MHz
      CLKOUT0_PHASE      => 0.000,
      CLKOUT0_DUTY_CYCLE => 0.500,
      CLKOUT1_DIVIDE     => 4, -- 250.000 MHz
      CLKOUT1_PHASE      => 0.000,
      CLKOUT1_DUTY_CYCLE => 0.500,
      CLKOUT2_DIVIDE     => 3, -- 333.333 MHz
      CLKOUT2_PHASE      => 0.000,
      CLKOUT2_DUTY_CYCLE => 0.500,
      CLKIN_PERIOD       => 50.0,
      REF_JITTER         => 0.016)
    port map (
      CLKFBOUT => sys_clk_fb,
      CLKOUT0  => sys_clk_50m_buf,
      CLKOUT1  => sys_clk_250_buf,
      CLKOUT2  => ddr_clk_buf,
      CLKOUT3  => open,
      CLKOUT4  => open,
      CLKOUT5  => open,
      LOCKED   => sys_clk_pll_locked,
      RST      => '0',
      CLKFBIN  => sys_clk_fb,
      CLKIN    => sys_clk_in);

  cmp_clk_50m_buf : BUFG
    port map (
      O => sys_clk_50m,
      I => sys_clk_50m_buf);

  cmp_clk_250_buf : BUFG
    port map (
      O => sys_clk_250,
      I => sys_clk_250_buf);

  cmp_ddr_clk_buf : BUFG
    port map (
      O => ddr_clk,
      I => ddr_clk_buf);

  cmp_clk_125_pllref : IBUFDS
    generic map
    (DIFF_TERM    => true,
     IBUF_LOW_PWR => false)  -- Low power (TRUE) vs. performance (FALSE) setting for referenced
    port map
    (O  => clk_125m_pllref,
     I  => clk_125m_pllref_p_i,
     IB => clk_125m_pllref_n_i);

  cmp_si570_clk : IBUFDS
    generic map
    (DIFF_TERM    => true,
     IBUF_LOW_PWR => false)  -- Low power (TRUE) vs. performance (FALSE) setting for referenced
    port map
    (O  => si570_clk,
     I  => si570_clk_p_i,
     IB => si570_clk_n_i);

  ------------------------------------------------------------------------------
  -- Local clock from gennum LCLK
  ------------------------------------------------------------------------------
  cmp_l_clk_buf : IBUFDS
    generic map (
      DIFF_TERM    => false,            -- Differential Termination
      IBUF_LOW_PWR => true,             -- Low power (TRUE) vs. performance (FALSE) setting for referenced I/O standards
      IOSTANDARD   => "DEFAULT")
    port map (
      O  => l_clk,                      -- Buffer output
      I  => L_CLKp,                     -- Diff_p buffer input (connect directly to top-level port)
      IB => L_CLKn                      -- Diff_n buffer input (connect directly to top-level port)
      );

  ------------------------------------------------------------------------------
  -- GBT Reference clocks
  ------------------------------------------------------------------------------
  cmp_fmc_gbtclk0_m2c_buf : IBUFDS
    generic map
    (DIFF_TERM    => true,
     IBUF_LOW_PWR => false,
     IOSTANDARD   => "DEFAULT")
    port map
    (O  => fmc_gbtclk0_m2c,
     I  => fmc_gbtclk0_m2c_p_i,
     IB => fmc_gbtclk0_m2c_n_i);

  cmp_gbtclk_buf101 : IBUFDS
    generic map
    (DIFF_TERM    => true,
     IBUF_LOW_PWR => false,
     IOSTANDARD   => "DEFAULT")
    port map
    (O  => clk_gtp101,
     I  => fpga_pll_ref_clk_101_p_i,
     IB => fpga_pll_ref_clk_101_n_i);

  cmp_gbtclk_buf123 : IBUFDS
    generic map
    (DIFF_TERM    => true,
     IBUF_LOW_PWR => false,
     IOSTANDARD   => "DEFAULT")
    port map
    (O  => clk_gtp123,
     I  => fpga_pll_ref_clk0_123_p_i,
     IB => fpga_pll_ref_clk0_123_n_i);
      
  ------------------------------------------------------------------------------
  -- System reset
  ------------------------------------------------------------------------------
  sys_rst_n <= L_RST_N and sys_clk_pll_locked;
  sys_rst   <= not(sys_rst_n);

  ------------------------------------------------------------------------------
  -- GN4124 interface
  ------------------------------------------------------------------------------
  cmp_gn4124_core : gn4124_core
    port map(
      rst_n_a_i       => sys_rst_n,
      status_o        => gn4124_status,
      -- P2L Direction Source Sync DDR related signals
      p2l_clk_p_i     => P2L_CLKp,
      p2l_clk_n_i     => P2L_CLKn,
      p2l_data_i      => P2L_DATA,
      p2l_dframe_i    => P2L_DFRAME,
      p2l_valid_i     => P2L_VALID,
      -- P2L Control
      p2l_rdy_o       => P2L_RDY,
      p_wr_req_i      => P_WR_REQ,
      p_wr_rdy_o      => P_WR_RDY,
      rx_error_o      => RX_ERROR,
      -- L2P Direction Source Sync DDR related signals
      l2p_clk_p_o     => L2P_CLKp,
      l2p_clk_n_o     => L2P_CLKn,
      l2p_data_o      => L2P_DATA,
      l2p_dframe_o    => L2P_DFRAME,
      l2p_valid_o     => L2P_VALID,
      l2p_edb_o       => L2P_EDB,
      -- L2P Control
      l2p_rdy_i       => L2P_RDY,
      l_wr_rdy_i      => L_WR_RDY,
      p_rd_d_rdy_i    => P_RD_D_RDY,
      tx_error_i      => TX_ERROR,
      vc_rdy_i        => VC_RDY,
      -- Interrupt interface
      dma_irq_o       => irq_sources,
      irq_p_i         => irq_to_gn4124,
      irq_p_o         => gn4124_gpio,
      -- DMA registers wishbone interface (slave classic)
      dma_reg_clk_i   => sys_clk_50m,
      dma_reg_adr_i   => dma_ctrl_wb_adr,
      dma_reg_dat_i   => cnx_master_out(c_SLAVE_DMA).dat,
      dma_reg_sel_i   => cnx_master_out(c_SLAVE_DMA).sel,
      dma_reg_stb_i   => cnx_master_out(c_SLAVE_DMA).stb,
      dma_reg_we_i    => cnx_master_out(c_SLAVE_DMA).we,
      dma_reg_cyc_i   => cnx_master_out(c_SLAVE_DMA).cyc,
      dma_reg_dat_o   => cnx_master_in(c_SLAVE_DMA).dat,
      dma_reg_ack_o   => cnx_master_in(c_SLAVE_DMA).ack,
      dma_reg_stall_o => cnx_master_in(c_SLAVE_DMA).stall,
      -- CSR wishbone interface (master pipelined)
      csr_clk_i       => sys_clk_50m,
      csr_adr_o       => gn_wb_adr,
      csr_dat_o       => cnx_slave_in(c_MASTER_GENNUM).dat,
      csr_sel_o       => cnx_slave_in(c_MASTER_GENNUM).sel,
      csr_stb_o       => cnx_slave_in(c_MASTER_GENNUM).stb,
      csr_we_o        => cnx_slave_in(c_MASTER_GENNUM).we,
      csr_cyc_o       => cnx_slave_in(c_MASTER_GENNUM).cyc,
      csr_dat_i       => cnx_slave_out(c_MASTER_GENNUM).dat,
      csr_ack_i       => cnx_slave_out(c_MASTER_GENNUM).ack,
      csr_stall_i     => cnx_slave_out(c_MASTER_GENNUM).stall,
      -- DMA wishbone interface (pipelined)
      dma_clk_i       => sys_clk_50m,
      dma_adr_o       => wb_dma_adr,
      dma_dat_o       => wb_dma_dat_o,
      dma_sel_o       => wb_dma_sel,
      dma_stb_o       => wb_dma_stb,
      dma_we_o        => wb_dma_we,
      dma_cyc_o       => wb_dma_cyc,
      dma_dat_i       => wb_dma_dat_i,
      dma_ack_i       => wb_dma_ack,
      dma_stall_i     => wb_dma_stall
      );

  p2l_pll_locked <= gn4124_status(0);

  -- Convert 32-bit word address into byte address for crossbar
  cnx_slave_in(c_MASTER_GENNUM).adr <= gn_wb_adr(29 downto 0) & "00";

  -- Convert 32-bit byte address into word address for DMA controller
  dma_ctrl_wb_adr <= "00" & cnx_master_out(c_SLAVE_DMA).adr(31 downto 2);

  -- Unused wishbone signals
  cnx_master_in(c_SLAVE_DMA).err <= '0';
  cnx_master_in(c_SLAVE_DMA).rty <= '0';
  cnx_master_in(c_SLAVE_DMA).int <= '0';

  ------------------------------------------------------------------------------
  -- CSR wishbone crossbar
  ------------------------------------------------------------------------------
  cmp_sdb_crossbar : xwb_sdb_crossbar
    generic map (
      g_num_masters => c_NUM_WB_MASTERS,
      g_num_slaves  => c_NUM_WB_SLAVES,
      g_registered  => true,
      g_wraparound  => true,
      g_layout      => c_INTERCONNECT_LAYOUT,
      g_sdb_addr    => c_SDB_ADDRESS
      )
    port map (
      clk_sys_i => sys_clk_50m,
      rst_n_i   => sys_rst_n,
      slave_i   => cnx_slave_in,
      slave_o   => cnx_slave_out,
      master_i  => cnx_master_in,
      master_o  => cnx_master_out
      );

  ------------------------------------------------------------------------------
  -- Carrier 1-wire master (c_SLAVE_ONEWIRE)
  --    DS18B20 (thermometer + unique ID)
  ------------------------------------------------------------------------------
  carrier_one_wire_b <= 'Z';

  ------------------------------------------------------------------------------
  -- Carrier CSR (c_SLAVE_SPEC_CSR)
  --    Carrier type and PCB version
  --    Bitstream (firmware) type and date
  --    Release tag
  --    VCXO DAC control (CLR_N)
  ------------------------------------------------------------------------------
  cmp_carrier_pts_csr : carrier_csr
    port map(
      rst_n_i                          => sys_rst_n,
      clk_sys_i                        => sys_clk_50m,
      wb_adr_i                         => cnx_master_out(c_SLAVE_SPEC_CSR).adr(3 downto 2),  -- cnx_master_out.adr is byte address
      wb_dat_i                         => cnx_master_out(c_SLAVE_SPEC_CSR).dat,
      wb_dat_o                         => cnx_master_in(c_SLAVE_SPEC_CSR).dat,
      wb_cyc_i                         => cnx_master_out(c_SLAVE_SPEC_CSR).cyc,
      wb_sel_i                         => cnx_master_out(c_SLAVE_SPEC_CSR).sel,
      wb_stb_i                         => cnx_master_out(c_SLAVE_SPEC_CSR).stb,
      wb_we_i                          => cnx_master_out(c_SLAVE_SPEC_CSR).we,
      wb_ack_o                         => cnx_master_in(c_SLAVE_SPEC_CSR).ack,
      wb_stall_o                       => cnx_master_in(c_SLAVE_SPEC_CSR).stall,
      carrier_csr_carrier_pcb_rev_i    => pcb_ver_i,
      carrier_csr_carrier_reserved_i   => X"000",
      carrier_csr_carrier_type_i       => c_CARRIER_TYPE,
      carrier_csr_stat_fmc_pres_i      => fmc_prsnt_m2c_l_i,
      carrier_csr_stat_p2l_pll_lck_i   => p2l_pll_locked,
      carrier_csr_stat_sys_pll_lck_i   => sys_clk_pll_locked,
      carrier_csr_stat_ddr3_cal_done_i => ddr3_calib_done,
      carrier_csr_stat_reserved_i      => (others => '0'),
      carrier_csr_ctrl_led_green_o     => led_green,
      carrier_csr_ctrl_led_red_o       => led_red,
      carrier_csr_ctrl_dac_clr_n_o     => open,
      carrier_csr_ctrl_reserved_o      => open
      );
      
  -- Unused wishbone signals
  cnx_master_in(c_SLAVE_SPEC_CSR).err   <= '0';
  cnx_master_in(c_SLAVE_SPEC_CSR).rty   <= '0';
  cnx_master_in(c_SLAVE_SPEC_CSR).int   <= '0';

  -- SPEC front panel leds
  led_red_o   <= led_red;
  led_green_o <= led_green;

  ------------------------------------------------------------------------------
  -- Carrier I2C (c_SLAVE_SI570)
  --    Si570 control
  --
  -- Note: I2C registers are 8-bit wide, but accessed as 32-bit registers
  ------------------------------------------------------------------------------
  si570_scl_b  <= 'Z';
  si570_sda_b  <= 'Z';
  si570_oe     <= '0';
  
  ------------------------------------------------------------------------------
  -- Carrier UART (c_SLAVE_UART)
  ------------------------------------------------------------------------------
  cmp_carrier_uart : xwb_simple_uart
    generic map (
      g_interface_mode      => CLASSIC,
      g_address_granularity => BYTE
      )
    port map (
      clk_sys_i => sys_clk_50m,
      rst_n_i   => sys_rst_n,

      slave_i => cnx_master_out(c_SLAVE_UART),
      slave_o => cnx_master_in(c_SLAVE_UART),
      desc_o  => open,

      uart_rxd_i => uart_rxd,
      uart_txd_o => uart_txd
      );

  --uart_rxd <= uart_rxd_i;
  --uart_txd_o <= uart_txd;

  -- external loopback
  uart_txd_o <= uart_rxd_i;
      
  ------------------------------------------------------------------------------
  -- Carrier SPI master
  --    VCXO DAC control
  ------------------------------------------------------------------------------
  dac_sclk_o <= '0';
  dac_din_o <= '0';
  dac_cs1_n_o <= '0';
  dac_cs2_n_o <= '0';
  
  ------------------------------------------------------------------------------
  -- Carrier SFP I2C (c_SLAVE_SFP_I2C)
  ------------------------------------------------------------------------------
  sfp_mod_def1_b <= 'Z';
  sfp_mod_def2_b <= 'Z';
  sfp_tx_disable_o <= '0';
    
  ------------------------------------------------------------------------------
  -- FMC system managment I2C master (c_SLAVE_FMC_SYS_I2C)
  --    Access to mezzanine EEPROM
  ------------------------------------------------------------------------------
  fmc_scl_b <= 'Z';
  fmc_sda_b <= 'Z';

  ------------------------------------------------------------------------------
  -- FMC IO Expanders I2C master (c_SLAVE_FMC_IO_I2C)
  --    Access to IO Expanders of FMC Carrier Tester
  ------------------------------------------------------------------------------
  fmc_io_scl_b <= 'Z';
  fmc_io_sda_b <= 'Z';

  ------------------------------------------------------------------------------
  -- Carrier Minic PHY
  --    FMC High Speed pins (MGT101, channel 0)
  --    SATA0 interface (straight - MGT101, channel 1)
  --    SATA1 interface (crossover - MGT123, channel 0)
  --    SFP interface (MGT123, channel 1)
  ------------------------------------------------------------------------------

  ------------------------------------------------------------------------------
  -- Interrupt stuff
  ------------------------------------------------------------------------------
  -- just forward irq pulses for test
  irq_to_gn4124 <= irq_sources(1) or irq_sources(0);

  ------------------------------------------------------------------------------
  -- DMA wishbone bus slaves
  --  -> DDR3 controller
  ------------------------------------------------------------------------------
  ddr3_calib_done <= '0';
  
  ------------------------------------------------------------------------------
  -- Assign unused outputs
  ------------------------------------------------------------------------------
  GPIO(0) <= gn4124_GPIO;
  GPIO(1) <= '0';                       -- connection to GN4124

  ------------------------------------------------------------------------------
  -- FMC input pins (c_SLAVE_FMC_PIN0, c_SLAVE_FMC_PIN1, c_SLAVE_FMC_PIN2)
  ------------------------------------------------------------------------------

  ------------------------------------------------------------------------------
  -- FPGA programmed led (heart beat)
  ------------------------------------------------------------------------------
  p_led_pwn_update_cnt : process (sys_clk_50m)
  begin
    if rising_edge(sys_clk_50m) then
      if (sys_rst_n = '0') then
        led_pwm_update_cnt <= (others => '0');
        led_pwm_update     <= '0';
      elsif (led_pwm_update_cnt = to_unsigned(954, 10)) then
        led_pwm_update_cnt <= (others => '0');
        led_pwm_update     <= '1';
      else
        led_pwm_update_cnt <= led_pwm_update_cnt + 1;
        led_pwm_update     <= '0';
      end if;
    end if;
  end process p_led_pwn_update_cnt;

  p_led_pwn_val : process (sys_clk_50m)
  begin
    if rising_edge(sys_clk_50m) then
      if (sys_rst_n = '0') then
        led_pwm_val      <= (others => '0');
        led_pwm_val_down <= '0';
      elsif (led_pwm_update = '1') then
        if led_pwm_val_down = '1' then
          if led_pwm_val = X"100" then
            led_pwm_val_down <= '0';
          end if;
          led_pwm_val <= led_pwm_val - 1;
        else
          if led_pwm_val = X"1FFFE" then
            led_pwm_val_down <= '1';
          end if;
          led_pwm_val <= led_pwm_val + 1;
        end if;
      end if;
    end if;
  end process p_led_pwn_val;

  p_led_pwn_cnt : process (sys_clk_50m)
  begin
    if rising_edge(sys_clk_50m) then
      if (sys_rst_n = '0') then
        led_pwm_cnt <= (others => '0');
      else
        led_pwm_cnt <= led_pwm_cnt + 1;
      end if;
    end if;
  end process p_led_pwn_cnt;

  p_led_pwn : process (sys_clk_50m)
  begin
    if rising_edge(sys_clk_50m) then
      if (sys_rst_n = '0') then
        led_pwm <= '0';
      elsif (led_pwm_cnt = 0) then
        led_pwm <= '1';
      elsif (led_pwm_cnt = led_pwm_val) then
        led_pwm <= '0';
      end if;
    end if;
  end process p_led_pwn;

  aux_leds_o(0) <= led_pwm;
  aux_leds_o(1) <= led_pwm;
  aux_leds_o(2) <= led_pwm;
  aux_leds_o(3) <= led_pwm;

end rtl;
