-- PROJECT FOFB
-- COMBPM ELECTRON TOP LEVEL
-- RBR

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity top_combpm_electron is
    port(
        gt_clk               : out std_logic;   -- Data clock from GT
        rst_n                : in std_logic;    -- Asyncheonous reset
        free_100_clk         : in std_logic;    -- Freerunning clock for GT

        -- Differential reference clock inputs and buffered output
        mgtref_clk_p          : in std_logic;
        mgtref_clk_n          : in std_logic;
        mgtref_buf_clk       : out std_logic;

        -- SFP interfaces
        sfp_txp              : out std_logic;
        sfp_txn              : out std_logic;
        sfp_rxp              : in std_logic;
        sfp_rxn              : in std_logic;
        sfp_rx_los           : in std_logic;
        sfp_mod_abs          : in std_logic;
        sfp_tx_disable       : out std_logic;
        sfp_tx_fault         : in std_logic;

        -- AXIS interface
        m_axis_tid           : out std_logic_vector(0 downto 0);
        m_axis_tdest         : out std_logic_vector(9 downto 0);
        m_axis_tdata         : out std_logic_vector(127 downto 0);
        m_axis_tstrb         : out std_logic_vector(15 downto 0);
        m_axis_tkeep         : out std_logic_vector(15 downto 0);
        m_axis_tlast         : out std_logic;
        m_axis_tuser         : out std_logic_vector(0 downto 0);
        m_axis_tvalid        : out std_logic;
        m_axis_tready        : in std_logic;

        -- AXI bus interface
        s_axi_awaddr         : in std_logic_vector(7 downto 0);
        s_axi_awprot         : in std_logic_vector(2 downto 0);
        s_axi_awvalid        : in std_logic;
        s_axi_awready        : out std_logic;
        s_axi_wdata          : in std_logic_vector(32-1 downto 0);
        s_axi_wstrb          : in std_logic_vector(32/8-1 downto 0);
        s_axi_wvalid         : in std_logic;
        s_axi_wready         : out std_logic;
        s_axi_bresp          : out std_logic_vector(1 downto 0);
        s_axi_bvalid         : out std_logic;
        s_axi_bready         : in std_logic;
        s_axi_araddr         : in std_logic_vector(7 downto 0);
        s_axi_arprot         : in std_logic_vector(2 downto 0);
        s_axi_arvalid        : in std_logic;
        s_axi_arready        : out std_logic;
        s_axi_rdata          : out std_logic_vector(32-1 downto 0);
        s_axi_rresp          : out std_logic_vector(1 downto 0);
        s_axi_rvalid         : out std_logic;
        s_axi_rready         : in std_logic
    );
end top_combpm_electron;

architecture struct of top_combpm_electron is

    --------------------------
    -- INTERFACE ATTRIBUTES --
    --------------------------
    ATTRIBUTE X_INTERFACE_INFO                       : STRING;
    ATTRIBUTE X_INTERFACE_PARAMETER                  : STRING;

    ATTRIBUTE X_INTERFACE_INFO of rst_n              :  SIGNAL is "xilinx.com:signal:reset:1.0 rst_n RST";
    ATTRIBUTE X_INTERFACE_PARAMETER of rst_n         :  SIGNAL is "POLARITY ACTIVE_LOW";

    ATTRIBUTE X_INTERFACE_PARAMETER of free_100_clk: SIGNAL is "FREQ_HZ 100000000";
    ATTRIBUTE X_INTERFACE_PARAMETER of mgtref_buf_clk: SIGNAL is "FREQ_HZ 156250000";
    ATTRIBUTE X_INTERFACE_PARAMETER of gt_clk: SIGNAL is "FREQ_HZ 156250000, ASSOCIATED_BUSIF m_axis:s_axi";

    ATTRIBUTE X_INTERFACE_INFO of sfp_txn: SIGNAL is "xilinx.com:interface:sfp:1.0 sfp TXN";
    ATTRIBUTE X_INTERFACE_INFO of sfp_rxn: SIGNAL is "xilinx.com:interface:sfp:1.0 sfp RXN";
    ATTRIBUTE X_INTERFACE_INFO of sfp_txp: SIGNAL is "xilinx.com:interface:sfp:1.0 sfp TXP";
    ATTRIBUTE X_INTERFACE_INFO of sfp_rxp: SIGNAL is "xilinx.com:interface:sfp:1.0 sfp RXP";
    ATTRIBUTE X_INTERFACE_INFO of sfp_rx_los: SIGNAL is "xilinx.com:interface:sfp:1.0 sfp RX_LOS";
    ATTRIBUTE X_INTERFACE_INFO of sfp_mod_abs: SIGNAL is "xilinx.com:interface:sfp:1.0 sfp MOD_ABS";
    ATTRIBUTE X_INTERFACE_INFO of sfp_tx_disable: SIGNAL is "xilinx.com:interface:sfp:1.0 sfp TX_DISABLE";
    ATTRIBUTE X_INTERFACE_INFO of sfp_tx_fault: SIGNAL is "xilinx.com:interface:sfp:1.0 sfp TX_FAULT";

    ATTRIBUTE X_INTERFACE_INFO of mgtref_clk_p: SIGNAL is "xilinx.com:interface:diff_clock:1.0 mgtrefclk CLK_P";
    ATTRIBUTE X_INTERFACE_INFO of mgtref_clk_n: SIGNAL is "xilinx.com:interface:diff_clock:1.0 mgtrefclk CLK_N";
    ATTRIBUTE X_INTERFACE_PARAMETER of mgtref_clk_p: SIGNAL is "FREQ_HZ 156250000";


    ------------------------
    -- SIGNAL DECLARATION --
    ------------------------
    signal sync_rst      : std_logic;       -- Reset synchonized to clock
    signal rst           : std_logic;
    signal tx_disable    : std_logic;
    signal rx_commadeten : std_logic;
    signal srst_gt       : std_logic;
    signal frame_counter : std_logic_vector(15 downto 0);
    signal frame_error   : std_logic;

    signal gt_usrclk          : std_logic;
    signal gt_datarx          : std_logic_vector(15 downto 0);
    signal gt_datatx          : std_logic_vector(15 downto 0);
    signal gt_powergood       : std_logic;
    signal gt_qplllock        : std_logic;
    signal gt_txclkactive     : std_logic;
    signal gt_rxclkactive     : std_logic;
    signal gt_txresetdone     : std_logic;
    signal gt_rxresetdone     : std_logic;
    signal gt_rxbyteisaligned : std_logic;
    signal gt_rxbyterealign   : std_logic;
    signal gt_rxcommadet      : std_logic;
    signal gt_txfault         : std_logic;
    signal gt_rxlos           : std_logic;
    signal gt_modabs          : std_logic;
    signal gt_rstall          : std_logic;
    signal gt_rxcommadeten    : std_logic;
    signal gt_txdisable       : std_logic;
    signal gt_rxcdrlock       : std_logic;

begin

    ---------------------------
    -- RESET SYNCHRONIZATION --
    ---------------------------
    inst_cdc_arst: xpm_cdc_async_rst
    port map(
        src_arst    => rst,
        dest_clk    => gt_clk,
        dest_arst   => sync_rst
    );

    -- Reset invert polarity
    rst <= not rst_n;

    ----------------------
    -- AXI-MM INTERFACE --
    ----------------------
    axiitf_inst: entity work.combpm_protocol_electron_ctrl_axi
    generic map(
        G_ADDR_W => 8
    )
    port map(
        sfp_txfault_i         => gt_txfault,
        sfp_rxlos_i           => gt_rxlos,
        sfp_modabs_i          => gt_modabs,
        sfp_txdisable_o       => tx_disable,
        gt_powergood_i        => gt_powergood,
        gt_qplllock_i         => gt_qplllock,
        gt_txclkactive_i      => gt_txclkactive,
        gt_rxclkactive_i      => gt_rxclkactive,
        gt_rxcdrlock_i        => gt_rxcdrlock,
        gt_txresetdone_i      => gt_txresetdone,
        gt_rxresetdone_i      => gt_rxresetdone,
        gt_rxbyteisaligned_i  => gt_rxbyteisaligned,
        gt_rxbyterealign_i    => gt_rxbyterealign,
        gt_rxcommadet_i       => gt_rxcommadet,
        gt_rxcommadeten_o     => rx_commadeten,
        gt_rstall_o           => srst_gt,
        protocol_framecnt_i   => frame_counter,
        protocol_frameerror_i => frame_error,

        clk                   => gt_usrclk,
        reset                 => sync_rst,
        S_AXI_AWADDR          => S_AXI_AWADDR,
        S_AXI_AWPROT          => S_AXI_AWPROT,
        S_AXI_AWVALID         => S_AXI_AWVALID,
        S_AXI_AWREADY         => S_AXI_AWREADY,
        S_AXI_WDATA           => S_AXI_WDATA,
        S_AXI_WSTRB           => S_AXI_WSTRB,
        S_AXI_WVALID          => S_AXI_WVALID,
        S_AXI_WREADY          => S_AXI_WREADY,
        S_AXI_BRESP           => S_AXI_BRESP,
        S_AXI_BVALID          => S_AXI_BVALID,
        S_AXI_BREADY          => S_AXI_BREADY,
        S_AXI_ARADDR          => S_AXI_ARADDR,
        S_AXI_ARPROT          => S_AXI_ARPROT,
        S_AXI_ARVALID         => S_AXI_ARVALID,
        S_AXI_ARREADY         => S_AXI_ARREADY,
        S_AXI_RDATA           => S_AXI_RDATA,
        S_AXI_RRESP           => S_AXI_RRESP,
        S_AXI_RVALID          => S_AXI_RVALID,
        S_AXI_RREADY          => S_AXI_RREADY
    );

    --------------------------------------
    -- LIBERA ELECTRON PROCOTOL DECODER --
    --------------------------------------
    protocol_inst: entity work.combpm_protocol_electron
    port map(
        rst_n              => rst_n,
        clk                => gt_usrclk,
        gt_datarx          => gt_datarx,
        gt_datatx          => gt_datatx,
        gt_powergood       => gt_powergood,
        gt_qplllock        => gt_qplllock,
        gt_txclkactive     => gt_txclkactive,
        gt_rxclkactive     => gt_rxclkactive,
        gt_txresetdone     => gt_txresetdone,
        gt_rxresetdone     => gt_rxresetdone,
        gt_rxcdrlock       => gt_rxcdrlock,
        gt_rxbyteisaligned => gt_rxbyteisaligned,
        gt_rxbyterealign   => gt_rxbyterealign,
        gt_rxcommadet      => gt_rxcommadet,
        gt_txfault         => gt_txfault,
        gt_rxlos           => gt_rxlos,
        gt_modabs          => gt_modabs,
        gt_rstall          => gt_rstall,
        gt_rxcommadeten    => gt_rxcommadeten,
        gt_txdisable       => gt_txdisable,

        m_axi_tid          => m_axis_tid,
        m_axi_tdest        => m_axis_tdest,
        m_axi_tdata        => m_axis_tdata,
        m_axi_tstrb        => m_axis_tstrb,
        m_axi_tkeep        => m_axis_tkeep,
        m_axi_tlast        => m_axis_tlast,
        m_axi_tuser        => m_axis_tuser,
        m_axi_tvalid       => m_axis_tvalid,
        m_axi_tready       => m_axis_tready,

        tx_disable_i       => tx_disable,
        rx_commadeten_i    => rx_commadeten,
        srst_gt_i          => srst_gt,
        frame_counter_o    => frame_counter,
        frame_error_o      => frame_error

    );

    ----------------
    -- GT WRAPPER --
    ----------------
    gt_clk  <= gt_usrclk;
    inst_gtwrapper: entity work.combpm_gtwrapper
    port map(
        -- 100MHz clock, main ref clock
        clk_100                                                    => free_100_clk,

        -- Usrclock for data transfer
        usrclk                                                     => gt_usrclk,

        -- Async reset active low
        rst_n                                                      => rst_n,

        -- Differential reference clock inputs and buffered output
        mgtrefclk_p                                                => mgtref_clk_p,
        mgtrefclk_n                                                => mgtref_clk_n,
        mgtrefclk                                                  => mgtref_buf_clk,

        -- SFP interfaces
        sfp_txp(0)                                                 => sfp_txp,
        sfp_txn(0)                                                 => sfp_txn,
        sfp_rxp(0)                                                 => sfp_rxp,
        sfp_rxn(0)                                                 => sfp_rxn,
        sfp_rx_los(0)                                              => sfp_rx_los,
        sfp_mod_abs(0)                                             => sfp_mod_abs,
        sfp_tx_disable(0)                                          => sfp_tx_disable,
        sfp_tx_fault(0)                                            => sfp_tx_fault,

        -- GT interfaces
        gt_datarx                                                  => gt_datarx,
        gt_datatx                                                  => gt_datatx,
        gt_powergood(0)                                            => gt_powergood,
        gt_qplllock(0)                                             => gt_qplllock,
        gt_txclkactive(0)                                          => gt_txclkactive,
        gt_rxclkactive(0)                                          => gt_rxclkactive,
        gt_txresetdone(0)                                          => gt_txresetdone,
        gt_rxresetdone(0)                                          => gt_rxresetdone,
        gt_rxbyteisaligned(0)                                      => gt_rxbyteisaligned,
        gt_rxbyterealign(0)                                        => gt_rxbyterealign,
        gt_rxcommadet(0)                                           => gt_rxcommadet,
        gt_txfault(0)                                              => gt_txfault,
        gt_rxlos(0)                                                => gt_rxlos,
        gt_rxcdrlock(0)                                            => gt_rxcdrlock,
        gt_modabs(0)                                               => gt_modabs,
        gt_rstall(0)                                               => gt_rstall,
        gt_rxcommadeten(0)                                         => gt_rxcommadeten,
        gt_txdisable(0)                                            => gt_txdisable
    );


end architecture struct;