----------------------------------------------
-- MSS copyright 1999-2001
-- Filename: PHASE_AMBIGUITY_REMOVAL.VHD
-- Authors: 
--		Alain Zarembowitch / MSS
--		Nayef Ahmar / MSS
-- Inheritance: Sirius v0.004 2-15-01
-- Edit date: 12-19-01
-- Revision: 0.001
--
-- VHDL code for Phase Ambiguity Removal
-- Timing is as expected, except for SOF which may be one bit early.
----------------------------------------------
library IEEE;
use IEEE.std_logic_1164.all;    
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity PHASE_AMBIGUITY_REMOVAL is
    port (        
    	ASYNC_RESET: in  std_logic;
			-- asynchronous reset active high for initialization to well known state prior to power up
		CLK: in std_logic;	
			-- reference clock for synchronous design
      	DATA_IN: in std_logic_vector(3 downto 0);     
			-- demodulated data bits from QPSK demodulator, soft quantized with 4 bits
			-- representation is 0 - F, 0 is most negative, F is most positive, 
			-- no zero representation, 7 is the least negative, 8 is the least positive.
			-- Read DATA_IN at rising edge of CLK when BIT_CLK = '1'
		BIT_CLK_IN: in std_logic;
			-- defines the bit period. pulse is 1 CLK period long.
		SOF: in std_logic;
			-- start of frame. synchronous with rising edge of CLK.
			-- The SOF is one bit early, therefore initialize	BIT_COUNT_TOGGLE <= '0';	-- next one is even	

		PHASE: in std_logic_vector(1 downto 0);
			-- two bits that will help us resolve the QPSK phase ambiguity
			-- This signal is valid only when the DETECT is HIGH

		DATA_OUT: out std_logic_vector(3 downto 0)
			-- output data after correction of I&Q phase ambiguity
			-- Latency: 1 bit + 1 CLK
	);
 end PHASE_AMBIGUITY_REMOVAL;
  
architecture BEHAVIOR of PHASE_AMBIGUITY_REMOVAL is
-----------------------------------------------------------------
-- COMPONENTS
-----------------------------------------------------------------
-----------------------------------------------------------------
-- SIGNALS
-----------------------------------------------------------------
signal zero: std_logic;
signal one: std_logic;   
signal BIT_COUNT_TOGGLE: std_logic;	-- zero for even numbered bits in a frame, 1 for odd
signal I_RECEIVE: std_logic_vector(3 downto 0);	
	-- space to store even numbered bits (soft quantized) from input.

signal Q_SEND: std_logic_vector(3 downto 0);
-----------------------------------------------------------------
-- IMPLEMENTATION
-----------------------------------------------------------------
begin 
zero <= '0';
one <= '1'; 


-- keep track of odd/even bits in a 2048-bit frame
BIT_COUNT_TOGGLE_DEFINITION: process(CLK, ASYNC_RESET, BIT_CLK_IN, SOF, BIT_COUNT_TOGGLE)
begin       
	if (ASYNC_RESET = '1') then
		BIT_COUNT_TOGGLE <= '0';	
	elsif (rising_edge(CLK)) then 
      if(BIT_CLK_IN = '1') then
			if (SOF = '1') then
				-- reset the bit count toggle to 0 as bit 48 is being received
				BIT_COUNT_TOGGLE <= '0';	-- next one is even	
			else
				BIT_COUNT_TOGGLE <= not (BIT_COUNT_TOGGLE);
			end if; 
	  end if;			 
	end if;
end process;


-- store even bits (soft quantized)
STORE_EVEN_BITS: process(CLK, ASYNC_RESET)
begin       
	if (ASYNC_RESET = '1') then
		I_RECEIVE <= "1000";
	elsif (rising_edge(CLK)) then   
	 	if((BIT_CLK_IN = '1') and ((BIT_COUNT_TOGGLE = '0') or (SOF = '1'))) then
			-- store soft quantized bit
			I_RECEIVE <= DATA_IN;
		end if;  
	end if;
end process; 

BIT2_CONVERSION: process (CLK, ASYNC_RESET, BIT_CLK_IN, BIT_COUNT_TOGGLE, DATA_IN, I_RECEIVE, Q_SEND, PHASE)
-- 2 Bit conversion for I-Q phase of 90 degree(phase = 01)
--I, Q_SEND:upper bits.  DATA, I_RECEIVE: lower bits. 
  begin

	if (ASYNC_RESET = '1') then
		Q_SEND <= "1000"; 	    
		DATA_OUT <= "1000";                
	elsif  rising_edge(CLK) then  
	  if(BIT_CLK_IN = '1') then
		if (BIT_COUNT_TOGGLE = '1')  then
        -- save the lower bit and send the upper bit of the 2 bits data    
			if (PHASE = "01") then 
            -- 2 Bit conversion for I-Q phase of +90 deg
        		if  ((DATA_IN(3) = '0') and (I_RECEIVE(3) = '0')) then
				  	--Receive 00 Send 01
					Q_SEND <= not DATA_IN; 	    
					DATA_OUT <= I_RECEIVE;                
				elsif  ((DATA_IN(3) = '0') and (I_RECEIVE(3) = '1')) then
				  	--Receive 10 Send 00  
					Q_SEND <= DATA_IN;	  
					DATA_OUT <= not I_RECEIVE;                
				elsif ((DATA_IN(3) = '1') and (I_RECEIVE(3) = '1')) then
				  	--Receive 11 Send 10  
					Q_SEND <= not DATA_IN;		
					DATA_OUT <= I_RECEIVE; 	            
				else  
					--Receive 01 Send 11 
					Q_SEND <= DATA_IN; 		
					DATA_OUT <= not I_RECEIVE;              			  
    			end if;

	
	        elsif (PHASE = "11") then
            -- 2 Bit conversion for I-Q phase of -90 degrees 
		 		if  ((DATA_IN(3) = '0') and (I_RECEIVE(3) = '0')) then
				  	--Receive 00 Send 10  
					Q_SEND <= DATA_IN; 	    
					DATA_OUT <=  not I_RECEIVE;                
				elsif  ((DATA_IN(3) = '0') and (I_RECEIVE(3) = '1')) then
				  	--Receive 10 Send 11  
					Q_SEND <=  not DATA_IN;	  
					DATA_OUT <= I_RECEIVE;                
				elsif ((DATA_IN(3) = '1') and (I_RECEIVE(3) = '1')) then
				  	--Receive 11 Send 01  
					Q_SEND <= DATA_IN;		
					DATA_OUT <= not I_RECEIVE; 	            
				else  
					--Receive 01 Send 00  
					Q_SEND <= not DATA_IN; 		
					DATA_OUT <= I_RECEIVE;              			  
    			end if;

			elsif (PHASE = "00") then
            -- 2 Bit conversion for I-Q phase of 0 degree
					Q_SEND <=  DATA_IN;	  
					DATA_OUT <= I_RECEIVE;
		
			elsif (PHASE = "10") then
            -- 2 Bit conversion for I-Q phase of 180 degree
					Q_SEND <= not DATA_IN;	  
					DATA_OUT <= not I_RECEIVE;
        	
			end if;

	    else 
		--send the saved lower bit of the 2 bits data  
    		DATA_OUT <= Q_SEND;

  		end if; 
  	  end if;
    end if;

  end process; 

end  BEHAVIOR; 

