repo2/atari_chips/gtia/gtiamax.vhd @ 1476
701 | markw | ---------------------------------------------------------------------------
|
|
-- (c) 2018 mark watson
|
|||
-- I am happy for anyone to use this for non-commercial use.
|
|||
-- If my vhdl files are used commercially or otherwise sold,
|
|||
-- please contact me for explicit permission at scrameta (gmail).
|
|||
-- This applies for source and binary form and derived works.
|
|||
---------------------------------------------------------------------------
|
|||
LIBRARY ieee;
|
|||
USE ieee.std_logic_1164.all;
|
|||
use ieee.numeric_std.all;
|
|||
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
|
|||
LIBRARY work;
|
|||
815 | markw | ENTITY gtiamax IS
|
|
701 | markw | PORT
|
|
(
|
|||
PHI2 : IN STD_LOGIC;
|
|||
CLK_OUT : OUT STD_LOGIC; -- Use PHI2 and internal oscillator to create a clock, feed out here
|
|||
CLK_SLOW : IN STD_LOGIC; -- ... and back in here, then to pll!
|
|||
D : INOUT STD_LOGIC_VECTOR(7 DOWNTO 0);
|
|||
A : IN STD_LOGIC_VECTOR(4 DOWNTO 0);
|
|||
W_N : IN STD_LOGIC;
|
|||
815 | markw | CS_N : IN STD_LOGIC;
|
|
714 | markw | ||
815 | markw | S : INOUT STD_LOGIC_VECTOR(3 DOWNTO 0);
|
|
T : IN STD_LOGIC_VECTOR(3 DOWNTO 0);
|
|||
714 | markw | ||
815 | markw | AN : IN STD_LOGIC_VECTOR(2 DOWNTO 0);
|
|
HALT_N : IN STD_LOGIC;
|
|||
714 | markw | ||
815 | markw | OSC : IN STD_LOGIC; -- 2x PHI0 ish, iffy duty cycle at TTL levels (at 4V its ok!)
|
|
FO0 : OUT STD_LOGIC; -- as OSC, but corrected duty cycle
|
|||
PAL : IN STD_LOGIC; -- PAL clock (5/4...)
|
|||
718 | markw | ||
815 | markw | GPIO : INOUT STD_LOGIC_VECTOR(11 DOWNTO 0);
|
|
1318 | markw | NC : IN STD_LOGIC_VECTOR(6 DOWNTO 1);
|
|
815 | markw | CAD3 : IN STD_LOGIC;
|
|
CSYNC : OUT STD_LOGIC;
|
|||
COLOR : OUT STD_LOGIC;
|
|||
817 | markw | LUM : OUT STD_LOGIC_VECTOR(3 downto 0)
|
|
701 | markw | );
|
|
815 | markw | END gtiamax;
|
|
701 | markw | ||
815 | markw | ARCHITECTURE vhdl OF gtiamax IS
|
|
701 | markw | component int_osc is
|
|
port (
|
|||
clkout : out std_logic; -- clkout.clk
|
|||
oscena : in std_logic := '0' -- oscena.oscena
|
|||
);
|
|||
end component;
|
|||
714 | markw | ||
component pll
|
|||
port (
|
|||
inclk0 : in std_logic := '0';
|
|||
c0 : out std_logic;
|
|||
820 | markw | c1 : out std_logic;
|
|
714 | markw | locked : out std_logic
|
|
);
|
|||
end component;
|
|||
1318 | markw | ||
component osc_in is
|
|||
port (
|
|||
inclock : in std_logic := '0';
|
|||
dout : out std_logic_vector(1 downto 0);
|
|||
pad_in : in std_logic_vector(0 downto 0) := (others => '0')
|
|||
);
|
|||
end component osc_in;
|
|||
component osc_out is
|
|||
port (
|
|||
outclock : in std_logic := '0';
|
|||
din : in std_logic_vector(1 downto 0) := (others => '0');
|
|||
pad_out : out std_logic_vector(0 downto 0)
|
|||
);
|
|||
end component osc_out;
|
|||
714 | markw | ||
signal OSC_CLK : std_logic;
|
|||
signal PHI2_6X : std_logic;
|
|||
signal CLK : std_logic;
|
|||
820 | markw | signal FAST_CLK : std_logic;
|
|
714 | markw | signal RESET_N : std_logic;
|
|
signal ENABLE_CYCLE : std_logic;
|
|||
823 | markw | signal DATA_CYCLE : std_logic;
|
|
714 | markw | ||
716 | markw | signal ADDR_IN : std_logic_vector(4 downto 0);
|
|
signal WRITE_DATA : std_logic_vector(7 downto 0);
|
|||
714 | markw | ||
716 | markw | signal BUS_DATA : std_logic_vector(7 downto 0);
|
|
signal BUS_OE : std_logic;
|
|||
signal REQUEST : std_logic;
|
|||
signal WRITE_N : std_logic;
|
|||
815 | markw | signal GTIA_DO : std_logic_vector(7 downto 0);
|
|
817 | markw | ||
signal GTIA_WRITE_ENABLE : std_logic;
|
|||
819 | markw | signal PAL_CLEAN : std_logic;
|
|
signal PAL_NTSC_N : std_logic;
|
|||
1318 | markw | signal COLOUR_OSC : std_logic_vector(1 downto 0);
|
|
signal COLOUR_OSC_PHASED : std_logic_vector(1 downto 0);
|
|||
819 | markw | ||
817 | markw | signal OSC_CLEAN : std_logic;
|
|
1405 | markw | signal OSC_CLEAN_FAST : std_logic;
|
|
820 | markw | signal OSC_CLEAN_VIDEO : std_logic;
|
|
817 | markw | signal OSC_CLEAN_EVENT : std_logic;
|
|
1405 | markw | signal OSC_CLEAN_FAST_EVENT : std_logic;
|
|
signal CC_FALLING_FAST : std_logic;
|
|||
817 | markw | signal CC_FALLING : std_logic;
|
|
1405 | markw | signal OSC_CLEAN_PREV_REG : std_logic;
|
|
817 | markw | ||
signal S_OUT : std_logic_vector(3 downto 0);
|
|||
signal VIDEO_COLOUR : std_logic_vector(7 downto 0);
|
|||
signal VIDEO_HSYNC : std_logic;
|
|||
signal VIDEO_VSYNC : std_logic;
|
|||
signal VIDEO_CSYNC : std_logic;
|
|||
signal VIDEO_BLANK : std_logic;
|
|||
signal VIDEO_BURST : std_logic;
|
|||
signal VIDEO_START_OF_FIELD : std_logic;
|
|||
signal VIDEO_ODD_LINE : std_logic;
|
|||
822 | markw | ||
signal HALT_N_ADJ : std_logic;
|
|||
824 | markw | ||
signal AN_DEL_NEXT : std_logic_vector(2 downto 0);
|
|||
signal AN_DEL_REG : std_logic_vector(2 downto 0);
|
|||
signal AN_DEL2_NEXT : std_logic_vector(2 downto 0);
|
|||
signal AN_DEL2_REG : std_logic_vector(2 downto 0);
|
|||
1318 | markw | ||
signal ddr_pal : std_logic_vector(1 downto 0);
|
|||
701 | markw | BEGIN
|
|
1318 | markw | --NC <= (others=>'Z');
|
|
815 | markw | GPIO <= (others=>'Z');
|
|
701 | markw | ||
1318 | markw | pal_in : osc_in
|
|
port map
|
|||
(
|
|||
inclock => fast_clk,
|
|||
dout => colour_osc,
|
|||
pad_in(0) => pal
|
|||
);
|
|||
--colour_osc <= pal_clean when pal_ntsc_n='1' else osc_clean_video;
|
|||
col_out : osc_out
|
|||
port map
|
|||
(
|
|||
outclock => fast_clk,
|
|||
din => colour_osc_phased,
|
|||
pad_out(0)=> color
|
|||
);
|
|||
--COLOR <= colour_osc_phased;
|
|||
701 | markw | oscillator : int_osc
|
|
port map
|
|||
(
|
|||
714 | markw | clkout => OSC_CLK,
|
|
701 | markw | oscena => '1'
|
|
);
|
|||
730 | markw | --phi_multiplier : entity work.phi_mult
|
|
--port map
|
|||
--(
|
|||
-- clkin => OSC_CLK,
|
|||
-- phi2 => PHI2,
|
|||
-- clkout => PHI2_6X -- 6x phi2, aligned!
|
|||
--);
|
|||
PHI2_6X <= OSC_CLK;
|
|||
714 | markw | ||
pll_inst : pll
|
|||
PORT MAP(inclk0 => CLK_SLOW,
|
|||
820 | markw | c0 => CLK, -- 56MHz
|
|
c1 => FAST_CLK, -- 300MHz
|
|||
714 | markw | locked => RESET_N);
|
|
1405 | markw | process(cc_falling_fast,reset_n)
|
|
824 | markw | begin
|
|
if (reset_n='0') then
|
|||
AN_DEL_REG <= (others=>'0');
|
|||
AN_DEL2_REG <= (others=>'0');
|
|||
1405 | markw | elsif (cc_falling_fast'event and cc_falling_fast='1') then
|
|
824 | markw | AN_DEL_REG <= AN_DEL_NEXT;
|
|
AN_DEL2_REG <= AN_DEL2_NEXT;
|
|||
end if;
|
|||
end process;
|
|||
1405 | markw | AN_DEL_NEXT <= AN;
|
|
AN_DEL2_NEXT <= AN_DEL_REG;
|
|||
824 | markw | ||
716 | markw | bus_adapt : entity work.slave_timing_6502
|
|
PORT MAP
|
|||
(
|
|||
CLK => CLK,
|
|||
RESET_N => RESET_N,
|
|||
-- input from the cart port
|
|||
PHI2 => PHI2,
|
|||
bus_addr => A,
|
|||
bus_data => D,
|
|||
-- output to the cart port
|
|||
bus_data_out => BUS_DATA,
|
|||
bus_drive => BUS_OE,
|
|||
817 | markw | bus_cs => NOT(CS_N),
|
|
716 | markw | bus_rw_n => W_N,
|
|
-- request for a memory bus cycle (read or write)
|
|||
BUS_REQUEST => REQUEST,
|
|||
ADDR_IN => ADDR_IN,
|
|||
DATA_IN => WRITE_DATA,
|
|||
RW_N => WRITE_N,
|
|||
717 | markw | -- end of cycle
|
|
ENABLE_CYCLE => ENABLE_CYCLE,
|
|||
823 | markw | DATA_CYCLE => DATA_CYCLE,
|
|
822 | markw | HALT_N => HALT_N,
|
|
HALT_N_OUT => HALT_N_ADJ,
|
|||
717 | markw | ||
815 | markw | DATA_OUT => GTIA_DO
|
|
716 | markw | );
|
|
817 | markw | ||
819 | markw | ||
820 | markw | osc_cleaner3 : entity work.correct_duty
|
|
PORT MAP(
|
|||
CLK => FAST_CLK,
|
|||
RESET_N => RESET_N,
|
|||
CLKIN => OSC,
|
|||
CLKOUT => OSC_CLEAN_VIDEO,
|
|||
CLKOUT_EVENT => open
|
|||
);
|
|||
819 | markw | osc_cleaner2 : entity work.correct_duty
|
|
PORT MAP(
|
|||
820 | markw | CLK => FAST_CLK,
|
|
819 | markw | RESET_N => RESET_N,
|
|
CLKIN => PAL,
|
|||
CLKOUT => PAL_CLEAN,
|
|||
CLKOUT_EVENT => open
|
|||
);
|
|||
817 | markw | osc_cleaner : entity work.correct_duty
|
|
PORT MAP(
|
|||
1405 | markw | CLK => FAST_CLK,
|
|
817 | markw | RESET_N => RESET_N,
|
|
CLKIN => OSC,
|
|||
1405 | markw | CLKOUT => OSC_CLEAN_FAST,
|
|
CLKOUT_EVENT => OSC_CLEAN_FAST_EVENT
|
|||
817 | markw | );
|
|
1405 | markw | CC_FALLING_FAST <= OSC_CLEAN_FAST_EVENT and not(OSC_CLEAN_FAST);
|
|
817 | markw | ||
1405 | markw | sync_clk : entity work.synchronizer
|
|
port map
|
|||
(
|
|||
CLK => CLK,
|
|||
RAW => OSC_CLEAN_FAST,
|
|||
SYNC => OSC_CLEAN
|
|||
);
|
|||
process(clk,reset_n)
|
|||
begin
|
|||
if (reset_n='0') then
|
|||
OSC_CLEAN_PREV_REG <= '0';
|
|||
elsif (clk'event and clk='1') then
|
|||
OSC_CLEAN_PREV_REG <= OSC_CLEAN;
|
|||
end if;
|
|||
end process;
|
|||
OSC_CLEAN_EVENT <= OSC_CLEAN_PREV_REG xor OSC_CLEAN;
|
|||
817 | markw | CC_FALLING <= OSC_CLEAN_EVENT and not(OSC_CLEAN);
|
|
819 | markw | pal_ntsc_n <= '1'; -- TODO GPIO
|
|
815 | markw | gtia1 : entity work.gtia
|
|
714 | markw | PORT MAP(CLK => CLK,
|
|
815 | markw | ENABLE_179 => ENABLE_CYCLE,
|
|
WR_EN => GTIA_WRITE_ENABLE,
|
|||
RESET_N => RESET_N,
|
|||
ADDR => ADDR_IN(4 DOWNTO 0),
|
|||
817 | markw | CPU_DATA_IN => WRITE_DATA(7 DOWNTO 0),
|
|
815 | markw | DATA_OUT => GTIA_DO,
|
|
714 | markw | ||
815 | markw | -- pmg dma
|
|
821 | markw | MEMORY_DATA_IN => D,
|
|
822 | markw | ANTIC_FETCH => not(HALT_N_ADJ),
|
|
823 | markw | CPU_ENABLE_ORIGINAL => DATA_CYCLE,
|
|
725 | markw | ||
819 | markw | PAL => pal_ntsc_n,
|
|
740 | markw | ||
815 | markw | -- ANTIC interface
|
|
817 | markw | COLOUR_CLOCK_ORIGINAL => CC_FALLING,
|
|
COLOUR_CLOCK => CC_FALLING,
|
|||
818 | markw | COLOUR_CLOCK_HIGHRES => OSC_CLEAN_EVENT,
|
|
824 | markw | AN => AN_DEL2_REG,
|
|
740 | markw | ||
815 | markw | -- keyboard interface
|
|
818 | markw | CONSOL_IN => NOT(S),
|
|
815 | markw | CONSOL_OUT => S_OUT,
|
|
737 | markw | ||
815 | markw | -- keyboard interface
|
|
TRIG => T,
|
|||
-- TO scandoubler...
|
|||
COLOUR_out => VIDEO_COLOUR,
|
|||
VSYNC => VIDEO_VSYNC,
|
|||
HSYNC => VIDEO_HSYNC,
|
|||
CSYNC => VIDEO_CSYNC,
|
|||
BLANK => VIDEO_BLANK,
|
|||
BURST => VIDEO_BURST,
|
|||
START_OF_FIELD => VIDEO_START_OF_FIELD,
|
|||
ODD_LINE => VIDEO_ODD_LINE
|
|||
718 | markw | );
|
|
815 | markw | GTIA_WRITE_ENABLE <= NOT(WRITE_N) and REQUEST;
|
|
718 | markw | ||
819 | markw | col_phase : entity work.hue
|
|
PORT MAP
|
|||
(
|
|||
820 | markw | clk => fast_clk,
|
|
819 | markw | reset_n => reset_n,
|
|
hue => video_colour(7 downto 4),
|
|||
burst => video_burst,
|
|||
blank => video_blank,
|
|||
vpos_lsb => video_odd_line,
|
|||
pal => pal_ntsc_n,
|
|||
colour_osc => colour_osc,
|
|||
colour_osc_phased => colour_osc_phased
|
|||
);
|
|||
714 | markw | -- Wire up pins
|
|
CLK_OUT <= PHI2_6X;
|
|||
815 | markw | D <= BUS_DATA when BUS_OE='1' else (others=>'Z');
|
|
714 | markw | ||
815 | markw | S(0) <= '0' when S_OUT(0)='1' else 'Z';
|
|
S(1) <= '0' when S_OUT(1)='1' else 'Z';
|
|||
S(2) <= '0' when S_OUT(2)='1' else 'Z';
|
|||
S(3) <= '0' when S_OUT(3)='1' else 'Z';
|
|||
714 | markw | ||
817 | markw | CSYNC <= NOT(VIDEO_CSYNC);
|
|
1318 | markw | --COLOR <= colour_osc_phased;
|
|
817 | markw | LUM(3 downto 0) <= VIDEO_COLOUR(3 downto 0);
|
|
1405 | markw | FO0 <= OSC_CLEAN_FAST;
|
|
817 | markw | ||
701 | markw | END vhdl;
|