-------------------------------------------------------------------------------
--  th9958_ssg.vhd
--  Synchronus Signal Generator for TH9958
--
--  Copyright (C) 2008 Takayuki Hara
--  All rights reserved.
-------------------------------------------------------------------------------
--
--  Redistribution and use of this software or any derivative works,
--  are permitted provided that the following conditions are met:
--
--  1. Redistributions of source code must retain the above copyright
--     notice, this list of conditions and the following disclaimer.
--  2. Redistributions in binary form must reproduce the above
--     copyright notice, this list of conditions and the following
--     disclaimer in the documentation and/or other materials
--     provided with the distribution.
--  3. Redistributions may not be sold, nor may they be used in a 
--     commercial product or activity without specific prior written
--     permission.
--
--  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
--  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
--  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
--  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
--  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
--  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
--  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
--  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 
--  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
--  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
--  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
--  POSSIBILITY OF SUCH DAMAGE.
--
-------------------------------------------------------------------------------

LIBRARY IEEE;
	USE IEEE.STD_LOGIC_1164.ALL;
	USE IEEE.STD_LOGIC_UNSIGNED.ALL;
	USE IEEE.STD_LOGIC_ARITH.ALL;

ENTITY TH9958_SSG IS
	PORT(
		CLK					: IN	STD_LOGIC;
		RESET_N				: IN	STD_LOGIC;
		ENABLE				: IN	STD_LOGIC;
		-- OUTPUT SIGNAL
		H_CNT				: OUT	STD_LOGIC_VECTOR(  9 DOWNTO 0 );
		V_CNT				: OUT	STD_LOGIC_VECTOR(  9 DOWNTO 0 );
		RIGHT_SIDE			: OUT	STD_LOGIC;
		FIELD				: OUT	STD_LOGIC;
		-- REGISTER
		REG_PAL_MODE		: IN	STD_LOGIC;
		REG_INTERLACE_MODE	: IN	STD_LOGIC
	);
END TH9958_SSG;

ARCHITECTURE RTL OF TH9958_SSG IS
	SIGNAL FF_H_CNT				: STD_LOGIC_VECTOR(  9 DOWNTO 0 );
	SIGNAL FF_V_CNT				: STD_LOGIC_VECTOR(  9 DOWNTO 0 );
	SIGNAL FF_RIGHT_SIDE		: STD_LOGIC;
	SIGNAL FF_FIELD				: STD_LOGIC;

	SIGNAL W_MODE				: STD_LOGIC_VECTOR(  1 DOWNTO 0 );
	SIGNAL W_H_CNT_FULL			: STD_LOGIC;
	SIGNAL W_V_CNT_FULL			: STD_LOGIC;
	SIGNAL W_V_CNT_FULL_LINE	: STD_LOGIC_VECTOR(  9 DOWNTO 0 );
BEGIN

	H_CNT		<= FF_H_CNT;
	V_CNT		<= FF_V_CNT;
	RIGHT_SIDE	<= FF_RIGHT_SIDE;
	FIELD		<= FF_FIELD;

	-- LOGIC
	W_H_CNT_FULL <= '1' WHEN( FF_H_CNT = 683 )ELSE '0';
	W_V_CNT_FULL <= '1' WHEN( FF_V_CNT = W_V_CNT_FULL_LINE )ELSE '0';

	W_MODE <= REG_PAL_MODE & REG_INTERLACE_MODE;
	WITH W_MODE SELECT W_V_CNT_FULL_LINE <= 
		CONV_STD_LOGIC_VECTOR( 523, 10 )	WHEN "00",
		CONV_STD_LOGIC_VECTOR( 524, 10 )	WHEN "01",
		CONV_STD_LOGIC_VECTOR( 625, 10 )	WHEN "10",
		CONV_STD_LOGIC_VECTOR( 624, 10 )	WHEN "11",
		(OTHERS => 'X')						WHEN OTHERS;

	-- H COUNTER
	PROCESS( RESET_N, CLK )
	BEGIN
		IF( RESET_N = '0' )THEN
			FF_H_CNT <= (OTHERS => '0');
		ELSIF( CLK'EVENT AND CLK = '1' )THEN
			IF( ENABLE = '1' )THEN
				IF( W_H_CNT_FULL = '1' )THEN
					FF_H_CNT <= (OTHERS => '0');
				ELSE
					FF_H_CNT <= FF_H_CNT + 1;
				END IF;
			END IF;
		END IF;
	END PROCESS;

	-- RIGHT SIDE
	PROCESS( RESET_N, CLK )
	BEGIN
		IF( RESET_N = '0' )THEN
			FF_RIGHT_SIDE <= '0';
		ELSIF( CLK'EVENT AND CLK = '1' )THEN
			IF( ENABLE = '1' )THEN
				IF( (W_H_CNT_FULL AND W_V_CNT_FULL AND FF_FIELD) = '1' )THEN
					FF_RIGHT_SIDE <= '0';
				ELSIF( W_H_CNT_FULL = '1' )THEN
					FF_RIGHT_SIDE <= NOT FF_RIGHT_SIDE;
				END IF;
			END IF;
		END IF;
	END PROCESS;

	-- V COUNTER
	PROCESS( RESET_N, CLK )
	BEGIN
		IF( RESET_N = '0' )THEN
			FF_V_CNT <= (OTHERS => '0');
		ELSIF( CLK'EVENT AND CLK = '1' )THEN
			IF( ENABLE = '1' )THEN
				IF( (W_H_CNT_FULL AND W_V_CNT_FULL) = '1' )THEN
					FF_V_CNT <= (OTHERS => '0');
				ELSIF( W_H_CNT_FULL = '1' )THEN
					FF_V_CNT <= FF_V_CNT + 1;
				END IF;
			END IF;
		END IF;
	END PROCESS;

	-- FIELD
	PROCESS( RESET_N, CLK )
	BEGIN
		IF( RESET_N = '0' )THEN
			FF_FIELD <= '0';
		ELSIF( CLK'EVENT AND CLK = '1' )THEN
			IF( ENABLE = '1' )THEN
				IF( (W_H_CNT_FULL AND W_V_CNT_FULL) = '1' )THEN
					FF_FIELD <= NOT FF_FIELD;
				END IF;
			END IF;
		END IF;
	END PROCESS;
END RTL;