-------------------------------------------------------------
-- MSS copyright 1999-2005
--	Filename:  ENCODER_ROOT
-- Author: Alain Zarembowitch / MSS
--	Version: 7
--	Date last modified: 5-5-05
-- Inheritance: 	none
--
-- description:  
-- COM-1010
-- Convolutional encoder
--
-- Rev 2  12-30-03 AZ
-- Corrected error in differential encoding
--
-- Rev 4  8-12-04 AZ
-- Corrected error in timing when using parallel output (DR#70)
-- Corrected error: TCM34 clock unconnected
--
-- Rev 5 9-9-04 AZ
-- Added CCSDS support K=7  
--
-- Rev 6 11-10-04 AZ
-- Force alignment with I-channel at the start of the puncturing period.
-- 
-- Rev 7 5-5-05
-- Force SOF_RESET to ground when in test mode or continuous mode
-- Otherwise, COM-5101 may reset it accidentally (charge up floating pin)
---------------------------------------------------------------

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity ENCODER_ROOT is
    port ( 
		--GLOBAL CLOCKS, RESET
	   CLK : in std_logic;	-- master clock for this FPGA, synchronous 
		ASYNC_RESET: in std_logic;	-- asynchronous reset

		--// Input samples
		DATA_IN: in std_logic;
			-- input bit. Read at rising edge of CLK when SAMPLE_CLK_IN = '1';
		SAMPLE_CLK_IN: in std_logic;
			-- one CLK-wide pulse
		SAMPLE_CLK_IN_REQ: out std_logic;
			-- one CLK-wide pulse requesting another sample from the module upstream
			-- used for flow control.
	  	SOF_RESET: in std_logic;
			-- 1 CLK-wide pulse indicating that the encoder shall be reset. 
			-- Aligned with SAMPLE_CLK_IN.
			-- Used in the block mode. Ignored in continuous mode.

		--// Output samples
		DATA_OUT: out std_logic_vector(3 downto 0);
			-- output sample. Read at rising edge of CLK when SAMPLE_CLK_IN = '1';
			-- can be 1-bit serial (bit 0 only), 2-bit parallel (for QPSK modulation)
			-- 3-bit parallel (for 8-PSK TCM), 4-bit parallel (for 16-PSK TCM) 
		SAMPLE_CLK_OUT: out std_logic;
			-- one CLK-wide pulse
		SAMPLE_CLK_OUT_REQ: in std_logic;
			-- one CLK-wide pulse requesting another sample from the module upstream
			-- used for flow control.

		--// Controls
	   CONTROL: in std_logic_vector(15 downto 0);
		TP: out std_logic_vector(4 downto 0)

			
			);
end entity;

architecture behavioral of ENCODER_ROOT is
--------------------------------------------------------
--      COMPONENTS
--------------------------------------------------------
component ENCODER_K5R7 is
    port ( 
		--GLOBAL CLOCKS, RESET
	   CLK : in std_logic;	-- master clock for this FPGA, synchronous 
		ASYNC_RESET: in std_logic;	-- asynchronous reset

		--// Input samples
		DATA_IN: in std_logic;
			-- input bit. Read at rising edge of CLK when SAMPLE_CLK_IN = '1';
		SAMPLE_CLK_IN: in std_logic;
			-- one CLK-wide pulse
	  	SOF_RESET: in std_logic;
			-- 1 CLK-wide pulse indicating that the encoder shall be reset. 
			-- Aligned with SAMPLE_CLK_IN.
			-- Used in the block mode. 

		--// Output samples
		DATA_OUT: out std_logic_vector(6 downto 0);
			-- output sample. Read at rising edge of CLK when SAMPLE_CLK_IN = '1';
			-- 7-bit parallel output
		SAMPLE_CLK_OUT: out std_logic
			-- one CLK-wide pulse. same rate as SAMPLE_CLK_IN
			-- Latency is 1 CLK.
		
			);
end component;

component ENCODER_K7R2 is
    port ( 
		--GLOBAL CLOCKS, RESET
	   CLK : in std_logic;	-- master clock for this FPGA, synchronous 
		ASYNC_RESET: in std_logic;	-- asynchronous reset

		--// Input samples
		DATA_IN: in std_logic;
			-- input bit. Read at rising edge of CLK when SAMPLE_CLK_IN = '1';
		SAMPLE_CLK_IN: in std_logic;
			-- one CLK-wide pulse
	  	SOF_RESET: in std_logic;
			-- 1 CLK-wide pulse indicating that the encoder shall be reset. 
			-- Aligned with SAMPLE_CLK_IN.
			-- Used in the block mode. 

		--// Output samples
		DATA_OUT: out std_logic_vector(1 downto 0);
			-- output sample. Read at rising edge of CLK when SAMPLE_CLK_IN = '1';
			-- 2-bit parallel output
		SAMPLE_CLK_OUT: out std_logic
			-- one CLK-wide pulse. same rate as SAMPLE_CLK_IN
			-- Latency is 1 CLK.
			);
end component;

component ENCODER_K9R3 is
    port ( 
		--GLOBAL CLOCKS, RESET
	   CLK : in std_logic;	-- master clock for this FPGA, synchronous 
		ASYNC_RESET: in std_logic;	-- asynchronous reset

		--// Input samples
		DATA_IN: in std_logic;
			-- input bit. Read at rising edge of CLK when SAMPLE_CLK_IN = '1';
		SAMPLE_CLK_IN: in std_logic;
			-- one CLK-wide pulse
	  	SOF_RESET: in std_logic;
			-- 1 CLK-wide pulse indicating that the encoder shall be reset. 
			-- Aligned with SAMPLE_CLK_IN.
			-- Used in the block mode. 

		--// Output samples
		DATA_OUT: out std_logic_vector(2 downto 0);
			-- output sample. Read at rising edge of CLK when SAMPLE_CLK_IN = '1';
			-- 3-bit parallel output
		SAMPLE_CLK_OUT: out std_logic
			-- one CLK-wide pulse. same rate as SAMPLE_CLK_IN
			-- Latency is 1 CLK.
		
			);
end component;

component ENCODER_K9R2 is
    port ( 
		--GLOBAL CLOCKS, RESET
	   CLK : in std_logic;	-- master clock for this FPGA, synchronous 
		ASYNC_RESET: in std_logic;	-- asynchronous reset

		--// Input samples
		DATA_IN: in std_logic;
			-- input bit. Read at rising edge of CLK when SAMPLE_CLK_IN = '1';
		SAMPLE_CLK_IN: in std_logic;
			-- one CLK-wide pulse
	  	SOF_RESET: in std_logic;
			-- 1 CLK-wide pulse indicating that the encoder shall be reset. 
			-- Aligned with SAMPLE_CLK_IN.
			-- Used in the block mode. 

		--// Output samples
		DATA_OUT: out std_logic_vector(1 downto 0);
			-- output sample. Read at rising edge of CLK when SAMPLE_CLK_IN = '1';
			-- 2-bit parallel output
		SAMPLE_CLK_OUT: out std_logic
			-- one CLK-wide pulse. same rate as SAMPLE_CLK_IN
			-- Latency is 1 CLK.
		
			);
end component;

component TCM_23 is
    port ( 
		--GLOBAL CLOCKS, RESET
	   CLK : in std_logic;	-- master clock for this FPGA, synchronous 
		ASYNC_RESET: in std_logic;	-- asynchronous reset

		--// Input samples
		DATA_IN: in std_logic;
			-- input bit. Read at rising edge of CLK when SAMPLE_CLK_IN = '1';
		SAMPLE_CLK_IN: in std_logic;
			-- one CLK-wide pulse
	  	SOF_RESET: in std_logic;
			-- 1 CLK-wide pulse indicating that the encoder shall be reset. 
			-- Aligned with SAMPLE_CLK_IN.
			-- Used in the block mode. 


		--// Output samples
		DATA_OUT: out std_logic_vector(2 downto 0);
			-- output sample. Read at rising edge of CLK when SAMPLE_CLK_OUT = '1';
			-- 3-bit parallel output
		SAMPLE_CLK_OUT: out std_logic
			-- one CLK-wide pulse. same rate as SAMPLE_CLK_IN
			-- Latency is 1 CLK.
		
			);
end component;

component TCM_34 is
    port ( 
		--GLOBAL CLOCKS, RESET
	   CLK : in std_logic;	-- master clock for this FPGA, synchronous 
		ASYNC_RESET: in std_logic;	-- asynchronous reset

		--// Input samples
		DATA_IN: in std_logic;
			-- input bit. Read at rising edge of CLK when SAMPLE_CLK_IN = '1';
		SAMPLE_CLK_IN: in std_logic;
			-- one CLK-wide pulse
	  	SOF_RESET: in std_logic;
			-- 1 CLK-wide pulse indicating that the encoder shall be reset. 
			-- Aligned with SAMPLE_CLK_IN.
			-- Used in the block mode. 


		--// Output samples
		DATA_OUT: out std_logic_vector(3 downto 0);
			-- output sample. Read at rising edge of CLK when SAMPLE_CLK_OUT = '1';
			-- 4-bit parallel output
		SAMPLE_CLK_OUT: out std_logic
			-- one CLK-wide pulse. same rate as SAMPLE_CLK_IN
			-- Latency is 1 CLK.
		
			);
end component;

--------------------------------------------------------
--     SIGNALS
--------------------------------------------------------
-- Suffix _D indicates a one CLK delayed version of the net with the same name
-- Suffix _E indicates an extended precision version of the net with the same name
-- Suffix _N indicates an inverted version of the net with the same name
--// CONSTANTS
signal ZERO: std_logic;
signal ONE: std_logic;

--// RECLOCKED INPUT SIGNALS
signal DATA_IN_D: std_logic;
signal SAMPLE_CLK_IN_D: std_logic;
signal SOF_RESET_IN_D: std_logic;

--// Differentially encoded signal
signal DATA1: std_logic;
signal SAMPLE1_CLK: std_logic;
signal SOF1: std_logic;

--// convolutional encoder enabled clocks
signal SAMPLE1_CLK_K5R7: std_logic;
signal SAMPLE1_CLK_K7R2: std_logic;
signal SAMPLE1_CLK_K9R3: std_logic;
signal SAMPLE1_CLK_K9R2: std_logic;
signal SAMPLE1_CLK_TCM23: std_logic;
signal SAMPLE1_CLK_TCM34: std_logic;

--// convolutionally encoded signal (before puncturing)
signal DATA2_K5R7: std_logic_vector(6 downto 0);
signal SAMPLE2_CLK_K5R7: std_logic;
signal DATA2_K7R2: std_logic_vector(1 downto 0);
signal SAMPLE2_CLK_K7R2: std_logic;
signal DATA2_K9R3: std_logic_vector(2 downto 0);
signal SAMPLE2_CLK_K9R3: std_logic;
signal DATA2_K9R2: std_logic_vector(1 downto 0);
signal SAMPLE2_CLK_K9R2: std_logic;
signal DATA2_TCM23: std_logic_vector(2 downto 0);
signal SAMPLE2_CLK_TCM23: std_logic;
signal DATA2_TCM34: std_logic_vector(3 downto 0);
signal SAMPLE2_CLK_TCM34: std_logic;
signal SAMPLE2_CLK: std_logic;
signal DATA2: std_logic_vector(6 downto 0);

--// encoder output serialization clocks
signal ENCODED_BIT_COUNT: std_logic_vector(3 downto 0);
signal SAMPLE2_COUNT: std_logic_vector(2 downto 0);

--// convoluted punctured data, bit serial
signal SAMPLE3_CLK: std_logic;
signal SAMPLE3_CLK_D: std_logic;      
signal SAMPLE3_CLK_ALIGN_I: std_logic;
signal DATA3: std_logic;
signal DATA3_D: std_logic;

signal SAMPLE_OUT_LOCAL: std_logic;
signal SAMPLE4_CLK: std_logic;
signal DATA4: std_logic_vector(3 downto 0);
signal OUTPUT_BIT_COUNT: std_logic_vector(1 downto 0);
signal OUTPUT_BIT_COUNT_D: std_logic_vector(1 downto 0);
signal NCO_CONTROL: std_logic_vector(26 downto 0);
signal NCO_ACC: std_logic_vector(27 downto 0);
signal NCO_ACC_4MSB: std_logic_vector(3 downto 0);
signal N_INPUT_SAMPLES: std_logic_vector(3 downto 0);

signal SAMPLE2_COUNT_TEST: std_logic;
signal SAMPLE_CLK_IN_REQ_local: std_logic;

signal SAMPLE_CLK_IN_REQ_k9r23: std_logic;
signal SAMPLE_CLK_IN_REQ_k9r13: std_logic;      

signal SAMPLE_CLK_IN_REQ_test: std_logic;

signal SAMPLE_CLK_IN_REQ_k9r23_count: std_logic_vector(1 downto 0); 
signal COUNT_DOWN: std_logic_vector(2 downto 0);
--------------------------------------------------------
--      IMPLEMENTATION
--------------------------------------------------------

begin
--// CONSTANTS ---------------------
ZERO <= '0';
ONE <= '1';

--// Reclock input signals 
RECLOCK_001: process(ASYNC_RESET, CLK)
begin
	if(ASYNC_RESET = '1') then
		DATA_IN_D <= '0';
		SAMPLE_CLK_IN_D <= '0';
		SOF_RESET_IN_D <= '0';
	elsif rising_edge(CLK) then   
		DATA_IN_D <= DATA_IN;
		SAMPLE_CLK_IN_D <= SAMPLE_CLK_IN;
		SOF_RESET_IN_D <= SOF_RESET;
	end if;
end process;


--// Differential encoding if enabled
-- Also force SOF_RESET to ground when in test mode or continuous mode
DIFF_ENC_001: process(ASYNC_RESET, CLK)
begin
	if(ASYNC_RESET = '1') then
		DATA1 <= '0';
		SAMPLE1_CLK <= '0';
		SOF1 <= '0';
	elsif rising_edge(CLK) then   
		SAMPLE1_CLK <= SAMPLE_CLK_IN_D;

		if(CONTROL(6) = '1') and (CONTROL(11 downto 10) = "00") then
			SOF1 <= SOF_RESET_IN_D;
		else
			SOF1 <= '0';
		end if;

		if(SAMPLE_CLK_IN_D = '1') then
			if(CONTROL(5) = '1') then
				-- diff encoding enabled
				DATA1 <= DATA_IN_D xor DATA1;
		 	else
				-- disabled
				DATA1 <= DATA_IN_D;
			end if;
	 	end if;
	end if;
end process;

--// Enable the selected convolutional encoder
ENCODER_ENABLE_001: process(SAMPLE1_CLK, CONTROL)
begin
	if(CONTROL(4 downto 1) = 0) then
		SAMPLE1_CLK_K5R7 <= SAMPLE1_CLK;
 	else
		SAMPLE1_CLK_K5R7 <= '0';
  	end if;
end process;


ENCODER_ENABLE_002: process(SAMPLE1_CLK, CONTROL)
begin
	if(CONTROL(4 downto 1) > 0)  and (CONTROL(4 downto 1) < 6) then
		-- K=7 Intelsat version 
		SAMPLE1_CLK_K7R2 <= SAMPLE1_CLK;
	elsif(CONTROL(4 downto 1) > 10)  then
		-- CCSDS version
		SAMPLE1_CLK_K7R2 <= SAMPLE1_CLK;
 	else
		SAMPLE1_CLK_K7R2 <= '0';
  	end if;
end process;

ENCODER_ENABLE_003: process(SAMPLE1_CLK, CONTROL)
begin
	if(CONTROL(4 downto 1) = 6)  then
		SAMPLE1_CLK_K9R3 <= SAMPLE1_CLK;
 	else
		SAMPLE1_CLK_K9R3 <= '0';
  	end if;
end process;


ENCODER_ENABLE_004: process(SAMPLE1_CLK, CONTROL)
begin
	if(CONTROL(4 downto 1) > 6)  and (CONTROL(4 downto 1) < 9) then
		SAMPLE1_CLK_K9R2 <= SAMPLE1_CLK;
 	else
		SAMPLE1_CLK_K9R2 <= '0';
  	end if;
end process;

ENCODER_ENABLE_005: process(SAMPLE1_CLK, CONTROL)
begin
	if(CONTROL(4 downto 1) =9)  then
		SAMPLE1_CLK_TCM23 <= SAMPLE1_CLK;
 	else
		SAMPLE1_CLK_TCM23 <= '0';
  	end if;
end process;

ENCODER_ENABLE_006: process(SAMPLE1_CLK, CONTROL)
begin
	if(CONTROL(4 downto 1) = 10)  then
		SAMPLE1_CLK_TCM34 <= SAMPLE1_CLK;
 	else
		SAMPLE1_CLK_TCM34 <= '0';
  	end if;
end process;


--// convolutional encoding K = 5, R=1/7
ENCODER_K5R7_001: ENCODER_K5R7 port map(
	ASYNC_RESET => ASYNC_RESET,
	CLK => CLK, 
	DATA_IN => DATA1,
	SAMPLE_CLK_IN => SAMPLE1_CLK_K5R7,
	SOF_RESET => SOF1,
	DATA_OUT => DATA2_K5R7,
	SAMPLE_CLK_OUT => SAMPLE2_CLK_K5R7
);

--// convolutional encoding K = 7, R=1/2
-- Uses Intelsat G0/G1 polynomials. 
-- Be sure to switch G0/G1 polynomials at output when selecting CCSDS
ENCODER_K7R2_001: ENCODER_K7R2 port map(
	ASYNC_RESET => ASYNC_RESET,
	CLK => CLK, 
	DATA_IN => DATA1,
	SAMPLE_CLK_IN => SAMPLE1_CLK_K7R2,
	SOF_RESET => SOF1,
	DATA_OUT => DATA2_K7R2,
	SAMPLE_CLK_OUT => SAMPLE2_CLK_K7R2
);

--// convolutional encoding K = 9, R=1/3
ENCODER_K9R3_001: ENCODER_K9R3 port map(
	ASYNC_RESET => ASYNC_RESET,
	CLK => CLK, 
	DATA_IN => DATA1,
	SAMPLE_CLK_IN => SAMPLE1_CLK_K9R3,
	SOF_RESET => SOF1,
	DATA_OUT => DATA2_K9R3,
	SAMPLE_CLK_OUT => SAMPLE2_CLK_K9R3
);

--// convolutional encoding K = 9, R=1/2
ENCODER_K9R2_001: ENCODER_K9R2 port map(
	ASYNC_RESET => ASYNC_RESET,
	CLK => CLK, 
	DATA_IN => DATA1,
	SAMPLE_CLK_IN => SAMPLE1_CLK_K9R2,
	SOF_RESET => SOF1,
	DATA_OUT => DATA2_K9R2,
	SAMPLE_CLK_OUT => SAMPLE2_CLK_K9R2
);

--// Treillis encoder rate 2/3
-- Puncturing is already built-in.
TCM_23_001: TCM_23 port map(
	ASYNC_RESET => ASYNC_RESET,
	CLK => CLK,
	DATA_IN => DATA1,
	SAMPLE_CLK_IN => SAMPLE1_CLK_TCM23,
	SOF_RESET => SOF1,
	DATA_OUT => DATA2_TCM23,
	SAMPLE_CLK_OUT => SAMPLE2_CLK_TCM23
);

--// Treillis encoder rate 3/4
-- Puncturing is already built-in.
TCM_34_001: TCM_34 port map(
	ASYNC_RESET => ASYNC_RESET,
	CLK => CLK,
	DATA_IN => DATA1,
	SAMPLE_CLK_IN => SAMPLE1_CLK_TCM34,
	SOF_RESET => SOF1,
	DATA_OUT => DATA2_TCM34,
	SAMPLE_CLK_OUT => SAMPLE2_CLK_TCM34
);



--// Serialization and Puncturing
-- For each convolutional encoder output clock, generate 2, 3 or 7 consecutive
-- clocks, depending on the basic rate 1/2, 1/3 or 1/7. 

-- Did a new batch of convoluted bits arrive?
SAMPLE2_CLK <= SAMPLE2_CLK_K5R7 or SAMPLE2_CLK_K7R2 or SAMPLE2_CLK_K9R3 or 
	SAMPLE2_CLK_K9R2 or SAMPLE2_CLK_TCM23 or SAMPLE2_CLK_TCM34;

-- If so, reset counter, and count convoluted bits up to at most 7
ENCODED_BIT_COUNT_GEN: process(ASYNC_RESET, CLK)
begin
	if(ASYNC_RESET = '1') then
		ENCODED_BIT_COUNT <= (others => '0');
 	elsif rising_edge(CLK) then
		if(SAMPLE2_CLK = '1') then
			-- new batch of convoluted bits. reset counter
			ENCODED_BIT_COUNT <= (others => '0');
		elsif(ENCODED_BIT_COUNT < 8) then
			-- Count to 8 and stay there until next batch of convoluted bits.
			ENCODED_BIT_COUNT <= ENCODED_BIT_COUNT + 1;
	  	end if;
 	end if;
end process;

-- count the number of SAMPLE2_CLK in the puncturing period
-- counts even when no puncturing is used.
SAMPLE2_COUNT_GEN: process(ASYNC_RESET, CLK,SAMPLE2_COUNT)
begin
	if(ASYNC_RESET = '1') then
		SAMPLE2_COUNT <= (others => '0');
		SAMPLE2_COUNT_TEST <= '0';
 	elsif rising_edge(CLK) then
		if(SAMPLE2_CLK = '1') then
			SAMPLE2_COUNT_TEST <= NOT SAMPLE2_COUNT_TEST;
			if((CONTROL(4 downto 1) = 2) or (CONTROL(4 downto 1) = 8) or (CONTROL(4 downto 1) = 12)) and (SAMPLE2_COUNT = 1) then
				-- Rate 2/3, puncturing period is modulo 2 batches of convoluted bits.
				SAMPLE2_COUNT <= (others => '0');				
			elsif((CONTROL(4 downto 1) = 3) or (CONTROL(4 downto 1) = 13)) and (SAMPLE2_COUNT = 2) then
				-- Rate 3/4, puncturing period is modulo 3 batches of convoluted bits.
				SAMPLE2_COUNT <= (others => '0');
			elsif((CONTROL(4 downto 1) = 4) or (CONTROL(4 downto 1) = 14)) and (SAMPLE2_COUNT = 4) then
				-- Rate 5/6, puncturing period is modulo 5 batches of convoluted bits.
				SAMPLE2_COUNT <= (others => '0');
			elsif((CONTROL(4 downto 1) = 5) or (CONTROL(4 downto 1) = 15)) and (SAMPLE2_COUNT = 6) then
				-- Rate 7/8, puncturing period is modulo 7 batches of convoluted bits.
				SAMPLE2_COUNT <= (others => '0');
			else 
				-- increment.
				SAMPLE2_COUNT <= SAMPLE2_COUNT + 1;
		  	end if;
	  	end if;
 	end if;
end process;
 
-- Enable or disable the serial output, depending on the puncturing selected,
-- the bitcount and the samplecount.
PUNCTURED_BIT_ENABLE_GEN: process(CONTROL, ENCODED_BIT_COUNT, SAMPLE2_COUNT)
begin
	if(CONTROL(4 downto 1) = 0) then
		-- K=5, R=1/7, no puncturing
		if(ENCODED_BIT_COUNT < 7) then
			SAMPLE3_CLK <= '1';
		else
			SAMPLE3_CLK <= '0';
	 	end if;
	elsif(CONTROL(4 downto 1) = 1) or (CONTROL(4 downto 1) = 11) then
		-- K=7, R=1/2, no puncturing
		if(ENCODED_BIT_COUNT < 2) then
			SAMPLE3_CLK <= '1';
		else
			SAMPLE3_CLK <= '0';
	 	end if;
	elsif(CONTROL(4 downto 1) = 6) then
		-- K=9, R=1/3, no puncturing
		if(ENCODED_BIT_COUNT < 3) then
			SAMPLE3_CLK <= '1';
		else
			SAMPLE3_CLK <= '0';
	 	end if;
	elsif(CONTROL(4 downto 1) = 7) then
		-- K=9, R=1/2, no puncturing
		if(ENCODED_BIT_COUNT < 2) then
			SAMPLE3_CLK <= '1';
		else
			SAMPLE3_CLK <= '0';
	 	end if;
	elsif(CONTROL(4 downto 1) = 2)  then
		-- K=7, R=2/3, puncturing period, Intelsat
		if(SAMPLE2_COUNT = 0) and (ENCODED_BIT_COUNT =  0) then
			SAMPLE3_CLK <= '1';
		elsif(SAMPLE2_COUNT = 0) and (ENCODED_BIT_COUNT =  1) then
			SAMPLE3_CLK <= '1';
		elsif(SAMPLE2_COUNT = 1) and (ENCODED_BIT_COUNT =  0) then
			SAMPLE3_CLK <= '1';
		else
			SAMPLE3_CLK <= '0';
	 	end if;
	elsif(CONTROL(4 downto 1) = 3) then
		-- K=7, R=3/4, puncturing period, Intelsat
		if(SAMPLE2_COUNT = 0) and (ENCODED_BIT_COUNT =  0) then
			SAMPLE3_CLK <= '1';
		elsif(SAMPLE2_COUNT = 0) and (ENCODED_BIT_COUNT =  1) then
			SAMPLE3_CLK <= '1';
		elsif(SAMPLE2_COUNT = 1) and (ENCODED_BIT_COUNT =  0) then
			SAMPLE3_CLK <= '1';
		elsif(SAMPLE2_COUNT = 2) and (ENCODED_BIT_COUNT =  1) then
			SAMPLE3_CLK <= '1';
		else
			SAMPLE3_CLK <= '0';
	 	end if;
	elsif(CONTROL(4 downto 1) = 4) then
		-- K=7, R=5/6, puncturing period, Intelsat
		if(SAMPLE2_COUNT = 0) and (ENCODED_BIT_COUNT =  0) then
			SAMPLE3_CLK <= '1';
		elsif(SAMPLE2_COUNT = 0) and (ENCODED_BIT_COUNT =  1) then
			SAMPLE3_CLK <= '1';
		elsif(SAMPLE2_COUNT = 1) and (ENCODED_BIT_COUNT =  0) then
			SAMPLE3_CLK <= '1';
		elsif(SAMPLE2_COUNT = 2) and (ENCODED_BIT_COUNT =  1) then
			SAMPLE3_CLK <= '1';
		elsif(SAMPLE2_COUNT = 3) and (ENCODED_BIT_COUNT =  0) then
			SAMPLE3_CLK <= '1';
		elsif(SAMPLE2_COUNT = 4) and (ENCODED_BIT_COUNT =  1) then
			SAMPLE3_CLK <= '1';
		else
			SAMPLE3_CLK <= '0';
	 	end if;
	elsif(CONTROL(4 downto 1) = 5) then
		-- K=7, R=7/8, puncturing period, Intelsat
		if(SAMPLE2_COUNT = 0) and (ENCODED_BIT_COUNT =  0) then
			SAMPLE3_CLK <= '1';
		elsif(SAMPLE2_COUNT = 0) and (ENCODED_BIT_COUNT =  1) then
			SAMPLE3_CLK <= '1';
		elsif(SAMPLE2_COUNT = 1) and (ENCODED_BIT_COUNT =  0) then
			SAMPLE3_CLK <= '1';
		elsif(SAMPLE2_COUNT = 2) and (ENCODED_BIT_COUNT =  0) then
			SAMPLE3_CLK <= '1';
		elsif(SAMPLE2_COUNT = 3) and (ENCODED_BIT_COUNT =  0) then
			SAMPLE3_CLK <= '1';
		elsif(SAMPLE2_COUNT = 4) and (ENCODED_BIT_COUNT =  1) then
			SAMPLE3_CLK <= '1';
		elsif(SAMPLE2_COUNT = 5) and (ENCODED_BIT_COUNT =  0) then
			SAMPLE3_CLK <= '1';
		elsif(SAMPLE2_COUNT = 6) and (ENCODED_BIT_COUNT =  1) then
			SAMPLE3_CLK <= '1';
		else
			SAMPLE3_CLK <= '0';
	 	end if;
	elsif(CONTROL(4 downto 1) = 8)  then
	-- K=9, R=2/3, puncturing period
		if((SAMPLE2_COUNT = 0) and (ENCODED_BIT_COUNT =  0)) then
			SAMPLE3_CLK <= '1';
		elsif((SAMPLE2_COUNT = 1) and (ENCODED_BIT_COUNT =  1)) then
			SAMPLE3_CLK <= '1';
		elsif((SAMPLE2_COUNT = 1) and (ENCODED_BIT_COUNT =  0)) then
			SAMPLE3_CLK <= '1';
		else
			SAMPLE3_CLK <= '0';
	 	end if;
	elsif(CONTROL(4 downto 1) = 12)  then
		-- K=7, R=2/3, puncturing period, CCSDS
		if(SAMPLE2_COUNT = 0) and (ENCODED_BIT_COUNT =  0) then
			SAMPLE3_CLK <= '1';
		elsif(SAMPLE2_COUNT = 0) and (ENCODED_BIT_COUNT =  1) then
			SAMPLE3_CLK <= '1';
		elsif(SAMPLE2_COUNT = 1) and (ENCODED_BIT_COUNT =  1) then
			SAMPLE3_CLK <= '1';
		else
			SAMPLE3_CLK <= '0';
	 	end if;
	elsif(CONTROL(4 downto 1) = 13) then
		-- K=7, R=3/4, puncturing period, CCSDS
		if(SAMPLE2_COUNT = 0) and (ENCODED_BIT_COUNT =  0) then
			SAMPLE3_CLK <= '1';
		elsif(SAMPLE2_COUNT = 0) and (ENCODED_BIT_COUNT =  1) then
			SAMPLE3_CLK <= '1';
		elsif(SAMPLE2_COUNT = 1) and (ENCODED_BIT_COUNT =  1) then
			SAMPLE3_CLK <= '1';
		elsif(SAMPLE2_COUNT = 2) and (ENCODED_BIT_COUNT =  0) then
			SAMPLE3_CLK <= '1';
		else
			SAMPLE3_CLK <= '0';
	 	end if;
	elsif(CONTROL(4 downto 1) = 14) then
		-- K=7, R=5/6, puncturing period, CCSDS
		if(SAMPLE2_COUNT = 0) and (ENCODED_BIT_COUNT =  0) then
			SAMPLE3_CLK <= '1';
		elsif(SAMPLE2_COUNT = 0) and (ENCODED_BIT_COUNT =  1) then
			SAMPLE3_CLK <= '1';
		elsif(SAMPLE2_COUNT = 1) and (ENCODED_BIT_COUNT =  1) then
			SAMPLE3_CLK <= '1';
		elsif(SAMPLE2_COUNT = 2) and (ENCODED_BIT_COUNT =  0) then
			SAMPLE3_CLK <= '1';
		elsif(SAMPLE2_COUNT = 3) and (ENCODED_BIT_COUNT =  1) then
			SAMPLE3_CLK <= '1';
		elsif(SAMPLE2_COUNT = 4) and (ENCODED_BIT_COUNT =  0) then
			SAMPLE3_CLK <= '1';
		else
			SAMPLE3_CLK <= '0';
	 	end if;
	elsif(CONTROL(4 downto 1) = 15) then
		-- K=7, R=7/8, puncturing period, CCSDS
		if(SAMPLE2_COUNT = 0) and (ENCODED_BIT_COUNT =  0) then
			SAMPLE3_CLK <= '1';
		elsif(SAMPLE2_COUNT = 0) and (ENCODED_BIT_COUNT =  1) then
			SAMPLE3_CLK <= '1';
		elsif(SAMPLE2_COUNT = 1) and (ENCODED_BIT_COUNT =  1) then
			SAMPLE3_CLK <= '1';
		elsif(SAMPLE2_COUNT = 2) and (ENCODED_BIT_COUNT =  1) then
			SAMPLE3_CLK <= '1';
		elsif(SAMPLE2_COUNT = 3) and (ENCODED_BIT_COUNT =  1) then
			SAMPLE3_CLK <= '1';
		elsif(SAMPLE2_COUNT = 4) and (ENCODED_BIT_COUNT =  0) then
			SAMPLE3_CLK <= '1';
		elsif(SAMPLE2_COUNT = 5) and (ENCODED_BIT_COUNT =  1) then
			SAMPLE3_CLK <= '1';
		elsif(SAMPLE2_COUNT = 6) and (ENCODED_BIT_COUNT =  0) then
			SAMPLE3_CLK <= '1';
		else
			SAMPLE3_CLK <= '0';
	 	end if;
 	else
		SAMPLE3_CLK <= '0';
	end if; 	
end process;

--// Select output from convolutional encoders
-- Data2 is large enough for the largest rate (1/7).
ENCODER_OUTPUT_SELECT: process(ASYNC_RESET, CLK)
begin
	if(ASYNC_RESET = '1') then
		DATA2 <= (others => '0');
  	elsif rising_edge(CLK) then
		if(CONTROL(4 downto 1) = 0) then
			-- Encoder: K =5, R = 1/7
			DATA2(6 downto 0) <= DATA2_K5R7;
		elsif(CONTROL(4 downto 1) > 0)  and (CONTROL(4 downto 1) < 6) then
			-- Encoder: K =7, R = 1/2  Intelsat
			DATA2(1 downto 0) <= DATA2_K7R2;
		elsif(CONTROL(4 downto 1) = 11) then
			-- Encoder: K =7, R = 1/2 CCSDS. Basic convolutional code. 
			-- Switch G0/G1 polynomials. Invert G2 (CCSDS terminology) output.
			DATA2(0) <= DATA2_K7R2(1);
			DATA2(1) <= not DATA2_K7R2(0);
		elsif(CONTROL(4 downto 1) > 11) then
			-- Encoder: K =7, R = 1/2 CCSDS. Switch G0/G1 polynomials. 
			-- No inverter at G2 output when using punctured codes.
			DATA2(0) <= DATA2_K7R2(1);
			DATA2(1) <= DATA2_K7R2(0);
		elsif(CONTROL(4 downto 1) = 6)  then
			DATA2(2 downto 0) <= DATA2_K9R3;
		elsif(((CONTROL(4 downto 1) > 6)  and (CONTROL(4 downto 1) < 9)) and (CONTROL(11 downto 10) = "11")) then
			DATA2(1 downto 0) <= DATA2_K9R3(1 downto 0);
		elsif(CONTROL(4 downto 1) > 6)  and (CONTROL(4 downto 1) < 9) then
			DATA2(1 downto 0) <= DATA2_K9R2;
		end if;
	end if;
end process;


--// get convoluted punctured bit from array DATA2.
DATA3_GEN: process(DATA2, ENCODED_BIT_COUNT)
begin
	if(ENCODED_BIT_COUNT = 0) then
		DATA3 <= DATA2(0);
	elsif(ENCODED_BIT_COUNT = 1) then
		DATA3 <= DATA2(1);
	elsif(ENCODED_BIT_COUNT = 2) then
		DATA3 <= DATA2(2);
	elsif(ENCODED_BIT_COUNT = 3) then
		DATA3 <= DATA2(3);
	elsif(ENCODED_BIT_COUNT = 4) then
		DATA3 <= DATA2(4);
	elsif(ENCODED_BIT_COUNT = 5) then
		DATA3 <= DATA2(5);
	else
		DATA3 <= DATA2(6);
	end if;
end process;


-- force first punctured bit in a period to be aligned with I   
SAMPLE3_CLK_ALIGN_I <= '1' when (ENCODED_BIT_COUNT = 0) else '0';

--// Serial parallel conversion, as specified by CONTROL(9 downto 8)
-- Special case: TCM modulation. Always parallel ouput. Bypass serial to parallel conversion.
-- Count output bits modulo 1,2,3 or 4
OUTPUT_BIT_COUNT_GEN: process(ASYNC_RESET, CLK)
begin
	if(ASYNC_RESET = '1') then
		OUTPUT_BIT_COUNT <= (others => '0');
	elsif rising_edge(CLK) then
		if(SAMPLE3_CLK = '1') then
			if(CONTROL(9 downto 8) = 0) or (CONTROL(4 downto 1) = 9) or (CONTROL(4 downto 1) = 10) then
				-- 1-bit serial output or TCM parallel output. Modulo 1 counter
				OUTPUT_BIT_COUNT <= (others => '0');
			elsif(CONTROL(9 downto 8) = 1) and ((OUTPUT_BIT_COUNT = 1) or (SAMPLE3_CLK_ALIGN_I = '1')) then
				-- 2-bit parallel output. Modulo 2 counter
				OUTPUT_BIT_COUNT <= (others => '0');
			elsif(CONTROL(9 downto 8) = 2) and (OUTPUT_BIT_COUNT = 2) then
				-- 3-bit parallel output. Modulo 3 counter
				OUTPUT_BIT_COUNT <= (others => '0');
			elsif(CONTROL(9 downto 8) = 3) and (OUTPUT_BIT_COUNT = 3) then
				-- 4-bit parallel output. Modulo 4 counter
				OUTPUT_BIT_COUNT <= (others => '0');
		 	else
				OUTPUT_BIT_COUNT <= OUTPUT_BIT_COUNT + 1;
		 	end if;
--		else
--			SAMPLE4_CLK <= '0';
	 	end if;
	end if;
end process;

-- realign signal
RECLOCK_002: process(ASYNC_RESET, CLK)
begin
	if(ASYNC_RESET = '1') then
		DATA3_D <= '0';
		SAMPLE3_CLK_D <= '0';
	elsif rising_edge(CLK) then
		DATA3_D <= DATA3;
		SAMPLE3_CLK_D <= SAMPLE3_CLK;      
  	end if;
end process;

--// serial to parallel conversion
S2P: process(ASYNC_RESET, CLK)
begin
	if(ASYNC_RESET = '1') then
		DATA4 <= (others => '0');
		SAMPLE4_CLK <= '0';
		OUTPUT_BIT_COUNT_D <= (others => '0');
	elsif rising_edge(CLK) then
		SAMPLE4_CLK <= SAMPLE3_CLK_D;
		OUTPUT_BIT_COUNT_D <= OUTPUT_BIT_COUNT;

		if(SAMPLE3_CLK_D = '1') then
			if(OUTPUT_BIT_COUNT = 0) then
				DATA4(0) <= DATA3_D;
			elsif(OUTPUT_BIT_COUNT = 1) then
				DATA4(1) <= DATA3_D;
			elsif(OUTPUT_BIT_COUNT = 2) then
				DATA4(2) <= DATA3_D;
		  	elsif (OUTPUT_BIT_COUNT = 3) then
				DATA4(3) <= DATA3_D;
			end if;
	 	end if;
  	end if;
end process;

--// output 
-- TCM sample bypasses parallel to serial conversion
RECLOCK_003: process(ASYNC_RESET, CLK)
begin
	if(ASYNC_RESET = '1') then
		DATA_OUT <= (others => '0');
		SAMPLE_CLK_OUT <= '0';
	elsif rising_edge(CLK) then
		if(CONTROL(4 downto 1) = 9) and (SAMPLE2_CLK_TCM23 = '1') then
			-- treillis encoding, rate 2/3. 
			-- Bypass the dual parallel to serial + serial to parallel conversions
			DATA_OUT(2 downto 0) <= DATA2_TCM23;
			DATA_OUT(3) <= '0';
			SAMPLE_CLK_OUT <= SAMPLE2_CLK_TCM23;
		elsif(CONTROL(4 downto 1) = 10) and (SAMPLE2_CLK_TCM34 = '1') then
			-- treillis encoding, rate 3/4
			-- Bypass the dual parallel to serial + serial to parallel conversions
			DATA_OUT <= DATA2_TCM34;
			SAMPLE_CLK_OUT <= SAMPLE2_CLK_TCM34;
			
		elsif(SAMPLE4_CLK = '1')  and (OUTPUT_BIT_COUNT_D = 0) then
			DATA_OUT <= DATA4;
			SAMPLE_CLK_OUT <= '1';
	  	else
			SAMPLE_CLK_OUT <= '0';
	 	end if;
  	end if;
end process;

--// Flow control. NCO control
-- NCO generates the input sample request from the output sample requests received.
-- Truncate to the larger integer. i.e. requests more than needed.
-- Example: if rate 1/7: NCO_CONTROL = 1/7*2^24
-- NCO_CONTROL represents the number of bits requested for each SAMPLE_CLK_REQ. 
-- NCO_CONTROL format is 3.24. Thus for rate 1/2, serial output, 
-- the NCO_CONTROL value is 0.5 = 000.1000000000000000000000000
-- If the rate cannot be represented exactly by the 3.24 format, then NCO_CONTROL 
-- should be rounded UP. It is OK to request more input bits than needed as the flow control
-- mechanism will regulate the flow.

NCO_001: process(ASYNC_RESET, CLK)
begin
	if(ASYNC_RESET = '1') then
		NCO_CONTROL <= (others => '0');
	elsif rising_edge(CLK) then
		if(CONTROL(4 downto 1) = 9) then
			-- rate 2/3 TCM. No serial to parallel conversion. 3bit wide output only
			NCO_CONTROL <= "010000000000000000000000000";

		elsif(CONTROL(4 downto 1) = 10) then
			-- rate 3/4 TCM. No serial to parallel conversion. 4bit wide output only
				NCO_CONTROL <= "011000000000000000000000000";

		elsif(CONTROL(9 downto 8) = 0) then
			-- 1 bit serial output
			if(CONTROL(4 downto 1) = 0) then
				-- Rate 1/7
				NCO_CONTROL <= "000001001001001001001001010";
			elsif(CONTROL(4 downto 1) = 6) then
				-- Rate 1/3
				NCO_CONTROL <= "000010101010101010101010110";
			elsif(CONTROL(4 downto 1) = 1) or (CONTROL(4 downto 1) = 7) or (CONTROL(4 downto 1) = 11) then
				-- Rate 1/2
				NCO_CONTROL <= "000100000000000000000000000";
			elsif(CONTROL(4 downto 1) = 2) or (CONTROL(4 downto 1) = 8) or (CONTROL(4 downto 1) = 12) then
				-- Rate 2/3
				NCO_CONTROL <= "000101010101010101010101011";
			elsif(CONTROL(4 downto 1) = 3)  or (CONTROL(4 downto 1) = 13) then
				-- Rate 3/4
				NCO_CONTROL <= "000110000000000000000000000";
			elsif(CONTROL(4 downto 1) = 4) or (CONTROL(4 downto 1) = 14) then
				-- Rate 5/6
				NCO_CONTROL <= "000110101010101010101010110";
			elsif(CONTROL(4 downto 1) = 5)  or (CONTROL(4 downto 1) = 15) then
				-- Rate 7/8
				NCO_CONTROL <= "000111000000000000000000000";
			end if;
		elsif(CONTROL(9 downto 8) = 1) then
			-- 2 bit parallel output
			if(CONTROL(4 downto 1) = 0) then
				-- Rate 1/7
				NCO_CONTROL <= "000010010010010010010010011";
			elsif(CONTROL(4 downto 1) = 6) then
				-- Rate 1/3
				NCO_CONTROL <= "000101010101010101010101011";
			elsif(CONTROL(4 downto 1) = 1) or (CONTROL(4 downto 1) = 7) or (CONTROL(4 downto 1) = 11) then
				-- Rate 1/2
				NCO_CONTROL <= "001000000000000000000000000";
			elsif(CONTROL(4 downto 1) = 2) or (CONTROL(4 downto 1) = 8) or (CONTROL(4 downto 1) = 12) then
				-- Rate 2/3
				NCO_CONTROL <= "001010101010101010101010110";
			elsif(CONTROL(4 downto 1) = 3) or (CONTROL(4 downto 1) = 13) then
				-- Rate 3/4
				NCO_CONTROL <= "001100000000000000000000000";
			elsif(CONTROL(4 downto 1) = 4) or (CONTROL(4 downto 1) = 14)  then
				-- Rate 5/6
				NCO_CONTROL <= "001101010101010101010101011";
			elsif(CONTROL(4 downto 1) = 5) or (CONTROL(4 downto 1) = 15)  then
				-- Rate 7/8
				NCO_CONTROL <= "001110000000000000000000000";
			end if;
		elsif(CONTROL(9 downto 8) = 2) then
			-- 3 bit parallel output
			if(CONTROL(4 downto 1) = 0) then
				-- Rate 1/7
				NCO_CONTROL <= "000011011011011011011011100";
			elsif(CONTROL(4 downto 1) = 6) then
				-- Rate 1/3
				NCO_CONTROL <= "001000000000000000000000000";
			elsif(CONTROL(4 downto 1) = 1) or (CONTROL(4 downto 1) = 7) or (CONTROL(4 downto 1) = 11) then
				-- Rate 1/2
				NCO_CONTROL <= "001000000000000000000000000";
			elsif(CONTROL(4 downto 1) = 2) or (CONTROL(4 downto 1) = 8) or (CONTROL(4 downto 1) = 12) then
				-- Rate 2/3
				NCO_CONTROL <= "001100000000000000000000000";
			elsif(CONTROL(4 downto 1) = 3) or (CONTROL(4 downto 1) = 13) then
				-- Rate 3/4
				NCO_CONTROL <= "010010000000000000000000000";
			elsif(CONTROL(4 downto 1) = 4) or (CONTROL(4 downto 1) = 14) then
				-- Rate 5/6
				NCO_CONTROL <= "010100000000000000000000000";
			elsif(CONTROL(4 downto 1) = 5) or (CONTROL(4 downto 1) = 15)  then
				-- Rate 7/8
				NCO_CONTROL <= "010101000000000000000000000";
			end if;
		else
			-- 4 bit parallel output
			if(CONTROL(4 downto 1) = 0) then
				-- Rate 1/7
				NCO_CONTROL <= "000100100100100100100100101";
			elsif(CONTROL(4 downto 1) = 6) then
				-- Rate 1/3
				NCO_CONTROL <= "001010101010101010101010110";
			elsif(CONTROL(4 downto 1) = 1) or (CONTROL(4 downto 1) = 7) or (CONTROL(4 downto 1) = 11) then
				-- Rate 1/2
				NCO_CONTROL <= "010000000000000000000000000";
			elsif(CONTROL(4 downto 1) = 2) or (CONTROL(4 downto 1) = 8) or (CONTROL(4 downto 1) = 12) then
				-- Rate 2/3
				NCO_CONTROL <= "010101010101010101010101011";
			elsif(CONTROL(4 downto 1) = 3) or (CONTROL(4 downto 1) = 13) then
				-- Rate 3/4
				NCO_CONTROL <= "011000000000000000000000000";
			elsif(CONTROL(4 downto 1) = 4) or (CONTROL(4 downto 1) = 14)  then
				-- Rate 5/6
				NCO_CONTROL <= "011010101010101010101010110";
			elsif(CONTROL(4 downto 1) = 5) or (CONTROL(4 downto 1) = 15) then
				-- Rate 7/8
				NCO_CONTROL <= "011100000000000000000000000";
			end if;
		end if;
	end if;
end process;


-- MSBs increase by the number of bits to be requested
NCO_002: process(ASYNC_RESET, CLK)
begin
	if(ASYNC_RESET = '1') then
		NCO_ACC <= (others => '0');
	elsif rising_edge(CLK) then
		if(SAMPLE_CLK_OUT_REQ = '1') then
			NCO_ACC <= NCO_ACC + ("0" & NCO_CONTROL);
	  	end if;
  	end if;
end process;


-- MSBs increase by the number of bits actually requested
NCO_003: process(ASYNC_RESET, CLK)
begin
	if(ASYNC_RESET = '1') then
		NCO_ACC_4MSB <= (others => '0');
	elsif rising_edge(CLK) then
		if(SAMPLE_CLK_IN_REQ_local = '1') then
			NCO_ACC_4MSB <= NCO_ACC_4MSB + 1;
	  	end if;
  	end if;
end process;
 
-- number of input samples to be requested
N_INPUT_SAMPLES <= NCO_ACC(27 downto 24) -  NCO_ACC_4MSB; 

-- generate sample requests
-- Make sure the requests are single requests separated by enough clocks to 
-- prevent problems when serializing the encoder parallel output.
-- For example, ensure 7 clocks of separation between consecutive input bit requests if rate 1/7, etc.
SAMPLE_CLK_IN_REQ_local <= '1' when ((N_INPUT_SAMPLES /= 0) and (COUNT_DOWN = 0)) else '0';

SEPARATION_GEN_001:  process(ASYNC_RESET, CLK)
begin
	if(ASYNC_RESET = '1') then
		COUNT_DOWN <= (others => '0');
	elsif rising_edge(CLK) then
		if(SAMPLE_CLK_IN_REQ_local = '1') then
			-- re-arm counter
			if(CONTROL(4 downto 1) = 0) then
				COUNT_DOWN <= "110";	-- min 7 clocks separation
			elsif(CONTROL(4 downto 1) > 0)  and (CONTROL(4 downto 1) < 6) then
				COUNT_DOWN <= "001";	-- min 2 clocks separation
			elsif(CONTROL(4 downto 1) = 6)  then
				COUNT_DOWN <= "010";	-- min 3 clocks separation
			elsif(CONTROL(4 downto 1) > 6)  and (CONTROL(4 downto 1) < 9) then
				COUNT_DOWN <= "001";	-- min 2 clocks separation
			elsif(CONTROL(4 downto 1) = 9)  then
				COUNT_DOWN <= "010";	-- min 3 clocks separation
			elsif(CONTROL(4 downto 1) = 10)  then
				COUNT_DOWN <= "011";	-- min 4 clocks separation
			elsif(CONTROL(4 downto 1) > 10)  then
				COUNT_DOWN <= "001";	-- min 2 clocks separation
			end if;
	  	elsif(COUNT_DOWN /= 0) then
			COUNT_DOWN <= COUNT_DOWN - 1;
		end if;
  	end if;
end process;


-- generate sample requests
-- maximum number is 4 input bits per output sample
SAMPLE_CLK_IN_REQ <= SAMPLE_CLK_IN_REQ_local;



end behavioral;

