------------------------------------------------------------------------------- -- th9958_sprite_det.vhd -- sprite 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_SPRITE_DET IS PORT( CLK : IN STD_LOGIC; RESET_N : IN STD_LOGIC; ENABLE : IN STD_LOGIC; -- CONTROL SIGNAL H_CNT : IN STD_LOGIC_VECTOR( 9 DOWNTO 0 ); SCR_Y : IN STD_LOGIC_VECTOR( 7 DOWNTO 0 ); CLR_OVERMAP : IN STD_LOGIC; -- VRAM I/F VRAM_Q : IN STD_LOGIC_VECTOR( 7 DOWNTO 0 ); SPD_REQ : OUT STD_LOGIC; SPD_A : OUT STD_LOGIC_VECTOR( 16 DOWNTO 0 ); -- MODE SP_MODE : IN STD_LOGIC; -- RAM RAM_D : OUT STD_LOGIC_VECTOR( 9 DOWNTO 0 ); RAM_A : OUT STD_LOGIC_VECTOR( 2 DOWNTO 0 ); RAM_WE : OUT STD_LOGIC; -- STATUS S_5S : OUT STD_LOGIC; S_5TH_SP : OUT STD_LOGIC_VECTOR( 4 DOWNTO 0 ); -- REGISTER REG_LN : IN STD_LOGIC; REG_MAG : IN STD_LOGIC; REG_SI : IN STD_LOGIC; REG_SPA_L : IN STD_LOGIC_VECTOR( 5 DOWNTO 0 ); REG_SPA_H : IN STD_LOGIC_VECTOR( 1 DOWNTO 0 ) ); END TH9958_SPRITE_DET; ARCHITECTURE RTL OF TH9958_SPRITE_DET IS SIGNAL W_SP_NUM : STD_LOGIC_VECTOR( 4 DOWNTO 0 ); SIGNAL W_DOT_STATE : STD_LOGIC_VECTOR( 2 DOWNTO 0 ); SIGNAL W_DOT_PHASE : STD_LOGIC_VECTOR( 1 DOWNTO 0 ); SIGNAL W_DOT_STATE_001 : STD_LOGIC; SIGNAL W_DOT_STATE_010 : STD_LOGIC; SIGNAL W_PRE_REQ : STD_LOGIC; SIGNAL W_PRE_CLR : STD_LOGIC; SIGNAL W_START : STD_LOGIC; SIGNAL W_DIFF : STD_LOGIC_VECTOR( 7 DOWNTO 0 ); SIGNAL W_UNDISP_LINE : STD_LOGIC_VECTOR( 7 DOWNTO 0 ); SIGNAL W_SP_SIZE : STD_LOGIC_VECTOR( 1 DOWNTO 0 ); SIGNAL W_SP_MASK : STD_LOGIC_VECTOR( 4 DOWNTO 0 ); SIGNAL W_SP_LINE : STD_LOGIC_VECTOR( 4 DOWNTO 0 ); SIGNAL W_UNDISP : STD_LOGIC; SIGNAL W_END : STD_LOGIC; SIGNAL W_SP_MAX : STD_LOGIC; SIGNAL W_SP_DISP : STD_LOGIC; SIGNAL FF_SP_NUM : STD_LOGIC_VECTOR( 4 DOWNTO 0 ); SIGNAL FF_REQ : STD_LOGIC; SIGNAL FF_DIFF : STD_LOGIC_VECTOR( 4 DOWNTO 0 ); SIGNAL FF_END : STD_LOGIC; SIGNAL FF_UNDISP : STD_LOGIC; SIGNAL FF_ACT : STD_LOGIC; SIGNAL FF_SP_CNT : STD_LOGIC_VECTOR( 3 DOWNTO 0 ); SIGNAL FF_SP_OVERMAP : STD_LOGIC; SIGNAL FF_SP_OVERNUM : STD_LOGIC_VECTOR( 4 DOWNTO 0 ); CONSTANT C_ALL0 : STD_LOGIC_VECTOR( 9 DOWNTO 0 ) := (OTHERS => '0'); BEGIN S_5S <= FF_SP_OVERMAP; S_5TH_SP <= FF_SP_OVERNUM; SPD_REQ <= FF_REQ; SPD_A <= REG_SPA_H & REG_SPA_L & "00" & FF_SP_NUM & "00"; RAM_D <= FF_SP_NUM & FF_DIFF; RAM_A <= FF_SP_CNT( 2 DOWNTO 0 ); RAM_WE <= W_SP_DISP; W_SP_NUM <= H_CNT( 9 DOWNTO 5 ); W_DOT_STATE <= H_CNT( 4 DOWNTO 2 ); W_DOT_PHASE <= H_CNT( 1 DOWNTO 0 ); W_DOT_STATE_001 <= '1' WHEN( W_DOT_STATE = "001" )ELSE '0'; W_DOT_STATE_010 <= '1' WHEN( W_DOT_STATE = "010" )ELSE '0'; W_PRE_REQ <= W_DOT_STATE_001 AND (NOT W_DOT_PHASE(1)) AND (NOT W_DOT_PHASE(0)); W_PRE_CLR <= W_DOT_STATE_010 AND (NOT W_DOT_PHASE(1)) AND (NOT W_DOT_PHASE(0)); W_START <= '1' WHEN( H_CNT = C_ALL0 )ELSE '0'; W_DIFF <= VRAM_Q - SCR_Y; W_UNDISP_LINE <= CONV_STD_LOGIC_VECTOR( 208, 8 ) WHEN( REG_LN = '0' )ELSE CONV_STD_LOGIC_VECTOR( 216, 8 ); W_SP_SIZE <= REG_MAG & REG_SI; WITH W_SP_SIZE SELECT W_SP_MASK <= "11111" WHEN "00", "11110" WHEN "01", "11110" WHEN "10", "11100" WHEN "11", "XXXXX" WHEN OTHERS; W_SP_LINE <= W_SP_MASK AND W_DIFF( 7 DOWNTO 3 ); W_UNDISP <= '1' WHEN( W_SP_LINE /= "00000" )ELSE '0'; W_END <= '1' WHEN( W_UNDISP_LINE = VRAM_Q )ELSE '0'; W_SP_MAX <= FF_SP_CNT(3) OR (FF_SP_CNT(2) AND (NOT SP_MODE)); W_SP_DISP <= (NOT FF_END) AND (NOT FF_UNDISP) AND FF_ACT; PROCESS( RESET_N, CLK ) BEGIN IF( RESET_N = '0' )THEN FF_SP_NUM <= (OTHERS => '0'); ELSIF( CLK'EVENT AND CLK = '1' )THEN IF( ENABLE = '1' )THEN FF_SP_NUM <= W_SP_NUM; END IF; END IF; END PROCESS; PROCESS( RESET_N, CLK ) BEGIN IF( RESET_N = '0' )THEN FF_REQ <= '0'; ELSIF( CLK'EVENT AND CLK = '1' )THEN IF( ENABLE = '1' )THEN FF_REQ <= W_PRE_REQ AND (NOT FF_END); END IF; END IF; END PROCESS; PROCESS( RESET_N, CLK ) BEGIN IF( RESET_N = '0' )THEN FF_DIFF <= (OTHERS => '0'); FF_UNDISP <= '0'; ELSIF( CLK'EVENT AND CLK = '1' )THEN IF( ENABLE = '1' )THEN IF( (W_PRE_CLR AND (NOT FF_END)) = '1' )THEN FF_DIFF <= W_DIFF( 4 DOWNTO 0 ); FF_UNDISP <= W_UNDISP; END IF; END IF; END IF; END PROCESS; PROCESS( RESET_N, CLK ) BEGIN IF( RESET_N = '0' )THEN FF_END <= '0'; ELSIF( CLK'EVENT AND CLK = '1' )THEN IF( W_START = '1' )THEN FF_END <= '0'; ELSIF( ENABLE = '1' )THEN IF( (W_PRE_CLR AND (NOT FF_END)) = '1' )THEN FF_END <= FF_END OR W_END; END IF; END IF; END IF; END PROCESS; PROCESS( RESET_N, CLK ) BEGIN IF( RESET_N = '0' )THEN FF_ACT <= '0'; ELSIF( CLK'EVENT AND CLK = '1' )THEN IF( ENABLE = '1' )THEN FF_ACT <= W_PRE_CLR AND (NOT FF_END); END IF; END IF; END PROCESS; PROCESS( RESET_N, CLK ) BEGIN IF( RESET_N = '0' )THEN FF_SP_CNT <= (OTHERS => '0'); ELSIF( CLK'EVENT AND CLK = '1' )THEN IF( ENABLE = '1' )THEN IF( W_START = '1' )THEN FF_SP_CNT <= (OTHERS => '0'); ELSIF( ((NOT W_SP_MAX) AND W_SP_DISP) = '1' )THEN FF_SP_CNT <= FF_SP_CNT + 1; END IF; END IF; END IF; END PROCESS; PROCESS( RESET_N, CLK ) BEGIN IF( RESET_N = '0' )THEN FF_SP_OVERMAP <= '0'; ELSIF( CLK'EVENT AND CLK = '1' )THEN IF( ENABLE = '1' )THEN IF( CLR_OVERMAP = '1' )THEN FF_SP_OVERMAP <= '0'; ELSE FF_SP_OVERMAP <= FF_SP_OVERMAP OR (W_SP_MAX AND W_SP_DISP); END IF; END IF; END IF; END PROCESS; PROCESS( RESET_N, CLK ) BEGIN IF( RESET_N = '0' )THEN FF_SP_OVERNUM <= (OTHERS => '1'); ELSIF( CLK'EVENT AND CLK = '1' )THEN IF( ENABLE = '1' )THEN IF( CLR_OVERMAP = '1' )THEN FF_SP_OVERNUM <= (OTHERS => '1'); ELSIF( (W_SP_MAX AND W_SP_DISP AND (NOT FF_SP_OVERMAP)) = '1' )THEN FF_SP_OVERNUM <= FF_SP_NUM; END IF; END IF; END IF; END PROCESS; END RTL;