----------------------------------------------------------------------------------
-- Company: 
-- Engineer: 
-- 
-- Create Date: 01/28/2020 02:01:43 PM
-- Design Name: 
-- Module Name: udp_registers_sim - 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;

-- 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_registers_sim is
--  Port ( );
end udp_registers_sim;

architecture Behavioral of udp_registers_sim is
   signal clk        : std_logic := '0';
   signal reset      : std_logic := '1';
   
   constant LC_HOST_MAC       : std_logic_vector(47 downto 0) := x"111111111111";
   constant LC_HOST_IP        : std_logic_vector(31 downto 0) := x"22222222";
   constant LC_HOST_NET_MASK  : std_logic_vector(31 downto 0) := x"33333333";
   constant LC_RX_SRC_UDP     : std_logic_vector(15 downto 0) := x"4444";
   constant LC_RX_SRC_IP      : std_logic_vector(31 downto 0) := x"55555555";
   constant LC_RX_SRC_MAC     : std_logic_vector(47 downto 0) := x"666666666666";
   constant LC_DATA_CNT       : std_logic_vector(63 downto 0) := x"0000000000000001";
   
   signal packet_length       : std_logic_vector(15 downto 0);
   
   signal s_axis_tvalid           : std_logic := '0';
   signal s_axis_tready           : std_logic := '0';
   signal s_axis_tlast            : std_logic := '0';
   signal s_axis_tkeep            : std_logic_vector(63 downto 0) := (others => '0');
   signal s_axis_tdata            : std_logic_vector(511 downto 0) := (others => '0');
   
   signal cnt                    : natural := 0;

   -- magic number
   constant LC_MAGIC_NUMBER               : std_logic_vector(27 downto 0) := x"dfc1dfc";
   -- message type
   constant LC_WRITE                      : std_logic_vector(3 downto 0) := "0001";
   constant LC_READ                       : std_logic_vector(3 downto 0) := "0010";
   constant LC_INFO                       : std_logic_vector(3 downto 0) := "0011";
   constant LC_RESP                       : std_logic_vector(3 downto 0) := "0100";
   constant LC_ERR                        : std_logic_vector(3 downto 0) := "1000";
   -- register addresses
   constant LC_REG_DST_IP                 : std_logic_vector(31 downto 0) := x"00000000";
   constant LC_REG_DST_MAC_HIGH           : std_logic_vector(31 downto 0) := x"00000001";
   constant LC_REG_DST_MAC_LOW            : std_logic_vector(31 downto 0) := x"00000002";
   constant LC_REG_DST_UDP                : std_logic_vector(31 downto 0) := x"00000003";
   constant LC_REG_DST_QP                 : std_logic_vector(31 downto 0) := x"00000004";
   constant LC_REG_FIRST_PSN              : std_logic_vector(31 downto 0) := x"00000005";
   constant LC_REG_Q_KEY                  : std_logic_vector(31 downto 0) := x"00000006";
   constant LC_REG_CONTROL                : std_logic_vector(31 downto 0) := x"00000007";
   constant LC_REG_STATUS                 : std_logic_vector(31 downto 0) := x"00000008";
   constant LC_REG_STAT_WORD_CNT_HIGH     : std_logic_vector(31 downto 0) := x"00000009";
   constant LC_REG_STAT_WORD_CNT_LOW      : std_logic_vector(31 downto 0) := x"0000000a";
   constant LC_REG_ID                     : std_logic_vector(31 downto 0) := x"0000000b";
   -- registers default values
   constant LC_REG_DEF_DST_IP             : std_logic_vector(31 downto 0) := x"00000000";
   constant LC_REG_DEF_DST_MAC_HIGH       : std_logic_vector(31 downto 0) := x"00000000";
   constant LC_REG_DEF_DST_MAC_LOW        : std_logic_vector(31 downto 0) := x"00000000";
   constant LC_REG_DEF_DST_UDP            : std_logic_vector(31 downto 0) := x"00000000";
   constant LC_REG_DEF_DST_QP             : std_logic_vector(31 downto 0) := x"00000000";
   constant LC_REG_DEF_FIRST_PSN          : std_logic_vector(31 downto 0) := x"00000000";
   constant LC_REG_DEF_Q_KEY              : std_logic_vector(31 downto 0) := x"00000000";
   constant LC_REG_DEF_CONTROL            : std_logic_vector(31 downto 0) := x"00000000";
   constant LC_REG_DEF_ID                 : std_logic_vector(31 downto 0) := x"dfc0cec0";
   -- error codes
   constant LC_ERR_REG_NOT_EXIST          : std_logic_vector(31 downto 0) := x"00000001";
   constant LC_ERR_OVERFLOW               : std_logic_vector(31 downto 0) := x"00000010";

  
   signal m_axis_tready           : std_logic := '0'; 
begin
   clk <= not clk after 0.5ns;
   reset <= '0' after 10ns;
   
   process(CLK) 
      begin 
         if rising_edge(CLK) then
            if reset = '1' then 
               s_axis_tvalid <= '0';                                  
               s_axis_tlast  <= '0';                                  
               s_axis_tkeep  <= (others => '0');  
               s_axis_tdata  <= (others => '0'); 
            else 
               s_axis_tkeep <= (others => '0');  
               s_axis_tdata <= (others => '0');  
               s_axis_tvalid <= '0';                                
               s_axis_tlast  <= '0';  
               if cnt < 5 then 
                  null;
                  cnt <= cnt + 1;
                  s_axis_tkeep <= (others => '0');  
                  s_axis_tdata <= (others => '0');  
                  s_axis_tvalid <= '0';                                
                  s_axis_tlast  <= '0';  
                  packet_length <= x"0000";
               else
                  if (s_axis_tvalid and s_axis_tready) = '1' then 
                     cnt <= 0;
                  else
                     s_axis_tvalid <= '1';                                  
                     s_axis_tlast  <= '1';              
                     -- GET INFO         
--                     packet_length <= x"0004";
--                     s_axis_tkeep(3 downto 0)  <= (others => '1');  
--                     s_axis_tdata(31 downto 0)  <= LC_MAGIC_NUMBER & LC_INFO; 
                     -- WRITE REGISTERS
                     packet_length <= x"0014";
                     s_axis_tkeep(19 downto 0)  <= (others => '1');  
                     s_axis_tdata(159 downto 0)  <= x"00000001" & LC_REG_CONTROL & x"ffffffff" & LC_REG_DST_IP & LC_MAGIC_NUMBER & LC_WRITE; 
                     -- WRITE ERROR REGISTERS
--                     packet_length <= x"0014";
--                     s_axis_tkeep(19 downto 0)  <= (others => '1');  
--                     s_axis_tdata(159 downto 0)  <= x"0000dfcd" & x"ffffffff" & x"ffffffff" & LC_REG_DST_IP & LC_MAGIC_NUMBER & LC_WRITE; 
                     -- READ REGISTERS
                     packet_length <= x"0014";
                  end if;   
               end if;
            end if;
         end if;
      end process;
      
   udp_registers_inst: entity work.udp_registers
   generic map(
      g_udp_port              => x"dfcc"
   )
   port map(
      ------------   UDP 100G Interface    ---------
      -- Core clock and reset
      RESET                   => reset,
      CLK                     => clk,
      -- Host info
      HOST_MAC                => LC_HOST_MAC,
      HOST_IP                 => LC_HOST_IP,
      HOST_NET_MASK           => LC_HOST_NET_MASK,
      -- RX Datapath --
      S_AXIS_TVALID           => s_axis_tvalid,
      S_AXIS_TREADY           => s_axis_tready,
      S_AXIS_TLAST            => s_axis_tlast,
      S_AXIS_TKEEP            => s_axis_tkeep,
      S_AXIS_TDATA            => s_axis_tdata,
      -- RX net info
      RX_DST_UDP              => open,
      RX_SRC_UDP              => LC_RX_SRC_UDP,
      RX_SRC_IP               => LC_RX_SRC_IP,
      RX_SRC_MAC              => LC_RX_SRC_MAC,
      RX_PACKET_LENGTH        => packet_length,
      -- TX Datapath --
      M_AXIS_TVALID           => open,
      M_AXIS_TREADY           => m_axis_tready,
      M_AXIS_TLAST            => open,
      M_AXIS_TKEEP            => open,
      M_AXIS_TDATA            => open,
      -- TX net info
      TX_SRC_UDP              => open,
      TX_DST_UDP              => open,
      TX_DST_IP               => open,
      TX_DST_MAC              => open,
      -- control signals
      REG_CHANNEL_RUN         => open,
      REG_CHANNEL_CLEAR       => open,
      REG_CHANNEL_OVERFLOW    => '0',   
      REG_CHANNEL_WORD_CNT    => LC_DATA_CNT,
      -- packets related signals
      -- mac/ip/udp
      REG_ROCE_TX_DEST_IP     => open,
      REG_ROCE_TX_DEST_MAC    => open,
      REG_ROCE_TX_DEST_UDP    => open,
      -- roce
      REG_ROCE_TX_DEST_QP     => open,
      REG_ROCE_TX_PSN         => open,
      REG_ROCE_TX_Q_KEY       => open
    );

   m_axis_tready <= not m_axis_tready after 100ns;

end Behavioral;
