-------------------------------------------------------------
-- MSS copyright 2004-2012
-- Filename:  P8_TO_S1_CONVERSION.VHD
-- Author: Alain Zarembowitch / MSS
-- Version: 3
-- Date last modified: 8/2/12
-- Inheritance: S8_TO_S1_CONVERSION  8-29-04
--
-- description:  8-bit parallel to 1-bit serial conversion with flow-control.
-- Key conversion rule is that MSb is transmitted first.     
-- Small elastic buffer for better throughput than the previous version ( S8_TO_S1_CONVERSION)
--
-- Rev 2 5/19/12 AZ
-- initialized variables for simulation
--
-- Rev 3 8/2/12 AZ
-- Added BUF_EMPTY monitoring
-- Corrected bug SYNC_RESET was asynchronous
---------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity P8_TO_S1_CONVERSION is
    Port ( 
		--// CLK, RESET
		CLK: in std_logic;
		SYNC_RESET: in std_logic;

		--// 8-bit parallel input signals
		DATA8_IN: in std_logic_vector(7 downto 0);
		SAMPLE8_CLK_IN: in std_logic;
		SAMPLE8_CLK_IN_REQ: out std_logic;
			-- flow control information

		--// 1-bit serial output signals
		DATA1_OUT: out std_logic := '0';  
		SAMPLE1_CLK_OUT: out std_logic := '0';
		SAMPLE1_CLK_OUT_REQ: in std_logic;
			-- flow control information
		BUF_EMPTY: out std_logic
			-- indicates when no data available within
	);
end entity;

architecture Behavioral of P8_TO_S1_CONVERSION is
--------------------------------------------------------
--      COMPONENTS
--------------------------------------------------------
--------------------------------------------------------
--     SIGNALS
--------------------------------------------------------   
constant DEPTH: integer := 128;   -- elastic buffer depth, in bits    
constant DEPTHLOG2: integer := 7;   -- log2(DEPTH) elastic buffer depth, in bits    
signal BUF: std_logic_vector((DEPTH-1) downto 0) := (others => '0');       
signal BIT_COUNT: std_logic_vector(DEPTHLOG2 downto 0) := (others => '0');  -- valid range 0 (buffer is empty) - DEPTH (buffer is full) 
signal BIT_COUNT_DEC: std_logic_vector(DEPTHLOG2 downto 0) := (others => '0'); -- points to current bit to read. valid range 0 - (DEPTH-1) 
signal READ_INDEX: integer range 0 to (DEPTH-1) := 0;

--------------------------------------------------------
--      IMPLEMENTATION
--------------------------------------------------------
begin
               
INPUT_ELASTIC_BUF_GEN: process(CLK)
begin
	if rising_edge(CLK) then       
		if(SAMPLE8_CLK_IN = '1') then
			BUF((DEPTH-1) downto 8) <= BUF((DEPTH-9) downto 0); -- shift left
			BUF(7 downto 0) <= DATA8_IN;
		end if;
	end if;
end process;
                        
READ_INDEX <= conv_integer(BIT_COUNT_DEC((DEPTHLOG2-1) downto 0));                        
                        
BIT_COUNT_GEN: process(CLK)
begin
	if rising_edge(CLK) then       
		if (SYNC_RESET = '1') then   
			BIT_COUNT <= (others => '0');    
		elsif(SAMPLE8_CLK_IN = '1') then 
			if(SAMPLE1_CLK_OUT_REQ = '1') and (BIT_COUNT /= 0) then
				--  +8 input bits - 1 output bit
				BIT_COUNT <= BIT_COUNT + 7;
				SAMPLE1_CLK_OUT <= '1';
				DATA1_OUT <= BUF(READ_INDEX);
			else        
				-- +8 input bits
				BIT_COUNT <= BIT_COUNT + 8;
				SAMPLE1_CLK_OUT <= '0';
			end if;
		elsif(SAMPLE1_CLK_OUT_REQ = '1') and (BIT_COUNT /= 0) then    
			-- -1 output bit
			BIT_COUNT <= BIT_COUNT_DEC ;    
			SAMPLE1_CLK_OUT <= '1';
			DATA1_OUT <= BUF(READ_INDEX);
		else
			SAMPLE1_CLK_OUT <= '0';
		end if;
	end if;
end process;      

BIT_COUNT_DEC <= BIT_COUNT - 1;
               
SAMPLE8_CLK_IN_REQ <= '1' when (BIT_COUNT(DEPTHLOG2 downto  (DEPTHLOG2-1)) = 0) else '0';

BUF_EMPTY <= '1' when (BIT_COUNT = 0) else 
				 '1' when (BIT_COUNT = 1) and (SAMPLE1_CLK_OUT_REQ = '1') and (SAMPLE8_CLK_IN = '0') else
				 '0';

end Behavioral;
