----------------------------------------------------------------------------------
-- Company: 
-- Engineer: 
-- 
-- Create Date: 03/13/2020 01:09:55 PM
-- Design Name: 
-- Module Name: udp_to_cmac_cdc - Behavioral
-- Project Name: 
-- Target Devices: 
-- Tool Versions: 
-- Description: 
-- 
-- Dependencies: 
-- 
-- Revision:
-- Revision 0.01 - File Created
-- Additional Comments:
-- 
----------------------------------------------------------------------------------


library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

Library xpm;
use xpm.vcomponents.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 udp_to_cmac_cdc is
   generic (
      g_mac_pkt_len              : natural := 140
   );
   port (
      UDP_RESET                  : in  std_logic := '0';
      CMAC_RESET                 : in  std_logic := '0';
      -- Core clock
      CMAC_CLK                   : in  std_logic := '0';
      UDP_CLK                    : in  std_logic := '0';

      ------------   CMAC side    ---------
      -- TX Datapath
      CMAC_M_AXIS_TX_TVALID      : out std_logic := '0';
      CMAC_M_AXIS_TX_TREADY      : in  std_logic := '0';
      CMAC_M_AXIS_TX_TUSER       : out std_logic := '0';
      CMAC_M_AXIS_TX_TLAST       : out std_logic := '0';
      CMAC_M_AXIS_TX_TKEEP       : out std_logic_vector(63 downto 0);
      CMAC_M_AXIS_TX_TDATA       : out std_logic_vector(511 downto 0);
      -- RX Datapath
      CMAC_S_AXIS_RX_TVALID      : in  std_logic := '0';
      CMAC_S_AXIS_RX_TREADY      : out std_logic := '0';
      CMAC_S_AXIS_RX_TUSER       : in  std_logic := '0';
      CMAC_S_AXIS_RX_TLAST       : in  std_logic := '0';
      CMAC_S_AXIS_RX_TKEEP       : in  std_logic_vector(63 downto 0) := (others => '0');
      CMAC_S_AXIS_RX_TDATA       : in  std_logic_vector(511 downto 0) := (others => '0');
      -- Control signals
      CMAC_CTL_RX_ENABLE         : out std_logic := '0';
      CMAC_CTL_TX_ENABLE         : out std_logic := '0';      
      CMAC_CTL_TX_SEND_RFI       : out std_logic := '0';
      CMAC_CTL_TX_SEND_LFI       : out std_logic := '0';
      CMAC_CTL_TX_SEND_IDLE      : out std_logic := '0';
      CMAC_CTL_TX_PREAMBLE       : out std_logic_vector(55 downto 0) := (others => '0');
      -- Status signals
      CMAC_STAT_RX_ALIGNED       : in  std_logic := '1';
      CMAC_STAT_RX_REMOTE_FAULT  : in  std_logic := '0';
      CMAC_STAT_TX_OVERFLOW      : in  std_logic := '0';
      CMAC_STAT_TX_UNDERFLOW     : in  std_logic := '0';     
      -- User interface reset signals from CMAC
      CMAC_USR_RX_RESET          : in  std_logic := '0';
      CMAC_USR_TX_RESET          : in  std_logic := '0';      
      -- CMAC core reset
      CMAC_CMAC_RESET            : out std_logic := '0';
      -- CMAC datapaths reset
      CMAC_RX_RESET              : out std_logic := '0';
      CMAC_TX_RESET              : out std_logic := '0';
   
      ------------   UDP side    ---------
      -- TX Datapath
      UDP_M_AXIS_TX_TVALID       : in  std_logic := '0';
      UDP_M_AXIS_TX_TREADY       : out std_logic := '0';
      UDP_M_AXIS_TX_TUSER        : in  std_logic := '0';
      UDP_M_AXIS_TX_TLAST        : in  std_logic := '0';
      UDP_M_AXIS_TX_TKEEP        : in  std_logic_vector(63 downto 0);
      UDP_M_AXIS_TX_TDATA        : in  std_logic_vector(511 downto 0);
      -- RX Datapath
      UDP_S_AXIS_RX_TVALID       : out std_logic := '0';
      UDP_S_AXIS_RX_TREADY       : in  std_logic := '0';
      UDP_S_AXIS_RX_TUSER        : out std_logic := '0';
      UDP_S_AXIS_RX_TLAST        : out std_logic := '0';
      UDP_S_AXIS_RX_TKEEP        : out std_logic_vector(63 downto 0) := (others => '0');
      UDP_S_AXIS_RX_TDATA        : out std_logic_vector(511 downto 0) := (others => '0');
      -- Control signals
      UDP_CTL_RX_ENABLE          : in  std_logic := '0';
      UDP_CTL_TX_ENABLE          : in  std_logic := '0';      
      UDP_CTL_TX_SEND_RFI        : in  std_logic := '0';
      UDP_CTL_TX_SEND_LFI        : in  std_logic := '0';
      UDP_CTL_TX_SEND_IDLE       : in  std_logic := '0';
      UDP_CTL_TX_PREAMBLE        : in  std_logic_vector(55 downto 0) := (others => '0');
      -- Status signals
      UDP_STAT_RX_ALIGNED        : out std_logic := '1';
      UDP_STAT_RX_REMOTE_FAULT   : out std_logic := '0';
      UDP_STAT_TX_OVERFLOW       : out std_logic := '0';
      UDP_STAT_TX_UNDERFLOW      : out std_logic := '0';     
      -- User interface reset signals from CMAC
      UDP_USR_RX_RESET           : out std_logic := '0';
      UDP_USR_TX_RESET           : out std_logic := '0';      
      -- CMAC core reset
      UDP_CMAC_RESET             : in  std_logic := '0';
      -- CMAC datapaths reset
      UDP_RX_RESET               : in  std_logic := '0';
      UDP_TX_RESET               : in  std_logic := '0'
    );
end udp_to_cmac_cdc;

architecture Behavioral of udp_to_cmac_cdc is

component xcdc_bit is
   generic (
      g_length       : integer := 2;
      g_rst_val      : std_logic := '0'
           );
   port (
      RSTN        : in  std_logic;
      DCLK        : in  std_logic;
      DATA_IN     : in  std_logic;
      DATA_OUT    : out std_logic
        );
end component;

component xcdc is
   generic (
      g_length       : integer := 2;
      g_rst_val      : std_logic := '0';
      g_data_width   : integer := 1
           );
   port (
      RSTN        : in  std_logic;
      DCLK        : in  std_logic;
      DATA_IN     : in  std_logic_vector(g_data_width-1 downto 0);
      DATA_OUT    : out std_logic_vector(g_data_width-1 downto 0)
        );
end component;

begin

------------------------------------------------------------------
--                   From UDP to CMAC
------------------------------------------------------------------

      axis_fifo_to_cmac: xpm_fifo_axis
      generic map(
        CLOCKING_MODE         => "independent_clock",
        FIFO_DEPTH            => 2*g_mac_pkt_len,
        TDATA_WIDTH           => CMAC_M_AXIS_TX_TDATA'length,
        USE_ADV_FEATURES      => "1000",
        PACKET_FIFO           => "true"
      )
      port map(
        s_aresetn             => CMAC_RESET,
        m_aclk                => CMAC_CLK,
        s_aclk                => UDP_CLK,
        s_axis_tvalid         => UDP_M_AXIS_TX_TVALID,
        s_axis_tready         => UDP_M_AXIS_TX_TREADY,
        s_axis_tdata          => UDP_M_AXIS_TX_TDATA, 
        s_axis_tstrb          => x"ffffffffffffffff",      
        s_axis_tkeep          => UDP_M_AXIS_TX_TKEEP, 
        s_axis_tlast          => UDP_M_AXIS_TX_TLAST, 
        s_axis_tid            => "0",                     
        s_axis_tdest          => "0",                     
        s_axis_tuser          => "0",                     
        m_axis_tvalid         => CMAC_M_AXIS_TX_TVALID,
        m_axis_tready         => CMAC_M_AXIS_TX_TREADY,
        m_axis_tdata          => CMAC_M_AXIS_TX_TDATA, 
        m_axis_tstrb          => x"ffffffffffffffff", 
        m_axis_tkeep          => CMAC_M_AXIS_TX_TKEEP, 
        m_axis_tlast          => CMAC_M_AXIS_TX_TLAST, 
        m_axis_tid            => open,
        m_axis_tdest          => open,
        m_axis_tuser          => open,
        injectsbiterr_axis    => '0',
        injectdbiterr_axis    => '0',
        sbiterr_axis          => open,
        dbiterr_axis          => open
      );

   rx_enable_cdc:    xcdc_bit generic map(g_rst_val => '0' )   port map('1', CMAC_CLK, UDP_CTL_RX_ENABLE,      CMAC_CTL_RX_ENABLE);
   tx_enable_cdc:    xcdc_bit generic map(g_rst_val => '0' )   port map('1', CMAC_CLK, UDP_CTL_TX_ENABLE,      CMAC_CTL_TX_ENABLE);
   tx_send_rfi_cdc:  xcdc_bit generic map(g_rst_val => '0' )   port map('1', CMAC_CLK, UDP_CTL_TX_SEND_RFI,    CMAC_CTL_TX_SEND_RFI);
   tx_send_lfi_cdc:  xcdc_bit generic map(g_rst_val => '0' )   port map('1', CMAC_CLK, UDP_CTL_TX_SEND_LFI,    CMAC_CTL_TX_SEND_LFI);
   tx_send_idle_cdc: xcdc_bit generic map(g_rst_val => '0' )   port map('1', CMAC_CLK, UDP_CTL_TX_SEND_IDLE,   CMAC_CTL_TX_SEND_IDLE);
   cmac_reset_cdc:   xcdc_bit generic map(g_rst_val => '0' )   port map('1', CMAC_CLK, UDP_CMAC_RESET,         CMAC_CMAC_RESET);
   rx_reset_cdc:     xcdc_bit generic map(g_rst_val => '0' )   port map('1', CMAC_CLK, UDP_RX_RESET,           CMAC_RX_RESET);
   tx_reset_cdc:     xcdc_bit generic map(g_rst_val => '0' )   port map('1', CMAC_CLK, UDP_TX_RESET,           CMAC_TX_RESET);
   tx_preamble_cdc:  xcdc generic map(g_rst_val => '0', g_data_width => UDP_CTL_TX_PREAMBLE'length) 
                                                               port map('1', CMAC_CLK, UDP_CTL_TX_PREAMBLE,    CMAC_CTL_TX_PREAMBLE);


------------------------------------------------------------------
--                   From CMAC to UDP  
------------------------------------------------------------------

      axis_fifo_to_udp: xpm_fifo_axis
      generic map(
        CLOCKING_MODE         => "independent_clock",
        FIFO_DEPTH            => 2*g_mac_pkt_len,
        TDATA_WIDTH           => CMAC_M_AXIS_TX_TDATA'length,
        USE_ADV_FEATURES      => "1000",
        PACKET_FIFO           => "true"
      )
      port map(
        s_aresetn             => UDP_RESET,
        m_aclk                => UDP_CLK,
        s_aclk                => CMAC_CLK,
        s_axis_tvalid         => CMAC_S_AXIS_RX_TVALID,
        s_axis_tready         => CMAC_S_AXIS_RX_TREADY,
        s_axis_tdata          => CMAC_S_AXIS_RX_TDATA, 
        s_axis_tstrb          => x"ffffffffffffffff",      
        s_axis_tkeep          => CMAC_S_AXIS_RX_TKEEP, 
        s_axis_tlast          => CMAC_S_AXIS_RX_TLAST, 
        s_axis_tid            => "0",                     
        s_axis_tdest          => "0",                     
        s_axis_tuser          => "0",                     
        m_axis_tvalid         => UDP_S_AXIS_RX_TVALID,
        m_axis_tready         => UDP_S_AXIS_RX_TREADY,
        m_axis_tdata          => UDP_S_AXIS_RX_TDATA, 
        m_axis_tstrb          => x"ffffffffffffffff", 
        m_axis_tkeep          => UDP_S_AXIS_RX_TKEEP, 
        m_axis_tlast          => UDP_S_AXIS_RX_TLAST, 
        m_axis_tid            => open,
        m_axis_tdest          => open,
        m_axis_tuser          => open,
        injectsbiterr_axis    => '0',
        injectdbiterr_axis    => '0',
        sbiterr_axis          => open,
        dbiterr_axis          => open
      );

   rx_aligned_cdc:      xcdc_bit generic map(g_rst_val => '0') port map('1', UDP_CLK, CMAC_STAT_RX_ALIGNED,       UDP_STAT_RX_ALIGNED);
   tx_overflow_cdc:     xcdc_bit generic map(g_rst_val => '0') port map('1', UDP_CLK, CMAC_STAT_TX_OVERFLOW,      UDP_STAT_TX_OVERFLOW);
   tx_underflow_cdc:    xcdc_bit generic map(g_rst_val => '0') port map('1', UDP_CLK, CMAC_STAT_TX_UNDERFLOW,     UDP_STAT_TX_UNDERFLOW);
   usr_rx_reset_cdc:    xcdc_bit generic map(g_rst_val => '0') port map('1', UDP_CLK, CMAC_USR_RX_RESET,          UDP_USR_RX_RESET);
   usr_tx_reset_cdc:    xcdc_bit generic map(g_rst_val => '0') port map('1', UDP_CLK, CMAC_USR_TX_RESET,          UDP_USR_TX_RESET);
   rx_remote_fauld_cdc: xcdc_bit generic map(g_rst_val => '0') port map('1', UDP_CLK, CMAC_STAT_RX_REMOTE_FAULT,  UDP_STAT_RX_REMOTE_FAULT);



end Behavioral;
