-------------------------------------------------------------------------------
--
-- Project name: 
--
-- (C) Copyright 2020 DFC Design, s.r.o., Brno, Czech Republic
-- Author: Jakub Hadamek (j.hadamek@dfcdesign.cz)
--
-------------------------------------------------------------------------------
--
-- This is wrapper of CMAC IP core 
-- 
-------------------------------------------------------------------------------


library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
--use IEEE.NUMERIC_STD.ALL;

-- Uncomment the following library declaration if instantiating
-- any Xilinx leaf cells in this code.
--library UNISIM;
--use UNISIM.VComponents.all;

entity cmac_usplus_wrapper0 is
   generic (
      g_data_width      : integer := 512
   );
   port ( 
      -- reset sync to init_clk
      RESET                : in  std_logic;
      TX_RESET             : in  std_logic;
      RX_RESET             : in  std_logic;
      -- GT reference clock
      REF_CLK_P            : in  std_logic;
      REF_CLK_N            : in  std_logic;
      -- free running clock
      INIT_CLK             : in  std_logic;
      -- RX clock
      CORE_CLK             : out std_logic;
      -- GT lines
      RX_P                 : in  std_logic_vector(3 downto 0);
      RX_N                 : in  std_logic_vector(3 downto 0);
      TX_P                 : out std_logic_vector(3 downto 0);
      TX_N                 : out std_logic_vector(3 downto 0);
      -- Master axis
      M_AXIS_TREADY        : in  std_logic;
      M_AXIS_TVALID        : out std_logic;
      M_AXIS_TDATA         : out std_logic_vector(g_data_width-1 downto 0);
      M_AXIS_TUSER         : out std_logic;
      M_AXIS_TKEEP         : out std_logic_vector(g_data_width/8-1 downto 0);
      M_AXIS_TLAST         : out std_logic;
      -- Slave axis
      S_AXIS_TREADY        : out std_logic;
      S_AXIS_TVALID        : in  std_logic;
      S_AXIS_TDATA         : in  std_logic_vector(g_data_width-1 downto 0);
      S_AXIS_TUSER         : in  std_logic;
      S_AXIS_TKEEP         : in  std_logic_vector(g_data_width/8-1 downto 0);
      S_AXIS_TLAST         : in  std_logic; 
      -- RX control signals
      RX_ENABLE            : in  std_logic;
      RX_ALIGNED           : out std_logic;
      RX_RFI               : out std_logic;
      USR_RX_RESET         : out std_logic;
      -- TX control signals
      TX_ENABLE            : in  std_logic;      
      TX_SEND_RFI          : in  std_logic;
      TX_SEND_LFI          : in  std_logic;
      TX_SEND_IDLE         : in  std_logic;
      USR_TX_RESET         : out std_logic;
      -- Common control signals
      TX_OVERFLOW          : out std_logic;
      TX_UNDERFLOW         : out std_logic
      );
end;

architecture Behavioral of cmac_usplus_wrapper0 is


   constant LC_PREAMBLE          : std_logic_vector(55 downto 0) := x"55555555555555";
   constant LC_LOOPBACK_MODE     : std_logic_vector(11 downto 0) := (others => '0');

   function orvec(vector : std_logic_vector)
                 return std_logic is
      variable out_val  : std_logic := '0';
   begin
      for i in 0 to vector'length-1 loop
         out_val := out_val or vector(i);
      end loop;
      return out_val;
   end orvec;
   
   function andvec_4(vector : std_logic_vector(3 downto 0))
                 return std_logic is
      variable out_val  : std_logic := '1';
   begin
      for i in 0 to vector'length-1 loop
         out_val := out_val and vector(i);
      end loop;
      return out_val;
   end andvec_4;

   function andvec(vector : std_logic_vector)
                 return std_logic is
      variable out_val  : std_logic := '1';
   begin
      for i in 0 to vector'length-1 loop
         out_val := out_val and vector(i);
      end loop;
      return out_val;
   end andvec;


   constant LC_TX_PREAMBLE : std_logic_vector(55 downto 0) := x"55555555555555";

   signal tx_clk_i         : std_logic;
   signal rx_clk_i         : std_logic;
   signal loopback_i       : std_logic_vector(11 downto 0);
   signal powergood_i      : std_logic_vector(3 downto 0);
   
   signal gt_tx_reset      : std_logic;
   signal gt_rx_reset      : std_logic;
   signal sys_reset        : std_logic;
   signal core_tx_reset    : std_logic;
   signal core_rx_reset    : std_logic;
   
   
   signal drp_addr         : std_logic_vector(9 downto 0) := (others => '0');
   signal drp_di           : std_logic_vector(15 downto 0) := (others => '0');
   signal drp_en           : std_logic := '0';
   signal drp_do           : std_logic_vector(15 downto 0) := (others => '0');
   signal drp_rdy          : std_logic := '0';
   signal drp_we           : std_logic := '0';
   
   signal rx_resync        : std_logic := '0';
   signal test_pattern_res : std_logic_vector(2 downto 0) := (others => '0');
   begin
   
   -- Data path clock signals
   CORE_CLK <= tx_clk_i;
   
   -- Resel all
   gt_tx_reset    <= RESET;
   gt_rx_reset    <= RESET;
   core_tx_reset  <= TX_RESET;
   core_rx_reset  <= RX_RESET;
   sys_reset      <= RESET;

   
   
   
   cmac_usplus_inst: entity work.cmac_usplus_0
      port map(
         -- GT RX
         gt0_rxp_in                     => RX_P(0),
         gt0_rxn_in                     => RX_N(0),
         gt1_rxp_in                     => RX_P(1),
         gt1_rxn_in                     => RX_N(1),
         gt2_rxp_in                     => RX_P(2),
         gt2_rxn_in                     => RX_N(2),
         gt3_rxp_in                     => RX_P(3),
         gt3_rxn_in                     => RX_N(3),
         -- GT TX
         gt0_txn_out                    => TX_N(0),
         gt0_txp_out                    => TX_P(0),
         gt1_txn_out                    => TX_N(1),
         gt1_txp_out                    => TX_P(1),
         gt2_txn_out                    => TX_N(2),
         gt2_txp_out                    => TX_P(2),
         gt3_txn_out                    => TX_N(3),
         gt3_txp_out                    => TX_P(3),
         -- TX path clock output
         gt_txusrclk2                   => tx_clk_i,
         -- Loopback mode
         gt_loopback_in                 => LC_LOOPBACK_MODE,
         gt_rxrecclkout                 => open,
         -- Output clock ready 
         gt_powergoodout                => powergood_i,
         gt_ref_clk_out                 => open,
         -- Reset TX and RX datapath - only GT
         gtwiz_reset_tx_datapath        => gt_tx_reset,
         gtwiz_reset_rx_datapath        => gt_rx_reset,
         -- Reset GT and then also Core
         sys_reset                      => sys_reset,
         -- GT reference clock
         gt_ref_clk_p                   => REF_CLK_P,
         gt_ref_clk_n                   => REF_CLK_N,
         -- Free running clock
         init_clk                       => INIT_CLK,
         -- RX data
         rx_axis_tvalid                 => M_AXIS_TVALID,
         rx_axis_tdata                  => M_AXIS_TDATA,
         rx_axis_tlast                  => M_AXIS_TLAST,
         rx_axis_tkeep                  => M_AXIS_TKEEP,
         rx_axis_tuser                  => M_AXIS_TUSER,
         -- Optical transport network
         rx_otn_bip8_0                  => open,
         rx_otn_bip8_1                  => open,
         rx_otn_bip8_2                  => open,
         rx_otn_bip8_3                  => open,
         rx_otn_bip8_4                  => open,
         rx_otn_data_0                  => open,
         rx_otn_data_1                  => open,
         rx_otn_data_2                  => open,
         rx_otn_data_3                  => open,
         rx_otn_data_4                  => open,
         rx_otn_ena                     => open,
         rx_otn_lane0                   => open,
         rx_otn_vlmarker                => open,
         -- Received preamble
         rx_preambleout                 => open,
         -- RX reset output for user logic
         usr_rx_reset                   => USR_RX_RESET,                 -- What is this signal reseting?
         -- RX clock - output
         gt_rxusrclk2                   => rx_clk_i,
         -- RX statistics
         -- RX aligned and deskewed - core locked
         stat_rx_aligned                => RX_ALIGNED,
         stat_rx_aligned_err            => open,
         stat_rx_bad_code               => open,
         stat_rx_bad_fcs                => open,
         stat_rx_bad_preamble           => open,
         stat_rx_bad_sfd                => open,
         stat_rx_bip_err_0              => open,
         stat_rx_bip_err_1              => open,
         stat_rx_bip_err_10             => open,
         stat_rx_bip_err_11             => open,
         stat_rx_bip_err_12             => open,
         stat_rx_bip_err_13             => open,
         stat_rx_bip_err_14             => open,
         stat_rx_bip_err_15             => open,
         stat_rx_bip_err_16             => open,
         stat_rx_bip_err_17             => open,
         stat_rx_bip_err_18             => open,
         stat_rx_bip_err_19             => open,
         stat_rx_bip_err_2              => open,
         stat_rx_bip_err_3              => open,
         stat_rx_bip_err_4              => open,
         stat_rx_bip_err_5              => open,
         stat_rx_bip_err_6              => open,
         stat_rx_bip_err_7              => open,
         stat_rx_bip_err_8              => open,
         stat_rx_bip_err_9              => open,
         stat_rx_block_lock             => open,
         stat_rx_broadcast              => open,
         stat_rx_fragment               => open,
         stat_rx_framing_err_0          => open,
         stat_rx_framing_err_1          => open,
         stat_rx_framing_err_10         => open,
         stat_rx_framing_err_11         => open,
         stat_rx_framing_err_12         => open,
         stat_rx_framing_err_13         => open,
         stat_rx_framing_err_14         => open,
         stat_rx_framing_err_15         => open,
         stat_rx_framing_err_16         => open,
         stat_rx_framing_err_17         => open,
         stat_rx_framing_err_18         => open,
         stat_rx_framing_err_19         => open,
         stat_rx_framing_err_2          => open,
         stat_rx_framing_err_3          => open,
         stat_rx_framing_err_4          => open,
         stat_rx_framing_err_5          => open,
         stat_rx_framing_err_6          => open,
         stat_rx_framing_err_7          => open,
         stat_rx_framing_err_8          => open,
         stat_rx_framing_err_9          => open,
         stat_rx_framing_err_valid_0    => open,
         stat_rx_framing_err_valid_1    => open,
         stat_rx_framing_err_valid_10   => open,
         stat_rx_framing_err_valid_11   => open,
         stat_rx_framing_err_valid_12   => open,
         stat_rx_framing_err_valid_13   => open,
         stat_rx_framing_err_valid_14   => open,
         stat_rx_framing_err_valid_15   => open,
         stat_rx_framing_err_valid_16   => open,
         stat_rx_framing_err_valid_17   => open,
         stat_rx_framing_err_valid_18   => open,
         stat_rx_framing_err_valid_19   => open,
         stat_rx_framing_err_valid_2    => open,
         stat_rx_framing_err_valid_3    => open,
         stat_rx_framing_err_valid_4    => open,
         stat_rx_framing_err_valid_5    => open,
         stat_rx_framing_err_valid_6    => open,
         stat_rx_framing_err_valid_7    => open,
         stat_rx_framing_err_valid_8    => open,
         stat_rx_framing_err_valid_9    => open,
         stat_rx_got_signal_os          => open,
         stat_rx_hi_ber                 => open,
         stat_rx_inrangeerr             => open,
         stat_rx_internal_local_fault   => open,
         stat_rx_jabber                 => open,
         stat_rx_local_fault            => open,
         stat_rx_mf_err                 => open,
         stat_rx_mf_len_err             => open,
         stat_rx_mf_repeat_err          => open,
         stat_rx_misaligned             => open,
         stat_rx_multicast              => open,
         stat_rx_oversize               => open,
         stat_rx_packet_1024_1518_bytes => open,
         stat_rx_packet_128_255_bytes   => open,
         stat_rx_packet_1519_1522_bytes => open,
         stat_rx_packet_1523_1548_bytes => open,
         stat_rx_packet_1549_2047_bytes => open,
         stat_rx_packet_2048_4095_bytes => open,
         stat_rx_packet_256_511_bytes   => open,
         stat_rx_packet_4096_8191_bytes => open,
         stat_rx_packet_512_1023_bytes  => open,
         stat_rx_packet_64_bytes        => open,
         stat_rx_packet_65_127_bytes    => open,
         stat_rx_packet_8192_9215_bytes => open,
         stat_rx_packet_bad_fcs         => open,
         stat_rx_packet_large           => open,
         stat_rx_packet_small           => open,
         -- Enable receive
         ctl_rx_enable                  => RX_ENABLE,
         -- Force RX resync
         ctl_rx_force_resync            => rx_resync,
         -- check test pattern on RX
         ctl_rx_test_pattern            => '0', --RX_TEST_PATTERN,
         -- Core RX reset -- async (should be high until rx_clk is stable) - what is this signal reseting?
         core_rx_reset                  => core_rx_reset,              
         -- RX clock - input  -- should be  322.265225 MHz (due to datasheet) - is this right?
         rx_clk                         => tx_clk_i,              
         -- Another RX statistics
         stat_rx_received_local_fault   => open, 
         stat_rx_remote_fault           => RX_RFI,
         stat_rx_status                 => open,
         stat_rx_stomped_fcs            => open,
         stat_rx_synced                 => open,
         stat_rx_synced_err             => open,
         stat_rx_test_pattern_mismatch  => open, --test_pattern_res,
         stat_rx_toolong                => open,
         stat_rx_total_bytes            => open,
         stat_rx_total_good_bytes       => open,
         stat_rx_total_good_packets     => open,
         stat_rx_total_packets          => open,
         stat_rx_truncated              => open,
         stat_rx_undersize              => open,
         stat_rx_unicast                => open,
         stat_rx_vlan                   => open,
         stat_rx_pcsl_demuxed           => open,
         stat_rx_pcsl_number_0          => open,
         stat_rx_pcsl_number_1          => open,
         stat_rx_pcsl_number_10         => open,
         stat_rx_pcsl_number_11         => open,
         stat_rx_pcsl_number_12         => open,
         stat_rx_pcsl_number_13         => open,
         stat_rx_pcsl_number_14         => open,
         stat_rx_pcsl_number_15         => open,
         stat_rx_pcsl_number_16         => open,
         stat_rx_pcsl_number_17         => open,
         stat_rx_pcsl_number_18         => open,
         stat_rx_pcsl_number_19         => open,
         stat_rx_pcsl_number_2          => open,
         stat_rx_pcsl_number_3          => open,
         stat_rx_pcsl_number_4          => open,
         stat_rx_pcsl_number_5          => open,
         stat_rx_pcsl_number_6          => open,
         stat_rx_pcsl_number_7          => open,
         stat_rx_pcsl_number_8          => open,
         stat_rx_pcsl_number_9          => open,
         -- TX statistics
         stat_tx_bad_fcs                => open,
         stat_tx_broadcast              => open,
         stat_tx_frame_error            => open,
         stat_tx_local_fault            => open,
         stat_tx_multicast              => open,
         stat_tx_packet_1024_1518_bytes => open,
         stat_tx_packet_128_255_bytes   => open,
         stat_tx_packet_1519_1522_bytes => open,
         stat_tx_packet_1523_1548_bytes => open,
         stat_tx_packet_1549_2047_bytes => open,
         stat_tx_packet_2048_4095_bytes => open,
         stat_tx_packet_256_511_bytes   => open,
         stat_tx_packet_4096_8191_bytes => open,
         stat_tx_packet_512_1023_bytes  => open,
         stat_tx_packet_64_bytes        => open,
         stat_tx_packet_65_127_bytes    => open,
         stat_tx_packet_8192_9215_bytes => open,
         stat_tx_packet_large           => open,
         stat_tx_packet_small           => open,
         stat_tx_total_bytes            => open,
         stat_tx_total_good_bytes       => open,
         stat_tx_total_good_packets     => open,
         stat_tx_total_packets          => open,
         stat_tx_unicast                => open,
         stat_tx_vlan                   => open,
         -- TX enable
         ctl_tx_enable                  => TX_ENABLE,
         -- Generate test pattern on TX
         ctl_tx_test_pattern            => '0', --TX_TEST_PATTERN,
         -- Send IDLE
         ctl_tx_send_idle               => TX_SEND_IDLE,
         -- Send remote fault indication
         ctl_tx_send_rfi                => TX_SEND_RFI,
         -- Send local fault indication
         ctl_tx_send_lfi                => TX_SEND_LFI,
         -- Core TX reset
         core_tx_reset                  => core_tx_reset,     -- async (should be high until tx_clk is stable) - What is this signal reseting?
         -- TX data
         tx_axis_tready                 => S_AXIS_TREADY, 
         tx_axis_tvalid                 => S_AXIS_TVALID,
         tx_axis_tdata                  => S_AXIS_TDATA,
         tx_axis_tlast                  => S_AXIS_TLAST,
         tx_axis_tkeep                  => S_AXIS_TKEEP,
         tx_axis_tuser                  => S_AXIS_TUSER,
         -- TX overflow or underflow
         tx_ovfout                      => TX_OVERFLOW,
         tx_unfout                      => TX_UNDERFLOW,
         -- Custom preamble
         tx_preamblein                  => LC_PREAMBLE,
         -- Reset output for tx logic
         usr_tx_reset                   => USR_TX_RESET,           -- What is this signal reseting?
   
         -- Dynamic reconfiguration port
         core_drp_reset                 => '0',
         drp_clk                        => '0',
         drp_addr                       => drp_addr,
         drp_di                         => drp_di,
         drp_en                         => drp_en,
         drp_do                         => drp_do,
         drp_rdy                        => drp_rdy,
         drp_we                         => drp_we  
      );



end;
