----------------------------------------------------------------------------------
-- Company: 
-- Engineer: 
-- 
-- Create Date: 01/14/2020 10:27:47 AM
-- Design Name: 
-- Module Name: channel_control_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 channel_control_sim is
   --port ( );    
end channel_control_sim;

architecture Behavioral of channel_control_sim is
   signal pcie_clk               : std_logic := '0';
   signal data_clk               : std_logic := '0';
   signal pcie_reset             : std_logic := '1';
   signal data_reset             : std_logic := '1';
   
   signal run                    : std_logic := '0';
   signal run_control            : std_logic := '0';
   signal clear_control          : std_logic := '0';
   signal clear_cdc              : std_logic := '0';
   signal clear                  : std_logic := '0';
   signal reset                  : std_logic := '1';
   signal resetn                 : std_logic := '0';
   
   signal s_axis_tvalid          : std_logic := '0';     
   signal s_axis_tlast           : std_logic := '0';     
   signal s_axis_tready          : std_logic := '0';         
   signal s_axis_tdata           : std_logic_vector(255 downto 0) := (others => '0');   
   signal s_axis_tkeep           : std_logic_vector(31 downto 0) := (others => '0');    
   
   signal s_axis_ch0_tvalid      : std_logic := '0';     
   signal s_axis_ch0_tlast       : std_logic := '0';     
   signal s_axis_ch0_tready      : std_logic := '0';         
   signal s_axis_ch0_tdata       : std_logic_vector(511 downto 0) := (others => '0');   
   signal s_axis_ch0_tkeep       : std_logic_vector(63 downto 0) := (others => '0');    
   
   signal s_axis_ch1_tvalid      : std_logic := '0';     
   signal s_axis_ch1_tlast       : std_logic := '0';     
   signal s_axis_ch1_tready      : std_logic := '0';         
   signal s_axis_ch1_tdata       : std_logic_vector(511 downto 0) := (others => '0');   
   signal s_axis_ch1_tkeep       : std_logic_vector(63 downto 0) := (others => '0');    
   
   signal ch0_s_axis_tvalid      : std_logic := '0';     
   signal ch0_s_axis_tlast       : std_logic := '0';     
   signal ch0_s_axis_tready      : std_logic := '0';         
   signal ch0_s_axis_tdata       : std_logic_vector(511 downto 0) := (others => '0');   
   signal ch0_s_axis_tkeep       : std_logic_vector(63 downto 0) := (others => '0');    
   signal ch0_s_axis_tvalid_cdc  : std_logic := '0';     
   signal ch0_s_axis_tlast_cdc   : std_logic := '0';     
   signal ch0_s_axis_tready_cdc  : std_logic := '0';         
   signal ch0_s_axis_tdata_cdc   : std_logic_vector(511 downto 0) := (others => '0');   
   signal ch0_s_axis_tkeep_cdc   : std_logic_vector(63 downto 0) := (others => '0');     
   signal ch0_rstn               : std_logic := '0';

   signal ch1_s_axis_tvalid      : std_logic := '0';     
   signal ch1_s_axis_tlast       : std_logic := '0';     
   signal ch1_s_axis_tready      : std_logic := '0';         
   signal ch1_s_axis_tdata       : std_logic_vector(511 downto 0) := (others => '0');   
   signal ch1_s_axis_tkeep       : std_logic_vector(63 downto 0) := (others => '0');    
   signal ch1_s_axis_tvalid_cdc  : std_logic := '0';     
   signal ch1_s_axis_tlast_cdc   : std_logic := '0';     
   signal ch1_s_axis_tready_cdc  : std_logic := '0';         
   signal ch1_s_axis_tdata_cdc   : std_logic_vector(511 downto 0) := (others => '0');   
   signal ch1_s_axis_tkeep_cdc   : std_logic_vector(63 downto 0) := (others => '0');    
   signal ch1_rstn               : std_logic := '0';  

   
   constant LC_LAST_CYCLE_TKEEP  : std_logic_vector(31 downto 0) := (others => '0');
   constant LC_DATA_CYCLES       : std_logic_vector(7 downto 0) := (others => '0'); 
   constant LC_PAUSE_CYCLES      : std_logic_vector(63 downto 0) := (others => '0');
   
   signal overflow               : std_logic := '0';
   signal overflow_cdc           : std_logic := '0';
   signal running                : std_logic := '0';
 
 
   signal ch0_valid              : std_logic := '0';
   signal ch1_valid              : std_logic := '0';
   
begin
   
   pcie_clk <= not pcie_clk after 0.5ns;
   data_clk <= not data_clk after 0.3ns;
   reset <= '0' after 20ns;
   resetn <= not reset;
   run_control <= '1' after 100ns;
   
   pcie_reset <= reset;
   data_reset <= reset;
   
   
   adc_sim_axis_generator_inst: entity work.axis_generator
   generic map (
      g_stream_width       => 256
   )
   port map(
      CLK                  => data_clk,
      RESET                => data_reset,
      M_AXIS_TVALID        => s_axis_tvalid,
      M_AXIS_TREADY        => '1',
      M_AXIS_TLAST         => s_axis_tlast,
      M_AXIS_TKEEP         => s_axis_tkeep,
      M_AXIS_TDATA         => s_axis_tdata,
      -- VIO control
      LAST_CYCLE_TKEEP     => LC_LAST_CYCLE_TKEEP,
      DATA_CYCLES          => LC_DATA_CYCLES,     
      PAUSE_CYCLES         => LC_PAUSE_CYCLES,    
      CONTINUOUS           => '1'
   );

   transoform_adc_stream_inst: entity work.transform_adc_stream
   port map(
      -- Input clock and reset
      S_CLK                => data_clk,
      S_RESET              => data_reset,
      -- input stream
      S_AXIS_TVALID        => s_axis_tvalid,
      S_AXIS_TDATA         => s_axis_tdata,
      -- Output clock and reset
      M_CLK                => pcie_clk,
      M_RESET              => pcie_reset,
      -- output stream channel 0
      M_AXIS_CH0_TVALID    => s_axis_ch0_tvalid,
      M_AXIS_CH0_TREADY    => s_axis_ch0_tready,
      M_AXIS_CH0_TDATA     => s_axis_ch0_tdata,
      -- output stream channel 1
      M_AXIS_CH1_TVALID    => s_axis_ch1_tvalid,
      M_AXIS_CH1_TREADY    => s_axis_ch1_tready,
      M_AXIS_CH1_TDATA     => s_axis_ch1_tdata
   );

   
   pcie_adc_app_inst: entity work.pcie_adc_app
   generic map(
      g_batch_length => 16,
      g_data_pcie_clk_same => true,
      g_debug           => false
   )
   port map(
      -- PCIE clocks and reset
      PCIE_CLK             => pcie_clk,
      PCIE_RESET           => pcie_reset,
      -- JESD clocks and reset
      DATA_CLK             => pcie_clk,
      DATA_RESET           => pcie_reset,
      -- AXI Registers
		S_AXI_AWADDR	      => "0000000000",
		S_AXI_AWPROT	      => "000",
		S_AXI_AWVALID	      => '0',
		S_AXI_AWREADY        => open,
		S_AXI_WDATA	         => x"00000000",
		S_AXI_WSTRB	         => "0000",
		S_AXI_WVALID	      => '0',
		S_AXI_WREADY	      => open,
		S_AXI_BRESP	         => "00",
		S_AXI_BVALID	      => open,
		S_AXI_BREADY	      => '0',
		S_AXI_ARADDR         => "0000000000",
		S_AXI_ARPROT	      => "000",
		S_AXI_ARVALID	      => '0',
		S_AXI_ARREADY	      => open,
		S_AXI_RDATA          => open,
		S_AXI_RRESP          => open,
		S_AXI_RVALID	      => open,
		S_AXI_RREADY	      => '0', 
      -- Data input
      -- channel 0
      S_AXIS_CH0_TVALID    => s_axis_ch0_tvalid,
      S_AXIS_CH0_TLAST     => s_axis_ch0_tlast,
      S_AXIS_CH0_TREADY    => s_axis_ch0_tready, 
      S_AXIS_CH0_TDATA     => s_axis_ch0_tdata, 
      S_AXIS_CH0_TKEEP     => s_axis_ch0_tkeep, 
      -- channel 1
      S_AXIS_CH1_TVALID    => s_axis_ch1_tvalid,
      S_AXIS_CH1_TLAST     => s_axis_ch1_tlast, 
      S_AXIS_CH1_TREADY    => s_axis_ch1_tready,
      S_AXIS_CH1_TDATA     => s_axis_ch1_tdata, 
      S_AXIS_CH1_TKEEP     => s_axis_ch1_tkeep, 
      -- Data output to pcie xdma channel
      -- channel 0
      M_AXIS_CH0_TVALID    => ch0_valid,
      M_AXIS_CH0_TLAST     => open,
      M_AXIS_CH0_TREADY    => '1',
      M_AXIS_CH0_TDATA     => open,
      M_AXIS_CH0_TKEEP     => open,
      -- channel 1
      M_AXIS_CH1_TVALID    => open,
      M_AXIS_CH1_TLAST     => open,
      M_AXIS_CH1_TREADY    => '0',
      M_AXIS_CH1_TDATA     => open,
      M_AXIS_CH1_TKEEP     => open,
      -- PCIE interrupt
      INTERRUPT            => open,
      CH0_DMA_STATUS       => x"00",
      CH1_DMA_STATUS       => x"00"
    );


   ch1_valid <= not ch0_valid;












--   s_axis_tready <= running and not overflow and ch0_s_axis_tready and ch1_s_axis_tready;
   
--   ch0_s_axis_tvalid <= s_axis_tvalid and running and not overflow;
--   ch0_s_axis_tlast  <= s_axis_tlast;
--   ch0_s_axis_tdata  <= s_axis_tdata;
--   ch0_s_axis_tkeep  <= s_axis_tkeep;

--   ch1_s_axis_tvalid <= s_axis_tvalid and running and not overflow;
--   ch1_s_axis_tlast  <= s_axis_tlast;
--   ch1_s_axis_tdata  <= s_axis_tdata;
--   ch1_s_axis_tkeep  <= s_axis_tkeep;
   
--   overflow_proc: process(data_clk)
--      begin 
--         if rising_edge(data_clk) then 
--            if reset = '1' then 
--               running <= '0';
--               overflow <= '0';
--            else
--               if (not running and not ch0_s_axis_tready and not ch1_s_axis_tready) = '1' then
--                  overflow <= '0';
--                  running <= '0';
--               elsif (not running and ch0_s_axis_tready and ch1_s_axis_tready) = '1' then 
--                  running <= '1';
--               elsif (running and not overflow and (not ch0_s_axis_tready or not ch1_s_axis_tready)) = '1' then 
--                  overflow <= '1';
--               elsif clear_cdc = '1' and overflow = '1' then
--                  overflow <= '0';
--                  running <= '0';
--               end if;
--            end if;
--         end if;
--      end process;

--   clear_cdc_inst: entity work.xcdc
--   generic map(
--      g_length       => 2,
--      g_rst_val      => '0',
--      g_data_width   => 1
--   )
--   port map(
--      RSTN        => resetn,
--      DCLK        => clk,
--      DATA_IN(0)  => clear,
--      DATA_OUT(0) => clear_cdc
--   );

--   overflow_cdc_inst: entity work.xcdc
--   generic map(
--      g_length       => 2,
--      g_rst_val      => '0',
--      g_data_width   => 1
--   )
--   port map(
--      RSTN        => resetn,
--      DCLK        => clk,
--      DATA_IN(0)  => overflow,
--      DATA_OUT(0) => overflow_cdc
--   );
   
--   clear <= clear_control;
--   run <= run_control and not clear_control;

--   axis_data_fifo_ch0: entity work.axis_data_fifo_0
--   port map(
--      s_axis_aresetn => ch0_rstn,
--      s_axis_aclk    => data_clk,
--      s_axis_tvalid  => ch0_s_axis_tvalid,
--      s_axis_tready  => ch0_s_axis_tready,
--      s_axis_tlast   => ch0_s_axis_tlast,
--      s_axis_tdata   => ch0_s_axis_tdata,
--      s_axis_tkeep   => ch0_s_axis_tkeep,
--      m_axis_aclk    => clk,
--      m_axis_tvalid  => ch0_s_axis_tvalid_cdc,
--      m_axis_tready  => ch0_s_axis_tready_cdc,
--      m_axis_tlast   => ch0_s_axis_tlast_cdc,
--      m_axis_tdata   => ch0_s_axis_tdata_cdc,
--      m_axis_tkeep   => ch0_s_axis_tkeep_cdc
--   );
   
--   axis_data_fifo_ch1: entity work.axis_data_fifo_0
--   port map(
--      s_axis_aresetn => ch1_rstn,
--      s_axis_aclk    => data_clk,
--      s_axis_tvalid  => ch1_s_axis_tvalid,
--      s_axis_tready  => ch1_s_axis_tready,
--      s_axis_tlast   => ch1_s_axis_tlast,
--      s_axis_tdata   => ch1_s_axis_tdata,
--      s_axis_tkeep   => ch1_s_axis_tkeep,
--      m_axis_aclk    => clk,
--      m_axis_tvalid  => ch1_s_axis_tvalid_cdc,
--      m_axis_tready  => ch1_s_axis_tready_cdc,
--      m_axis_tlast   => ch1_s_axis_tlast_cdc,
--      m_axis_tdata   => ch1_s_axis_tdata_cdc,
--      m_axis_tkeep   => ch1_s_axis_tkeep_cdc
--   );   
   
  
--   ch0_control_inst: entity work.channel_control
--   generic map(
--      -- if there is need to finish packet of packet length
--      -- before it's stopped
--      g_packet_mode     => true
--      -- should be MAX_UDP_PACKET - 1 (because of RoCE headers)
----      g_packet_length   => 140
--   )
--   port map(
--      CLK               => clk,
--      RESET             => reset,
--      -- Control signals
--      RUN               => run,
--      FIFO_RSTN         => ch0_rstn,
--      OVERFLOW          => overflow_cdc,
--      -- Status signals
--      SEND_CNT          => open,
--      -- Data input
--      S_AXIS_TVALID     => ch0_s_axis_tvalid_cdc,
--      S_AXIS_TLAST      => ch0_s_axis_tlast_cdc, 
--      S_AXIS_TREADY     => ch0_s_axis_tready_cdc,
--      S_AXIS_TDATA      => ch0_s_axis_tdata_cdc, 
--      S_AXIS_TKEEP      => ch0_s_axis_tkeep_cdc, 
--      -- Data output
--      M_AXIS_TVALID     => open,
--      M_AXIS_TLAST      => open,
--      M_AXIS_TREADY     => '1',
--      M_AXIS_TDATA      => open,
--      M_AXIS_TKEEP      => open 
--    );

--   ch1_control_inst: entity work.channel_control
--   generic map(
--      -- if there is need to finish packet of packet length
--      -- before it's stopped
--      g_packet_mode     => false
--      -- should be MAX_UDP_PACKET - 1 (because of RoCE headers)
----      g_packet_length   => 140
--   )
--   port map(
--      CLK               => clk,
--      RESET             => reset,
--      -- Control signals
--      RUN               => run,
--      FIFO_RSTN         => ch1_rstn,
--      OVERFLOW          => overflow_cdc,
--      -- Status signals
--      SEND_CNT          => open,
--      -- Data input
--      S_AXIS_TVALID     => ch1_s_axis_tvalid_cdc,
--      S_AXIS_TLAST      => ch1_s_axis_tlast_cdc, 
--      S_AXIS_TREADY     => ch1_s_axis_tready_cdc,
--      S_AXIS_TDATA      => ch1_s_axis_tdata_cdc, 
--      S_AXIS_TKEEP      => ch1_s_axis_tkeep_cdc, 
--      -- Data output
--      M_AXIS_TVALID     => open,
--      M_AXIS_TLAST      => open,
--      M_AXIS_TREADY     => '1',
--      M_AXIS_TDATA      => open,
--      M_AXIS_TKEEP      => open 
--    );

end;
