Sunsoft FME-7 VHDL

Discuss hardware-related topics, such as development cartridges, CopyNES, PowerPak, EPROMs, or whatever.

Moderator: Moderators

Post Reply
squall926
Posts: 35
Joined: Wed Jan 03, 2018 3:50 pm

Sunsoft FME-7 VHDL

Post by squall926 »

Hello!

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.

Code: Select all

----------------------------------------------------------------------------------
-- 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;

Thanks!!!
lidnariq
Posts: 11432
Joined: Sun Apr 13, 2008 11:12 am

Re: Sunsoft FME-7 VHDL

Post by lidnariq »

squall926 wrote: Sun Apr 11, 2021 7:52 pm wait until (falling_edge(romsel));
[...]
when 0 to 7 => ppu_bank(reg_sel) <= unsigned(cpu_data_i);
Data bus is not valid on the falling edge of /ROMSEL!

You must wait for the rising edge, or approximately 70ns after the falling edge. See: viewtopic.php?p=244126#p244126
squall926
Posts: 35
Joined: Wed Jan 03, 2018 3:50 pm

Re: Sunsoft FME-7 VHDL

Post by squall926 »

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.
lidnariq
Posts: 11432
Joined: Sun Apr 13, 2008 11:12 am

Re: Sunsoft FME-7 VHDL

Post by lidnariq »

squall926 wrote: Sun Apr 11, 2021 7:52 pm -- PRG-ROM Max 128kB 8kB window (A16, A15, A14, A13)
type cpu_t is array(0 to 3) of unsigned(3 downto 0);
But Mr. Gimmick has 256KB PRG?

The other things you ask about tentatively look ok
squall926
Posts: 35
Joined: Wed Jan 03, 2018 3:50 pm

Re: Sunsoft FME-7 VHDL

Post by squall926 »

Code: Select 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 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.
lidnariq
Posts: 11432
Joined: Sun Apr 13, 2008 11:12 am

Re: Sunsoft FME-7 VHDL

Post by lidnariq »

What symptoms do you see?

Are you sure Mr. Gimmick can start without the IRQ?
User avatar
krzysiobal
Posts: 1037
Joined: Sun Jun 12, 2011 12:06 pm
Location: Poland
Contact:

Re: Sunsoft FME-7 VHDL

Post by krzysiobal »

This is NOT good (no romsel taken into account when decoding), but hopefully for a game without WRAM won't matter:

Code: Select all

cpu_rom_ce	<= 
		'0' when ((cpu_rw_i = '1' and cpu_addr_i(14 downto 13) = "11") and M2 = '1') else 
squall926
Posts: 35
Joined: Wed Jan 03, 2018 3:50 pm

Re: Sunsoft FME-7 VHDL

Post by squall926 »

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. :lol:
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.
squall926
Posts: 35
Joined: Wed Jan 03, 2018 3:50 pm

Re: Sunsoft FME-7 VHDL

Post by squall926 »

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.

Code: Select all

	process(M2) begin
		if(rising_edge(M2)) then
			if(romsel = '0') then
				cpu_a15 <= '1';
			else
				cpu_a15 <= '0';
			end if;
		end if;
	end process;
Any ideia is wellcome.
lidnariq
Posts: 11432
Joined: Sun Apr 13, 2008 11:12 am

Re: Sunsoft FME-7 VHDL

Post by lidnariq »

You can't regenerate A15 in a synchronous fashion; you need some kind of delay to wait the right amount after M2 to then check whether /ROMSEL fell.

(edit: The MMC3 abused 11 inverters in series ... or maybe a ton more ... to generate this signal for its RAM enable - see page 3 of the schematics here https://github.com/furrtek/VGChips/blob ... matics.PDF )
User avatar
Ben Boldt
Posts: 1149
Joined: Tue Mar 22, 2016 8:27 pm
Location: Minnesota, USA

Re: Sunsoft FME-7 VHDL

Post by Ben Boldt »

Be aware, if you get FME-7 working, you can add an AY-3-8910 chip with very simple logic to get Sunsoft 5B audio.
Post Reply