375 lines
12 KiB
VHDL
375 lines
12 KiB
VHDL
-------------------------------------------------------------------------------
|
|
--
|
|
-- Synthesizable model of TI's TMS9918A, TMS9928A, TMS9929A.
|
|
--
|
|
-- $Id: vdp18_ctrl.vhd,v 1.26 2006/06/18 10:47:01 arnim Exp $
|
|
--
|
|
-- Timing Controller
|
|
--
|
|
-------------------------------------------------------------------------------
|
|
--
|
|
-- Copyright (c) 2006, Arnim Laeuger (arnim.laeuger@gmx.net)
|
|
--
|
|
-- All rights reserved
|
|
--
|
|
-- Redistribution and use in source and synthezised forms, with or without
|
|
-- modification, are permitted provided that the following conditions are met:
|
|
--
|
|
-- Redistributions of source code must retain the above copyright notice,
|
|
-- this list of conditions and the following disclaimer.
|
|
--
|
|
-- Redistributions in synthesized 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.
|
|
--
|
|
-- Neither the name of the author nor the names of other contributors may
|
|
-- be used to endorse or promote products derived from this software 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 AUTHOR 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.
|
|
--
|
|
-- Please report bugs to the author, but before you do so, please
|
|
-- make sure that this is not a derivative work and that
|
|
-- you have the latest version of this file.
|
|
--
|
|
-------------------------------------------------------------------------------
|
|
|
|
library ieee;
|
|
use ieee.std_logic_1164.all;
|
|
use ieee.numeric_std.all;
|
|
|
|
use work.vdp18_pack.opmode_t;
|
|
use work.vdp18_pack.hv_t;
|
|
use work.vdp18_pack.access_t;
|
|
|
|
entity vdp18_ctrl is
|
|
|
|
port (
|
|
clk_i : in std_logic;
|
|
clk_en_5m37_i : in boolean;
|
|
reset_i : in boolean;
|
|
opmode_i : in opmode_t;
|
|
num_pix_i : in hv_t;
|
|
num_line_i : in hv_t;
|
|
vert_inc_i : in boolean;
|
|
reg_blank_i : in boolean;
|
|
reg_size1_i : in boolean;
|
|
stop_sprite_i : in boolean;
|
|
clk_en_acc_o : out boolean;
|
|
access_type_o : out access_t;
|
|
vert_active_o : out boolean;
|
|
hor_active_o : out boolean;
|
|
irq_o : out boolean
|
|
);
|
|
|
|
end vdp18_ctrl;
|
|
|
|
|
|
use work.vdp18_pack.all;
|
|
|
|
architecture rtl of vdp18_ctrl is
|
|
|
|
-----------------------------------------------------------------------------
|
|
-- This enables a workaround for a bug in XST.
|
|
-- ISE 8.1.02i implements wrong functionality otherwise :-(
|
|
--
|
|
constant xst_bug_wa_c : boolean := true;
|
|
--
|
|
-----------------------------------------------------------------------------
|
|
|
|
signal access_type_s : access_t;
|
|
|
|
-- pragma translate_off
|
|
-- Testbench signals --------------------------------------------------------
|
|
--
|
|
signal ac_s : std_logic_vector(3 downto 0);
|
|
--
|
|
-----------------------------------------------------------------------------
|
|
-- pragma translate_on
|
|
|
|
signal vert_active_q,
|
|
hor_active_q : boolean;
|
|
signal sprite_active_q : boolean;
|
|
signal sprite_line_act_q : boolean;
|
|
|
|
begin
|
|
|
|
-- pragma translate_off
|
|
-- Testbench signals --------------------------------------------------------
|
|
--
|
|
ac_s <= enum_to_vec_f(access_type_s);
|
|
--
|
|
-----------------------------------------------------------------------------
|
|
-- pragma translate_on
|
|
|
|
|
|
-----------------------------------------------------------------------------
|
|
-- Process decode_access
|
|
--
|
|
-- Purpose:
|
|
-- Decode horizontal counter value to access type.
|
|
--
|
|
decode_access: process (opmode_i,
|
|
num_pix_i,
|
|
vert_active_q,
|
|
sprite_line_act_q,
|
|
reg_size1_i)
|
|
variable num_pix_plus_6_v : hv_t;
|
|
variable mod_6_v : hv_t;
|
|
variable num_pix_plus_8_v : hv_t;
|
|
variable num_pix_plus_32_v : hv_t;
|
|
variable num_pix_spr_v : integer;
|
|
begin
|
|
-- default assignment
|
|
access_type_s <= AC_CPU;
|
|
|
|
-- prepare number of pixels for pattern operations
|
|
num_pix_plus_6_v := num_pix_i + 6;
|
|
num_pix_plus_8_v := num_pix_i + 8;
|
|
num_pix_plus_32_v := num_pix_i + 32;
|
|
num_pix_spr_v := to_integer(num_pix_i and "111111110");
|
|
|
|
case opmode_i is
|
|
-- Graphics I, II and Multicolor Mode -----------------------------------
|
|
when OPMODE_GRAPH1 |
|
|
OPMODE_GRAPH2 |
|
|
OPMODE_MULTIC =>
|
|
--
|
|
-- Patterns
|
|
--
|
|
if vert_active_q then
|
|
if num_pix_plus_8_v(0) = '0' then
|
|
if not xst_bug_wa_c then
|
|
|
|
-- original code, we want this
|
|
case num_pix_plus_8_v(6 to 7) is
|
|
when "01" =>
|
|
access_type_s <= AC_PNT;
|
|
when "10" =>
|
|
if opmode_i /= OPMODE_MULTIC then
|
|
-- no access to pattern color table in multicolor mode
|
|
access_type_s <= AC_PCT;
|
|
end if;
|
|
when "11" =>
|
|
access_type_s <= AC_PGT;
|
|
when others =>
|
|
null;
|
|
end case;
|
|
|
|
else
|
|
|
|
-- workaround for XST bug, we need this
|
|
if num_pix_plus_8_v(6 to 7) = "01" then
|
|
access_type_s <= AC_PNT;
|
|
elsif num_pix_plus_8_v(6 to 7) = "10" then
|
|
if opmode_i /= OPMODE_MULTIC then
|
|
access_type_s <= AC_PCT;
|
|
end if;
|
|
elsif num_pix_plus_8_v(6 to 7) = "11" then
|
|
access_type_s <= AC_PGT;
|
|
end if;
|
|
|
|
end if;
|
|
end if;
|
|
end if;
|
|
|
|
--
|
|
-- Sprite test
|
|
--
|
|
if sprite_line_act_q then
|
|
if num_pix_i(0) = '0' and
|
|
num_pix_i(0 to 5) /= "011111" and
|
|
num_pix_i(6 to 7) = "00" and
|
|
num_pix_i(4 to 5) /= "00" then
|
|
-- sprite test interleaved with pattern accesses - 23 slots
|
|
access_type_s <= AC_STST;
|
|
end if;
|
|
if num_pix_plus_32_v(0 to 4) = "00000" or
|
|
num_pix_plus_32_v(0 to 7) = "00001000" then
|
|
-- sprite tests before starting pattern phase - 9 slots
|
|
access_type_s <= AC_STST;
|
|
end if;
|
|
|
|
--
|
|
-- Sprite Attribute Table and Sprite Pattern Table
|
|
--
|
|
case num_pix_spr_v is
|
|
when 250 | -78 |
|
|
-62 | -46 =>
|
|
access_type_s <= AC_SATY;
|
|
when 254 | -76 |
|
|
-60 | -44 =>
|
|
access_type_s <= AC_SATX;
|
|
when 252 | -74 |
|
|
-58 | -42 =>
|
|
access_type_s <= AC_SATN;
|
|
when -86 | -70 |
|
|
-54 | -38 =>
|
|
access_type_s <= AC_SATC;
|
|
when -84 | -68 |
|
|
-52 | -36 =>
|
|
access_type_s <= AC_SPTH;
|
|
when -82 | -66 |
|
|
-50 | -34 =>
|
|
if reg_size1_i then
|
|
access_type_s <= AC_SPTL;
|
|
end if;
|
|
when others =>
|
|
null;
|
|
end case;
|
|
end if;
|
|
|
|
-- Text Mode ------------------------------------------------------------
|
|
when OPMODE_TEXTM =>
|
|
if vert_active_q and
|
|
num_pix_plus_6_v(0) = '0' and
|
|
num_pix_plus_6_v(0 to 4) /= "01111" then
|
|
mod_6_v := mod_6_f(num_pix_plus_6_v);
|
|
case mod_6_v(6 to 7) is
|
|
when "00" =>
|
|
access_type_s <= AC_PNT;
|
|
when "10" =>
|
|
access_type_s <= AC_PGT;
|
|
when others =>
|
|
null;
|
|
end case;
|
|
end if;
|
|
|
|
-- Unknown --------------------------------------------------------------
|
|
when others =>
|
|
null;
|
|
|
|
end case;
|
|
|
|
end process decode_access;
|
|
--
|
|
-----------------------------------------------------------------------------
|
|
|
|
|
|
-----------------------------------------------------------------------------
|
|
-- Process vert_flags
|
|
--
|
|
-- Purpose:
|
|
-- Track the vertical position with flags.
|
|
--
|
|
vert_flags: process (clk_i, reset_i)
|
|
begin
|
|
if reset_i then
|
|
vert_active_q <= false;
|
|
sprite_active_q <= false;
|
|
sprite_line_act_q <= false;
|
|
|
|
elsif clk_i'event and clk_i = '1' then
|
|
if clk_en_5m37_i then
|
|
-- line-local sprite processing
|
|
if sprite_active_q then
|
|
-- sprites are globally enabled
|
|
if vert_inc_i then
|
|
-- reload at beginning of every new line
|
|
-- => scan with STST
|
|
sprite_line_act_q <= true;
|
|
end if;
|
|
|
|
if num_pix_i = hv_sprite_start_c then
|
|
-- reload when access to sprite memory starts
|
|
sprite_line_act_q <= true;
|
|
end if;
|
|
end if;
|
|
|
|
if vert_inc_i then
|
|
-- global sprite processing
|
|
if reg_blank_i then
|
|
sprite_active_q <= false;
|
|
sprite_line_act_q <= false;
|
|
elsif num_line_i = -2 then
|
|
-- start at line -1
|
|
sprite_active_q <= true;
|
|
-- initialize immediately
|
|
sprite_line_act_q <= true;
|
|
elsif num_line_i = 191 then
|
|
-- stop at line 192
|
|
sprite_active_q <= false;
|
|
-- force stop
|
|
sprite_line_act_q <= false;
|
|
end if;
|
|
|
|
-- global vertical display
|
|
if reg_blank_i then
|
|
vert_active_q <= false;
|
|
elsif num_line_i = -1 then
|
|
-- start vertical display at line 0
|
|
vert_active_q <= true;
|
|
elsif num_line_i = 191 then
|
|
-- stop at line 192
|
|
vert_active_q <= false;
|
|
end if;
|
|
end if;
|
|
|
|
if stop_sprite_i then
|
|
-- stop processing of sprites in this line
|
|
sprite_line_act_q <= false;
|
|
end if;
|
|
|
|
end if;
|
|
end if;
|
|
end process vert_flags;
|
|
--
|
|
-----------------------------------------------------------------------------
|
|
|
|
|
|
-----------------------------------------------------------------------------
|
|
-- Process hor_flags
|
|
--
|
|
-- Purpose:
|
|
-- Track the horizontal position.
|
|
--
|
|
hor_flags: process (clk_i, reset_i)
|
|
begin
|
|
if reset_i then
|
|
hor_active_q <= false;
|
|
|
|
elsif clk_i'event and clk_i = '1' then
|
|
if clk_en_5m37_i then
|
|
if not reg_blank_i and
|
|
num_pix_i = -1 then
|
|
hor_active_q <= true;
|
|
end if;
|
|
|
|
if opmode_i = OPMODE_TEXTM then
|
|
if num_pix_i = 239 then
|
|
hor_active_q <= false;
|
|
end if;
|
|
else
|
|
if num_pix_i = 255 then
|
|
hor_active_q <= false;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
end process hor_flags;
|
|
--
|
|
-----------------------------------------------------------------------------
|
|
|
|
|
|
-----------------------------------------------------------------------------
|
|
-- Ouput mapping
|
|
-----------------------------------------------------------------------------
|
|
-- generate clock enable for flip-flops working on access_type
|
|
clk_en_acc_o <= clk_en_5m37_i and num_pix_i(8) = '1';
|
|
access_type_o <= access_type_s;
|
|
vert_active_o <= vert_active_q;
|
|
hor_active_o <= hor_active_q;
|
|
irq_o <= vert_inc_i and num_line_i = 191;
|
|
|
|
end rtl;
|