I build a simple nes cart to run some mappers. Alread make MMC1, MMC3, VRC2b, but MMC2 and Sunsoft FME-7 it's hard.
Can someone help me to identify where I can go wrong? I didn't do the IRQ part.
The code above is from Sunsoft mapper 69 without sound.
----------------------------------------------------------------------------------
-- Company:
-- Engineer:
--
-- Create Date: 14:50:37 04/11/2021
-- Design Name:
-- Module Name: Sunsoft - Behavioral
-- Project Name:
-- Target Devices:
-- Tool versions:
-- Description:
--
-- Dependencies:
--
-- Revision:
-- Revision 0.01 - File Created
-- Additional Comments:
--
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
use IEEE.NUMERIC_STD.ALL;
-- Uncomment the following library declaration if instantiating
-- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;
entity Sunsoft is
Port (
M2 : in STD_LOGIC;
romsel : in std_logic;
-- CPU in
cpu_rw_i : in STD_LOGIC;
cpu_addr_i : in STD_LOGIC_VECTOR(14 DOWNTO 0);
cpu_data_i : in STD_LOGIC_VECTOR(7 DOWNTO 0);
-- CPU out
cpu_addr_o : out STD_LOGIC_VECTOR(18 downto 13);
cpu_wr_o : out STD_LOGIC;
cpu_rd_o : out STD_LOGIC;
cpu_rom_ce : out STD_LOGIC;
cpu_ram_ce : out STD_LOGIC;
-- PPU in
ppu_addr_i : in STD_LOGIC_VECTOR(13 downto 10);
ppu_rd_i : in STD_LOGIC;
ppu_wr_i : in STD_LOGIC;
-- PPU out
ppu_addr_o : out STD_LOGIC_VECTOR(18 downto 10);
ppu_rom_ce : out STD_LOGIC;
ppu_ram_ce : out STD_LOGIC;
ciram_a10 : out STD_LOGIC;
ciram_ce : out STD_LOGIC;
irq : out STD_LOGIC
);
end Sunsoft;
architecture Behavioral of Sunsoft is
-- PRG-ROM Max 128kB 8kB window (A16, A15, A14, A13)
type cpu_t is array(0 to 3) of unsigned(3 downto 0);
-- PRG-ROM Max 256kB 1kB window (A17, A16, A15, A14, A13, A12, A11, A10)
type ppu_t is array(0 to 7) of unsigned(7 downto 0);
signal prg_bank : cpu_t;
signal ppu_bank : ppu_t;
signal reg_sel : integer range 0 to 15 := 0;
signal prg_aout : unsigned(3 downto 0) := "0000";
signal ppu_aout : unsigned(7 downto 0) := "00000000";
signal mirroring : unsigned(1 downto 0);
begin
process
begin
wait until (falling_edge(romsel));
if(cpu_rw_i = '0') then
case(cpu_addr_i(14 downto 12)) is
-- $8000-$9FFF
when "000" | "001"=> reg_sel <= to_integer(unsigned(cpu_data_i(3 downto 0)));
-- $A000-$BFFF
when "010" | "011" =>
case reg_sel is
-- Character banks
when 0 to 7 => ppu_bank(reg_sel) <= unsigned(cpu_data_i);
-- Programmer banks
when 8 to 11 => prg_bank(reg_sel-8) <= unsigned(cpu_data_i(3 downto 0));
-- Mirroring control
when 12 => mirroring <= unsigned(cpu_data_i(1 downto 0));
-- Controls IRQ
when 13 to 15 => null;
end case;
when others => null;
end case;
end if;
end process;
cpu_wr_o <= cpu_rw_i;
cpu_rd_o <= not cpu_rw_i;
cpu_rom_ce <=
'0' when ((cpu_rw_i = '1' and cpu_addr_i(14 downto 13) = "11") and M2 = '1') else
'0' when (cpu_rw_i = '1' and romsel = '0') else '1';
cpu_ram_ce <= '1';
cpu_addr_o <= "00" & std_logic_vector(prg_aout);
with ((not romsel) & cpu_addr_i(14 downto 13)) select prg_aout <=
prg_bank(0) when "011", -- $6000
prg_bank(1) when "100", -- $8000
prg_bank(2) when "101", -- $A000
prg_bank(3) when "110", -- $C000
"1111" when "111", -- $E000 - Fixed last
"1111" when others;
ppu_aout <= ppu_bank(to_integer(unsigned(ppu_addr_i(12 downto 10))));
ppu_addr_o <= "0" & std_logic_vector(ppu_aout);
ppu_rom_ce <= '0' when (ppu_addr_i(13) = '0' and ppu_rd_i = '0') else '1';
ppu_ram_ce <= '1';
ciram_a10 <= ppu_addr_i(10) when mirroring = "00" else
ppu_addr_i(11) when mirroring = "01" else
mirroring(0);
ciram_ce <= not ppu_addr_i(13);
irq <= 'Z';
end Behavioral;
oh, sorry, i was doing tests and i didn’t go back to rising_edge.
The cpu_rom_ce wire and cpu_addr_out program banks is right?
I'm not sure if I calculated the A15 correctly.
the cpld is a Xl95144xl
The game tested is Mr. Gimmick.
entity Sunsoft is
Port (
M2 : in STD_LOGIC;
romsel : in std_logic;
-- CPU in
cpu_rw_i : in STD_LOGIC;
cpu_addr_i : in STD_LOGIC_VECTOR(14 DOWNTO 0);
cpu_data_i : in STD_LOGIC_VECTOR(7 DOWNTO 0);
-- CPU out
cpu_addr_o : out STD_LOGIC_VECTOR(18 downto 13);
cpu_wr_o : out STD_LOGIC;
cpu_rd_o : out STD_LOGIC;
cpu_rom_ce : out STD_LOGIC;
cpu_ram_ce : out STD_LOGIC;
-- PPU in
ppu_addr_i : in STD_LOGIC_VECTOR(13 downto 10);
ppu_rd_i : in STD_LOGIC;
ppu_wr_i : in STD_LOGIC;
-- PPU out
ppu_addr_o : out STD_LOGIC_VECTOR(18 downto 10);
ppu_rom_ce : out STD_LOGIC;
ppu_ram_ce : out STD_LOGIC;
ciram_a10 : out STD_LOGIC;
ciram_ce : out STD_LOGIC;
irq : out STD_LOGIC
);
end Sunsoft;
architecture Behavioral of Sunsoft is
-- PRG-ROM Max 256kB 8kB window (A17, A16, A15, A14, A13)
type cpu_t is array(0 to 3) of unsigned(4 downto 0);
-- PRG-ROM Max 256kB 1kB window (A17, A16, A15, A14, A13, A12, A11, A10)
type ppu_t is array(0 to 7) of unsigned(7 downto 0);
signal prg_bank : cpu_t;
signal ppu_bank : ppu_t;
signal reg_sel : integer range 0 to 15 := 0;
signal prg_aout : unsigned(4 downto 0) := "00000";
signal ppu_aout : unsigned(7 downto 0) := "00000000";
signal mirroring : unsigned(1 downto 0);
begin
process
begin
wait until (rising_edge(romsel));
if(cpu_rw_i = '0') then
case(cpu_addr_i(14 downto 12)) is
-- $8000-$9FFF
when "000" | "001"=> reg_sel <= to_integer(unsigned(cpu_data_i(3 downto 0)));
-- $A000-$BFFF
when "010" | "011" =>
case reg_sel is
-- Character banks
when 0 to 7 => ppu_bank(reg_sel) <= unsigned(cpu_data_i);
-- Programmer banks
when 8 to 11 => prg_bank(reg_sel - 8)<= unsigned(cpu_data_i(4 downto 0));
-- Mirroring control
when 12 => mirroring <= unsigned(cpu_data_i(1 downto 0));
-- Controls IRQ
when 13 to 15 => null;
end case;
when others => null;
end case;
end if;
end process;
cpu_wr_o <= cpu_rw_i;
cpu_rd_o <= not cpu_rw_i;
cpu_rom_ce <=
'0' when ((cpu_rw_i = '1' and cpu_addr_i(14 downto 13) = "11") and M2 = '1') else
'0' when (cpu_rw_i = '1' and romsel = '0') else '1';
cpu_ram_ce <= '1';
cpu_addr_o <= "0" & std_logic_vector(prg_aout);
with ((not romsel) & cpu_addr_i(14 downto 13)) select prg_aout <=
prg_bank(0) when "011", -- $6000
prg_bank(1) when "100", -- $8000
prg_bank(2) when "101", -- $A000
prg_bank(3) when "110", -- $C000
"11111" when "111", -- $E000 - Fixed last
"00000" when others;
ppu_aout <= ppu_bank(to_integer(unsigned(ppu_addr_i(12 downto 10))));
ppu_addr_o <= "0" & std_logic_vector(ppu_aout);
ppu_rom_ce <= '0' when (ppu_addr_i(13) = '0' and ppu_rd_i = '0') else '1';
ppu_ram_ce <= '1';
ciram_a10 <= ppu_addr_i(10) when mirroring = "00" else
ppu_addr_i(11) when mirroring = "01" else
mirroring(0);
ciram_ce <= not ppu_addr_i(13);
irq <= 'Z';
end Behavioral;
Adjusted, but nothing. I'm blind, I don't see where I can go wrong.
I got just a Black screen, nothing more. To night ill test a Batman, and impl. The irq.
The mmc3 without irq running Mario work, só i think this work too,, but no 100% right about.
About no romsel on romce decode, its on Second line else.
On First line used without because need enable on $6000 and romsel only cover $8000+.
But this is first mapper i try make covering $6000 romce.
Tried batman Japan, got same blackcreen. no garbage, nothing.
About irq, workking on it, but at now, cannot fit. trying do a better code.
tryed too calc A15. Nothing change on screen.