-------------------------------------------------------------
--	Filename:  CIC.VHD
--  Author: Alain Zarembowitch 
--	Version: 9
--	Date last modified:  2/2/16 AZ
--  Inheritance: 	none
--
-- Objective: Cascaded Integrated Comb filter and decimation.
-- Observe limits listed in the interface for control parameters N,R,M and truncation.
-- Use R = 1 to bypass this filter.
--
-- Implementation: The precision of the CIC internal signals is extended to 64-bit
-- at the input. This limits the range of recommended control parameters so that
-- Bin + Nlog2(RM) < 65. 
--
-- For more details, see "CIC Filter Introduction", Matthew P. Donadio
-- and Xilinx LogicCore documentation on "Cascaded Integrated-Comb (CIC) Filter v1.0".
--
-- Synthesized Size (Xilinx Spartan-3, irrespective of user-selected R,M,N values).
-- 589 Flip Flops, 994 LUTs, 675 Slices for 32-bit internal computation precision 
-- 1147 Flip Flops, 1848 LUTs, 1264 Slices for 64-bit internal computation precision 
-- 
-- Maximum speed (Xilinx Spartan-3 lowest speed grade -4)
-- 131 MHz for 32-bit internal computation precision
-- 104 MHz for 64-bit internal computation precision
--
-- Rev 2 8-7-05 AZ
-- Added bypass when decimation R = 1.
--
-- Rev 3 4-28-07 AZ
-- added support for decimation factors 2-7
-- 
-- Rev 4 6-23-07 AZ
-- tweaked for speed (210 MHz, 4.5 ns)
--
-- Rev 5 7-5-08 AZ
-- Added reset
--
-- Rev 6 3-8-09 AZ
-- bug with sign extension during the DATA20 shift
-- 
-- Rev 7  12/18/11 AZ
-- fixed bug for R=2
--
-- Rev 8 4/6/14 AZ
-- rephrased for better timing. Inspired by cic_interp4.vhd
--
-- Rev 9 2/2/16 AZ
-- prevent X propagation during simulation
-------------------------------------------------------------

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

entity CIC is
	 Generic(
		N: in integer range 1 to 8 := 2;
			-- number of stages
		M: in integer range 1 to 2 := 1;
			-- differential delay
		SIMULATION: in std_logic := '0'
	 );
    port ( 

	--// GLOBAL CLOCKS, RESET
   CLK : in std_logic;				-- Master clock for this FPGA
	SYNC_RESET: in std_logic;		-- Synchronous reset active high

	
	--// INPUT DATA STREAM
	DATA_IN: in std_logic_vector(11 downto 0);
		-- input samples, 12-bit precision
		-- read at rising edge of CLK when SAMPLE_CLK_IN = '1'.
		-- Format: 2's complement 
	SAMPLE_CLK_IN: in std_logic;
		-- sample clock (1 CLK-wide pulse), approximately 16 samples/symbol
		-- KEY assumption: samples have to be equally spaced in time!

	--// CONTROL PARAMETERS
	R: in integer range 1 to 16384;
		-- decimation
		-- Set R = 1 to bypass.
		-- Otherwise, nominal range is 8 to 16384.
	TRUNCATE_OBITS: in integer range 0 to 63;
		-- number of least significant bits to be truncated at the output. 
		-- Must be set to N*log2(RM), which is the bit growth during the CIC
		-- calculation due to the gain G = (RM)^N.
		-- As this CIC module is designed to be flexible, it is generally more efficient
		-- to compute this field by the application (i.e. outside this module) 
		-- since the parameters N,R,M are generally known and fixed at the time of 
		-- synthesis.

	--// OUTPUT DATA STREAM
	DATA_OUT: out std_logic_vector(11 downto 0);   
		-- Format: 2's complement
		-- read at rising edge of CLK when SAMPLE_CLK_OUT = '1'.
	SAMPLE_CLK_OUT: out std_logic
		-- sample clock. 1 CLK-wide pulse. 
		-- Read the output data at the rising edge of CLK when SAMPLE_CLK_OUT = '1'
		-- As this is the resampling clock, it is also a convenient test point
		-- to compare transmit bit clock to receive bit clock when the bit timing loop is tracking.
		-- The latency between output samples and input samples is variable (depends on N,R,M):
		-- 11 CLKs fixed + 1 CLK for each 8 bits of output truncation + 1 CLK for each remaining 1 bit of output truncation.
		-- For example: if N=4,M=1,R=7, TRUNCATE_OBITS = 12. The total latency is 16 CLKs.

			);
end entity;

architecture behavioral of CIC is
--------------------------------------------------------
--      COMPONENTS
--------------------------------------------------------

--------------------------------------------------------
--     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
-- Suffic _INC indicates increment.

-- for simulation purposes
--constant BOUT: integer  := 31;	-- detected saturation at R>64 for BOUT = 32. Visible through simulation too.
constant BOUT: integer  := 48;		-- should be sufficient for R up to 16384
	-- computation precision to accommodate bit growth (total array length BOUT+1)
constant BIN: integer  := 11;	
	-- computation precision to accommodate bit growth (total array length BIN+1)

signal SAMPLE_CLK_IN_D: std_logic := '0';
signal DATA_IN_D: std_logic_vector(BOUT downto 0) := (others => '0');

--// integrators
signal SAMPLE1_CLK: std_logic := '0';
signal DATA1: std_logic_vector(BOUT downto 0) := (others => '0');
signal SAMPLE2_CLK: std_logic := '0';
signal DATA2: std_logic_vector(BOUT downto 0) := (others => '0');
signal SAMPLE3_CLK: std_logic := '0';
signal DATA3: std_logic_vector(BOUT downto 0) := (others => '0');
signal SAMPLE4_CLK: std_logic := '0';
signal DATA4: std_logic_vector(BOUT downto 0) := (others => '0');
signal SAMPLE5_CLK: std_logic := '0';
signal DATA5: std_logic_vector(BOUT downto 0) := (others => '0');
signal SAMPLE6_CLK: std_logic := '0';
signal DATA6: std_logic_vector(BOUT downto 0) := (others => '0');
signal SAMPLE7_CLK: std_logic := '0';
signal DATA7: std_logic_vector(BOUT downto 0) := (others => '0');
signal SAMPLE8_CLK: std_logic := '0';
signal DATA8: std_logic_vector(BOUT downto 0) := (others => '0');
signal SAMPLE9_CLK: std_logic := '0';
signal DATA9: std_logic_vector(BOUT downto 0) := (others => '0');
signal DATA9_D: std_logic_vector(BOUT downto 0) := (others => '0');
signal DATA9_D2: std_logic_vector(BOUT downto 0) := (others => '0');

--// decimation
signal DECIMATION_COUNTER: std_logic_vector(13 downto 0) := (others => '0');	
signal DECIMATION_COUNTER_INC: std_logic_vector(13 downto 0) := (others => '0');	
signal SAMPLE11_CLK: std_logic := '0';
signal DATA11: std_logic_vector(BOUT downto 0) := (others => '0');
signal DATA11_D: std_logic_vector(BOUT downto 0) := (others => '0');
signal DATA11_D2: std_logic_vector(BOUT downto 0) := (others => '0');
signal SAMPLE12_CLK: std_logic := '0';
signal DATA12: std_logic_vector(BOUT downto 0) := (others => '0');
signal DATA12_D: std_logic_vector(BOUT downto 0) := (others => '0');
signal DATA12_D2: std_logic_vector(BOUT downto 0) := (others => '0');
signal SAMPLE13_CLK: std_logic := '0';
signal DATA13: std_logic_vector(BOUT downto 0) := (others => '0');
signal DATA13_D: std_logic_vector(BOUT downto 0) := (others => '0');
signal DATA13_D2: std_logic_vector(BOUT downto 0) := (others => '0');
signal SAMPLE14_CLK: std_logic := '0';
signal DATA14: std_logic_vector(BOUT downto 0) := (others => '0');
signal DATA14_D: std_logic_vector(BOUT downto 0) := (others => '0');
signal DATA14_D2: std_logic_vector(BOUT downto 0) := (others => '0');
signal SAMPLE15_CLK: std_logic := '0';
signal DATA15: std_logic_vector(BOUT downto 0) := (others => '0');
signal DATA15_D: std_logic_vector(BOUT downto 0) := (others => '0');
signal DATA15_D2: std_logic_vector(BOUT downto 0) := (others => '0');
signal SAMPLE16_CLK: std_logic := '0';
signal DATA16: std_logic_vector(BOUT downto 0) := (others => '0');
signal DATA16_D: std_logic_vector(BOUT downto 0) := (others => '0');
signal DATA16_D2: std_logic_vector(BOUT downto 0) := (others => '0');
signal SAMPLE17_CLK: std_logic := '0';
signal DATA17: std_logic_vector(BOUT downto 0) := (others => '0');
signal DATA17_D: std_logic_vector(BOUT downto 0) := (others => '0');
signal DATA17_D2: std_logic_vector(BOUT downto 0) := (others => '0');
signal SAMPLE18_CLK: std_logic := '0';
signal DATA18: std_logic_vector(BOUT downto 0) := (others => '0');
signal SAMPLE19_CLK: std_logic := '0';
signal DATA19: std_logic_vector(BOUT downto 0) := (others => '0');

signal SHIFT_COUNTER: integer range 0 to 63;
signal SAMPLE20_CLK: std_logic := '0';
signal DATA20: std_logic_vector(BOUT downto 0) := (others => '0');
signal OUTPUT_SAMPLE_FLAG: std_logic := '0';
--------------------------------------------------------
--      IMPLEMENTATION
--------------------------------------------------------

begin

--// Reclock input signal for best timing. 
-- Extend precision to 32-bits because of the bit growth.  
RECLOCK_001: process(CLK)
begin
	if rising_edge(CLK) then
		SAMPLE_CLK_IN_D <= SAMPLE_CLK_IN;

		if(SIMULATION = '1') and (DATA_IN(0) = 'X') then
			-- prevent X propagation in code below during simulation
			DATA_IN_D <= (others => '0');
		elsif(SAMPLE_CLK_IN = '1') then
			DATA_IN_D(BIN downto 0) <= DATA_IN;
			-- precision extension
			DATA_IN_D(BOUT downto (BIN+1)) <= (others => DATA_IN(BIN));
		end if;	
	end if;
end process;

--// 8 Integrator stages
-- Integrator stage 1
INTEGRATOR_001: process(CLK)
begin
	if rising_edge(CLK) then
		SAMPLE1_CLK <= SAMPLE_CLK_IN_D;

		if(SYNC_RESET = '1') then
			DATA1 <= (others => '0');
		elsif(SAMPLE_CLK_IN_D = '1') then
			DATA1 <= DATA1 + DATA_IN_D;
		end if;
	end if;
end process;

-- Integrator stage 2
INTEGRATOR_002: process(CLK)
begin
	if rising_edge(CLK) then
		SAMPLE2_CLK <= SAMPLE1_CLK;

		if(SYNC_RESET = '1') then
			DATA2 <= (others => '0');
		elsif(SAMPLE1_CLK = '1') then
			DATA2 <= DATA2 + DATA1;
		end if;
	end if;
end process;

-- Integrator stage 3
INTEGRATOR_003: process(CLK)
begin
	if rising_edge(CLK) then
		SAMPLE3_CLK <= SAMPLE2_CLK;

		if(SYNC_RESET = '1') then
			DATA3 <= (others => '0');
		elsif(SAMPLE2_CLK = '1') then
			DATA3 <= DATA3 + DATA2;
		end if;
	end if;
end process;

-- Integrator stage 4
INTEGRATOR_004: process(CLK)
begin
	if rising_edge(CLK) then
		SAMPLE4_CLK <= SAMPLE3_CLK;

		if(SYNC_RESET = '1') then
			DATA4 <= (others => '0');
		elsif(SAMPLE3_CLK = '1') then
			DATA4 <= DATA4 + DATA3;
		end if;
	end if;
end process;

-- Integrator stage 5
INTEGRATOR_005: process(CLK)
begin
	if rising_edge(CLK) then
		SAMPLE5_CLK <= SAMPLE4_CLK;

		if(SYNC_RESET = '1') then
			DATA5 <= (others => '0');
		elsif(SAMPLE4_CLK = '1') then
			DATA5 <= DATA5 + DATA4;
		end if;
	end if;
end process;

-- Integrator stage 6
INTEGRATOR_006: process(CLK)
begin
	if rising_edge(CLK) then
		SAMPLE6_CLK <= SAMPLE5_CLK;

		if(SYNC_RESET = '1') then
			DATA6 <= (others => '0');
		elsif(SAMPLE5_CLK = '1') then
			DATA6 <= DATA6 + DATA5;
		end if;
	end if;
end process;

-- Integrator stage 7
INTEGRATOR_007: process(CLK)
begin
	if rising_edge(CLK) then
		SAMPLE7_CLK <= SAMPLE6_CLK;

		if(SYNC_RESET = '1') then
			DATA7 <= (others => '0');
		elsif(SAMPLE6_CLK = '1') then
			DATA7 <= DATA7 + DATA6;
		end if;
	end if;
end process;

-- Integrator stage 8
INTEGRATOR_008: process(CLK)
begin
	if rising_edge(CLK) then
		SAMPLE8_CLK <= SAMPLE7_CLK;

		if(SYNC_RESET = '1') then
			DATA8 <= (others => '0');
		elsif(SAMPLE7_CLK = '1') then
			DATA8 <= DATA8 + DATA7;
		end if;
	end if;
end process;

--// Select number of integrator stages N 
STAGES_SEL_001: process(SAMPLE1_CLK, SAMPLE2_CLK, SAMPLE3_CLK, SAMPLE4_CLK, SAMPLE5_CLK, SAMPLE6_CLK,
				SAMPLE7_CLK, SAMPLE8_CLK, DATA1, DATA2, DATA3, DATA4, DATA5, DATA6, DATA7, DATA8)
begin
   case (N) is 
      when 1 =>
         SAMPLE9_CLK <= SAMPLE1_CLK;
			DATA9 <= DATA1;
      when 2 =>
         SAMPLE9_CLK <= SAMPLE2_CLK;
			DATA9 <= DATA2;
      when 3 =>
         SAMPLE9_CLK <= SAMPLE3_CLK;
			DATA9 <= DATA3;
      when 4 =>
         SAMPLE9_CLK <= SAMPLE4_CLK;
			DATA9 <= DATA4;
      when 5 =>
         SAMPLE9_CLK <= SAMPLE5_CLK;
			DATA9 <= DATA5;
      when 6 =>
         SAMPLE9_CLK <= SAMPLE6_CLK;
			DATA9 <= DATA6;
      when 7 =>
         SAMPLE9_CLK <= SAMPLE7_CLK;
			DATA9 <= DATA7;
      when others =>
         SAMPLE9_CLK <= SAMPLE8_CLK;
			DATA9 <= DATA8;
   end case;
end process;

--// decimation counter
DECIMATION_COUNTER_INC <= DECIMATION_COUNTER + 1;
DECIMATION_COUNTER_001: process(CLK, R)
begin
	if rising_edge(CLK) then
		if(SYNC_RESET = '1') then
			DECIMATION_COUNTER <= (others => '0');
		elsif(SAMPLE9_CLK = '1') then
			if(DECIMATION_COUNTER_INC = R) then  -- trying to improve speed 6/23/07 AZ
				-- modulo R counter
				DECIMATION_COUNTER <= (others => '0');
			else 
				DECIMATION_COUNTER <= DECIMATION_COUNTER_INC;
			end if;
		end if;
	end if;
end process;

--// 8 comb stages
-- Comb stage 1 
COMB1: process(CLK)
begin
	if rising_edge(CLK) then
		if(SAMPLE9_CLK = '1') and (DECIMATION_COUNTER = 0) then
			SAMPLE11_CLK <= '1';
			DATA9_D <= DATA9;
			DATA9_D2 <= DATA9_D;

			if(M = 1) then
				DATA11 <= DATA9 - DATA9_D;
			elsif(M = 2) then
				DATA11 <= DATA9 - DATA9_D2;
			end if;
		else
			SAMPLE11_CLK <= '0';
		end if;
	end if;
end process;

-- Comb stage 2 
COMB2: process(CLK)
begin
	if rising_edge(CLK) then
		SAMPLE12_CLK <= SAMPLE11_CLK;

		if(SAMPLE11_CLK = '1') then
			DATA11_D <= DATA11;
			DATA11_D2 <= DATA11_D;

			if(M = 1) then
				DATA12 <= DATA11 - DATA11_D;
			elsif(M = 2) then
				DATA12 <= DATA11 - DATA11_D2;
			end if;
		end if;
	end if;
end process;

-- Comb stage 3 
COMB3: process(CLK)
begin
	if rising_edge(CLK) then
		SAMPLE13_CLK <= SAMPLE12_CLK;

		if(SAMPLE12_CLK = '1') then
			DATA12_D <= DATA12;
			DATA12_D2 <= DATA12_D;

			if(M = 1) then
				DATA13 <= DATA12 - DATA12_D;
			elsif(M = 2) then
				DATA13 <= DATA12 - DATA12_D2;
			end if;
		end if;
	end if;
end process;

-- Comb stage 4 
COMB4: process(CLK)
begin
	if rising_edge(CLK) then
		SAMPLE14_CLK <= SAMPLE13_CLK;

		if(SAMPLE13_CLK = '1') then
			DATA13_D <= DATA13;
			DATA13_D2 <= DATA13_D;

			if(M = 1) then
				DATA14 <= DATA13 - DATA13_D;
			elsif(M = 2) then
				DATA14 <= DATA13 - DATA13_D2;
			end if;
		end if;
	end if;
end process;

-- Comb stage 5 
COMB5: process(CLK)
begin
	if rising_edge(CLK) then
		SAMPLE15_CLK <= SAMPLE14_CLK;

		if(SAMPLE14_CLK = '1') then
			DATA14_D <= DATA14;
			DATA14_D2 <= DATA14_D;

			if(M = 1) then
				DATA15 <= DATA14 - DATA14_D;
			elsif(M = 2) then
				DATA15 <= DATA14 - DATA14_D2;
			end if;
		end if;
	end if;
end process;

-- Comb stage 6 
COMB6: process(CLK)
begin
	if rising_edge(CLK) then
		SAMPLE16_CLK <= SAMPLE15_CLK;

		if(SAMPLE15_CLK = '1') then
			DATA15_D <= DATA15;
			DATA15_D2 <= DATA15_D;

			if(M = 1) then
				DATA16 <= DATA15 - DATA15_D;
			elsif(M = 2) then
				DATA16 <= DATA15 - DATA15_D2;
			end if;
		end if;
	end if;
end process;

-- Comb stage 7 
COMB7: process(CLK)
begin
	if rising_edge(CLK) then
		SAMPLE17_CLK <= SAMPLE16_CLK;

		if(SAMPLE16_CLK = '1') then
			DATA16_D <= DATA16;
			DATA16_D2 <= DATA16_D;

			if(M = 1) then
				DATA17 <= DATA16 - DATA16_D;
			elsif(M = 2) then
				DATA17 <= DATA16 - DATA16_D2;
			end if;
		end if;
	end if;
end process;

-- Comb stage 8 
COMB8: process(CLK)
begin
	if rising_edge(CLK) then
		SAMPLE18_CLK <= SAMPLE17_CLK;

		if(SAMPLE17_CLK = '1') then
			DATA17_D <= DATA17;
			DATA17_D2 <= DATA17_D;

			if(M = 1) then
				DATA18 <= DATA17 - DATA17_D;
			elsif(M = 2) then
				DATA18 <= DATA17 - DATA17_D2;
			end if;
		end if;
	end if;
end process;

--// Select number of comb stages N
STAGES_SEL_002: process(SAMPLE11_CLK, SAMPLE12_CLK, SAMPLE13_CLK, SAMPLE14_CLK, SAMPLE15_CLK, SAMPLE16_CLK,
				SAMPLE17_CLK, SAMPLE18_CLK, DATA11, DATA12, DATA13, DATA14, DATA15, DATA16, DATA17, DATA18)
begin
   case (N) is 
      when 1 =>
         SAMPLE19_CLK <= SAMPLE11_CLK;
			DATA19 <= DATA11;
      when 2 =>
         SAMPLE19_CLK <= SAMPLE12_CLK;
			DATA19 <= DATA12;
      when 3 =>
         SAMPLE19_CLK <= SAMPLE13_CLK;
			DATA19 <= DATA13;
      when 4 =>
         SAMPLE19_CLK <= SAMPLE14_CLK;
			DATA19 <= DATA14;
      when 5 =>
         SAMPLE19_CLK <= SAMPLE15_CLK;
			DATA19 <= DATA15;
      when 6 =>
         SAMPLE19_CLK <= SAMPLE16_CLK;
			DATA19 <= DATA16;
      when 7 =>
         SAMPLE19_CLK <= SAMPLE17_CLK;
			DATA19 <= DATA17;
      when others =>
         SAMPLE19_CLK <= SAMPLE18_CLK;
			DATA19 <= DATA18;
   end case;
end process;

--// Truncate signal
-- Shift by 8 or 1.
-- Start with the number of bits to be truncated, decrease by steps of 8 or 1 until
-- all bits to be truncated have been shifted out to the right.
-- This efficient, yet flexible shifting method was selected because we are certain
-- to have at least R clocks for shifting since we just decimated.
SHIFT_001: process(CLK, TRUNCATE_OBITS)
begin
	if rising_edge(CLK) then
		SAMPLE20_CLK <= SAMPLE19_CLK;		-- NOTE: DATA20 is not ready yet. wait until next process.

		if(SAMPLE19_CLK = '1') or (SYNC_RESET = '1') then
			
			-- new. save one clk (when R=2 for example)
			if(TRUNCATE_OBITS >= 8) then
				-- truncate 8 LSbs by shift 8 bits to the right
				SHIFT_COUNTER <= TRUNCATE_OBITS - 8;
				DATA20((BOUT-8) downto 0) <= DATA19(BOUT downto 8);
				DATA20(BOUT downto (BOUT-7)) <= (others => DATA19(BOUT));	-- sign extension
			elsif(TRUNCATE_OBITS >= 4) then
				-- truncate 4 LSb by shift 4 bits to the right
				SHIFT_COUNTER <= TRUNCATE_OBITS - 4;
				DATA20((BOUT-4) downto 0) <= DATA19(BOUT downto 4);
				DATA20(BOUT downto (BOUT-3)) <= (others => DATA19(BOUT));	-- sign extension
			elsif(TRUNCATE_OBITS >= 2) then
				-- truncate 2 LSb by shift 2 bits to the right
				SHIFT_COUNTER <= TRUNCATE_OBITS - 2;
				DATA20((BOUT-2) downto 0) <= DATA19(BOUT downto 2);
				DATA20(BOUT downto (BOUT-1)) <= (others => DATA19(BOUT));	-- sign extension
			elsif(TRUNCATE_OBITS > 0) then
				-- truncate 1 LSb by shift 1 bit to the right
				SHIFT_COUNTER <= TRUNCATE_OBITS - 1;
				DATA20((BOUT-1) downto 0) <= DATA19(BOUT downto 1);
				DATA20(BOUT downto BOUT) <= (others => DATA19(BOUT));	-- sign extension
			else
				SHIFT_COUNTER <= TRUNCATE_OBITS;
				DATA20 <= DATA19;
			end if;
		
			
			
		elsif(SHIFT_COUNTER >= 8) then
			-- truncate 8 LSbs by shift 8 bits to the right
			SHIFT_COUNTER <= SHIFT_COUNTER - 8;
			DATA20((BOUT-8) downto 0) <= DATA20(BOUT downto 8);
			DATA20(BOUT downto (BOUT-7)) <= (others => DATA20(BOUT));	-- sign extension
		elsif(SHIFT_COUNTER >= 4) then
			-- truncate 4 LSb by shift 4 bits to the right
			SHIFT_COUNTER <= SHIFT_COUNTER - 4;
			DATA20((BOUT-4) downto 0) <= DATA20(BOUT downto 4);
			DATA20(BOUT downto (BOUT-3)) <= (others => DATA20(BOUT));	-- sign extension
		elsif(SHIFT_COUNTER >= 2) then
			-- truncate 2 LSb by shift 2 bits to the right
			SHIFT_COUNTER <= SHIFT_COUNTER - 2;
			DATA20((BOUT-2) downto 0) <= DATA20(BOUT downto 2);
			DATA20(BOUT downto (BOUT-1)) <= (others => DATA20(BOUT));	-- sign extension
		elsif(SHIFT_COUNTER > 0) then
			-- truncate 1 LSb by shift 1 bit to the right
			SHIFT_COUNTER <= SHIFT_COUNTER - 1;
			DATA20((BOUT-1) downto 0) <= DATA20(BOUT downto 1);
			DATA20(BOUT downto BOUT) <= (others => DATA20(BOUT));	-- sign extension
		end if;
	end if;
end process;

-- reclock output. Wait until shift/truncate process is complete to send the
-- output sample.
RECLOCK_002: process(CLK)
begin
	if rising_edge(CLK) then
		if(R = 1) then
			-- bypass this stage
			DATA_OUT <= DATA_IN;
			SAMPLE_CLK_OUT <= SAMPLE_CLK_IN;

		elsif(SAMPLE20_CLK = '1') then
			-- new output sample being assembled.
			if(SHIFT_COUNTER = 0) then
				-- output sample is ready
				OUTPUT_SAMPLE_FLAG <= '0';
				SAMPLE_CLK_OUT <= '1';
				-- clamp before truncating MSbs
				if(DATA20(BOUT) = '0') and (DATA20((BOUT-1) downto 12) /= 0) then
					-- positive saturation after clamping
					DATA_OUT <= "011111111111";
				elsif(DATA20(BOUT) = '1') and ((not DATA20((BOUT-1) downto 12)) /= 0) then
					-- negative saturation after clamping
					DATA_OUT <= "100000000000";
				else
					-- just truncate MSBs
					DATA_OUT <= DATA20(11 downto 0);
				end if;
			else
				-- output sample need additional shift iterations
				OUTPUT_SAMPLE_FLAG <= '1';
				SAMPLE_CLK_OUT <= '0';
			end if;
		elsif(SHIFT_COUNTER = 0) and (OUTPUT_SAMPLE_FLAG = '1') then
			-- shift/truncate process is now complete.
			-- Get the output sample.
			OUTPUT_SAMPLE_FLAG <= '0';
			SAMPLE_CLK_OUT <= '1';
			-- clamp before truncating MSbs
			if(DATA20(BOUT) = '0') and (DATA20((BOUT-1) downto 12) /= 0) then
				-- positive saturation after clamping
				DATA_OUT <= "011111111111";
			elsif(DATA20(BOUT) = '1') and ((not DATA20((BOUT-1) downto 12)) /= 0) then
				-- negative saturation after clamping
				DATA_OUT <= "100000000000";
			else
				-- just truncate MSBs
				DATA_OUT <= DATA20(11 downto 0);
			end if;
		else
			SAMPLE_CLK_OUT <= '0';
		end if;
	end if;
end process;




end Behavioral;
