Use other base - fixes top/bottom text.

This commit is contained in:
sorgelig
2019-12-29 09:42:03 +08:00
parent 0105055d7a
commit 6cdec37da0
6 changed files with 1078 additions and 536 deletions

View File

@@ -13,7 +13,7 @@ set_global_assignment -name PARTITION_NETLIST_TYPE SOURCE -section_id Top
set_global_assignment -name PARTITION_FITTER_PRESERVATION_LEVEL PLACEMENT_AND_ROUTING -section_id Top
set_global_assignment -name PARTITION_COLOR 16764057 -section_id Top
set_global_assignment -name LAST_QUARTUS_VERSION "17.0.2 Lite Edition"
set_global_assignment -name LAST_QUARTUS_VERSION "17.0.2 Standard Edition"
set_global_assignment -name GENERATE_RBF_FILE ON
set_global_assignment -name PROJECT_OUTPUT_DIRECTORY output_files

View File

@@ -317,14 +317,10 @@ pacman pacman
.O_AUDIO(audio),
//.in0(~{2'b00, m_coin, m_fire, m_down,m_right,m_left,m_up}),
//.in1(~{1'b0, m_start2, m_start1, 5'b00000}),
.in0(~{2'b00,btn_coin_1, m_coin|btn_coin_2, m_cheat , m_down,m_right,m_left,m_up}),
.in1(~{status[12], m_start2|btn_start_2, m_start1|btn_start_1,1'b0,m_down_2,m_right_2,m_left_2,m_up_2}),
.in0_reg(~{2'b00,btn_coin_1, m_coin|btn_coin_2, m_cheat , m_down,m_right,m_left,m_up}),
.in1_reg(~{status[12], m_start2|btn_start_2, m_start1|btn_start_1,1'b0,m_down_2,m_right_2,m_left_2,m_up_2}),
//.dipsw1(8'b1_1_00_11_01),
.dipsw1(m_dip),
.dipsw2(8'b11111111),
.dipsw_reg(m_dip),
.RESET(RESET | status[0] | buttons[1]|ioctl_download),
.CLK(clk_sys),

View File

@@ -5,6 +5,7 @@ set_global_assignment -name VHDL_FILE cpu/T80_MCode.vhd
set_global_assignment -name VHDL_FILE cpu/T80_ALU.vhd
set_global_assignment -name VHDL_FILE cpu/T80.vhd
set_global_assignment -name VHDL_FILE dpram.vhd
set_global_assignment -name VHDL_FILE pacman_vram_addr.vhd
set_global_assignment -name VHDL_FILE pacman_video.vhd
set_global_assignment -name VHDL_FILE pacman_audio.vhd
set_global_assignment -name VHDL_FILE pacman.vhd

View File

@@ -1,7 +1,6 @@
--
-- A simulation model of Pacman hardware
-- Copyright (c) MikeJ - January 2006
-- Copyright (c) Sorgelig - 2017
--
-- All rights reserved
--
@@ -39,7 +38,6 @@
--
-- Revision list
--
-- version 006 Refactoring, 8 sprites support by Sorgelig
-- version 005 Papilio release by Jack Gassett
-- version 004 spartan3e release
-- version 003 Jan 2006 release, general tidy up
@@ -51,98 +49,100 @@ library ieee;
use ieee.std_logic_unsigned.all;
use ieee.numeric_std.all;
library UNISIM;
entity PACMAN is
generic(
eight_sprites : boolean := false
);
port (
O_VIDEO_R : out std_logic_vector(2 downto 0);
O_VIDEO_G : out std_logic_vector(2 downto 0);
O_VIDEO_B : out std_logic_vector(1 downto 0);
O_HSYNC : out std_logic;
O_VSYNC : out std_logic;
O_HBLANK : out std_logic;
O_VBLANK : out std_logic;
--
O_AUDIO : out std_logic_vector(7 downto 0);
--
in0 : in std_logic_vector(7 downto 0);
in1 : in std_logic_vector(7 downto 0);
dipsw1 : in std_logic_vector(7 downto 0);
dipsw2 : in std_logic_vector(7 downto 0);
--
dn_addr : in std_logic_vector(15 downto 0);
dn_data : in std_logic_vector(7 downto 0);
dn_wr : in std_logic;
--
RESET : in std_logic;
CLK : in std_logic;
ENA_6 : in std_logic
);
generic (
MRTNT : std_logic := '0' -- 1 to descramble Mr TNT ROMs, 0 otherwise
);
port (
O_VIDEO_R : out std_logic_vector(2 downto 0);
O_VIDEO_G : out std_logic_vector(2 downto 0);
O_VIDEO_B : out std_logic_vector(1 downto 0);
O_HSYNC : out std_logic;
O_VSYNC : out std_logic;
O_HBLANK : out std_logic;
O_VBLANK : out std_logic;
--
O_AUDIO : out std_logic_vector(7 downto 0);
--
in0_reg : in std_logic_vector(7 downto 0);
in1_reg : in std_logic_vector(7 downto 0);
dipsw_reg : in std_logic_vector(7 downto 0);
--
dn_addr : in std_logic_vector(15 downto 0);
dn_data : in std_logic_vector(7 downto 0);
dn_wr : in std_logic;
--
RESET : in std_logic;
CLK : in std_logic;
ENA_6 : in std_logic
);
end;
architecture RTL of PACMAN is
-- timing
signal hcnt : std_logic_vector(8 downto 0) := "010000000"; -- 80
signal vcnt : std_logic_vector(8 downto 0) := "011111000"; -- 0F8
-- timing
signal hcnt : std_logic_vector(8 downto 0) := "010000000"; -- 80
signal vcnt : std_logic_vector(8 downto 0) := "011111000"; -- 0F8
signal do_hsync : boolean;
signal hsync : std_logic;
signal vsync : std_logic;
signal hblank : std_logic;
signal vblank : std_logic := '1';
signal do_hsync : boolean;
signal hsync : std_logic;
signal vsync : std_logic;
signal hblank : std_logic;
signal vblank : std_logic := '1';
-- cpu
signal cpu_m1_l : std_logic;
signal cpu_mreq_l : std_logic;
signal cpu_iorq_l : std_logic;
signal cpu_rd_l : std_logic;
signal cpu_rfsh_l : std_logic;
signal cpu_int_l : std_logic := '1';
signal cpu_addr : std_logic_vector(15 downto 0);
signal cpu_data_out : std_logic_vector(7 downto 0);
signal cpu_data_in : std_logic_vector(7 downto 0);
-- cpu
signal cpu_ena : std_logic;
signal cpu_m1_l : std_logic;
signal cpu_mreq_l : std_logic;
signal cpu_iorq_l : std_logic;
signal cpu_rd_l : std_logic;
signal cpu_rfsh_l : std_logic;
signal cpu_wait_l : std_logic;
signal cpu_int_l : std_logic;
signal cpu_nmi_l : std_logic;
signal cpu_busrq_l : std_logic;
signal cpu_addr : std_logic_vector(15 downto 0);
signal cpu_data_out : std_logic_vector(7 downto 0);
signal cpu_data_in : std_logic_vector(7 downto 0);
signal program_rom_dinl : std_logic_vector(7 downto 0);
signal program_rom_dinh : std_logic_vector(7 downto 0);
signal sync_bus_cs_l : std_logic;
signal rom_data_out : std_logic_vector(7 downto 0);
signal rom_data : std_logic_vector(7 downto 0);
signal control_reg : std_logic_vector(7 downto 0);
--
signal sync_bus_db : std_logic_vector(7 downto 0);
signal sync_bus_r_w_l : std_logic;
signal sync_bus_wreq_l : std_logic;
signal sync_bus_stb : std_logic;
signal program_rom_dinl : std_logic_vector(7 downto 0);
signal program_rom_dinh : std_logic_vector(7 downto 0);
signal sync_bus_cs_l : std_logic;
signal cpu_vec_reg : std_logic_vector(7 downto 0);
signal sync_bus_reg : std_logic_vector(7 downto 0);
signal control_reg : std_logic_vector(7 downto 0);
--
signal vram_addr_ab : std_logic_vector(11 downto 0);
signal ab : std_logic_vector(11 downto 0);
signal hp : std_logic_vector ( 4 downto 0);
signal vp : std_logic_vector ( 4 downto 0);
signal ram_cs : std_logic;
signal ram_data : std_logic_vector(7 downto 0);
signal vram_data : std_logic_vector(7 downto 0);
signal sprite_xy_data : std_logic_vector(7 downto 0);
signal vram_addr : std_logic_vector(11 downto 0);
signal sync_bus_db : std_logic_vector(7 downto 0);
signal sync_bus_r_w_l : std_logic;
signal sync_bus_wreq_l : std_logic;
signal sync_bus_stb : std_logic;
signal iodec_spr_l : std_logic;
signal iodec_out_l : std_logic;
signal iodec_wdr_l : std_logic;
signal iodec_sn1_l : std_logic;
signal iodec_sn2_l : std_logic;
signal iodec_in0_l : std_logic;
signal iodec_in1_l : std_logic;
signal iodec_dipsw1_l : std_logic;
signal iodec_dipsw2_l : std_logic;
signal cpu_vec_reg : std_logic_vector(7 downto 0);
signal sync_bus_reg : std_logic_vector(7 downto 0);
-- watchdog
signal watchdog_cnt : std_logic_vector(3 downto 0);
signal watchdog_reset_l : std_logic;
signal vram_l : std_logic;
signal rams_data_out : std_logic_vector(7 downto 0);
-- more decode
signal wr0_l : std_logic;
signal wr1_l : std_logic;
signal wr2_l : std_logic;
signal iodec_out_l : std_logic;
signal iodec_wdr_l : std_logic;
signal iodec_in0_l : std_logic;
signal iodec_in1_l : std_logic;
signal iodec_dipsw_l : std_logic;
signal sn_we : std_logic;
signal wav1,wav2,wav3 : std_logic_vector(7 downto 0);
-- watchdog
signal watchdog_cnt : std_logic_vector(3 downto 0);
signal watchdog_reset_l : std_logic;
signal rom0_cs,rom1_cs : std_logic;
@@ -151,323 +151,506 @@ begin
rom0_cs <= '1' when dn_addr(15 downto 14) = "00" else '0';
rom1_cs <= '1' when dn_addr(15 downto 14) = "01" else '0';
--
-- video timing
--
p_hvcnt : process
begin
wait until rising_edge(clk);
if (ena_6 = '1') then
if hcnt = "111111111" then
hcnt <= "010000000"; -- 080
else
hcnt <= hcnt +"1";
end if;
-- hcnt 8 on circuit is 256H_L
if do_hsync then
if vcnt = "111111111" then
vcnt <= "011111000"; -- 0F8
else
vcnt <= vcnt +"1";
end if;
end if;
end if;
end process;
--
-- video timing
--
p_hvcnt : process
variable hcarry,vcarry : boolean;
begin
wait until rising_edge(clk);
if (ena_6 = '1') then
hcarry := (hcnt = "111111111");
if hcarry then
hcnt <= "010000000"; -- 080
else
hcnt <= hcnt +"1";
end if;
-- hcnt 8 on circuit is 256H_L
vcarry := (vcnt = "111111111");
if do_hsync then
if vcarry then
vcnt <= "011111000"; -- 0F8
else
vcnt <= vcnt +"1";
end if;
end if;
end if;
end process;
vsync <= not vcnt(8);
do_hsync <= (hcnt = "010101111"); -- 0AF
p_sync_comb : process(hcnt, vcnt)
begin
vsync <= not vcnt(8);
do_hsync <= (hcnt = "010101111"); -- 0AF
end process;
p_sync : process
begin
wait until rising_edge(clk);
if (ena_6 = '1') then
p_sync : process
begin
wait until rising_edge(clk);
if (ena_6 = '1') then
-- Timing hardware is coded differently to the real hw
-- to avoid the use of multiple clocks. Result is identical.
if (hcnt = "010001111") and not eight_sprites then -- 08F
hblank <= '1';
elsif (hcnt = "011101111") and not eight_sprites then
hblank <= '0'; -- 0EF
elsif (hcnt = "111111111") and eight_sprites then
hblank <= '1';
elsif (hcnt = "011111111") and eight_sprites then
hblank <= '0';
end if;
if (hcnt = "010010111") then -- 097
O_HBLANK <= '1';
elsif (hcnt = "010001111") then -- 08F
hblank <= '1';
elsif (hcnt = "011101111") then
hblank <= '0'; -- 0EF
elsif (hcnt = "011110111") then -- 0F7
O_HBLANK <= '0';
end if;
if do_hsync then
hsync <= '1';
elsif (hcnt = "011001111") then -- 0CF
hsync <= '0';
end if;
if do_hsync then
hsync <= '1';
elsif (hcnt = "011001111") then -- 0CF
hsync <= '0';
end if;
if do_hsync then
if (vcnt = "111101111") then -- 1EF
vblank <= '1';
elsif (vcnt = "100001111") then -- 10F
vblank <= '0';
end if;
end if;
end if;
end process;
if do_hsync then
if (vcnt = "111101111") then -- 1EF
vblank <= '1';
elsif (vcnt = "100001111") then -- 10F
vblank <= '0';
end if;
end if;
end if;
end process;
--
-- cpu
--
p_irq_req_watchdog : process
variable rising_vblank : boolean;
begin
wait until rising_edge(clk);
if (ena_6 = '1') then
rising_vblank := do_hsync and (vcnt = "111101111"); -- 1EF
--
-- cpu
--
p_cpu_wait_comb : process(sync_bus_wreq_l)
begin
cpu_wait_l <= '1';
if (sync_bus_wreq_l = '0') then
cpu_wait_l <= '0';
end if;
end process;
if (control_reg(0) = '0') then
cpu_int_l <= '1';
elsif rising_vblank then -- 1EF
cpu_int_l <= '0';
end if;
p_irq_req_watchdog : process
variable rising_vblank : boolean;
begin
wait until rising_edge(clk);
if (ena_6 = '1') then
rising_vblank := do_hsync and (vcnt = "111101111"); -- 1EF
--rising_vblank := do_hsync; -- debug
-- interrupt 8c
-- watchdog 8c
-- note sync reset
if (reset = '1') then
watchdog_cnt <= "1111";
elsif (iodec_wdr_l = '0') then
watchdog_cnt <= "0000";
elsif rising_vblank then
watchdog_cnt <= watchdog_cnt + "1";
end if;
if (control_reg(0) = '0') then
cpu_int_l <= '1';
elsif rising_vblank then -- 1EF
cpu_int_l <= '0';
end if;
--watchdog_reset_l <= not reset;
watchdog_reset_l <= '1';
if (watchdog_cnt = "1111") then
watchdog_reset_l <= '0';
end if;
end if;
end process;
u_cpu : entity work.T80sed
port map
(
RESET_n => watchdog_reset_l and (not reset),
CLK_n => clk,
CLKEN => hcnt(0) and ena_6,
WAIT_n => sync_bus_wreq_l,
INT_n => cpu_int_l,
NMI_n => '1',
BUSRQ_n => '1',
M1_n => cpu_m1_l,
MREQ_n => cpu_mreq_l,
IORQ_n => cpu_iorq_l,
RD_n => cpu_rd_l,
WR_n => open,
RFSH_n => cpu_rfsh_l,
HALT_n => open,
BUSAK_n => open,
A => cpu_addr,
DI => cpu_data_in,
DO => cpu_data_out
);
-- rom 0x0000 - 0x3FFF
-- syncbus 0x4000 - 0x7FFF
sync_bus_cs_l <= '0' when cpu_mreq_l = '0' and cpu_rfsh_l = '1' and cpu_addr(14) = '1' else '1';
sync_bus_wreq_l <= '0' when sync_bus_cs_l = '0' and hcnt(1) = '1' and cpu_rd_l = '0' else '1';
sync_bus_stb <= '0' when sync_bus_cs_l = '0' and hcnt(1) = '0' else '1';
sync_bus_r_w_l <= '0' when sync_bus_stb = '0' and cpu_rd_l = '1' else '1';
--
-- sync bus custom ic
--
p_sync_bus_reg : process
begin
wait until rising_edge(clk);
if (ena_6 = '1') then
-- register on sync bus module that is used to store interrupt vector
if (cpu_iorq_l = '0') and (cpu_m1_l = '1') then
cpu_vec_reg <= cpu_data_out;
end if;
-- read holding reg
if (hcnt(1 downto 0) = "01") then
sync_bus_reg <= cpu_data_in;
end if;
end if;
end process;
-- watchdog 8c
-- note sync reset
if (reset = '1') then
watchdog_cnt <= "1111";
elsif (iodec_wdr_l = '0') then
watchdog_cnt <= "0000";
elsif rising_vblank then
watchdog_cnt <= watchdog_cnt + "1";
end if;
-- WRITE
-- out_l 0x5000 - 0x503F control space
-- sn1_l 0x5040 - 0x504F sound
-- sn2_l 0x5050 - 0x505F sound
-- spr_l 0x5060 - 0x506F sprite
-- wdr_l 0x50C0 - 0x50FF watchdog reset
iodec_out_l <= '0' when sync_bus_r_w_l = '0' and cpu_addr(15 downto 6) = X"50"&"00" else '1';
iodec_sn1_l <= '0' when sync_bus_r_w_l = '0' and cpu_addr(15 downto 4) = X"50"&X"4" else '1';
iodec_sn2_l <= '0' when sync_bus_r_w_l = '0' and cpu_addr(15 downto 4) = X"50"&X"5" else '1';
iodec_spr_l <= '0' when sync_bus_r_w_l = '0' and cpu_addr(15 downto 4) = X"50"&X"6" else '1';
iodec_wdr_l <= '0' when sync_bus_r_w_l = '0' and cpu_addr(15 downto 6) = X"50"&"11" else '1';
watchdog_reset_l <= '1';
if (watchdog_cnt = "1111") then
watchdog_reset_l <= '0';
end if;
-- READ
-- in0_l 0x5000 - 0x503F in port 0
-- in1_l 0x5040 - 0x507F in port 1
-- dipsw_l 0x5080 - 0x50BF dip switches
iodec_in0_l <= '0' when sync_bus_r_w_l = '1' and cpu_addr(15 downto 6) = X"50"&"00" else '1';
iodec_in1_l <= '0' when sync_bus_r_w_l = '1' and cpu_addr(15 downto 6) = X"50"&"01" else '1';
iodec_dipsw1_l <= '0' when sync_bus_r_w_l = '1' and cpu_addr(15 downto 6) = X"50"&"10" else '1';
iodec_dipsw2_l <= '0' when sync_bus_r_w_l = '1' and cpu_addr(15 downto 6) = X"50"&"11" else '1';
-- simulation
-- pragma translate_off
-- synopsys translate_off
watchdog_reset_l <= not reset; -- watchdog disable
-- synopsys translate_on
-- pragma translate_on
end if;
end process;
p_control_reg : process
begin
-- 8 bit addressable latch 7K
-- (made into register)
-- other cpu signals
cpu_busrq_l <= '1';
cpu_nmi_l <= '1';
-- 0 interrupt ena
-- 1 sound ena
-- 2 not used
-- 3 flip
-- 4 1 player start lamp
-- 5 2 player start lamp
-- 6 coin lockout
-- 7 coin counter
p_cpu_ena : process(hcnt, ena_6)
begin
cpu_ena <= '0';
if (ena_6 = '1') then
cpu_ena <= hcnt(0);
end if;
end process;
wait until rising_edge(clk);
if (ena_6 = '1') then
if (watchdog_reset_l = '0') then
control_reg <= (others => '0');
elsif (iodec_out_l = '0') then
control_reg(to_integer(unsigned(cpu_addr(2 downto 0)))) <= cpu_data_out(0);
end if;
end if;
end process;
u_cpu : entity work.T80sed
port map (
RESET_n => watchdog_reset_l,
CLK_n => clk,
CLKEN => cpu_ena,
WAIT_n => cpu_wait_l,
INT_n => cpu_int_l,
NMI_n => cpu_nmi_l,
BUSRQ_n => cpu_busrq_l,
M1_n => cpu_m1_l,
MREQ_n => cpu_mreq_l,
IORQ_n => cpu_iorq_l,
RD_n => cpu_rd_l,
WR_n => open,
RFSH_n => cpu_rfsh_l,
HALT_n => open,
BUSAK_n => open,
A => cpu_addr,
DI => cpu_data_in,
DO => cpu_data_out
);
--
-- primary addr decode
--
p_mem_decode_comb : process(cpu_rfsh_l, cpu_rd_l, cpu_mreq_l, cpu_addr)
begin
-- rom 0x0000 - 0x3FFF
-- syncbus 0x4000 - 0x7FFF
cpu_data_in <= cpu_vec_reg when (cpu_iorq_l = '0') and (cpu_m1_l = '0') else
sync_bus_reg when sync_bus_wreq_l = '0' else
program_rom_dinl when cpu_addr(15 downto 14) = "00" else -- ROM at 0000 - 3fff
program_rom_dinh when cpu_addr(15 downto 14) = "10" else -- ROM at 8000 - bfff
in0 when iodec_in0_l = '0' else
in1 when iodec_in1_l = '0' else
dipsw1 when iodec_dipsw1_l = '0' else
dipsw2 when iodec_dipsw2_l = '0' else
ram_data;
-- 7M
-- 7N
sync_bus_cs_l <= '1';
-- program_rom_cs_l <= '1';
u_program_rom0 : work.dpram generic map (14,8)
port map
(
clock_a => clk,
wren_a => dn_wr and rom0_cs,
address_a => dn_addr(13 downto 0),
data_a => dn_data,
if (cpu_mreq_l = '0') and (cpu_rfsh_l = '1') then
clock_b => clk,
address_b => cpu_addr(13 downto 0),
q_b => program_rom_dinl
);
-- if (cpu_addr(14) = '0') and (cpu_rd_l = '0') then
-- program_rom_cs_l <= '0';
-- end if;
u_program_rom1 : work.dpram generic map (14,8)
port map
(
clock_a => clk,
wren_a => dn_wr and rom1_cs,
address_a => dn_addr(13 downto 0),
data_a => dn_data,
if (cpu_addr(14) = '1') then
sync_bus_cs_l <= '0';
end if;
clock_b => clk,
address_b => cpu_addr(13 downto 0),
q_b => program_rom_dinh
);
end if;
end process;
--
-- sync bus custom ic
--
p_sync_bus_reg : process
begin
wait until rising_edge(clk);
if (ena_6 = '1') then
-- register on sync bus module that is used to store interrupt vector
if (cpu_iorq_l = '0') and (cpu_m1_l = '1') then
cpu_vec_reg <= cpu_data_out;
end if;
ram_cs <= '1' when cpu_addr(15 downto 12) = X"4" else '0';
-- read holding reg
if (hcnt(1 downto 0) = "01") then
sync_bus_reg <= cpu_data_in;
end if;
end if;
end process;
u_rams : work.dpram generic map (12,8)
port map
(
clock_a => clk,
enable_a => ena_6,
wren_a => not sync_bus_r_w_l and ram_cs,
address_a => cpu_addr(11 downto 0),
data_a => cpu_data_out, -- cpu only source of ram data
q_a => ram_data,
p_sync_bus_comb : process(cpu_rd_l, sync_bus_cs_l, hcnt)
begin
-- sync_bus_stb is now an active low clock enable signal
sync_bus_stb <= '1';
sync_bus_r_w_l <= '1';
clock_b => clk,
address_b => vram_addr(11 downto 0),
q_b => vram_data
);
if (sync_bus_cs_l = '0') and (hcnt(1) = '0') then
if (cpu_rd_l = '1') then
sync_bus_r_w_l <= '0';
end if;
sync_bus_stb <= '0';
end if;
--
-- video subsystem
--
sync_bus_wreq_l <= '1';
if (sync_bus_cs_l = '0') and (hcnt(1) = '1') and (cpu_rd_l = '0') then
sync_bus_wreq_l <= '0';
end if;
end process;
--
-- vram addr custom ic
--
u_vram_addr : entity work.PACMAN_VRAM_ADDR
port map (
AB => vram_addr_ab,
H256_L => hcnt(8),
H128 => hcnt(7),
H64 => hcnt(6),
H32 => hcnt(5),
H16 => hcnt(4),
H8 => hcnt(3),
H4 => hcnt(2),
H2 => hcnt(1),
H1 => hcnt(0),
V128 => vcnt(7),
V64 => vcnt(6),
V32 => vcnt(5),
V16 => vcnt(4),
V8 => vcnt(3),
V4 => vcnt(2),
V2 => vcnt(1),
V1 => vcnt(0),
FLIP => control_reg(3)
);
-- vram addr custom ic
hp <= hcnt(7 downto 3) when control_reg(3) = '0' else not hcnt(7 downto 3);
vp <= vcnt(7 downto 3) when control_reg(3) = '0' else not vcnt(7 downto 3);
vram_addr <= '0' & hcnt(2) & vp & hp when hcnt(8)='1' else
x"FF" & hcnt(6 downto 4) & hcnt(2) when hblank = '1' else
'0' & hcnt(2) & hp(3) & hp(3) & hp(3) & hp(3) & hp(0) & vp;
p_ab_mux_comb : process(hcnt, cpu_addr, vram_addr_ab)
begin
--When 2H is low, the CPU controls the bus.
if (hcnt(1) = '0') then
ab <= cpu_addr(11 downto 0);
else
ab <= vram_addr_ab;
end if;
end process;
sprite_xy_ram : work.dpram generic map (4,8)
port map
(
clock_a => CLK,
enable_a => ENA_6,
wren_a => not iodec_spr_l,
address_a => cpu_addr(3 downto 0),
data_a => cpu_data_out,
p_vram_comb : process(hcnt, cpu_addr, sync_bus_stb)
variable a,b : std_logic;
begin
clock_b => CLK,
address_b => vram_addr(3 downto 0),
q_b => sprite_xy_data
);
a := not (cpu_addr(12) or sync_bus_stb);
b := hcnt(1) and hcnt(0);
vram_l <= not (a or b);
end process;
u_video : entity work.PACMAN_VIDEO
port map
(
I_HCNT => hcnt,
I_VCNT => vcnt,
--
vram_data => vram_data,
sprite_xy => sprite_xy_data,
--
I_HBLANK => hblank,
I_VBLANK => vblank,
I_FLIP => control_reg(3),
O_HBLANK => O_HBLANK,
p_io_decode_comb : process(sync_bus_r_w_l, sync_bus_stb, ab, cpu_addr)
variable sel : std_logic_vector(2 downto 0);
variable dec : std_logic_vector(7 downto 0);
variable selb : std_logic_vector(1 downto 0);
variable decb : std_logic_vector(3 downto 0);
begin
-- WRITE
-- out_l 0x5000 - 0x503F control space
-- wr0_l 0x5040 - 0x504F sound
-- wr1_l 0x5050 - 0x505F sound
-- wr2_l 0x5060 - 0x506F sprite
-- 0x5080 - 0x50BF unused
-- wdr_l 0x50C0 - 0x50FF watchdog reset
-- READ
-- in0_l 0x5000 - 0x503F in port 0
-- in1_l 0x5040 - 0x507F in port 1
-- dipsw_l 0x5080 - 0x50BF dip switches
-- 7J
dec := "11111111";
sel := sync_bus_r_w_l & ab(7) & ab(6);
if (cpu_addr(12) = '1') and ( sync_bus_stb = '0') then
case sel is
when "000" => dec := "11111110";
when "001" => dec := "11111101";
when "010" => dec := "11111011";
when "011" => dec := "11110111";
when "100" => dec := "11101111";
when "101" => dec := "11011111";
when "110" => dec := "10111111";
when "111" => dec := "01111111";
when others => null;
end case;
end if;
iodec_out_l <= dec(0);
iodec_wdr_l <= dec(3);
iodec_in0_l <= dec(4);
iodec_in1_l <= dec(5);
iodec_dipsw_l <= dec(6);
-- 7M
decb := "1111";
selb := ab(5) & ab(4);
if (dec(1) = '0') then
case selb is
when "00" => decb := "1110";
when "01" => decb := "1101";
when "10" => decb := "1011";
when "11" => decb := "0111";
when others => null;
end case;
end if;
wr0_l <= decb(0);
wr1_l <= decb(1);
wr2_l <= decb(2);
end process;
p_control_reg : process
variable ena : std_logic_vector(7 downto 0);
begin
-- 8 bit addressable latch 7K
-- (made into register)
-- 0 interrupt ena
-- 1 sound ena
-- 2 not used
-- 3 flip
-- 4 1 player start lamp
-- 5 2 player start lamp
-- 6 coin lockout
-- 7 coin counter
wait until rising_edge(clk);
if (ena_6 = '1') then
ena := "00000000";
if (iodec_out_l = '0') then
case ab(2 downto 0) is
when "000" => ena := "00000001";
when "001" => ena := "00000010";
when "010" => ena := "00000100";
when "011" => ena := "00001000";
when "100" => ena := "00010000";
when "101" => ena := "00100000";
when "110" => ena := "01000000";
when "111" => ena := "10000000";
when others => null;
end case;
end if;
if (watchdog_reset_l = '0') then
control_reg <= (others => '0');
else
for i in 0 to 7 loop
if (ena(i) = '1') then
control_reg(i) <= cpu_data_out(0);
end if;
end loop;
end if;
end if;
end process;
p_db_mux_comb : process(hcnt, cpu_data_out, rams_data_out)
begin
-- simplified data source for video subsystem
-- only cpu or ram are sources of interest
if (hcnt(1) = '0') then
sync_bus_db <= cpu_data_out;
else
sync_bus_db <= rams_data_out;
end if;
end process;
rom_data <= program_rom_dinl when cpu_addr(15) = '0' else program_rom_dinh;
rom_data_out <= rom_data(7 downto 6) & rom_data(3) & rom_data(4) & rom_data(5) & rom_data(2 downto 0) when MRTNT = '1' else rom_data;
p_cpu_data_in_mux_comb : process(cpu_addr, cpu_iorq_l, cpu_m1_l, sync_bus_wreq_l,
iodec_in0_l, iodec_in1_l, iodec_dipsw_l, cpu_vec_reg, sync_bus_reg, rom_data_out,
rams_data_out, in0_reg, in1_reg, dipsw_reg)
begin
-- simplifed again
if (cpu_iorq_l = '0') and (cpu_m1_l = '0') then
cpu_data_in <= cpu_vec_reg;
elsif (sync_bus_wreq_l = '0') then
cpu_data_in <= sync_bus_reg;
else
if (cpu_addr(15 downto 14) = "00") then -- ROM at 0000 - 3fff
cpu_data_in <= rom_data_out;
elsif (cpu_addr(15 downto 13) = "100") then -- ROM at 8000 - 9fff
cpu_data_in <= rom_data_out;
else
cpu_data_in <= rams_data_out;
if (iodec_in0_l = '0') then cpu_data_in <= in0_reg; end if;
if (iodec_in1_l = '0') then cpu_data_in <= in1_reg; end if;
if (iodec_dipsw_l = '0') then cpu_data_in <= dipsw_reg; end if;
end if;
end if;
end process;
u_rams : work.dpram generic map (12,8)
port map
(
clock_a => clk,
enable_a => ena_6,
wren_a => not sync_bus_r_w_l and not vram_l,
address_a => ab(11 downto 0),
data_a => cpu_data_out, -- cpu only source of ram data
clock_b => clk,
address_b => ab(11 downto 0),
q_b => rams_data_out
);
u_program_rom0 : work.dpram generic map (14,8)
port map
(
clock_a => clk,
wren_a => dn_wr and rom0_cs,
address_a => dn_addr(13 downto 0),
data_a => dn_data,
clock_b => clk,
address_b => cpu_addr(13 downto 0),
q_b => program_rom_dinl
);
u_program_rom1 : work.dpram generic map (14,8)
port map
(
clock_a => clk,
wren_a => dn_wr and rom1_cs,
address_a => dn_addr(13 downto 0),
data_a => dn_data,
clock_b => clk,
address_b => cpu_addr(13 downto 0),
q_b => program_rom_dinh
);
--
-- video subsystem
--
u_video : entity work.PACMAN_VIDEO
generic map (
MRTNT => MRTNT
)
port map (
I_HCNT => hcnt,
I_VCNT => vcnt,
--
I_AB => ab,
I_DB => sync_bus_db,
--
I_HBLANK => hblank,
I_VBLANK => vblank,
I_FLIP => control_reg(3),
I_WR2_L => wr2_l,
--
dn_addr => dn_addr,
dn_data => dn_data,
dn_wr => dn_wr,
--
O_RED => O_VIDEO_R,
O_GREEN => O_VIDEO_G,
O_BLUE => O_VIDEO_B,
--
ENA_6 => ena_6,
CLK => clk
);
--
O_RED => O_VIDEO_R,
O_GREEN => O_VIDEO_G,
O_BLUE => O_VIDEO_B,
--
ENA_6 => ena_6,
CLK => clk
);
O_HSYNC <= hSync;
O_VSYNC <= vSync;
O_VBLANK <= vblank;
O_HSYNC <= hSync;
O_VSYNC <= vSync;
--
--
-- audio subsystem
--
u_audio : entity work.PACMAN_AUDIO
port map (
I_HCNT => hcnt,
--
I_AB => cpu_addr(11 downto 0),
I_DB => cpu_data_out,
--
I_WR1_L => iodec_sn2_l,
I_WR0_L => iodec_sn1_l,
I_SOUND_ON => control_reg(1),
--
dn_addr => dn_addr,
dn_data => dn_data,
dn_wr => dn_wr,
--
O_AUDIO => O_AUDIO,
ENA_6 => ena_6,
CLK => clk
);
--O_HBLANK <= hblank;
O_VBLANK <= vblank;
--
--
-- audio subsystem
--
u_audio : entity work.PACMAN_AUDIO
port map (
I_HCNT => hcnt,
--
I_AB => ab,
I_DB => sync_bus_db,
--
I_WR1_L => wr1_l,
I_WR0_L => wr0_l,
I_SOUND_ON => control_reg(1),
--
dn_addr => dn_addr,
dn_data => dn_data,
dn_wr => dn_wr,
--
O_AUDIO => O_AUDIO,
ENA_6 => ena_6,
CLK => clk
);
end RTL;

View File

@@ -38,7 +38,6 @@
--
-- Revision list
--
-- version 004 Refactoring, 8 sprite support by Sorgelig
-- version 003 Jan 2006 release, general tidy up
-- version 001 initial release
--
@@ -47,36 +46,39 @@ library ieee;
use ieee.std_logic_unsigned.all;
use ieee.numeric_std.all;
library UNISIM;
entity PACMAN_VIDEO is
generic(
alt_transp : boolean := false
);
port (
I_HCNT : in std_logic_vector(8 downto 0);
I_VCNT : in std_logic_vector(8 downto 0);
--
vram_data : in std_logic_vector(7 downto 0);
sprite_xy : in std_logic_vector(7 downto 0);
--
I_HBLANK : in std_logic;
I_VBLANK : in std_logic;
I_FLIP : in std_logic;
O_HBLANK : out std_logic;
--
dn_addr : in std_logic_vector(15 downto 0);
dn_data : in std_logic_vector(7 downto 0);
dn_wr : in std_logic;
--
O_RED : out std_logic_vector(2 downto 0);
O_GREEN : out std_logic_vector(2 downto 0);
O_BLUE : out std_logic_vector(1 downto 0);
ENA_6 : in std_logic;
CLK : in std_logic
);
generic (
MRTNT : std_logic := '0' -- 1 to descramble Mr TNT ROMs, 0 otherwise
);
port (
I_HCNT : in std_logic_vector(8 downto 0);
I_VCNT : in std_logic_vector(8 downto 0);
--
I_AB : in std_logic_vector(11 downto 0);
I_DB : in std_logic_vector( 7 downto 0);
--
I_HBLANK : in std_logic;
I_VBLANK : in std_logic;
I_FLIP : in std_logic;
I_WR2_L : in std_logic;
--
dn_addr : in std_logic_vector(15 downto 0);
dn_data : in std_logic_vector(7 downto 0);
dn_wr : in std_logic;
--
O_RED : out std_logic_vector(2 downto 0);
O_GREEN : out std_logic_vector(2 downto 0);
O_BLUE : out std_logic_vector(1 downto 0);
ENA_6 : in std_logic;
CLK : in std_logic
);
end;
architecture RTL of PACMAN_VIDEO is
signal sprite_xy_ram_temp : std_logic_vector(7 downto 0);
signal dr : std_logic_vector(7 downto 0);
signal char_reg : std_logic_vector(7 downto 0);
@@ -84,20 +86,19 @@ architecture RTL of PACMAN_VIDEO is
signal char_match_reg : std_logic;
signal char_hblank_reg : std_logic;
signal char_hblank_reg_t1 : std_logic;
signal sprite_data : std_logic_vector(7 downto 0);
signal db_reg : std_logic_vector(7 downto 0);
signal xflip : std_logic;
signal yflip : std_logic;
signal obj_on : std_logic;
signal obj_on2 : std_logic;
signal ca : std_logic_vector(12 downto 0);
signal char_rom_5ef_dout : std_logic_vector(7 downto 0);
signal char_rom_5ef_buf : std_logic_vector(7 downto 0);
signal shift_regl : std_logic_vector(3 downto 0);
signal shift_regu : std_logic_vector(3 downto 0);
signal shift_op : std_logic_vector(1 downto 0);
signal shift_op_t1 : std_logic_vector(1 downto 0);
signal shift_sel : std_logic_vector(1 downto 0);
signal vout_obj_on : std_logic;
@@ -107,14 +108,15 @@ architecture RTL of PACMAN_VIDEO is
signal vout_hblank_t1 : std_logic;
signal vout_db : std_logic_vector(4 downto 0);
signal sprite_ram_ip : std_logic_vector(5 downto 0);
signal sprite_ram_op : std_logic_vector(5 downto 0);
signal sprite_addr : std_logic_vector(7 downto 0);
signal sprite_addr_t1 : std_logic_vector(7 downto 0);
signal cntr_ld : std_logic;
signal sprite_ram_ip : std_logic_vector(3 downto 0);
signal sprite_ram_op : std_logic_vector(3 downto 0);
signal ra : std_logic_vector(7 downto 0);
signal ra_t1 : std_logic_vector(7 downto 0);
signal lut_4a : std_logic_vector(7 downto 0);
signal lut_4a_t1 : std_logic_vector(7 downto 0);
signal sprite_ram_reg : std_logic_vector(5 downto 0);
signal sprite_ram_reg : std_logic_vector(3 downto 0);
signal video_op_sel : std_logic;
signal final_col : std_logic_vector(3 downto 0);
@@ -125,110 +127,170 @@ architecture RTL of PACMAN_VIDEO is
signal rom4a_cs : std_logic;
begin
prom_cs <= '1' when dn_addr(15 downto 14) = "11" else '0';
gfx_cs <= '1' when dn_addr(15 downto 13) = "100" else '0';
dr <= not sprite_xy when I_HBLANK = '1' else "11111111"; -- pull ups on board
-- ram enable is low when HBLANK_L is 0 (for sprite access) or
-- 2H is low (for cpu writes)
-- we can simplify this
dr <= not sprite_xy_ram_temp when I_HBLANK = '1' else "11111111"; -- pull ups on board
p_char_regs : process
variable sum : std_logic_vector(8 downto 0);
variable match : std_logic;
begin
wait until rising_edge (CLK);
if (I_HCNT(2 downto 0) = "011") and (ENA_6 = '1') then -- rising 4h
sprite_xy_ram : work.dpram generic map (4,8)
port map
(
clock_a => CLK,
enable_a => ENA_6,
wren_a => not I_WR2_L,
address_a => I_AB(3 downto 0),
data_a => I_DB,
-- 1f, 2f
sum := (I_VCNT(7 downto 0) & '1') + (dr & not I_HBLANK);
clock_b => CLK,
address_b => I_AB(3 downto 0),
q_b => sprite_xy_ram_temp
);
-- 3e
match := '0';
p_char_regs : process
variable inc : std_logic;
variable sum : std_logic_vector(8 downto 0);
variable match : std_logic;
begin
wait until rising_edge (CLK);
if (I_HCNT(2 downto 0) = "011") and (ENA_6 = '1') then -- rising 4h
inc := (not I_HBLANK);
if (sum(8 downto 5) = "1111") then
match := '1';
-- 1f, 2f
sum := (I_VCNT(7 downto 0) & '1') + (dr & inc);
-- 3e
match := '0';
if (sum(8 downto 5) = "1111") then
match := '1';
end if;
-- 1h
char_sum_reg <= sum(4 downto 1);
char_match_reg <= match;
char_hblank_reg <= I_HBLANK;
-- 4d
db_reg <= I_DB; -- character reg
end if;
end process;
-- 1h
char_sum_reg <= sum(4 downto 1);
char_match_reg <= match;
char_hblank_reg <= I_HBLANK;
-- 4d
sprite_data <= vram_data; -- character reg
end if;
end process;
xflip <= I_FLIP when char_hblank_reg = '0' else sprite_data(1);
yflip <= I_FLIP when char_hblank_reg = '0' else sprite_data(0);
obj_on <= char_match_reg or I_HCNT(8); -- 256h not 256h_l
ca(12) <= char_hblank_reg;
ca(11 downto 6) <= sprite_data(7 downto 2);
ca(5) <= sprite_data(1) when char_hblank_reg = '0' else char_sum_reg(3) xor xflip;
ca(4) <= sprite_data(0) when char_hblank_reg = '0' else I_HCNT(3);
ca(3) <= I_HCNT(2) xor yflip;
ca(2) <= char_sum_reg(2) xor xflip;
ca(1) <= char_sum_reg(1) xor xflip;
ca(0) <= char_sum_reg(0) xor xflip;
-- char roms
char_rom_5ef : work.dpram generic map (13,8)
port map
(
clock_a => clk,
wren_a => dn_wr and gfx_cs,
address_a => dn_addr(12 downto 0),
data_a => dn_data,
clock_b => clk,
address_b => ca,
q_b => char_rom_5ef_buf
);
p_char_shift : process
begin
-- 4 bit shift req
wait until rising_edge (CLK);
if (ENA_6 = '1') then
case shift_sel is
when "00" => null;
when "01" => shift_regu <= '0' & shift_regu(3 downto 1);
shift_regl <= '0' & shift_regl(3 downto 1);
when "10" => shift_regu <= shift_regu(2 downto 0) & '0';
shift_regl <= shift_regl(2 downto 0) & '0';
when "11" => shift_regu <= char_rom_5ef_buf(7 downto 4); -- load
shift_regl <= char_rom_5ef_buf(3 downto 0);
when others => null;
end case;
end if;
end process;
shift_sel(0) <= I_HCNT(0) and I_HCNT(1) when vout_yflip = '0' else '1';
shift_sel(1) <= '1' when vout_yflip = '0' else I_HCNT(0) and I_HCNT(1);
shift_op(0) <= shift_regl(3) when vout_yflip = '0' else shift_regl(0);
shift_op(1) <= shift_regu(3) when vout_yflip = '0' else shift_regu(0);
p_video_out_reg : process
begin
wait until rising_edge (CLK);
if (ENA_6 = '1') then
if (I_HCNT(2 downto 0) = "111") then
vout_obj_on <= obj_on;
vout_yflip <= yflip;
vout_hblank <= I_HBLANK;
vout_db(4 downto 0) <= vram_data(4 downto 0); -- colour reg
end if;
if I_HCNT(3 downto 0) = "0111" and (vout_hblank='1' or I_HBLANK='1' or vout_obj_on='0') then
sprite_addr <= dr;
p_flip_comb : process(char_hblank_reg, I_FLIP, db_reg)
begin
if (char_hblank_reg = '0') then
xflip <= I_FLIP;
yflip <= I_FLIP;
else
sprite_addr <= sprite_addr + "1";
xflip <= db_reg(1);
yflip <= db_reg(0);
end if;
end if;
end process;
end process;
p_char_addr_comb : process(db_reg, I_HCNT,
char_match_reg, char_sum_reg, char_hblank_reg,
xflip, yflip)
begin
obj_on <= char_match_reg or I_HCNT(8); -- 256h not 256h_l
ca(12) <= char_hblank_reg;
ca(11 downto 6) <= db_reg(7 downto 2);
-- 2h, 4e
if (char_hblank_reg = '0') then
ca(5) <= db_reg(1);
ca(4) <= db_reg(0);
else
ca(5) <= char_sum_reg(3) xor xflip;
ca(4) <= I_HCNT(3);
end if;
ca(3) <= I_HCNT(2) xor yflip;
ca(1) <= char_sum_reg(1) xor xflip;
-- descramble ROMs for Mr TNT (swap address lines A0 and A2)
if MRTNT = '1' then
ca(2) <= char_sum_reg(0) xor xflip;
ca(0) <= char_sum_reg(2) xor xflip;
else
ca(2) <= char_sum_reg(2) xor xflip;
ca(0) <= char_sum_reg(0) xor xflip;
end if;
end process;
-- descramble ROMs for Mr TNT (swap data lines D4 and D6)
char_rom_5ef_dout <= char_rom_5ef_buf(7) & char_rom_5ef_buf(4) & char_rom_5ef_buf(5) & char_rom_5ef_buf(6) & char_rom_5ef_buf(3 downto 0) when MRTNT = '1' else char_rom_5ef_buf;
-- char roms
char_rom_5ef : work.dpram generic map (13,8)
port map
(
clock_a => clk,
wren_a => dn_wr and gfx_cs,
address_a => dn_addr(12 downto 0),
data_a => dn_data,
clock_b => clk,
address_b => ca,
q_b => char_rom_5ef_buf
);
p_char_shift : process
begin
-- 4 bit shift req
wait until rising_edge (CLK);
if (ENA_6 = '1') then
case shift_sel is
when "00" => null;
when "01" => shift_regu <= '0' & shift_regu(3 downto 1);
shift_regl <= '0' & shift_regl(3 downto 1);
when "10" => shift_regu <= shift_regu(2 downto 0) & '0';
shift_regl <= shift_regl(2 downto 0) & '0';
when "11" => shift_regu <= char_rom_5ef_dout(7 downto 4); -- load
shift_regl <= char_rom_5ef_dout(3 downto 0);
when others => null;
end case;
end if;
end process;
p_char_shift_comb : process(I_HCNT, vout_yflip, shift_regu, shift_regl)
variable ip : std_logic;
begin
ip := I_HCNT(0) and I_HCNT(1);
if (vout_yflip = '0') then
shift_sel(0) <= ip;
shift_sel(1) <= '1';
shift_op(0) <= shift_regl(3);
shift_op(1) <= shift_regu(3);
else
shift_sel(0) <= '1';
shift_sel(1) <= ip;
shift_op(0) <= shift_regl(0);
shift_op(1) <= shift_regu(0);
end if;
end process;
p_video_out_reg : process
begin
wait until rising_edge (CLK);
if (ENA_6 = '1') then
if (I_HCNT(2 downto 0) = "111") then
vout_obj_on <= obj_on;
vout_yflip <= yflip;
vout_hblank <= I_HBLANK;
vout_db(4 downto 0) <= I_DB(4 downto 0); -- colour reg
end if;
end if;
end process;
rom4a_cs <= '1' when dn_addr(9 downto 8) = "01" else '0';
@@ -248,49 +310,78 @@ port map
);
cntr_ld <= '1' when (I_HCNT(3 downto 0) = "0111") and (vout_hblank='1' or vout_obj_on='0') else '0';
p_ra_cnt : process
begin
wait until rising_edge (CLK);
if (ENA_6 = '1') then
if (cntr_ld = '1') then
ra <= dr;
else
ra <= ra + "1";
end if;
end if;
end process;
u_sprite_ram : work.dpram generic map (8,6)
port map
(
clock_a => CLK,
enable_a => ENA_6,
wren_a => vout_obj_on_t1,
address_a => sprite_addr_t1,
data_a => sprite_ram_ip,
u_sprite_ram : work.dpram generic map (8,4)
port map
(
clock_a => CLK,
enable_a => ENA_6,
wren_a => vout_obj_on_t1,
address_a => ra_t1,
data_a => sprite_ram_ip,
clock_b => CLK,
enable_b => ENA_6,
address_b => ra,
q_b => sprite_ram_op
);
clock_b => CLK,
enable_b => ENA_6,
address_b => sprite_addr,
q_b => sprite_ram_op
);
sprite_ram_reg <= sprite_ram_op when vout_obj_on_t1 = '1' else "0000";
video_op_sel <= '1' when not (sprite_ram_reg = "0000") else '0';
sprite_ram_reg <= sprite_ram_op when vout_obj_on_t1 = '1' else "000000";
video_op_sel <= '0' when alt_transp and (sprite_ram_reg(1 downto 0) = "00") else
'0' when not alt_transp and (sprite_ram_reg(5 downto 2) = "0000") else
'1';
p_sprite_ram_ip_reg : process
begin
wait until rising_edge (CLK);
if (ENA_6 = '1') then
ra_t1 <= ra;
vout_obj_on_t1 <= vout_obj_on;
vout_hblank_t1 <= vout_hblank;
lut_4a_t1 <= lut_4a;
end if;
end process;
p_sprite_ram_ip_reg : process
begin
wait until rising_edge (CLK);
if (ENA_6 = '1') then
sprite_addr_t1 <= sprite_addr;
vout_obj_on_t1 <= vout_obj_on;
vout_hblank_t1 <= vout_hblank;
lut_4a_t1 <= lut_4a;
shift_op_t1 <= shift_op;
end if;
end process;
p_sprite_ram_ip_comb : process(vout_hblank_t1, video_op_sel, sprite_ram_reg, lut_4a_t1)
begin
-- 3a
if (vout_hblank_t1 = '0') then
sprite_ram_ip <= (others => '0');
else
if (video_op_sel = '1') then
sprite_ram_ip <= sprite_ram_reg;
else
sprite_ram_ip <= lut_4a_t1(3 downto 0);
end if;
end if;
end process;
sprite_ram_ip <= (others => '0') when vout_hblank_t1 = '0' else
sprite_ram_reg when video_op_sel = '1' else
lut_4a_t1(3 downto 0) & shift_op_t1;
p_video_op_comb : process(vout_hblank, I_VBLANK, video_op_sel, sprite_ram_reg, lut_4a)
begin
-- 3b
if (vout_hblank = '1') or (I_VBLANK = '1') then
final_col <= (others => '0');
else
if (video_op_sel = '1') then
final_col <= sprite_ram_reg; -- sprite
else
final_col <= lut_4a(3 downto 0);
end if;
end if;
end process;
final_col <= (others => '0') when (vout_hblank = '1') or (I_VBLANK = '1') else
sprite_ram_reg(5 downto 2) when video_op_sel = '1' else
lut_4a(3 downto 0);
-- assign video outputs from color LUT PROM
-- assign video outputs from color LUT PROM
rom7_cs <= '1' when dn_addr(9 downto 4) = "110000" else '0';
col_rom_7f : work.dpram generic map (4,8)
@@ -308,6 +399,4 @@ final_col <= (others => '0') when (vout_hblank = '1') or (I_VBLANK = '1') else
q_b(7 downto 6) => O_BLUE
);
O_HBLANK <= vout_hblank and vout_hblank_t1;
end architecture;

273
pacman_vram_addr.vhd Normal file
View File

@@ -0,0 +1,273 @@
--
-- A simulation model of Pacman hardware
-- Copyright (c) MikeJ & CarlW - January 2006
--
-- 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 CODE 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.
--
-- You are responsible for any legal issues arising from your use of this code.
--
-- The latest version of this file can be found at: www.fpgaarcade.com
--
-- Email pacman@fpgaarcade.com
--
-- Revision list
--
-- version 003 Jan 2006 release, general tidy up
-- version 001 initial release
--
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use ieee.numeric_std.all;
entity X74_157 is
port (
Y : out std_logic_vector (3 downto 0);
B : in std_logic_vector (3 downto 0);
A : in std_logic_vector (3 downto 0);
G : in std_logic;
S : in std_logic
);
end;
architecture RTL of X74_157 is
begin
p_y_comb : process(S,G,A,B)
begin
for i in 0 to 3 loop
-- quad 2 line to 1 line mux (true logic)
if (G = '1') then
Y(i) <= '0';
else
if (S = '0') then
Y(i) <= A(i);
else
Y(i) <= B(i);
end if;
end if;
end loop;
end process;
end RTL;
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
entity X74_257 is
port (
Y : out std_logic_vector (3 downto 0);
B : in std_logic_vector (3 downto 0);
A : in std_logic_vector (3 downto 0);
S : in std_logic
);
end;
architecture RTL of X74_257 is
signal ab : std_logic_vector (3 downto 0);
begin
Y <= ab; -- no tristate
p_ab : process(S,A,B)
begin
for i in 0 to 3 loop
if (S = '0') then
AB(i) <= A(i);
else
AB(i) <= B(i);
end if;
end loop;
end process;
end RTL;
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use ieee.numeric_std.all;
entity PACMAN_VRAM_ADDR is
port (
AB : out std_logic_vector (11 downto 0);
H256_L : in std_logic;
H128 : in std_logic;
H64 : in std_logic;
H32 : in std_logic;
H16 : in std_logic;
H8 : in std_logic;
H4 : in std_logic;
H2 : in std_logic;
H1 : in std_logic;
V128 : in std_logic;
V64 : in std_logic;
V32 : in std_logic;
V16 : in std_logic;
V8 : in std_logic;
V4 : in std_logic;
V2 : in std_logic;
V1 : in std_logic;
FLIP : in std_logic
);
end;
architecture RTL of PACMAN_VRAM_ADDR is
signal v128p : std_logic;
signal v64p : std_logic;
signal v32p : std_logic;
signal v16p : std_logic;
signal v8p : std_logic;
signal h128p : std_logic;
signal h64p : std_logic;
signal h32p : std_logic;
signal h16p : std_logic;
signal h8p : std_logic;
signal sel : std_logic;
signal y157 : std_logic_vector (11 downto 0);
component X74_157
port (
Y : out std_logic_vector (3 downto 0);
B : in std_logic_vector (3 downto 0);
A : in std_logic_vector (3 downto 0);
G : in std_logic;
S : in std_logic
);
end component;
component X74_257
port (
Y : out std_logic_vector (3 downto 0);
B : in std_logic_vector (3 downto 0);
A : in std_logic_vector (3 downto 0);
S : in std_logic
);
end component;
begin
p_vp_comb : process(FLIP, V8, V16, V32, V64, V128)
begin
v128p <= FLIP xor V128;
v64p <= FLIP xor V64;
v32p <= FLIP xor V32;
v16p <= FLIP xor V16;
v8p <= FLIP xor V8;
end process;
p_hp_comb : process(FLIP, H8, H16, H32, H64, H128)
begin
H128P <= FLIP xor H128;
H64P <= FLIP xor H64;
H32P <= FLIP xor H32;
H16P <= FLIP xor H16;
H8P <= FLIP xor H8;
end process;
p_sel : process(H16, H32, H64)
begin
sel <= not((H32 xor H16) or (H32 xor H64));
end process;
--p_oe257 : process(H2)
--begin
-- oe <= not(H2);
--end process;
U6 : X74_157
port map(
Y => y157(11 downto 8),
B(3) => '0',
B(2) => H4,
B(1) => h64p,
B(0) => h64p,
A => "1111",
G => '0',
S => sel
);
U5 : X74_157
port map(
Y => y157(7 downto 4),
B(3) => h64p,
B(2) => h64p,
B(1) => h8p,
B(0) => v128p,
A => "1111",
G => '0',
S => sel
);
U4 : X74_157
port map(
Y => y157(3 downto 0),
B(3) => v64p,
B(2) => v32p,
B(1) => v16p,
B(0) => v8p,
A(3) => H64,
A(2) => H32,
A(1) => H16,
A(0) => H4,
G => '0',
S => sel
);
U3 : X74_257
port map(
Y => AB(11 downto 8),
B(3) => '0',
B(2) => H4,
B(1) => v128p,
B(0) => v64p,
A => y157(11 downto 8),
S => H256_L
);
U2 : X74_257
port map(
Y => AB(7 downto 4),
B(3) => v32p,
B(2) => v16p,
B(1) => v8p,
B(0) => h128p,
A => y157(7 downto 4),
S => H256_L
);
U1 : X74_257
port map(
Y => AB(3 downto 0),
B(3) => h64p,
B(2) => h32p,
B(1) => h16p,
B(0) => h8p,
A => y157(3 downto 0),
S => H256_L
);
end RTL;