----------------------------------------------------------------------------------
-- Company: 
-- Engineer: 
-- 
-- Create Date:    15:17:37 08/24/2010 
-- Design Name: 
-- Module Name:    channel_sample_block_v1 - 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;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

-- Uncomment the following library declaration if instantiating
-- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;

entity channel_sample_block_v1 is
    Port ( adc_sample_logic_reset : in  STD_LOGIC;
           adc_clk : in  STD_LOGIC;
           adc_start_pulse : in  STD_LOGIC;
           adc_sample_block_length_reg : in   STD_LOGIC_VECTOR(25 downto 0);
           adc_din : in  STD_LOGIC_VECTOR (15 downto 0);
           ch_sample_logic_active : out   STD_LOGIC ;

           ch_buffer_fifo_rd_clk : in  STD_LOGIC;
           ch_buffer_fifo_rd_en : in  STD_LOGIC;
           ch_buffer_fifo_dout : out   STD_LOGIC_VECTOR(255 downto 0);
           ch_buffer_fifo_full : out  STD_LOGIC;
           ch_buffer_fifo_empty : out  STD_LOGIC;
           ch_buffer_fifo_almost_empty : out  STD_LOGIC;
           ch_buffer_fifo_rd_count : out   STD_LOGIC_VECTOR(9 downto 0) 
			  
		   );
end channel_sample_block_v1;



architecture Behavioral of channel_sample_block_v1 is

   Function to_std_logic(X: in Boolean) return Std_Logic is
   variable ret : std_logic;
   begin
   if x then ret := '1';  else ret := '0'; end if;
   return ret;
   end to_std_logic;



COMPONENT blk_sy_fwft_fifo_512x256
  PORT (
    clk : IN STD_LOGIC;
    rst : IN STD_LOGIC;
    din : IN STD_LOGIC_VECTOR(255 DOWNTO 0);
    wr_en : IN STD_LOGIC;
    rd_en : IN STD_LOGIC;
    dout : OUT STD_LOGIC_VECTOR(255 DOWNTO 0);
    full : OUT STD_LOGIC;
    empty : OUT STD_LOGIC;
    almost_empty : OUT STD_LOGIC;
    data_count : OUT STD_LOGIC_VECTOR(9 DOWNTO 0)
  );
END COMPONENT;


	COMPONENT risingedge2pulse_generator
	PORT(
		adc_clk : IN std_logic;
		rising_edge_signal_in : IN std_logic;          
		signal_pulse_out : OUT std_logic
		);
	END COMPONENT;



signal fsm_reset: std_logic;
signal fsm_active: std_logic;
signal fsm_sample_logic_busy: std_logic;
signal fsm_16bit_counter: std_logic_vector(3 downto 0);
signal fsm_block_counter: std_logic_vector(25 downto 0);

type fsm_type is(
		IDLE,	--  
		SAMPLE_LOOP ,
		SAMPLE_END	--  
);
signal fsm_state		: fsm_type;


signal pipe_reg_ce1: std_logic;
signal pipe_reg_ce2: std_logic;
signal pipe_reg_ce3: std_logic;
signal pipe_reg_ce4: std_logic;
signal pipe_reg_ce5: std_logic;
signal pipe_reg_ce6: std_logic;
signal pipe_reg_ce7: std_logic;
signal pipe_reg_ce8: std_logic;
signal pipe_reg_ce9: std_logic;
signal pipe_reg_ce10: std_logic;
signal pipe_reg_ce11: std_logic;
signal pipe_reg_ce12: std_logic;
signal pipe_reg_ce13: std_logic;
signal pipe_reg_ce14: std_logic;
signal pipe_reg_ce15: std_logic;
signal pipe_reg_ce16: std_logic;
signal pipe_reg_ce16_del1: std_logic;
signal pipe_reg_ce16_del2: std_logic;
signal pipe_reg_ce16_del3: std_logic;
signal pipe_reg_ce16_del4: std_logic;


signal pipe_fifo_wr: std_logic;

signal adc_pipe1_reg: std_logic_vector(255 downto 0);
signal adc_pipe_reg: std_logic_vector(255 downto 0);
signal adc_buffer_fifo_din: std_logic_vector(255 downto 0);

--signal sy_wrclk_pipe_fifo_wr_delay1: std_logic;
--signal sy_wrclk_pipe_fifo_wr_delay2: std_logic;
--signal sy_wrclk_pipe_fifo_wr_delay3: std_logic;
signal sy_wrclk_buffer_fifo_wr: std_logic;

signal sy_wrclk_adc_buffer_fifo_din: std_logic_vector(255 downto 0);

--signal test_sy_wrclk_buffer_fifo_wr: std_logic;

--attribute keep : boolean;
--
--attribute keep of test_sy_wrclk_buffer_fifo_wr: signal is true;

begin


adc_util_logic: process (adc_clk) 
begin
   if rising_edge(adc_clk) then  -- 
		  fsm_reset       <= adc_sample_logic_reset ;
   end if;
end process;

-- State Maschine 


ch_sample_logic_active <=  fsm_sample_logic_busy ;

ch_sample_controller_fsm: process (adc_clk) 
begin

if  rising_edge(adc_clk) then
   if (fsm_reset = '1')       then  
                                   fsm_active               <=   '0'    ;  
                                   fsm_sample_logic_busy    <=   '0'    ;  
                                   fsm_16bit_counter        <=   X"0"   ;  
                                   fsm_block_counter        <=   "00000000000000000000000000"      ;  
--                                   fsm_block_counter        <=   X"000000"      ;  
                                   fsm_state                <=   IDLE    ;   
    else

     case fsm_state is

							 
---------- 
        when IDLE =>   
                 if (adc_start_pulse = '1') then --  
                                   fsm_active               <=   '1'    ;  
                                   fsm_sample_logic_busy    <=   '1'    ;  
                                   fsm_16bit_counter        <=   X"0"   ;  
                                   fsm_block_counter        <=   adc_sample_block_length_reg      ;  
                                   fsm_state                <=   SAMPLE_LOOP    ;   
                  else
                                   fsm_active               <=   '0'    ;  
                                   fsm_sample_logic_busy    <=   '0'    ;  
                                   fsm_16bit_counter        <=   X"0"   ;  
                                   fsm_block_counter        <=   adc_sample_block_length_reg      ;  
                                   fsm_state                <=   IDLE    ;   
                 end if;

---------- 
        when SAMPLE_LOOP =>   
                                   fsm_sample_logic_busy    <=   '1'    ;  
                 if (fsm_16bit_counter /= X"F") then --  
                                   fsm_active               <=   '1'    ;  
                                   fsm_16bit_counter        <=   fsm_16bit_counter + 1    ;  
                                   fsm_block_counter        <=   fsm_block_counter      ;  
                                   fsm_state                <=   SAMPLE_LOOP    ;   
--                  elsif (fsm_block_counter /= X"000000") then --  
                  elsif (fsm_block_counter /= "00000000000000000000000000") then --  
                                   fsm_active               <=   '1'    ;  
                                   fsm_16bit_counter        <=   X"0"     ;  
                                   fsm_block_counter        <=   fsm_block_counter - 1      ;  
                                   fsm_state                <=   SAMPLE_LOOP    ;   
                  else
                                   fsm_active               <=   '0'    ;  
                                   fsm_16bit_counter        <=   X"0"     ;  
                                   fsm_block_counter        <=   fsm_block_counter      ;  
                                   fsm_state                <=   SAMPLE_END    ;   
                 end if;

---------- 
        when SAMPLE_END =>   
                                   fsm_active               <=   '0'    ;  
                                   fsm_block_counter        <=   fsm_block_counter      ;  
                 if (fsm_16bit_counter = X"8") then --  
                                   fsm_sample_logic_busy    <=   '0'    ;  
                                   fsm_16bit_counter        <=   X"0"     ;  
                                   fsm_state                <=   IDLE    ;   
                  else
                                   fsm_sample_logic_busy    <=   '1'    ;  
                                   fsm_16bit_counter        <=   fsm_16bit_counter + 1    ;  
                                   fsm_state                <=   SAMPLE_END    ;   
                 end if;

---------- 

----------
        when OTHERS => NULL ;
     end case ;
      
   end if;
end if;

end process;




adc_sample_logic: process (adc_clk) 
begin
   if rising_edge(adc_clk) then  -- 

      pipe_reg_ce1   <=  fsm_active and to_std_logic(fsm_16bit_counter(3 downto 0) = "0000") ; 
      pipe_reg_ce2   <=  pipe_reg_ce1 ; 
      pipe_reg_ce3   <=  pipe_reg_ce2 ; 
      pipe_reg_ce4   <=  pipe_reg_ce3 ; 
      pipe_reg_ce5   <=  pipe_reg_ce4 ; 
      pipe_reg_ce6   <=  pipe_reg_ce5 ; 
      pipe_reg_ce7   <=  pipe_reg_ce6 ; 
      pipe_reg_ce8   <=  pipe_reg_ce7 ; 

      pipe_reg_ce9   <=  pipe_reg_ce8 ; 
      pipe_reg_ce10  <=  pipe_reg_ce9 ; 
      pipe_reg_ce11  <=  pipe_reg_ce10 ; 
      pipe_reg_ce12  <=  pipe_reg_ce11 ; 
      pipe_reg_ce13  <=  pipe_reg_ce12 ; 
      pipe_reg_ce14  <=  pipe_reg_ce13 ; 
      pipe_reg_ce15  <=  pipe_reg_ce14 ; 
      pipe_reg_ce16  <=  pipe_reg_ce15 ; 


      pipe_reg_ce16_del1   <=  pipe_reg_ce16      and not adc_sample_logic_reset ; 
      pipe_reg_ce16_del2   <=  pipe_reg_ce16_del1       ; 
      pipe_reg_ce16_del3   <=  pipe_reg_ce16_del2       ; 
      pipe_reg_ce16_del4   <=  pipe_reg_ce16_del3       ; 
      pipe_fifo_wr         <=  pipe_reg_ce16_del4   ; 
   end if;

   if rising_edge(adc_clk) then  -- 
      if (pipe_reg_ce16 = '1') then
		   adc_pipe_reg(255 downto 240)     <= adc_din ;
      end if;
		
      if (pipe_reg_ce15 = '1') then
		   adc_pipe_reg(239 downto 224)     <= adc_din ;
      end if;
		
      if (pipe_reg_ce14 = '1') then
		   adc_pipe_reg(223 downto 208)     <= adc_din ;
      end if;
		
      if (pipe_reg_ce13 = '1') then
		   adc_pipe_reg(207 downto 192)     <= adc_din ;
      end if;
		
      if (pipe_reg_ce12 = '1') then
		   adc_pipe_reg(191 downto 176)     <= adc_din ;
      end if;
		
      if (pipe_reg_ce11 = '1') then
		   adc_pipe_reg(175 downto 160)     <= adc_din ;
      end if;
		
      if (pipe_reg_ce10 = '1') then
		   adc_pipe_reg(159 downto 144)     <= adc_din ;
      end if;
		
      if (pipe_reg_ce9 = '1') then
		   adc_pipe_reg(143 downto 128)     <= adc_din ;
      end if;
		
      if (pipe_reg_ce8 = '1') then
		   adc_pipe_reg(127 downto 112)     <= adc_din ;
      end if;
		
      if (pipe_reg_ce7 = '1') then
		  adc_pipe_reg(111 downto 96)       <= adc_din ;
      end if;

      if (pipe_reg_ce6 = '1') then
		  adc_pipe_reg(95 downto 80)        <= adc_din ;
      end if;

      if (pipe_reg_ce5 = '1') then
		  adc_pipe_reg(79 downto 64)        <= adc_din ;
      end if;

      if (pipe_reg_ce4 = '1') then
		  adc_pipe_reg(63 downto 48)        <= adc_din ;
      end if;

      if (pipe_reg_ce3 = '1') then
		  adc_pipe_reg(47 downto 32)        <= adc_din ;
      end if;

      if (pipe_reg_ce2 = '1') then
		  adc_pipe_reg(31 downto 16)        <= adc_din ;
      end if;

      if (pipe_reg_ce1 = '1') then
		  adc_pipe_reg(15 downto 0)         <= adc_din ;
      end if;
   end if;

-- 
-- pipe the first 8 samples
   if rising_edge(adc_clk) then  -- 
      if (pipe_reg_ce10 = '1') then
		  adc_pipe1_reg(127 downto 0)         <= adc_pipe_reg(127 downto 0) ;
      end if;
   end if;
	adc_pipe1_reg(255 downto 128)        <= adc_pipe_reg(255 downto 128) ;


   if rising_edge(adc_clk) then  -- 
      if (pipe_reg_ce16_del2 = '1') then
		  adc_buffer_fifo_din         <= adc_pipe1_reg ;
      end if;
   end if;


end process;


--	test_adc_write_fifo_risingedge2pulse_generator: risingedge2pulse_generator PORT MAP(
--		adc_clk => adc_clk,
--		rising_edge_signal_in => sy_wrclk_buffer_fifo_wr,
--		signal_pulse_out => test_sy_wrclk_buffer_fifo_wr
--	);

-- ******************************************************************************************
-- das sample buffer fifo muss auch mit der "ch_buffer_fifo_rd_clk" beschrieben werden, das
-- es wegen der "regional clocks" sonst nicht geroutet werden kann !!

	adc_write_fifo_risingedge2pulse_generator: risingedge2pulse_generator PORT MAP(
		adc_clk => ch_buffer_fifo_rd_clk,
--		rising_edge_signal_in => not pipe_fifo_wr,
		rising_edge_signal_in => pipe_fifo_wr,
		signal_pulse_out => sy_wrclk_buffer_fifo_wr
	);

adc_sample_buffer_write_logic: process (ch_buffer_fifo_rd_clk) 
begin

--   if rising_edge(ch_buffer_fifo_rd_clk) then  -- 
----		  sy_wrclk_pipe_fifo_wr_delay1     <=   pipe_fifo_wr ; --old pipeline
--		  sy_wrclk_pipe_fifo_wr_delay1     <=   pipe_reg_ce8 ;
--		  sy_wrclk_pipe_fifo_wr_delay2     <=   sy_wrclk_pipe_fifo_wr_delay1 ;
--		  sy_wrclk_pipe_fifo_wr_delay3     <=   sy_wrclk_pipe_fifo_wr_delay2 ;
--		  sy_wrclk_buffer_fifo_wr          <=   not sy_wrclk_pipe_fifo_wr_delay2 and sy_wrclk_pipe_fifo_wr_delay3 ; -- negative edge !
--
----		  sy_wrclk_adc_buffer_fifo_din     <=   adc_buffer_fifo_din ;
--
--   end if;

		  sy_wrclk_adc_buffer_fifo_din     <=   adc_buffer_fifo_din ;

end process;



ch_sample_buffer_fifo : blk_sy_fwft_fifo_512x256
		port map (
			clk => ch_buffer_fifo_rd_clk,
			rst => fsm_reset,
			din => sy_wrclk_adc_buffer_fifo_din, -- (255 downto 0),
			wr_en => sy_wrclk_buffer_fifo_wr,
			rd_en => ch_buffer_fifo_rd_en,
			dout => ch_buffer_fifo_dout,
			full => ch_buffer_fifo_full,
			empty => ch_buffer_fifo_empty,
			almost_empty => ch_buffer_fifo_almost_empty,
			data_count => ch_buffer_fifo_rd_count  -- (9 downto 0));
		);

end Behavioral;

