Skip to content

Commit

Permalink
First version
Browse files Browse the repository at this point in the history
  • Loading branch information
nand2mario committed Sep 15, 2022
0 parents commit 3e79993
Show file tree
Hide file tree
Showing 55 changed files with 72,664 additions and 0 deletions.
49 changes: 49 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# NESTang

<img src="doc/images/setup.jpg" width=400>

NESTang is a Nintendo Entertainment System emulator on the affordable [Sipeed Tang Primer 20K](https://wiki.sipeed.com/hardware/en/tang/tang-primer-20k/primer-20k.html) FPGA board. The core logic comes from [fpganes](https://github.com/strigeus/fpganes). I added SDRAM and HDMI interfaces and other things.

This is still a work in progress. Here's what works.

* Majority of games I tested work.
* 720p HDMI video and sound output.
* PC-side loader program for game loading and controller input.
* Cycle accurate emulation quality as we nearly recreated the NES circuits.
* Needs a MiSTer SDRAM module. Similar to [MiSTer](https://misterfpga.org/), SDRAM is needed for its low access latency required by emulation.

## Setup

Interested? Here's what you need:

* Sipeed Tang Primer 20K with Lite Carrier Board. About $30.
* Mister SDRAM module: [aliexpress](https://www.aliexpress.com/w/wholesale-mister-fpga-sdram.html) and [taobao](https://s.taobao.com/search?q=mister+sdram). I use a 128MB XSD v2.5. Others should also work as we only need 8MB of space.
* Muse-Lab HDMI PMod: [aliexpress](https://www.aliexpress.com/item/3256804122775243.html) and [taobao](https://item.taobao.com/item.htm?id=671021594308).
* Wires! These modules are not pin-to-pin matches for the board. So unfortunately we need wires to connect things up.

Now wire it up following [wiring instructions](doc/wiring.md).

Then it's time to play some NES games,
* Download a [NESTang release](https://github.com/nand2mario/nestang/releases/).
* Start **Gowin Programmer**, and program `nestang.fs` to the board. If you see a colorful NES palette, then your setup is working.
* Connect your game controller/controllers to your PC. I use a pair of old Xbox 360 controllers.
* Run `loader.exe -c COM4 game.nes` (replace COM4 with your port number) to load the game `game.nes` and run it.

Hurrah! and enjoy.

## Next steps

Here are what I may work on when I get time. No promise though. Suggestions and pull requests are welcome!
* A way to work without a PC.
* Support more games.
* Easy hardware setup without wires etc, and an enclosure.
* Cheats support.
* Saves and loads.

## Special Thanks

* [fpganes](https://github.com/strigeus/fpganes) by Ludvig Strigeus.
* [hdl-util/hdmi](https://github.com/hdl-util/hdmi) by Sameer Puri.

nand2mario
2022.9
Binary file added doc/images/setup.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added doc/images/wiring.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
47 changes: 47 additions & 0 deletions doc/wiring.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@

# Wiring instructions for NESTang

This is for two modules:
1. SDRAM memory module: Mister SDRAM XS-D v2.5 (128MB). Chip is 2 x Alliance memory AS4C32M16SB-7TIN. Only the first chip is used. So total available size is 64MB.
2. HDMI Pmod module: Muse-Lab PMOD-HDMI 1.0.

Both modules are not directly pin compatible with Tang 20K. So without spinning a custom PCB, the easiest way is to connect the pins manually with wires (luckily we are not working at high clock speed). For the memory module you probably need 40 male-female Dupont wires. For the HDMI module, you need 10 female-female wires.

Wiring diagram is as follow. For example,
- Top GPIO pin #1 (3V3) to Mister pin #29 (3V3)
- Top GPIO pin #3 (N6) to Mister pin #1 (DQ0)
- Bottom GPIO pin #1 (H12) to HDMI PMod pin HDMI_CKN (not drawn, but the module has labels)

```
Mister SDRAM XS/D v2.5 Top GPIO(J3) Bottom GPIO
+-----+ +-----+ +-----+
DQ0 |1 2| DQ1 3V3 29 3V3|1 2|GND 12 GND 3V3|1 2|3V3
DQ2 |3 4| DQ3 DQ0 1 N6|3 4|N7 2 DQ1 |3 4|
DQ4 |5 6| DQ5 DQ2 3 B11|5 6|A12 4 DQ3 |5 6|GND
DQ6 |7 8| DQ7 DQ4 5 L9|7 8|N8 6 DQ5 |7 8|
DQ15 |9 10| DQ14 DQ6 7 R9|9 10|N9 8 DQ7 |9 10|
|11 12| GND A6|11 12|A7 |11 12|
DQ13 |13 14| DQ12 C6|13 14|B8 |13 14|
DQ11 |15 16| DQ10 DQ15 9 C10|15 16|GND |15 16|
DQ9 |17 18| DQ8 DQ13 13 A11|17 18|C11 10 DQ14 |17 18|
A12 |19 20| CLK DQ11 15 B12|19 20|C12 14 DQ12 |19 20|
A9 |21 22| A11 DQ9 17 B13|21 22|A14 16 DQ10 HDMI_CKN H12|21 22|G11 HDMI_CKP
A7 |23 24| A8 A12 19 B14|23 24|A15 18 DQ8 HDMI_D0P H13|23 24|J12 HDMI_D0N
A5 |25 26| A6 A9 21 D14|25 26|E15 20 CLK HDMI_D1N K12|25 26|K13 HDMI_D1P
WE |27 28| A4 A7 23 F16|27 28|F14 22 A11 HDMI_D2N L13|27 28|K11 HDMI_D2P
3V3 |29 30| GND A5 25 G15|29 30|G14 24 A8 |29 30|
CAS |31 32| RAS WE 27 J14|31 32|J16 26 A6 |31 32|
CS1 |33 34| BA0 CAS 31 G12|33 34|F13 28 A4 |33 34|
BA1 |35 36| A10 CS1 33 M14|35 36|M15 32 RAS |35 36|K13 38 A1
A0 |37 38| A1 BA1 35 T14|37 38|R13 34 BA0 |37 38|K11 39 A2
A2 |39 40| A3 A0 37 P13|39 40|R12 36 A10 |39 40|T12 40 A3
+-----+ +-----+ +-----+
```

The end result will look something like this.

<img src='images/wiring.jpg' width=400>

Ugh! Ugly but works...

(#1 pins for both GPIO banks are on the left. The #1 pin for the SDRAM module is also on the left and facing the camera.)
31 changes: 31 additions & 0 deletions loader/loader.sln
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.3.32825.248
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "loader", "loader.vcxproj", "{C130226A-CC32-48C9-B9C7-39F1E4C35C7C}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{C130226A-CC32-48C9-B9C7-39F1E4C35C7C}.Debug|x64.ActiveCfg = Debug|x64
{C130226A-CC32-48C9-B9C7-39F1E4C35C7C}.Debug|x64.Build.0 = Debug|x64
{C130226A-CC32-48C9-B9C7-39F1E4C35C7C}.Debug|x86.ActiveCfg = Debug|Win32
{C130226A-CC32-48C9-B9C7-39F1E4C35C7C}.Debug|x86.Build.0 = Debug|Win32
{C130226A-CC32-48C9-B9C7-39F1E4C35C7C}.Release|x64.ActiveCfg = Release|x64
{C130226A-CC32-48C9-B9C7-39F1E4C35C7C}.Release|x64.Build.0 = Release|x64
{C130226A-CC32-48C9-B9C7-39F1E4C35C7C}.Release|x86.ActiveCfg = Release|Win32
{C130226A-CC32-48C9-B9C7-39F1E4C35C7C}.Release|x86.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {677CB93D-04E0-4092-A4E8-28123CB373BF}
EndGlobalSection
EndGlobal
141 changes: 141 additions & 0 deletions loader/loader.vcxproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>16.0</VCProjectVersion>
<Keyword>Win32Proj</Keyword>
<ProjectGuid>{c130226a-cc32-48c9-b9c7-39f1e4c35c7c}</ProjectGuid>
<RootNamespace>loader</RootNamespace>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>winmm.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="nes_loader.cpp" />
<ClCompile Include="stdafx.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="stdafx.h" />
<ClInclude Include="targetver.h" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
Loading

0 comments on commit 3e79993

Please sign in to comment.