XiNESA Nintendo Entertainment System simulator coded in pureVHDLWilliam Blinn, Dave Coulthart, Jay Fernandez, Neel Goyal, Jeff Lin1Table of ContentsChapter 1 – Introduction……………………………………………………………………2Chapter 2 – Project Design………………………………………………………………3Chapter 3 – What Worked, What Didn’t Work……………………15Chapter 4 – Who Did What…………………………………………………………………17Chapter 5 – Lessons & Advice………………………………………………………18Chapter 6 – Source Code……………………………………………………………………23References………………………………………………………………………………………………………562Chapter 1 – Introduction (Project Proposal)XiNES is a Nintendo Entertainment System simulator coded in pureVHDL and ported to the XSB-300E board, which utilizes a Xilinx SpartanFPGA. The NES itself consists of three main parts: a customized 6502CPU, a Picture Processing Unit (PPU), and a memory hierarchy thatincludes the actual game ROM. Our initial goal was to implement all ofthese to get a single commercial game to run at full speed on the board.Due to time constraints and difficulties in implementing the complex PPUwe decided to simplify the PPU. Our PPU now draws a test ROM consistingof a single frame.The main bulk of the project was spent implementing the system'sPPU. We used all resources available to us, including onlinedocumentation, open source emulators, and even patented schematics(all which is cited and credited). The 6502 was obtained by using a free,open-source VHDL implementation of the 6502, called Free-6502. Ourgoal was to connect our PPU and this 6502 implementation in some waysuch that the test ROM would display the frame.Our main objective in this project was graphics implementation. Wedid not have time to implement sound or to connect a controller.3Chapter 2 – Project Design6502 ProcessorThe 6502 processor is the main CPU of the NES. The VHDLcomponent declaration of the 6502 is:component core_6502 port (clk :in std_logic; reset :in std_logic; irq :in std_logic; nmi :in std_logic; addr :out std_logic_vector (15 downto 0); din :in std_logic_vector (7 downto 0); dout :out std_logic_vector (7 downto 0); dout_oe :out std_logic; wr :out std_logic; rd :out std_logic; sync :out std_logic );end component;Signal descriptionsclk: The main system clock. All synchronous signalsare clocked off the rising edge of clk.reset: An active high reset signal, asynchronous toclk.irq: An active high, level triggered, asynchronous,interrupt input.nmi: A rising edge triggered non-maskable interruptinput.addr: The address bus output.din: Data bus inputdout: Data bus outputdout_oe: Data bus output enable, used to controlexternal tri-state buffers. Active high.wr: An active high write signalrd: An active high read signal.sync: High during the first byte of an instructionfetch.The 6502 processor contains 64K of memory. There are four banksof 2K for RAM, 12K for registers, 4K for expansion modules, 8K for4WRAM (which is used for games that allow saving), and two banks of 16Kfor Program ROM.Registers $2006 and $2007 are used for reading from and writingdata to the VRAM. The address in VRAM to be read from or written to isspecified in $2006 and the data to be read or written is specified in$2007. When reading from register $2007, the first read is invalid andneeds to be discarded.Multi-Memory ControllersMulti-Memory Controllers (MMCs) are used in cartridges foraddressing extra memory. The 6502 processor's memory limit is 64K, ofwhich 32K is used for the Program ROM. The PPU's VRAM memory limit is16K. If either the 6502 or the PPU’s memory limit is exceeded, an MMC isneeded to address the extra memory.Of note, even though the 6502 supports 64K memory, there is only32K available for Program ROM, so ROMs larger than 32K will require theuse of an MMC.The Program ROM memory region on the CPU is divided into twobanks of 16K each. If a ROM is smaller than 16K, it will load into theupper bank of memory. Larger ROMs will load into the lower 16K bank aswell.The ROMWe initially decided that the ROM image that we wanted to use wasthe game Mario Brothers. It was chosen for its simplicity. The ROM is less5than 16K in size, which means that it does not require the use of anMMC. The game also has no scrolling involved so there will be a lesscomplex PPU. We then had our problem with sprites and frames so wedecided to use a test ROM that is one frame and displays “R G B” in bigletters in its respective colors.Memory HierarchyThere are two main memory components of the NES – the 64 KBmain memory interfacing with the 6502 CPU and the 16 KB Video RAM(VRAM) used by the Picture Processing Unit (PPU). Because of these highmemory requirements, the two memories will be stored in SRAM. The256-byte Sprite RAM, which is not a part of either the CPU or PPU addressspace, is the remaining piece of the memory hierarchy of the NES.CPU MemoryThe NES’s CPU memory is divided for different uses as follows:StartingAddressSize(bytes)Use0x00002KRAM0x08002KRAM (mirrored from 0x0000)0x10002KRAM (mirrored from 0x0000)0x18002KRAM (mirrored from 0x0000)0x200012KRegisters0x50004KExpansion Modules0x60008KWriteable RAM (WRAM)0x800016KProgram ROM (PRG-ROM) (Lower)0xC00016KPRG-ROM (Upper)While we will provide the entire CPU memory address space (toavoid the need for complicated address translation), memory associated6with certain advanced functionality will remain unused. In particular, theWRAM used by games for saving state and the expansion modulememory will be unused. The PRG-ROM is used to hold the actual gamecode. Because our simplified design does not include a Multi-MemoryController only the Upper PRG-ROM will be used to hold games up to 16KB in size.The registers are used primarily for communicating with the PPU,outputting sound, and managing the joystick. The PPU-associatedregisters are explained further in the PPU section of the document, whilethe sound registers and the joystick registers will be ignored because wedid
View Full Document