-----------------------------------------------------------------
-- Project : agfo12_b2.ise --  30sep08 - ANU-RSAA
-- File : op_fifo1.vhd -- gk,  07032008
-----------------------------------------------------------------
-- The original source code copied from Deepak. - Version 8
-- Modified for the Burst mode data acquisition.
-- This module (op_fifo1.vhd) takes care of the output FIFO of 
-- the AgFo firmware.
-- 
-----------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
library UNISIM;
use UNISIM.VComponents.all;
use IEEE.numeric_std.all;
-----------------------------------------------------------------
entity op_fifo1 is
    Port (     
	 reset					: in std_logic;
	 USB_RST					: in std_logic;
	 rd_clk_in           : in std_logic;
	 wr_clk_in	  			: in std_logic;
	 sctn_in 				: in std_logic;
	 fout_in 				: in std_logic;
--	 rd_addr_inc_out 		: out std_logic;
    burst_mode_in    	: in std_logic;
	 ch_sel_mode_in 	   : in std_logic;
	 data_in					: in std_logic_VECTOR(159 downto 0);
	 regceb  				: in std_logic;
	 burst_rd_complete_in : in std_logic;
    valid_data          : in std_logic;
	 
	 channel_no          : in STD_LOGIC_VECTOR (7 downto 0);
	 ch_sel_reg				: in std_logic_vector(7 downto 0);

 	 dinL1_out           : out std_logic_Vector(159 downto 0);
	 regcebL1_out        : out std_logic;

	 fifo_rd_er_flag_out : out std_logic;
	 vsib_pvalid_out     : out std_logic;
	 vsib_trigger_out    : out std_logic;
    read_start_out      : out std_logic;
	 read_started_out    : out std_logic;
    mux1_out            : out std_logic_vector(9 downto 0);
	 
	 --monitoring
	 regceb_flag_MON     : out std_logic
	

	
   );
end op_fifo1;
-----------------------------------------------------------------

architecture Behavioral of op_fifo1 is

---- FIFO DECLARATION -------------------------------------------
component fifo1
    port (
    din				: IN std_logic_VECTOR(159 downto 0);
    rd_clk			: IN std_logic;
    rd_en			: IN std_logic;
    rst				: IN std_logic;
    wr_clk			: IN std_logic;
    wr_en			: IN std_logic;
    dout				: OUT std_logic_VECTOR(19 downto 0);
    empty			: OUT std_logic;
    full				: OUT std_logic;
	 rd_data_count	: OUT std_logic_VECTOR(6 downto 0);
    wr_data_count	: OUT std_logic_VECTOR(3 downto 0)
	 ); 
end component;
---------- XST black box declaration
attribute box_type : string;
attribute box_type of fifo1 : component is "black_box";

signal dinL1,dinL1_in,dinL2_in,data_store,dinL1_lat : std_logic_vector(159 downto 0);
signal mux_cnt3 : std_logic_vector(1 downto 0) := "00";
signal mux_cnt3L1 : std_logic_vector(1 downto 0) := "00";
signal mux_cnt3L2 : std_logic_vector(1 downto 0) := "00";
signal mux_cnt3L3 : std_logic_vector(1 downto 0) := "00";
signal vsib_triggerL1,vsib_triggerL2, vsib_triggerL3, vsib_pvalidL1, vsib_pvalidL2,
       vsib_pvalidL3  : std_logic := '0';
signal vsib_trigger,rd_en,vsib_pvalid,regcebL1,regcebL2,fifo_rd_addrs_inc : std_logic := '0';
signal foutL1,sctnL1,vsib_load,rd_adrs_flag,read_started,
       regceb_clk_ratio,regceb_flag,start_read, marker_read, data_read,
       last_data, empty, reset_rd_clk, first_marker : std_logic := '0';
signal burst_mode, ch_sel_mode : std_logic;		 
signal burst_rd_completeL1 : std_logic;		 
signal regceb_counter: std_logic_vector(7 downto 0) ;
signal read_counter : std_logic_vector(2 downto 0) := "000";
signal sctn_counter : std_logic_vector(1 downto 0) := "00";
signal fout_counter : std_logic_vector(5 downto 0) := "000000";
signal data_out : std_logic_vector (19 downto 0);
signal rd_data_count : std_logic_vector(6 downto 0);
signal wr_data_count : std_logic_vector(3 downto 0);
signal marker_count : std_logic_vector(9 downto 0);
signal marker, marker_rd_clk : std_logic_vector(7 downto 0);
signal mux1_local : std_logic_vector(9 downto 0);
signal delay_counter : std_logic_vector(3 downto 0);
signal trigger_counter : std_logic_vector(25 downto 0); 
signal sctn_flag,sctn_flag_rd_clk,vsib_trigger_enable : std_logic;
signal vsib_trigger2,rst_opreg_load,regceb_cnt: std_logic;

constant CLK_RATIO : integer := 7;  -- ratio of write to read clock
-----------------------------------------------------------------
signal usbL1 : std_logic_vector(31 downto 0);
signal check_ld_low,usb_load_int,valid_load,valid_data_in,regceb_in,new_data : std_logic;
--signal ch_sel_reg : std_logic_vector(7 downto 0);
-----------------------------------------------------------------
begin

vsib_trigger_out <= vsib_triggerL3;
vsib_pvalid_out <= vsib_pvalidL3;
read_start_out <= start_read;
read_started_out <= read_started;

------ FIFO Instantiation ---------------------------------------
fifo_inst1 : fifo1
      port map (
            din 				=> dinL1_lat, --dinL1,
            rd_clk 			=> rd_clk_in,
            rd_en 			=> rd_en,
            rst 				=> reset, 
            wr_clk 			=> wr_clk_in,
            wr_en 			=> regcebL1,
            dout 				=> data_out,
            empty 			=> empty, 
            full 				=> open,
            rd_data_count 	=> rd_data_count,
            wr_data_count 	=> wr_data_count
			);
-----------------------------------------------------------------

dinL1_out <= dinL1_lat; --dinL1;
regcebL1_out <= regcebL1;
------------------------------------------------------------------
-- usb load decode
------------------------------------------------------------------


------------------------------------------------------------------

process(wr_clk_in)
begin
  if(wr_clk_in'event and wr_clk_in='1') then
--	 dinL1    <= dinL2_in;
--  dinL2_in <= dinL1_in;
--  dinL1_in <= data_in;
 	 dinL2_in <= data_in;
 	 dinL1_lat <= dinL1;
	 
--	 regcebL1 <= regceb_in;
--    regcebL2 <= regcebL1;
    regcebL1 <= regceb_flag;
	 valid_data_in <= valid_data;
	 foutL1 <= fout_in;
	 sctnL1 <= sctn_in;
	 regceb_in <= regceb;

	if(reset = '1') then
	   regceb_counter <= (others => '0');
		regceb_clk_ratio <= '0';
		regceb_flag <= '0';
		read_started <= '0';
	  	start_read <= '0';
		regceb_cnt <= '0';
	  new_data <= '0';

	else	 
------------------------------------	 
--	   if(regceb_in = '1' and data_read = '0' and marker_read = '0') then
--	     start_read <= '1';
--	   elsif(regceb_in = '1' and last_data = '1' and marker_read = '0' and data_read = '1') then
--        start_read <= '1';	 
--	   elsif(data_read = '0' and marker_read = '1') then
--	     read_started <= '1';
--	   elsif(data_read = '1' and last_data = '1') then	
--		  start_read <= '0';
--	   elsif(data_read = '0' and marker_read = '0' and read_started = '1') then
--        read_started <= '0';	 
--	   end if;
--------------------------------------
      if(wr_data_count > 0) then
		  start_read <= '1';
		  read_started <= '1';
		elsif(wr_data_count = 0 and start_read = '1') then 
		  start_read <= '0';
		elsif(wr_data_count = 0 and start_read = '0' and read_started = '1')then
		  read_started <= '0';
		end if;  
-----------------------------------------
-----------------------------------------

    if(ch_sel_mode_in = '1') then


-------------------21may09------------------------------------------
--			 if  foutL1  = '1' and new_data = '1' then
--			     regceb_flag <= '1';
--				  new_data <= '0';
--				  dinL1 <= data_store;
--			 end if;
-- 			 if regceb_flag = '1' and valid_data_in = '0' then
--			     regceb_flag <= '0';
--			 end if;	  
-------------------21may09------------------------------------------

		if (regceb_in = '1') and (regceb_counter <= channel_no) and (valid_data_in = '1') then
          regceb_counter <= regceb_counter + '1';
		 
----21/4/09
--			 if (regceb_counter = ch_sel_reg) then
--             regceb_flag <= '1';	
--		    else
--			     regceb_flag <= '0';
--		    end if;		
----21/4/09
-------------------21may09------------------------------------------
--			 if (regceb_counter = ch_sel_reg) and foutL1  = '1' then
--			     regceb_flag <= '1';
--				  new_data <= '0';
--				  dinL1    <= dinL2_in;
--			 elsif (regceb_counter = ch_sel_reg) and foutL1  = '0' then
--			     regceb_flag <= '0';
--				  data_store <= dinL2_in;
--				  new_data <= '1';
--			 end if;	  
--			 if regceb_flag = '1' then
--			     regceb_flag <= '0';
--			 end if;	  
-------------------21may09------------------------------------------

			 if  (regceb_counter = ch_sel_reg) and regceb_flag = '0' then --and foutL1  = '0' then
				  dinL1 <= dinL2_in;
			 elsif (regceb_counter = ch_sel_reg) and regceb_flag = '1' then	  
			     regceb_flag <= '0';
				  dinL1 <= dinL2_in;
			 elsif (regceb_counter /= ch_sel_reg) and  regceb_flag = '1' then
			     regceb_flag <= '0';
				  dinL1 <= (others => '0');
			 end if;		 
			 if foutL1 = '1' then
   	        regceb_flag <= '1';	
			 end if;

      elsif  regceb_in = '0' and foutL1 = '1'  and valid_data_in = '1' then
		        regceb_flag <= '1';	
--		elsif (regceb_in = '0') and (regceb_flag = '1') and (regceb_counter <= 23) then
--		elsif (regceb_in = '0') and (regceb_flag = '1') and (regceb_counter <= channel_no) and (valid_data_in = '1') then
		elsif (regceb_in = '0') and (regceb_flag = '1') and (valid_data_in = '1') then
	          regceb_flag <= '0';	
			    dinL1 <= (others => '0');
				 
--		elsif (regceb_counter > 23) then
--		elsif (regceb_counter > channel_no) then
--             regceb_counter <= (others => '0');
--             regceb_flag <= '0';
      elsif (valid_data_in = '0') then
      	    regceb_counter <= (others => '0');
				 	if foutL1 = '1' then
	   	        regceb_flag <= '1';	
					end if;
	
					if regceb_flag = '1' then 
						regceb_flag <= '0';
						dinL1 <= (others => '0');
				   end if;		
					
--             regceb_flag <= '0';
-- 				 new_data <= '0';
		end if;
	 elsif(burst_mode_in = '1') then
          regceb_flag <= regceb_in;
		    dinL1 <= dinL2_in;
			 
	 end if;
--------------------------------------
   end if;		 	 
  end if;
end process;
-----------------------------------------------------------------
process(rd_clk_in)
begin 
  if(rd_clk_in'event and rd_clk_in='1') then
     reset_rd_clk <= reset;
	  
	  if(reset_rd_clk = '1') then
	    vsib_pvalid <= '0';
		 vsib_trigger <= '0';
		 mux_cnt3 <= "10";
		 read_counter <= (others => '0');
		 marker_count <= (others => '0');
		 rd_en <= '0';		 
	  elsif(empty = '1' and read_counter = 0) then
	    if(ch_sel_mode = '1') then
		    mux_cnt3 <= "10";
		 elsif(burst_mode = '1') then
          if(burst_rd_completeL1 = '1' and first_marker = '0') then
             marker_count <= (others => '0');
				 mux_cnt3 <= "10";
          elsif(burst_rd_completeL1 = '0' and first_marker = '1') then
			  	 marker_count <= marker_count + 1;
				 mux_cnt3 <= "11";
          elsif(burst_rd_completeL1 = '1' and first_marker = '1') then
             marker_count <= (others => '0');
				 mux_cnt3 <= "10";
				 first_marker <= '0';
          end if;	
       end if;			 
		 vsib_pvalid <= '0';
	  elsif(empty = '0' and read_counter = 0 and (mux_cnt3 = "10" or mux_cnt3 = "11")) then
       mux_cnt3 <= "00";
		 vsib_pvalid <= '1';
		 if(mux_cnt3 = "10") then
          vsib_trigger <= '1';
		 else
          vsib_trigger <= '0';
       end if;			 
       rd_en <= '1';	
	  elsif(empty = '0' and read_counter < 7 and mux_cnt3 = "00") then
	    mux_cnt3 <= "01";
	  elsif(empty = '0' and read_counter = 7 and mux_cnt3 = "00") then
	    mux_cnt3 <= "01";
		 if(burst_mode = '1') then
		   if(burst_rd_completeL1 = '0' and first_marker = '0') then
			  first_marker <= '1';
			end if;
       end if;			
	  elsif(empty = '0' and read_counter < 7 and mux_cnt3 = "01") then
       mux_cnt3 <= "00";
	    read_counter <= read_counter + '1';
       rd_en <= '1';	
	  elsif(empty = '1' and read_counter = 7 and mux_cnt3 = "01") then
	  	 if(ch_sel_mode = '1') then
		    mux_cnt3 <= "10";
		 elsif(burst_mode = '1') then
		   if(first_marker = '1') then
          mux_cnt3 <= "11";
			else
          mux_cnt3 <= "10";
			end if; 
		 end if;	 
	    read_counter <= (others => '0');
	  end if;	 	
  
  if(rd_en = '1') then
	  rd_en <= '0';
  end if;
  
  if(vsib_trigger = '1') then
	    vsib_trigger <= '0';
  end if;
  
  mux_cnt3L1 <= mux_cnt3;
  mux_cnt3L2 <= mux_cnt3L1;
  
  
  -- existing as on 14/8/09--------------
--  vsib_triggerL1 <= vsib_trigger;
--  vsib_triggerL1 <= vsib_trigger;
--  vsib_triggerL2 <= vsib_triggerL1; --vsib_trigger2;
--  vsib_triggerL3 <= vsib_triggerL2;
-- existing as on 14/8/09--------------

--  vsib_triggerL1 <= vsib_trigger;
  vsib_triggerL2 <= vsib_trigger2;
  vsib_triggerL3 <= vsib_triggerL2;

  
  vsib_pvalidL1 <= vsib_pvalid;
  vsib_pvalidL2 <= vsib_pvalidL1;
  vsib_pvalidL3 <= vsib_pvalidL2;
  
 end if;
end process;
-----------------------------------------------------------------
process(rd_clk_in, mux_cnt3L2)
begin
if rd_clk_in'event and rd_clk_in= '1' then
 case mux_cnt3L2 is
  when "00" => mux1_local <= data_out(19 downto 10);    -- LSB 10 bits from FIFO
  when "01" => mux1_local <= data_out(9 downto 0);  -- MSB 10 bits from FIFO
  when "10" => mux1_local <=  "01" & marker_rd_clk; -- 01 followed by an 8-Bit marker
  when "11" => mux1_local <=  "01" & "01010101"; -- to get fd55 marker in burst mode
  when others => mux1_local <= mux1_local;
 end case;
	mux1_out <= mux1_local;
end if;	
end process;    
-------- Marker Process -----------------------------------------
process(wr_clk_in)
begin
 if wr_clk_in'event and wr_clk_in= '1' then
  if(reset='1') then
   sctn_counter <= (others => '0');
	fout_counter <= (others => '0');
  else
   if(sctnL1='0') then
     sctn_counter <= sctn_counter + '1';
 	end if;
   if(foutL1='1') then
     fout_counter <= fout_counter + '1';
 	end if;
  end if;	
  marker <= sctn_counter & fout_counter;
 end if;	
end process;

process(rd_clk_in)
begin
 if rd_clk_in'event and rd_clk_in= '1' then
   burst_mode <= burst_mode_in;
	ch_sel_mode <= ch_sel_mode_in;
   burst_rd_completeL1 <= burst_rd_complete_in;
   marker_rd_clk <= marker;
 end if;
end process;  
-------- process for Synchronizing VSIB trigger  -------------------
process(wr_clk_in)
begin
 if wr_clk_in'event and wr_clk_in= '1' then
  if(reset='1') then
   delay_counter <= (others => '0'); 
   sctn_flag <= '0';
  elsif(reset='0' and  delay_counter < 10) then
	  delay_counter <= delay_counter + 1;
  elsif(reset='0' and delay_counter = 10) then
     if(sctnL1='0') then
       sctn_flag <= '1';
     end if;
  end if;
 end if;  
end process;
-- Process for Capturing the sctn_flag with the rd_clk_in
-- & enable the VSIB trigger 
process(rd_clk_in)
begin
 if rd_clk_in'event and rd_clk_in= '1' then
  sctn_flag_rd_clk <= sctn_flag;
  if(reset_rd_clk='1') then
    vsib_trigger_enable <= '0';
  elsif(sctn_flag_rd_clk = '1') then
    vsib_trigger_enable <= '1';
  end if;
 end if; 
end process;
----------------------------------------------------------
-- Process for 1 trigger interval from the AgFo to the VSIB
---- For Channel Selection Mode
-- The decimal number   1280000 is obtained by 1/(128/163840000)
-- equal to hex number  138800  which gives 1 second trigger interval.
---- For burst mode 
--- the above number is 2048 (800 in hex)
process(rd_clk_in)
begin
 if(rd_clk_in'event and rd_clk_in = '1') then
   if(reset_rd_clk = '1') then
	  trigger_counter <= (others => '0');
	  vsib_trigger2 <= '0';
	elsif(vsib_trigger_enable = '1') then
    if(ch_sel_mode = '1') then
	  if(vsib_trigger = '1' and trigger_counter < X"1387FF") then
--	  if(vsib_trigger = '1' and trigger_counter < 1) then
	    trigger_counter <= trigger_counter + 1;
	  elsif(vsib_trigger = '1' and trigger_counter = X"1387FF") then	 
--	  elsif(vsib_trigger = '1' and trigger_counter = 1) then	 
	    trigger_counter <= (others => '0');
		 vsib_trigger2 <= '1';
	  end if;
	 elsif(burst_mode = '1') then
	   if(vsib_trigger = '1' and trigger_counter < X"7FF") then
--	  if(vsib_trigger = '1' and trigger_counter < 1) then
	    trigger_counter <= trigger_counter + 1;
	   elsif(vsib_trigger = '1' and trigger_counter = X"7FF") then	 
--	  elsif(vsib_trigger = '1' and trigger_counter = 1) then	 
	    trigger_counter <= (others => '0');
		 vsib_trigger2 <= '1';
		end if; 
    end if; 
   end if;
	if(vsib_trigger2 = '1') then
	   vsib_trigger2 <= '0';
	end if;
 end if;	
end process;


--monitoring points;

regceb_flag_MON <= regceb_flag;
-----------------------------------------------------------------
end Behavioral;
-----------------------------------------------------------------
-------------- end of the file : op_fifo1.vhd -------------------
