More FPGA bitstream updates

This commit is contained in:
spicyjpeg 2024-06-27 08:35:02 +02:00
parent a1f3312aa2
commit c4ff4eb62e
No known key found for this signature in database
GPG Key ID: 5CC87404C01DF393
13 changed files with 835 additions and 367 deletions

View File

@ -35,7 +35,9 @@ make \
BUILD=Release \ BUILD=Release \
PREFIX="$TOOLCHAIN_DIR/bin/mipsel-none-elf" \ PREFIX="$TOOLCHAIN_DIR/bin/mipsel-none-elf" \
FORMAT=elf32-littlemips \ FORMAT=elf32-littlemips \
FASTBOOT=true \ BOARD=system573 \
BOOT_MODE=psexe \
SPLASH_SCREEN=true \
EMBED_PSEXE="$PROJECT_DIR/build/${RELEASE_NAME}-tiny.psexe" \ EMBED_PSEXE="$PROJECT_DIR/build/${RELEASE_NAME}-tiny.psexe" \
|| exit 2 || exit 2

Binary file not shown.

View File

@ -79,28 +79,27 @@ Note that the number is different from the one used by Konami (`0x1234`).
| 14 | W | Output D2 (0 = grounded, 1 = high-z) | | 14 | W | Output D2 (0 = grounded, 1 = high-z) |
| 15 | W | Output D3 (0 = grounded, 1 = high-z) | | 15 | W | Output D3 (0 = grounded, 1 = high-z) |
### `0x1f6400ee` (FPGA, DDR/Mambo bitstream): **1-wire bus** ### `0x1f6400ee`: **1-wire bus**
When read: When read:
| Bits | RW | Description | | Bits | RW | Description |
| ----: | :- | :------------------------ | | ----: | :- | :------------------------ |
| 0-11 | | _Unused_ | | 0-7 | | _Unused_ |
| 8 | R | DS2433 1-wire bus readout |
| 9-11 | | _Unused_ |
| 12 | R | DS2401 1-wire bus readout | | 12 | R | DS2401 1-wire bus readout |
| 13 | R | DS2433 1-wire bus readout | | 13-15 | | _Unused_ |
| 14-15 | | _Unused_ |
When written: When written:
| Bits | RW | Description | | Bits | RW | Description |
| ----: | :- | :----------------------------------------------------------- | | ----: | :- | :----------------------------------------------------------- |
| 0-11 | | _Unused_ | | 0-7 | | _Unused_ |
| 8 | W | Drive DS2433 1-wire bus low (1 = pull to ground, 0 = high-z) |
| 9-11 | | _Unused_ |
| 12 | W | Drive DS2401 1-wire bus low (1 = pull to ground, 0 = high-z) | | 12 | W | Drive DS2401 1-wire bus low (1 = pull to ground, 0 = high-z) |
| 13 | W | Drive DS2433 1-wire bus low (1 = pull to ground, 0 = high-z) | | 13-15 | | _Unused_ |
| 14-15 | | _Unused_ |
Bit 13 is mapped to the bus of the (normally unpopulated) DS2433 footprint. It
is currently unclear whether and how Konami's bitstreams expose this bus.
## Building the bitstream ## Building the bitstream

View File

@ -5,252 +5,199 @@ CONFIG PROHIBIT = "P154"; # DOUT
## System clocks ## System clocks
TIMESPEC "TS_clock29M" = PERIOD "clock29M" 29.4500 MHz HIGH 50 %;
#TIMESPEC "TS_clock19M" = PERIOD "clock19M" 19.6608 MHz HIGH 50 %;
NET "clockIn29M" LOC = "P160"; NET "clockIn29M" LOC = "P160";
NET "clock29M" TNM = "clock29M";
#NET "clockIn19M" LOC = "P207"; #NET "clockIn19M" LOC = "P207";
#NET "clock19M" TNM = "clock19M";
## Host interface ## Host interface
NET "nHostRead" LOC = "P146"; NET "nHostRead" LOC = "P146";
NET "nHostRead" NODELAY;
NET "nHostWrite" LOC = "P145"; NET "nHostWrite" LOC = "P145";
NET "nHostWrite" NODELAY;
NET "nHostEnable" LOC = "P142"; NET "nHostEnable" LOC = "P142";
NET "nHostEnable" NODELAY;
NET "hostAddress[0]" LOC = "P117"; NET "hostAddress[0]" LOC = "P117";
NET "hostAddress[0]" NODELAY;
NET "hostAddress[1]" LOC = "P116"; NET "hostAddress[1]" LOC = "P116";
NET "hostAddress[1]" NODELAY;
NET "hostAddress[2]" LOC = "P115"; NET "hostAddress[2]" LOC = "P115";
NET "hostAddress[2]" NODELAY;
NET "hostAddress[3]" LOC = "P114"; NET "hostAddress[3]" LOC = "P114";
NET "hostAddress[3]" NODELAY;
NET "hostAddress[4]" LOC = "P113"; NET "hostAddress[4]" LOC = "P113";
NET "hostAddress[4]" NODELAY;
NET "hostAddress[5]" LOC = "P112"; NET "hostAddress[5]" LOC = "P112";
NET "hostAddress[5]" NODELAY;
NET "hostAddress[6]" LOC = "P110"; NET "hostAddress[6]" LOC = "P110";
NET "hostAddress[6]" NODELAY;
NET "hostData[0]" LOC = "P138"; NET "hostData[0]" LOC = "P138";
NET "hostData[0]" FAST;
NET "hostData[0]" DRIVE = 12;
NET "hostData[0]" NODELAY;
NET "hostData[1]" LOC = "P137"; NET "hostData[1]" LOC = "P137";
NET "hostData[1]" FAST;
NET "hostData[1]" DRIVE = 12;
NET "hostData[1]" NODELAY;
NET "hostData[2]" LOC = "P136"; NET "hostData[2]" LOC = "P136";
NET "hostData[2]" FAST;
NET "hostData[2]" DRIVE = 12;
NET "hostData[2]" NODELAY;
NET "hostData[3]" LOC = "P135"; NET "hostData[3]" LOC = "P135";
NET "hostData[3]" FAST;
NET "hostData[3]" DRIVE = 12;
NET "hostData[3]" NODELAY;
NET "hostData[4]" LOC = "P134"; NET "hostData[4]" LOC = "P134";
NET "hostData[4]" FAST;
NET "hostData[4]" DRIVE = 12;
NET "hostData[4]" NODELAY;
NET "hostData[5]" LOC = "P133"; NET "hostData[5]" LOC = "P133";
NET "hostData[5]" FAST;
NET "hostData[5]" DRIVE = 12;
NET "hostData[5]" NODELAY;
NET "hostData[6]" LOC = "P132"; NET "hostData[6]" LOC = "P132";
NET "hostData[6]" FAST;
NET "hostData[6]" DRIVE = 12;
NET "hostData[6]" NODELAY;
NET "hostData[7]" LOC = "P129"; NET "hostData[7]" LOC = "P129";
NET "hostData[7]" FAST;
NET "hostData[7]" DRIVE = 12;
NET "hostData[7]" NODELAY;
NET "hostData[8]" LOC = "P128"; NET "hostData[8]" LOC = "P128";
NET "hostData[8]" FAST;
NET "hostData[8]" DRIVE = 12;
NET "hostData[8]" NODELAY;
NET "hostData[9]" LOC = "P127"; NET "hostData[9]" LOC = "P127";
NET "hostData[9]" FAST;
NET "hostData[9]" DRIVE = 12;
NET "hostData[9]" NODELAY;
NET "hostData[10]" LOC = "P126"; NET "hostData[10]" LOC = "P126";
NET "hostData[10]" FAST;
NET "hostData[10]" DRIVE = 12;
NET "hostData[10]" NODELAY;
NET "hostData[11]" LOC = "P125"; NET "hostData[11]" LOC = "P125";
NET "hostData[11]" FAST;
NET "hostData[11]" DRIVE = 12;
NET "hostData[11]" NODELAY;
NET "hostData[12]" LOC = "P124"; NET "hostData[12]" LOC = "P124";
NET "hostData[12]" FAST;
NET "hostData[12]" DRIVE = 12;
NET "hostData[12]" NODELAY;
NET "hostData[13]" LOC = "P123"; NET "hostData[13]" LOC = "P123";
NET "hostData[13]" FAST;
NET "hostData[13]" DRIVE = 12;
NET "hostData[13]" NODELAY;
NET "hostData[14]" LOC = "P122"; NET "hostData[14]" LOC = "P122";
NET "hostData[14]" FAST;
NET "hostData[14]" DRIVE = 12;
NET "hostData[14]" NODELAY;
NET "hostData[15]" LOC = "P120"; NET "hostData[15]" LOC = "P120";
NET "hostData[15]" FAST;
NET "hostData[15]" DRIVE = 12;
NET "hostData[15]" NODELAY;
## SRAM interface ## SRAM interface
NET "nSRAMRead" LOC = "P40"; NET "nSRAMRead" LOC = "P40";
NET "nSRAMRead" FAST; NET "nSRAMRead" FAST;
NET "nSRAMRead" DRIVE = 12;
NET "nSRAMWrite" LOC = "P55"; NET "nSRAMWrite" LOC = "P55";
NET "nSRAMWrite" FAST; NET "nSRAMWrite" FAST;
NET "nSRAMWrite" DRIVE = 12;
NET "nSRAMEnable" LOC = "P34"; NET "nSRAMEnable" LOC = "P34";
NET "nSRAMEnable" FAST; NET "nSRAMEnable" FAST;
NET "nSRAMEnable" DRIVE = 12;
NET "sramAddress[0]" LOC = "P30"; NET "sramAddress[0]" LOC = "P30";
NET "sramAddress[0]" FAST;
NET "sramAddress[0]" DRIVE = 12;
NET "sramAddress[1]" LOC = "P32"; NET "sramAddress[1]" LOC = "P32";
NET "sramAddress[1]" FAST;
NET "sramAddress[1]" DRIVE = 12;
NET "sramAddress[2]" LOC = "P35"; NET "sramAddress[2]" LOC = "P35";
NET "sramAddress[2]" FAST;
NET "sramAddress[2]" DRIVE = 12;
NET "sramAddress[3]" LOC = "P37"; NET "sramAddress[3]" LOC = "P37";
NET "sramAddress[3]" FAST;
NET "sramAddress[3]" DRIVE = 12;
NET "sramAddress[4]" LOC = "P41"; NET "sramAddress[4]" LOC = "P41";
NET "sramAddress[4]" FAST;
NET "sramAddress[4]" DRIVE = 12;
NET "sramAddress[5]" LOC = "P43"; NET "sramAddress[5]" LOC = "P43";
NET "sramAddress[5]" FAST;
NET "sramAddress[5]" DRIVE = 12;
NET "sramAddress[6]" LOC = "P45"; NET "sramAddress[6]" LOC = "P45";
NET "sramAddress[6]" FAST;
NET "sramAddress[6]" DRIVE = 12;
NET "sramAddress[7]" LOC = "P47"; NET "sramAddress[7]" LOC = "P47";
NET "sramAddress[7]" FAST;
NET "sramAddress[7]" DRIVE = 12;
NET "sramAddress[8]" LOC = "P46"; NET "sramAddress[8]" LOC = "P46";
NET "sramAddress[8]" FAST;
NET "sramAddress[8]" DRIVE = 12;
NET "sramAddress[9]" LOC = "P44"; NET "sramAddress[9]" LOC = "P44";
NET "sramAddress[9]" FAST;
NET "sramAddress[9]" DRIVE = 12;
NET "sramAddress[10]" LOC = "P36"; NET "sramAddress[10]" LOC = "P36";
NET "sramAddress[10]" FAST;
NET "sramAddress[10]" DRIVE = 12;
NET "sramAddress[11]" LOC = "P42"; NET "sramAddress[11]" LOC = "P42";
NET "sramAddress[11]" FAST;
NET "sramAddress[11]" DRIVE = 12;
NET "sramAddress[12]" LOC = "P49"; NET "sramAddress[12]" LOC = "P49";
NET "sramAddress[12]" FAST;
NET "sramAddress[12]" DRIVE = 12;
NET "sramAddress[13]" LOC = "P48"; NET "sramAddress[13]" LOC = "P48";
NET "sramAddress[13]" FAST;
NET "sramAddress[13]" DRIVE = 12;
NET "sramAddress[14]" LOC = "P56"; NET "sramAddress[14]" LOC = "P56";
NET "sramAddress[14]" FAST;
NET "sramAddress[14]" DRIVE = 12;
NET "sramAddress[15]" LOC = "P58"; NET "sramAddress[15]" LOC = "P58";
NET "sramAddress[15]" FAST;
NET "sramAddress[15]" DRIVE = 12;
NET "sramAddress[16]" LOC = "P57"; NET "sramAddress[16]" LOC = "P57";
NET "sramAddress[16]" FAST;
NET "sramAddress[16]" DRIVE = 12;
NET "sramData[0]" LOC = "P28"; NET "sramData[0]" LOC = "P28";
NET "sramData[0]" FAST;
NET "sramData[0]" DRIVE = 12;
NET "sramData[0]" NODELAY;
NET "sramData[1]" LOC = "P24"; NET "sramData[1]" LOC = "P24";
NET "sramData[1]" FAST;
NET "sramData[1]" DRIVE = 12;
NET "sramData[1]" NODELAY;
NET "sramData[2]" LOC = "P22"; NET "sramData[2]" LOC = "P22";
NET "sramData[2]" FAST;
NET "sramData[2]" DRIVE = 12;
NET "sramData[2]" NODELAY;
NET "sramData[3]" LOC = "P21"; NET "sramData[3]" LOC = "P21";
NET "sramData[3]" FAST;
NET "sramData[3]" DRIVE = 12;
NET "sramData[3]" NODELAY;
NET "sramData[4]" LOC = "P23"; NET "sramData[4]" LOC = "P23";
NET "sramData[4]" FAST;
NET "sramData[4]" DRIVE = 12;
NET "sramData[4]" NODELAY;
NET "sramData[5]" LOC = "P27"; NET "sramData[5]" LOC = "P27";
NET "sramData[5]" FAST;
NET "sramData[5]" DRIVE = 12;
NET "sramData[5]" NODELAY;
NET "sramData[6]" LOC = "P29"; NET "sramData[6]" LOC = "P29";
NET "sramData[6]" FAST;
NET "sramData[6]" DRIVE = 12;
NET "sramData[6]" NODELAY;
NET "sramData[7]" LOC = "P31"; NET "sramData[7]" LOC = "P31";
NET "sramData[7]" FAST;
NET "sramData[7]" DRIVE = 12; ## DRAM interface
NET "sramData[7]" NODELAY;
# TODO: trace these pins out
NET "dramControl[0]" LOC = "P188";
NET "dramControl[1]" LOC = "P189";
NET "dramControl[2]" LOC = "P190";
NET "dramControl[3]" LOC = "P191";
NET "dramControl[4]" LOC = "P193";
NET "dramControl[5]" LOC = "P194";
NET "dramControl[6]" LOC = "P196";
NET "dramControl[7]" LOC = "P197";
NET "dramControl[8]" LOC = "P198";
NET "dramControl[9]" LOC = "P199";
NET "dramControl[10]" LOC = "P200";
NET "dramControl[11]" LOC = "P201";
NET "dramAddress[0]" LOC = "P186";
NET "dramAddress[1]" LOC = "P184";
NET "dramAddress[2]" LOC = "P180";
NET "dramAddress[3]" LOC = "P178";
NET "dramAddress[4]" LOC = "P176";
NET "dramAddress[5]" LOC = "P174";
NET "dramAddress[6]" LOC = "P175";
NET "dramAddress[7]" LOC = "P177";
NET "dramAddress[8]" LOC = "P179";
NET "dramAddress[9]" LOC = "P181";
NET "dramAddress[10]" LOC = "P185";
NET "dramAddress[11]" LOC = "P187";
NET "dramData[0]" LOC = "P15";
NET "dramData[1]" LOC = "P14";
NET "dramData[2]" LOC = "P10";
NET "dramData[3]" LOC = "P8";
NET "dramData[4]" LOC = "P2";
NET "dramData[5]" LOC = "P206";
NET "dramData[6]" LOC = "P205";
NET "dramData[7]" LOC = "P204";
NET "dramData[8]" LOC = "P3";
NET "dramData[9]" LOC = "P4";
NET "dramData[10]" LOC = "P5";
NET "dramData[11]" LOC = "P9";
NET "dramData[12]" LOC = "P11";
NET "dramData[13]" LOC = "P17";
NET "dramData[14]" LOC = "P19";
NET "dramData[15]" LOC = "P20";
## MP3 decoder interface
NET "mp3Reset" LOC = "P152";
NET "mp3Ready" LOC = "P159";
NET "mp3ClockIn" LOC = "P163";
NET "mp3ClockOut" LOC = "P162";
NET "mp3SDA" LOC = "P150";
NET "mp3SCL" LOC = "P151";
NET "mp3StatusCS" LOC = "P149";
NET "mp3StatusError" LOC = "P168";
NET "mp3StatusFrameSync" LOC = "P161";
NET "mp3StatusDataReq" LOC = "P148";
NET "mp3InSDIN" LOC = "P167";
NET "mp3InBCLK" LOC = "P164";
NET "mp3InLRCK" LOC = "P166";
NET "mp3OutSDOUT" LOC = "P172";
NET "mp3OutBCLK" LOC = "P169";
NET "mp3OutLRCK" LOC = "P171";
## I2S audio output
NET "dacSDIN" LOC = "P96";
NET "dacBCLK" LOC = "P94";
NET "dacLRCK" LOC = "P95";
NET "dacMCLK" LOC = "P97";
## Light outputs ## Light outputs
# TODO: figure out the actual pin order of the outputs NET "lightBankAH[0]" LOC = "P84";
NET "lightBankA[0]" LOC = "P69"; NET "lightBankAH[1]" LOC = "P83";
NET "lightBankA[0]" SLOW; NET "lightBankAH[2]" LOC = "P82";
NET "lightBankA[0]" DRIVE = 24; NET "lightBankAH[3]" LOC = "P81";
NET "lightBankA[1]" LOC = "P70";
NET "lightBankA[1]" SLOW; NET "lightBankAL[0]" LOC = "P80";
NET "lightBankA[1]" DRIVE = 24; NET "lightBankAL[1]" LOC = "P76";
NET "lightBankA[2]" LOC = "P72"; NET "lightBankAL[2]" LOC = "P75";
NET "lightBankA[2]" SLOW; NET "lightBankAL[3]" LOC = "P74";
NET "lightBankA[2]" DRIVE = 24;
NET "lightBankA[3]" LOC = "P73"; NET "lightBankBH[0]" LOC = "P73";
NET "lightBankA[3]" SLOW; NET "lightBankBH[1]" LOC = "P72";
NET "lightBankA[3]" DRIVE = 24; NET "lightBankBH[2]" LOC = "P70";
NET "lightBankA[4]" LOC = "P74"; NET "lightBankBH[3]" LOC = "P69";
NET "lightBankA[4]" SLOW;
NET "lightBankA[4]" DRIVE = 24;
NET "lightBankA[5]" LOC = "P75";
NET "lightBankA[5]" SLOW;
NET "lightBankA[5]" DRIVE = 24;
NET "lightBankA[6]" LOC = "P76";
NET "lightBankA[6]" SLOW;
NET "lightBankA[6]" DRIVE = 24;
NET "lightBankA[7]" LOC = "P80";
NET "lightBankA[7]" SLOW;
NET "lightBankA[7]" DRIVE = 24;
NET "lightBankB[0]" LOC = "P81";
NET "lightBankB[0]" SLOW;
NET "lightBankB[0]" DRIVE = 24;
NET "lightBankB[1]" LOC = "P82";
NET "lightBankB[1]" SLOW;
NET "lightBankB[1]" DRIVE = 24;
NET "lightBankB[2]" LOC = "P83";
NET "lightBankB[2]" SLOW;
NET "lightBankB[2]" DRIVE = 24;
NET "lightBankB[3]" LOC = "P84";
NET "lightBankB[3]" SLOW;
NET "lightBankB[3]" DRIVE = 24;
NET "lightBankD[0]" LOC = "P68"; NET "lightBankD[0]" LOC = "P68";
NET "lightBankD[0]" SLOW;
NET "lightBankD[0]" DRIVE = 24;
NET "lightBankD[1]" LOC = "P67"; NET "lightBankD[1]" LOC = "P67";
NET "lightBankD[1]" SLOW;
NET "lightBankD[1]" DRIVE = 24;
NET "lightBankD[2]" LOC = "P60"; NET "lightBankD[2]" LOC = "P60";
NET "lightBankD[2]" SLOW;
NET "lightBankD[2]" DRIVE = 24;
NET "lightBankD[3]" LOC = "P59"; NET "lightBankD[3]" LOC = "P59";
NET "lightBankD[3]" SLOW;
NET "lightBankD[3]" DRIVE = 24; ## General-purpose inputs (unused)
#NET "inputBank[0]" LOC = "P61";
#NET "inputBank[1]" LOC = "P62";
#NET "inputBank[2]" LOC = "P63";
#NET "inputBank[3]" LOC = "P64";
## Serial interfaces
# TODO: are pins 98 and 99 swapped?
NET "networkTXEnable" LOC = "P98";
NET "networkTX" LOC = "P99";
NET "networkRX" LOC = "P100";
NET "serialTX" LOC = "P89";
NET "serialRX" LOC = "P88";
NET "serialRTS" LOC = "P93";
NET "serialCTS" LOC = "P90";
NET "serialDTR" LOC = "P87";
NET "serialDSR" LOC = "P85";
## 1-wire bus ## 1-wire bus
NET "ds2401" LOC = "P109";
NET "ds2401" SLOW;
NET "ds2401" DRIVE = 24;
NET "ds2433" LOC = "P107"; NET "ds2433" LOC = "P107";
NET "ds2433" SLOW; NET "ds2401" LOC = "P109";
NET "ds2433" DRIVE = 24;

View File

@ -6,6 +6,7 @@
## Input and preliminary optimization ## Input and preliminary optimization
read_verilog src/main.v read_verilog src/main.v
read_verilog src/spartanxl.v
hierarchy -check -top FPGA hierarchy -check -top FPGA
proc proc
@ -39,23 +40,23 @@ clean
## FPGA-specific mapping ## FPGA-specific mapping
dfflegalize -cell $_DFFE_PP?P_ r -cell $_DLATCH_PP?_ r dfflegalize -cell $_DFFE_PP?P_ r -cell $_DLATCH_PP?_ r
opt_expr -mux_undef -noclkinv opt_expr -mux_undef -noclkinv
abc -g gates abc -g gates
techmap -map src/techmap.v
clean
xilinx_dffopt -lut4 xilinx_dffopt -lut4
clkbufmap -buf BUFGLS O:I
iopadmap -bits -inpad IBUF O:I -outpad OBUF I:O -toutpad OBUFT ~T:I:O -tinoutpad IOBUFT ~T:O:I:IO -ignore IFDX D -ignore IFDXI D -ignore OFDX Q -ignore OFDXI Q -ignore OFDTX O -ignore OFDTXI O #clkbufmap -buf BUFGLS O:I
iopadmap -bits -inpad IBUF O:I -ignore IPAD IPAD -ignore OPAD OPAD -ignore IOPAD IOPAD -ignore IFDX D -ignore IFDXI D -ignore BUFGLS I
iopadmap -bits -outpad OBUF I:O -toutpad OBUFT ~T:I:O -tinoutpad IOBUFT ~T:O:I:IO -ignore IPAD IPAD -ignore OPAD OPAD -ignore IOPAD IOPAD -ignore OFDX Q -ignore OFDXI Q -ignore OFDTX O -ignore OFDTXI O
extractinv -inv INV O:I extractinv -inv INV O:I
techmap -map src/techmap.v techmap -map src/techmap.v
clean clean
## Output ## Output
# FIXME: for some reason invoking hierarchy here results in $or/$reduce_or
# primitives being added back when using wired-or
#hierarchy -check
autoname autoname
hierarchy -check
stat -tech xilinx stat -tech xilinx
check -noinit check -noinit
blackbox =A:whitebox blackbox =A:whitebox

View File

@ -20,7 +20,7 @@ ngdbuild synth.edf synth.ngd ^
-uc ..\fpga.ucf ^ -uc ..\fpga.ucf ^
-p %TARGET% ^ -p %TARGET% ^
|| exit /b 2 || exit /b 2
map -o mapped.ncd synth.ngd ^ map -o mapped.ncd synth.ngd mapped.pcf ^
-p %TARGET% ^ -p %TARGET% ^
-cm %COVER_MODE% ^ -cm %COVER_MODE% ^
-os %OPTIMIZATION_MODE% ^ -os %OPTIMIZATION_MODE% ^
@ -29,7 +29,7 @@ map -o mapped.ncd synth.ngd ^
-detail ^ -detail ^
|| exit /b 2 || exit /b 2
par mapped.ncd fpga.ncd ^ par mapped.ncd fpga.ncd mapped.pcf ^
-w ^ -w ^
-detail ^ -detail ^
|| exit /b 3 || exit /b 3

View File

@ -1,40 +1,11 @@
/* Spartan-XL primitive library */
module BUF (input I, output O); endmodule
module INV (input I, output O); endmodule
module AND2 (input I0, input I1, output O); endmodule
module NAND2 (input I0, input I1, output O); endmodule
module AND2B1 (input I0, input I1, output O); endmodule
module OR2 (input I0, input I1, output O); endmodule
module NOR2 (input I0, input I1, output O); endmodule
module OR2B1 (input I0, input I1, output O); endmodule
module XOR2 (input I0, input I1, output O); endmodule
module XNOR2 (input I0, input I1, output O); endmodule
module BUFT (input I, input T, output O); endmodule
module FDCE (input D, input C, input CLR, input CE, output Q); endmodule
module FDPE (input D, input C, input PRE, input CE, output Q); endmodule
module LDCE_1 (input D, input G, input CLR, input GE, output Q); endmodule
module LDPE_1 (input D, input G, input PRE, input GE, output Q); endmodule
module IPAD (output IPAD); endmodule
module OPAD (input OPAD); endmodule
module IOPAD (inout IOPAD); endmodule
module IBUF (input I, output O); endmodule
module OBUF (input I, output O); endmodule
module OBUFT (input I, input T, output O); endmodule
module IOBUFT (input I, input T, output O, inout IO); endmodule
module BUFGLS (input I, output O); endmodule
module IFDX (input D, input C, input CE, output Q); endmodule
module IFDXI (input D, input C, input CE, output Q); endmodule
module OFDX (input D, input C, input CE, output Q); endmodule
module OFDXI (input D, input C, input CE, output Q); endmodule
module OFDTX (input D, input C, input CE, input T, output O); endmodule
module OFDTXI (input D, input C, input CE, input T, output O); endmodule
/* Top-level module */
module FPGA ( module FPGA (
// These are technically inputs, however they are already wired up to pad
// primitives within the module. They are only exposed here in order to
// allow for a testbench to inject the clocks during simulation.
inout clockIn29M,
inout clockIn19M,
input nHostRead, input nHostRead,
input nHostWrite, input nHostWrite,
input nHostEnable, input nHostEnable,
@ -47,54 +18,161 @@ module FPGA (
output [16:0] sramAddress, output [16:0] sramAddress,
inout [7:0] sramData, inout [7:0] sramData,
output [7:0] lightBankA, output [11:0] dramControl,
output [3:0] lightBankB, output [11:0] dramAddress,
inout [15:0] dramData,
output mp3Reset,
input mp3Ready,
output mp3ClockIn,
input mp3ClockOut,
inout mp3SDA,
inout mp3SCL,
output mp3StatusCS,
input mp3StatusError,
input mp3StatusFrameSync,
input mp3StatusDataReq,
output mp3InSDIN,
output mp3InBCLK,
output mp3InLRCK,
input mp3OutSDOUT,
input mp3OutBCLK,
input mp3OutLRCK,
output dacSDIN,
output dacBCLK,
output dacLRCK,
output dacMCLK,
output [3:0] lightBankAH,
output [3:0] lightBankAL,
output [3:0] lightBankBH,
output [3:0] lightBankD, output [3:0] lightBankD,
inout ds2401, output networkTXEnable,
inout ds2433 output networkTX,
input networkRX,
output serialTX,
input serialRX,
output serialRTS,
input serialCTS,
output serialDTR,
input serialDSR,
inout ds2433,
inout ds2401
); );
genvar i; genvar i;
/* Register definitions */
localparam SYS573D_FPGA_MAGIC = 8'h80;
localparam SYS573D_FPGA_MP3_PTR_H = 8'ha0;
localparam SYS573D_FPGA_MP3_PTR_L = 8'ha2;
localparam SYS573D_FPGA_MP3_ENDPTR_H = 8'ha4;
localparam SYS573D_FPGA_MP3_ENDPTR_L = 8'ha6;
localparam SYS573D_FPGA_MP3_COUNTER = 8'ha8;
localparam SYS573D_FPGA_MP3_KEY1 = 8'ha8;
localparam SYS573D_FPGA_MP3_FEED_STAT = 8'haa;
localparam SYS573D_FPGA_MP3_I2C = 8'hac;
localparam SYS573D_FPGA_MP3_FEED_CTRL = 8'hae;
localparam SYS573D_FPGA_DRAM_WRPTR_H = 8'hb0;
localparam SYS573D_FPGA_DRAM_WRPTR_L = 8'hb2;
localparam SYS573D_FPGA_DRAM_DATA = 8'hb4;
localparam SYS573D_FPGA_DRAM_RDPTR_H = 8'hb6;
localparam SYS573D_FPGA_DRAM_RDPTR_L = 8'hb8;
localparam SYS573D_FPGA_NET_DATA = 8'hc0;
localparam SYS573D_FPGA_DAC_COUNTER_H = 8'hca;
localparam SYS573D_FPGA_DAC_COUNTER_L = 8'hcc;
localparam SYS573D_FPGA_DAC_COUNTER_D = 8'hce;
localparam SYS573D_FPGA_LIGHTS_AH = 8'he0;
localparam SYS573D_FPGA_LIGHTS_AL = 8'he2;
localparam SYS573D_FPGA_LIGHTS_BH = 8'he4;
localparam SYS573D_FPGA_LIGHTS_D = 8'he6;
localparam SYS573D_FPGA_INIT = 8'he8;
localparam SYS573D_FPGA_MP3_KEY2 = 8'hea;
localparam SYS573D_FPGA_MP3_KEY3 = 8'hec;
localparam SYS573D_FPGA_DS_BUS = 8'hee;
/* System clocks */ /* System clocks */
wire clockIn29M, _clock29M; wire clock29M, clock19M;
wire clockIn19M, _clock19M;
IPAD _clockPad29M ( .IPAD(clockIn29M) ); // ISE rejects global buffer primitives unless they are wired either to an
IPAD _clockPad19M ( .IPAD(clockIn19M) ); // IBUF (which results in suboptimal routing, as the dedicated IOB clock
BUFGLS _clockBuf29M ( .I(clockIn29M), .O(_clock29M) ); // output is left unused) or directly to a pad primitive.
BUFGLS _clockBuf19M ( .I(clockIn19M), .O(_clock19M) ); IPAD clockPad29M (.IPAD(clockIn29M));
IPAD clockPad19M (.IPAD(clockIn19M));
BUFGLS clockBuf29M (.I(clockIn29M), .O(clock29M));
BUFGLS clockBuf19M (.I(clockIn19M), .O(clock19M));
/* Host address decoding */
// The FPGA shall only respond to addresses in 0x80-0xef range, as 0xf0-0xff
// is used by the CPLD and 0x00-0x7f seems to be reserved for debugging
// hardware. Bit 0 of the 573's address bus is not wired to the FPGA as all
// registers are 16 bits wide.
wire hostAddrValid = hostAddress[6] & (hostAddress[5:3] != 3'b111);
wire hostRegRead = ~nHostEnable & ~nHostRead & nHostWrite;
wire hostRegWrite = ~nHostEnable & nHostRead & ~nHostWrite;
wire [7:0] hostRegister = { 1'b1, hostAddress[5:0], 1'b0 };
/* Host interface */ /* Host interface */
wire _nHostRead, _nHostWrite, _nHostEnable; reg [2:0] _delayedHostRegRead = 3'b000;
wire [6:0] _hostAddress; wire _hostDataInClock;
wire [15:0] _hostDataIn;
wire [15:0] _hostDataOut;
wire _nHostReadFPGA = _nHostRead || _nHostEnable; wire [15:0] hostDataIn;
wire _nHostWriteFPGA = _nHostWrite || _nHostEnable; wor [15:0] hostDataOut;
// IOB flip-flop primitives (IFDX, OFDX) are explicitly used whenever reg hostDataInValid = 1'b0;
// possible in order to minimize propagation delays and CLB usage. reg hostDataOutValid = 1'b0;
IFDX _nHostReadBuf ( .C(_clock29M), .D(nHostRead), .Q(_nHostRead), .CE(1'b1) );
IFDX _nHostWriteBuf ( .C(_clock29M), .D(nHostWrite), .Q(_nHostWrite), .CE(1'b1) ); // Data is latched in the input flip flops once the 573 *deasserts* either
IFDX _nHostEnableBuf ( .C(_clock29M), .D(nHostEnable), .Q(_nHostEnable), .CE(1'b1) ); // the chip select or the write strobe. Konami's bitstream routes this
// signal through a global net (_hostDataInClock), possibly since it is
// asynchronous and not tied to the main clock.
BUFGLS hostDataInUpdateBuf(.I(hostRegWrite), .O(_hostDataInClock));
wire hostDataInPending = ~hostRegWrite & hostDataInValid;
always @(posedge clock29M) begin
// Konami's bitstream pulls the output flip flops' clock enable low
// after 3 cycles if the register being read is in 0xa0-0xaf range (i.e.
// MP3 status and counters), in order to prevent any further updates
// while the counters are running. A 3-bit shift register is used to
// implement the delay.
_delayedHostRegRead <= { _delayedHostRegRead[1:0], hostRegRead };
// The direction of the bus is only changed on clock edges in order to
// prevent any data from being output before the output flip flops are
// updated.
hostDataInValid <= hostRegWrite;
hostDataOutValid <= hostAddrValid & hostRegRead;
end
generate generate
for (i = 0; i < 7; i++) for (i = 0; i < 16; i = i + 1) begin
IFDX _hostAddressBuf ( IFDX hostDataInReg (
.C(_clock29M), .D(hostAddress[i]), .Q(_hostAddress[i]) .D(hostData[i]),
.C(~_hostDataInClock),
.CE(1'b1),
.Q(hostDataIn[i])
); );
OFDTX hostDataOutReg (
for (i = 0; i < 16; i++) begin .D(hostDataOut[i]),
IFDX _hostDataInBuf ( .C(clock29M),
.C(_clock29M), .D(hostData[i]), .Q(_hostDataIn[i]), .CE(1'b1) .CE(~_delayedHostRegRead[2]),
); .T(~hostDataOutValid),
OFDTX _hostDataOutBuf ( .O(hostData[i])
.C(_clock29M), .O(hostData[i]), .D(_hostDataOut[i]),
.CE(~_nHostReadFPGA), .T(_nHostReadFPGA)
); );
end end
endgenerate endgenerate
@ -105,71 +183,107 @@ module FPGA (
assign nSRAMWrite = 1'b1; assign nSRAMWrite = 1'b1;
assign nSRAMEnable = 1'b1; assign nSRAMEnable = 1'b1;
assign sramAddress = 17'h1ffff; assign sramAddress = 17'h1ffff;
assign sramData = 8'hff;
/* DRAM interface (currently unused) */
assign dramControl = 12'hfff;
assign dramAddress = 12'hfff;
/* MP3 decoder interface (currently unused) */
assign mp3Reset = 1'b1;
assign mp3ClockIn = 1'b1;
assign mp3StatusCS = 1'b1;
assign mp3InSDIN = 1'b1;
assign mp3InBCLK = 1'b1;
assign mp3InLRCK = 1'b1;
assign hostDataOut = (hostRegister == SYS573D_FPGA_MP3_I2C)
? { 2'h0, mp3SCL, mp3SDA, 12'h000 }
: 16'h0000;
reg mp3SDAState = 1'b0;
reg mp3SCLState = 1'b0;
always @(posedge clock29M)
if (hostDataInPending & (hostRegister == SYS573D_FPGA_MP3_I2C)) begin
mp3SDAState <= hostDataIn[12];
mp3SCLState <= hostDataIn[13];
end
assign mp3SDA = mp3SDAState ? 1'bz : 1'b0;
assign mp3SCL = mp3SCLState ? 1'bz : 1'b0;
/* I2S audio output */
assign dacSDIN = mp3OutSDOUT;
assign dacBCLK = mp3OutBCLK;
assign dacLRCK = mp3OutLRCK;
assign dacMCLK = mp3ClockOut;
/* Magic number */
assign hostDataOut = (hostRegister == SYS573D_FPGA_MAGIC)
? 16'h573f
: 16'h0000;
/* Light outputs */ /* Light outputs */
wire [3:0] _lightBankData = _hostDataIn[15:12];
wire _lightBankA0Write = ~_nHostWriteFPGA & (_hostAddress == 7'h70);
wire _lightBankA1Write = ~_nHostWriteFPGA & (_hostAddress == 7'h71);
wire _lightBankBWrite = ~_nHostWriteFPGA & (_hostAddress == 7'h72);
wire _lightBankDWrite = ~_nHostWriteFPGA & (_hostAddress == 7'h73);
generate generate
for (i = 0; i < 4; i++) begin for (i = 0; i < 4; i = i + 1) begin
// Use "inverted" flip-flops so that all lights are turned off on reg [3:0] lightBankState = 4'b1111;
// startup.
OFDXI _lightBankA0Buf ( wire dataIn = hostDataIn[i + 12];
.C(_clock29M), .Q(lightBankA[i + 4]), .D(_lightBankData[i]),
.CE(_lightBankA0Write) always @(posedge clock29M)
); if (hostDataInPending)
OFDXI _lightBankA1Buf ( case (hostRegister)
.C(_clock29M), .Q(lightBankA[i]), .D(_lightBankData[i]), SYS573D_FPGA_LIGHTS_AH:
.CE(_lightBankA1Write) lightBankState[0] <= dataIn;
); SYS573D_FPGA_LIGHTS_AL:
OFDXI _lightBankBBuf ( lightBankState[1] <= dataIn;
.C(_clock29M), .Q(lightBankB[i]), .D(_lightBankData[i]), SYS573D_FPGA_LIGHTS_BH:
.CE(_lightBankBWrite) lightBankState[2] <= dataIn;
); SYS573D_FPGA_LIGHTS_D:
OFDXI _lightBankDBuf ( lightBankState[3] <= dataIn;
.C(_clock29M), .Q(lightBankD[i]), .D(_lightBankData[i]), endcase
.CE(_lightBankDWrite)
); // Note that XCS40XL IOBs actually have a tristate flip flop, but
// there seems to be no primitive exposed by ISE to force its usage.
assign lightBankAH[i] = lightBankState[0] ? 1'bz : 1'b0;
assign lightBankAL[i] = lightBankState[1] ? 1'bz : 1'b0;
assign lightBankBH[i] = lightBankState[2] ? 1'bz : 1'b0;
assign lightBankD[i] = lightBankState[3] ? 1'bz : 1'b0;
end end
endgenerate endgenerate
/* Serial interfaces (currently unused) */
assign networkTXEnable = 1'b1;
assign networkTX = 1'b1;
assign serialTX = 1'b1;
assign serialRTS = 1'b1;
assign serialDTR = 1'b1;
/* 1-wire bus */ /* 1-wire bus */
wire _ds2401In, _ds2433In; assign hostDataOut = (hostRegister == SYS573D_FPGA_DS_BUS)
reg _ds2401Out, _ds2433Out; ? { 3'h0, ds2401, 3'h0, ds2433, 8'h00 }
: 16'h0000;
// Note that the 1-wire pins are open drain and pulled low by writing 1 reg ds2433State = 1'b0;
// (rather than 0) to the respective register bits, but not inverted when reg ds2401State = 1'b0;
// read.
IFDX _ds2401InBuf ( .C(_clock29M), .D(ds2401), .Q(_ds2401In), .CE(1'b1) );
IFDX _ds2433InBuf ( .C(_clock29M), .D(ds2433), .Q(_ds2433In), .CE(1'b1) );
OBUFT _ds2401OutBuf ( .O(ds2401), .I(1'b0), .T(~_ds2401Out) );
OBUFT _ds2433OutBuf ( .O(ds2433), .I(1'b0), .T(~_ds2433Out) );
wire _dsBusWrite = ~_nHostWriteFPGA & (_hostAddress == 7'h77); always @(posedge clock29M)
if (hostDataInPending & (hostRegister == SYS573D_FPGA_DS_BUS)) begin
always @(posedge _clock29M) ds2433State <= hostDataIn[8];
if (_dsBusWrite) begin ds2401State <= hostDataIn[12];
_ds2401Out <= _hostDataIn[12];
_ds2433Out <= _hostDataIn[13];
end end
/* Readable registers */ // The 1-wire pins are pulled low by writing 1 (rather than 0) to the
// respective register bits, but not inverted when read.
wire [15:0] _magicNumberData = 16'h573f; assign ds2433 = ds2433State ? 1'b0 : 1'bz;
wire [15:0] _dsBusData = { 2'h0, _ds2433In, _ds2401In, 12'h000 }; assign ds2401 = ds2401State ? 1'b0 : 1'bz;
wire _magicNumberRead = ~_nHostReadFPGA & (_hostAddress == 7'h40);
wire _dsBusRead = ~_nHostReadFPGA & (_hostAddress == 7'h77);
assign _hostDataOut =
_magicNumberRead ? _magicNumberData :
_dsBusRead ? _dsBusData :
16'h0000;
endmodule endmodule

368
fpga/src/spartanxl.v Normal file
View File

@ -0,0 +1,368 @@
/* Logic primitives */
module BUF (input I, output O);
`ifndef SYNTHESIS
assign O = I;
`endif
endmodule
module INV (input I, output O);
`ifndef SYNTHESIS
assign O = ~I;
`endif
endmodule
module AND2 (input I0, input I1, output O);
`ifndef SYNTHESIS
assign O = I0 & I1;
`endif
endmodule
module NAND2 (input I0, input I1, output O);
`ifndef SYNTHESIS
assign O = ~(I0 & I1);
`endif
endmodule
module AND2B1 (input I0, input I1, output O);
`ifndef SYNTHESIS
assign O = I0 & ~I1;
`endif
endmodule
module OR2 (input I0, input I1, output O);
`ifndef SYNTHESIS
assign O = I0 | I1;
`endif
endmodule
module NOR2 (input I0, input I1, output O);
`ifndef SYNTHESIS
assign O = ~(I0 | I1);
`endif
endmodule
module OR2B1 (input I0, input I1, output O);
`ifndef SYNTHESIS
assign O = I0 | ~I1;
`endif
endmodule
module XOR2 (input I0, input I1, output O);
`ifndef SYNTHESIS
assign O = (I0 != I1);
`endif
endmodule
module XNOR2 (input I0, input I1, output O);
`ifndef SYNTHESIS
assign O = (I0 == I1);
`endif
endmodule
module BUFT (input I, input T, output O);
`ifndef SYNTHESIS
assign O = T ? 1'bz : I;
`endif
endmodule
module FDCE (input D, input C, input CLR, input CE, output Q);
`ifndef SYNTHESIS
reg data;
assign Q = data;
initial
data = 1'b0;
always @(CLR)
data <= 1'b0;
always @(posedge C)
data <= CE ? D : data;
`endif
endmodule
module FDPE (input D, input C, input PRE, input CE, output Q);
`ifndef SYNTHESIS
reg data;
assign Q = data;
initial
data = 1'b1;
always @(PRE)
data <= 1'b1;
always @(posedge C)
data <= CE ? D : data;
`endif
endmodule
module LDCE_1 (input D, input G, input CLR, input GE, output Q);
`ifndef SYNTHESIS
reg data;
assign Q = data;
initial
data = 1'b0;
always @(CLR)
data <= 1'b0;
always @(~G)
data <= GE ? D : data;
`endif
endmodule
module LDPE_1 (input D, input G, input PRE, input GE, output Q);
`ifndef SYNTHESIS
reg data;
assign Q = data;
initial
data = 1'b1;
always @(PRE)
data <= 1'b1;
always @(~G)
data <= GE ? D : data;
`endif
endmodule
/* I/O primitives */
(* keep *) module BUFGLS (input I, output O);
`ifndef SYNTHESIS
BUF buffer (.I(I), .O(O));
`endif
endmodule
(* keep *) module IBUF (input I, output O);
`ifndef SYNTHESIS
BUF buffer (.I(I), .O(O));
`endif
endmodule
(* keep *) module OBUF (input I, output O);
`ifndef SYNTHESIS
BUF buffer (.I(I), .O(O));
`endif
endmodule
(* keep *) module OBUFT (input I, input T, output O);
`ifndef SYNTHESIS
BUFT buffer (.I(I), .T(T), .O(O));
`endif
endmodule
(* keep *) module IOBUFT (input I, input T, output O, inout IO);
`ifndef SYNTHESIS
assign O = IO;
BUFT buffer (.I(I), .T(T), .O(IO));
`endif
endmodule
(* keep *) module IFDX (input D, input C, input CE, output Q);
`ifndef SYNTHESIS
reg data;
assign Q = data;
initial
data = 1'b0;
always @(posedge C)
data <= CE ? D : data;
`endif
endmodule
(* keep *) module IFDXI (input D, input C, input CE, output Q);
`ifndef SYNTHESIS
reg data;
assign Q = data;
initial
data = 1'b1;
always @(posedge C)
data <= CE ? D : data;
`endif
endmodule
(* keep *) module OFDX (input D, input C, input CE, output Q);
`ifndef SYNTHESIS
IFDX ff (.D(D), .C(C), .CE(CE), .Q(Q));
`endif
endmodule
(* keep *) module OFDXI (input D, input C, input CE, output Q);
`ifndef SYNTHESIS
IFDXI ff (.D(D), .C(C), .CE(CE), .Q(Q));
`endif
endmodule
(* keep *) module OFDTX (input D, input C, input CE, input T, output O);
`ifndef SYNTHESIS
wire Q;
IFDX ff (.D(D), .C(C), .CE(CE), .Q(Q));
BUFT buffer (.I(Q), .T(T), .O(O));
`endif
endmodule
(* keep *) module OFDTXI (input D, input C, input CE, input T, output O);
`ifndef SYNTHESIS
wire Q;
IFDXI ff (.D(D), .C(C), .CE(CE), .Q(Q));
BUFT buffer (.I(Q), .T(T), .O(O));
`endif
endmodule
/* I/O pads */
(* keep *) module IPAD (output IPAD);
endmodule
(* keep *) module OPAD (input OPAD);
endmodule
(* keep *) module IOPAD (inout IOPAD);
endmodule
(* keep *) module UPAD (inout UPAD);
endmodule
(* keep *) module TDI (inout I);
endmodule
(* keep *) module TDO (input O);
endmodule
(* keep *) module TCK (inout I);
endmodule
(* keep *) module TMS (inout I);
endmodule
/* Fixed-function blocks (not simulated) */
(* keep *) module STARTUP (
input GSR,
input GTS,
input CLK,
output DONEIN,
output Q1Q4,
output Q2,
output Q3
);
endmodule
(* keep *) module OSC4 (
output F8M,
output F500K,
output F16K,
output F490,
output F15
);
endmodule
(* keep *) module BSCAN(
input TDI,
input TDO1,
input TDO2,
input TCK,
input TMS,
output TDO,
output DRCK,
output IDLE,
output SEL1,
output SEL2
);
endmodule
(* keep *) module RDBK (input TRIG, output DATA, output RIP);
endmodule
(* keep *) module RDCLK (input I);
endmodule
/* ISE built-in macros */
module CC8CE (
input C, input CLR, input CE, output [7:0] Q, output CEO, output TC
);
`ifndef SYNTHESIS
reg [7:0] data;
assign Q = data;
assign TC = &data;
assign CEO = TC & CE;
initial
data = 8'h00;
always @(CLR)
data <= 8'h00;
always @(posedge C)
data <= data + CE;
`endif
endmodule
module CC8CLE (
input [7:0] D, input L, input C, input CLR, input CE, output [7:0] Q,
output CEO, output TC
);
`ifndef SYNTHESIS
reg [7:0] data;
assign Q = data;
assign TC = &data;
assign CEO = TC & CE;
initial
data = 8'h00;
always @(CLR)
data <= 8'h00;
always @(posedge C)
if (L)
data <= D;
else
data <= data + CE;
`endif
endmodule
module CC16CE (
input C, input CLR, input CE, output [15:0] Q, output CEO, output TC
);
`ifndef SYNTHESIS
reg [15:0] data;
assign Q = data;
assign TC = &data;
assign CEO = TC & CE;
initial
data = 16'h0000;
always @(CLR)
data <= 16'h0000;
always @(posedge C)
data <= data + CE;
`endif
endmodule
module CC16CLE (
input [15:0] D, input L, input C, input CLR, input CE, output [15:0] Q,
output CEO, output TC
);
`ifndef SYNTHESIS
reg [15:0] data;
assign Q = data;
assign TC = &data;
assign CEO = TC & CE;
initial
data = 16'h0000;
always @(CLR)
data <= 16'h0000;
always @(posedge C)
if (L)
data <= D;
else
data <= data + CE;
`endif
endmodule

View File

@ -6,82 +6,85 @@
*/ */
(* techmap_celltype = "IOBUFT" *) (* techmap_celltype = "IOBUFT" *)
module _ISE_IOBUFT (inout IO, input I, output O, input T); module _ISE_IOBUFT (input I, input T, output O, inout IO);
IBUF _TECHMAP_REPLACE_.ibuf ( .I(IO), .O(O) ); IBUF _TECHMAP_REPLACE_.ibuf (.I(IO), .O(O));
OBUFT _TECHMAP_REPLACE_.obuf ( .O(IO), .I(I), .T(T) ); OBUFT _TECHMAP_REPLACE_.obuf (.O(IO), .I(I), .T(T));
endmodule endmodule
(* techmap_celltype = "$_BUF_" *) (* techmap_celltype = "$_BUF_" *)
module _ISE_BUF (input A, output Y); module _ISE_BUF (input A, output Y);
BUF _TECHMAP_REPLACE_ ( .I(A), .O(Y) ); BUF _TECHMAP_REPLACE_ (.I(A), .O(Y));
endmodule endmodule
(* techmap_celltype = "$_NOT_" *) (* techmap_celltype = "$_NOT_" *)
module _ISE_INV (input A, output Y); module _ISE_INV (input A, output Y);
INV _TECHMAP_REPLACE_ ( .I(A), .O(Y) ); INV _TECHMAP_REPLACE_ (.I(A), .O(Y));
endmodule endmodule
(* techmap_celltype = "$_AND_" *) (* techmap_celltype = "$_AND_" *)
module _ISE_AND2 (input A, input B, output Y); module _ISE_AND2 (input A, input B, output Y);
AND2 _TECHMAP_REPLACE_ ( .I0(A), .I1(B), .O(Y) ); AND2 _TECHMAP_REPLACE_ (.I0(A), .I1(B), .O(Y));
endmodule endmodule
(* techmap_celltype = "$_NAND_" *) (* techmap_celltype = "$_NAND_" *)
module _ISE_NAND2 (input A, input B, output Y); module _ISE_NAND2 (input A, input B, output Y);
NAND2 _TECHMAP_REPLACE_ ( .I0(A), .I1(B), .O(Y) ); NAND2 _TECHMAP_REPLACE_ (.I0(A), .I1(B), .O(Y));
endmodule endmodule
(* techmap_celltype = "$_ANDNOT_" *) (* techmap_celltype = "$_ANDNOT_" *)
module _ISE_AND2B1 (input A, input B, output Y); module _ISE_AND2B1 (input A, input B, output Y);
AND2B1 _TECHMAP_REPLACE_ ( .I0(A), .I1(B), .O(Y) ); AND2B1 _TECHMAP_REPLACE_ (.I0(A), .I1(B), .O(Y));
endmodule endmodule
(* techmap_celltype = "$_OR_" *) (* techmap_celltype = "$_OR_" *)
module _ISE_OR2 (input A, input B, output Y); module _ISE_OR2 (input A, input B, output Y);
OR2 _TECHMAP_REPLACE_ ( .I0(A), .I1(B), .O(Y) ); OR2 _TECHMAP_REPLACE_ (.I0(A), .I1(B), .O(Y));
endmodule endmodule
(* techmap_celltype = "$_NOR_" *) (* techmap_celltype = "$_NOR_" *)
module _ISE_NOR2 (input A, input B, output Y); module _ISE_NOR2 (input A, input B, output Y);
NOR2 _TECHMAP_REPLACE_ ( .I0(A), .I1(B), .O(Y) ); NOR2 _TECHMAP_REPLACE_ (.I0(A), .I1(B), .O(Y));
endmodule endmodule
(* techmap_celltype = "$_ORNOT_" *) (* techmap_celltype = "$_ORNOT_" *)
module _ISE_OR2B1 (input A, input B, output Y); module _ISE_OR2B1 (input A, input B, output Y);
OR2B1 _TECHMAP_REPLACE_ ( .I0(A), .I1(B), .O(Y) ); OR2B1 _TECHMAP_REPLACE_ (.I0(A), .I1(B), .O(Y));
endmodule endmodule
(* techmap_celltype = "$_XOR_" *) (* techmap_celltype = "$_XOR_" *)
module _ISE_XOR2 (input A, input B, output Y); module _ISE_XOR2 (input A, input B, output Y);
XOR2 _TECHMAP_REPLACE_ ( .I0(A), .I1(B), .O(Y) ); XOR2 _TECHMAP_REPLACE_ (.I0(A), .I1(B), .O(Y));
endmodule endmodule
(* techmap_celltype = "$_XNOR_" *) (* techmap_celltype = "$_XNOR_" *)
module _ISE_XNOR2 (input A, input B, output Y); module _ISE_XNOR2 (input A, input B, output Y);
XNOR2 _TECHMAP_REPLACE_ ( .I0(A), .I1(B), .O(Y) ); XNOR2 _TECHMAP_REPLACE_ (.I0(A), .I1(B), .O(Y));
endmodule endmodule
(* techmap_celltype = "$_TBUF_" *) (* techmap_celltype = "$_TBUF_" *)
module _ISE_BUFT (input A, input E, output Y); module _ISE_BUFT (input A, input E, output Y);
BUFT _TECHMAP_REPLACE_ ( .I(A), .T(~E), .O(Y) ); wire T;
INV _TECHMAP_REPLACE_.inv (.I(E), .O(T));
BUFT _TECHMAP_REPLACE_.buffer (.I(A), .T(T), .O(Y));
endmodule endmodule
(* techmap_celltype = "$_DFFE_PP0P_" *) (* techmap_celltype = "$_DFFE_PP0P_" *)
module _ISE_FDCE (input D, input C, input R, input E, output Q); module _ISE_FDCE (input D, input C, input R, input E, output Q);
FDCE _TECHMAP_REPLACE_ ( .D(D), .C(C), .CLR(R), .CE(E), .Q(Q) ); FDCE _TECHMAP_REPLACE_ (.D(D), .C(C), .CLR(R), .CE(E), .Q(Q));
endmodule endmodule
(* techmap_celltype = "$_DFFE_PP1P_" *) (* techmap_celltype = "$_DFFE_PP1P_" *)
module _ISE_FDPE (input D, input C, input R, input E, output Q); module _ISE_FDPE (input D, input C, input R, input E, output Q);
FDPE _TECHMAP_REPLACE_ ( .D(D), .C(C), .PRE(R), .CE(E), .Q(Q) ); FDPE _TECHMAP_REPLACE_ (.D(D), .C(C), .PRE(R), .CE(E), .Q(Q));
endmodule endmodule
(* techmap_celltype = "$_DLATCH_PP0_" *) (* techmap_celltype = "$_DLATCH_PP0_" *)
module _ISE_LDCE_1 (input E, input R, input D, output Q); module _ISE_LDCE_1 (input E, input R, input D, output Q);
LDCE_1 _TECHMAP_REPLACE_ ( .D(D), .G(E), .CLR(R), .GE(1'b1), .Q(Q) ); LDCE_1 _TECHMAP_REPLACE_ (.D(D), .G(E), .CLR(R), .GE(1'b1), .Q(Q));
endmodule endmodule
(* techmap_celltype = "$_DLATCH_PP1_" *) (* techmap_celltype = "$_DLATCH_PP1_" *)
module _ISE_LDPE_1 (input E, input R, input D, output Q); module _ISE_LDPE_1 (input E, input R, input D, output Q);
LDPE_1 _TECHMAP_REPLACE_ ( .D(D), .G(E), .PRE(R), .GE(1'b1), .Q(Q) ); LDPE_1 _TECHMAP_REPLACE_ (.D(D), .G(E), .PRE(R), .GE(1'b1), .Q(Q));
endmodule endmodule

View File

@ -13,8 +13,12 @@ uint16_t _bankSwitchReg, _cartOutputReg, _miscOutputReg;
/* System initialization */ /* System initialization */
static constexpr int _RESET_DELAY = 5000; static constexpr int _IDE_RESET_ASSERT_DELAY = 5000;
static constexpr int _FPGA_INIT_DELAY = 1000; static constexpr int _IDE_RESET_CLEAR_DELAY = 50000;
static constexpr int _FPGA_RESET_DELAY = 5000;
static constexpr int _FPGA_STARTUP_DELAY = 50000;
static constexpr int _FPGA_INIT_REG_DELAY = 5000;
void init(void) { void init(void) {
// Remapping the base address is required in order for IDE DMA to work // Remapping the base address is required in order for IDE DMA to work
@ -62,9 +66,9 @@ void initIOBoard(void) {
// Some of the digital I/O board's light outputs are controlled by the FPGA // Some of the digital I/O board's light outputs are controlled by the FPGA
// and cannot be turned off until the FPGA is initialized. // and cannot be turned off until the FPGA is initialized.
if (isDigitalIOPresent()) { if (isDigitalIOPresent()) {
//SYS573D_CPLD_LIGHTS_B0 = 0xf000; SYS573D_CPLD_LIGHTS_BL = 0xf000;
SYS573D_CPLD_LIGHTS_C0 = 0xf000; SYS573D_CPLD_LIGHTS_CL = 0xf000;
SYS573D_CPLD_LIGHTS_C1 = 0xf000; SYS573D_CPLD_LIGHTS_CH = 0xf000;
} else { } else {
SYS573A_LIGHTS_A = 0x00ff; SYS573A_LIGHTS_A = 0x00ff;
SYS573A_LIGHTS_B = 0x00ff; SYS573A_LIGHTS_B = 0x00ff;
@ -75,10 +79,10 @@ void initIOBoard(void) {
void resetIDEDevices(void) { void resetIDEDevices(void) {
SYS573_IDE_RESET = 0; SYS573_IDE_RESET = 0;
delayMicroseconds(_RESET_DELAY); delayMicroseconds(_IDE_RESET_ASSERT_DELAY);
SYS573_IDE_RESET = 1; SYS573_IDE_RESET = 1;
delayMicroseconds(_RESET_DELAY); delayMicroseconds(_IDE_RESET_CLEAR_DELAY);
} }
/* JAMMA and RTC functions */ /* JAMMA and RTC functions */
@ -231,6 +235,8 @@ bool loadRawBitstream(const uint8_t *data, size_t length) {
else else
return false; return false;
const uint16_t mask = SYS573D_CPLD_STAT_INIT | SYS573D_CPLD_STAT_DONE;
for (int i = 3; i; i--) { for (int i = 3; i; i--) {
SYS573D_CPLD_UNK_RESET = 0; SYS573D_CPLD_UNK_RESET = 0;
@ -243,22 +249,18 @@ bool loadRawBitstream(const uint8_t *data, size_t length) {
| SYS573D_CPLD_CTRL_DONE | SYS573D_CPLD_CTRL_DONE
| SYS573D_CPLD_CTRL_PROGRAM | SYS573D_CPLD_CTRL_PROGRAM
| SYS573D_CPLD_CTRL_UNKNOWN; | SYS573D_CPLD_CTRL_UNKNOWN;
delayMicroseconds(_FPGA_RESET_DELAY);
delayMicroseconds(_RESET_DELAY); if ((SYS573D_CPLD_STAT & mask) != SYS573D_CPLD_STAT_INIT)
if (!(SYS573D_CPLD_STAT & SYS573D_CPLD_STAT_INIT))
continue; continue;
writeFunc(data, length); writeFunc(data, length);
delayMicroseconds(_FPGA_STARTUP_DELAY);
const uint16_t mask = SYS573D_CPLD_STAT_INIT | SYS573D_CPLD_STAT_DONE; if ((SYS573D_CPLD_STAT & mask) != mask)
continue;
for (int j = 15; j; j--) {
if ((SYS573D_CPLD_STAT & mask) == mask)
return true; return true;
delayMicroseconds(_FPGA_INIT_DELAY);
}
} }
return false; return false;
@ -267,19 +269,19 @@ bool loadRawBitstream(const uint8_t *data, size_t length) {
void initKonamiBitstream(void) { void initKonamiBitstream(void) {
SYS573D_FPGA_INIT = 0xf000; SYS573D_FPGA_INIT = 0xf000;
SYS573D_FPGA_INIT = 0x0000; SYS573D_FPGA_INIT = 0x0000;
delayMicroseconds(_FPGA_INIT_DELAY); delayMicroseconds(_FPGA_INIT_REG_DELAY);
SYS573D_FPGA_INIT = 0xf000; SYS573D_FPGA_INIT = 0xf000;
delayMicroseconds(_FPGA_INIT_DELAY); delayMicroseconds(_FPGA_INIT_REG_DELAY);
// Turn off all lights including the ones that were left on by init(). // Turn off all lights including the ones that were left on by init().
SYS573D_FPGA_LIGHTS_A0 = 0xf000; SYS573D_FPGA_LIGHTS_AL = 0xf000;
SYS573D_FPGA_LIGHTS_A1 = 0xf000; SYS573D_FPGA_LIGHTS_AH = 0xf000;
SYS573D_CPLD_LIGHTS_B0 = 0xf000; SYS573D_CPLD_LIGHTS_BL = 0xf000;
SYS573D_FPGA_LIGHTS_B1 = 0xf000; SYS573D_FPGA_LIGHTS_BH = 0xf000;
SYS573D_CPLD_LIGHTS_C0 = 0xf000; SYS573D_CPLD_LIGHTS_CL = 0xf000;
SYS573D_CPLD_LIGHTS_C1 = 0xf000; SYS573D_CPLD_LIGHTS_CH = 0xf000;
SYS573D_FPGA_LIGHTS_D0 = 0xf000; SYS573D_FPGA_LIGHTS_D = 0xf000;
} }
/* I2C driver */ /* I2C driver */

View File

@ -153,11 +153,11 @@ static inline bool isDigitalIOPresent(void) {
} }
static inline bool getDIO1Wire(void) { static inline bool getDIO1Wire(void) {
return (SYS573D_FPGA_DS2401 >> 12) & 1; return (SYS573D_FPGA_DS_BUS / SYS573D_FPGA_DS_BUS_DS2401) & 1;
} }
static inline void setDIO1Wire(bool value) { static inline void setDIO1Wire(bool value) {
SYS573D_FPGA_DS2401 = (value ^ 1) << 12; SYS573D_FPGA_DS_BUS = (value ^ 1) * SYS573D_FPGA_DS_BUS_DS2401;
} }
/* Other APIs */ /* Other APIs */

View File

@ -268,7 +268,10 @@ bool App::_atapiEjectWorker(void) {
if (!(dev.flags & ide::DEVICE_ATAPI)) if (!(dev.flags & ide::DEVICE_ATAPI))
continue; continue;
auto error = auto error = ide::DISC_CHANGED;
while (error == ide::DISC_CHANGED)
error =
ide::devices[0].startStopUnit(ide::START_STOP_MODE_OPEN_TRAY); ide::devices[0].startStopUnit(ide::START_STOP_MODE_OPEN_TRAY);
if (error) { if (error) {

View File

@ -137,18 +137,47 @@ typedef enum {
SYS573D_CPLD_CTRL_UNKNOWN = 1 << 15 SYS573D_CPLD_CTRL_UNKNOWN = 1 << 15
} Sys573DCPLDControlFlag; } Sys573DCPLDControlFlag;
typedef enum {
SYS573D_FPGA_DS_BUS_DS2433 = 1 << 8,
SYS573D_FPGA_DS_BUS_DS2401 = 1 << 12
} Sys573DFPGADSBusFlag;
#define SYS573D_FPGA_MAGIC _MMIO16(DEV0_BASE | 0x640080) #define SYS573D_FPGA_MAGIC _MMIO16(DEV0_BASE | 0x640080)
#define SYS573D_FPGA_LIGHTS_A1 _MMIO16(DEV0_BASE | 0x6400e0)
#define SYS573D_FPGA_LIGHTS_A0 _MMIO16(DEV0_BASE | 0x6400e2) #define SYS573D_FPGA_MP3_PTR_H _MMIO16(DEV0_BASE | 0x6400a0)
#define SYS573D_FPGA_LIGHTS_B1 _MMIO16(DEV0_BASE | 0x6400e4) #define SYS573D_FPGA_MP3_PTR_L _MMIO16(DEV0_BASE | 0x6400a2)
#define SYS573D_FPGA_LIGHTS_D0 _MMIO16(DEV0_BASE | 0x6400e6) #define SYS573D_FPGA_MP3_ENDPTR_H _MMIO16(DEV0_BASE | 0x6400a4)
#define SYS573D_FPGA_MP3_ENDPTR_L _MMIO16(DEV0_BASE | 0x6400a6)
#define SYS573D_FPGA_MP3_COUNTER _MMIO16(DEV0_BASE | 0x6400a8)
#define SYS573D_FPGA_MP3_KEY1 _MMIO16(DEV0_BASE | 0x6400a8)
#define SYS573D_FPGA_MP3_FEED_STAT _MMIO16(DEV0_BASE | 0x6400aa)
#define SYS573D_FPGA_MP3_I2C _MMIO16(DEV0_BASE | 0x6400ac)
#define SYS573D_FPGA_MP3_FEED_CTRL _MMIO16(DEV0_BASE | 0x6400ae)
#define SYS573D_FPGA_DRAM_WRPTR_H _MMIO16(DEV0_BASE | 0x6400b0)
#define SYS573D_FPGA_DRAM_WRPTR_L _MMIO16(DEV0_BASE | 0x6400b2)
#define SYS573D_FPGA_DRAM_DATA _MMIO16(DEV0_BASE | 0x6400b4)
#define SYS573D_FPGA_DRAM_RDPTR_H _MMIO16(DEV0_BASE | 0x6400b6)
#define SYS573D_FPGA_DRAM_RDPTR_L _MMIO16(DEV0_BASE | 0x6400b8)
#define SYS573D_FPGA_NET_DATA _MMIO16(DEV0_BASE | 0x6400c0)
#define SYS573D_FPGA_DAC_COUNTER_H _MMIO16(DEV0_BASE | 0x6400ca)
#define SYS573D_FPGA_DAC_COUNTER_L _MMIO16(DEV0_BASE | 0x6400cc)
#define SYS573D_FPGA_DAC_COUNTER_D _MMIO16(DEV0_BASE | 0x6400ce)
#define SYS573D_FPGA_LIGHTS_AH _MMIO16(DEV0_BASE | 0x6400e0)
#define SYS573D_FPGA_LIGHTS_AL _MMIO16(DEV0_BASE | 0x6400e2)
#define SYS573D_FPGA_LIGHTS_BH _MMIO16(DEV0_BASE | 0x6400e4)
#define SYS573D_FPGA_LIGHTS_D _MMIO16(DEV0_BASE | 0x6400e6)
#define SYS573D_FPGA_INIT _MMIO16(DEV0_BASE | 0x6400e8) #define SYS573D_FPGA_INIT _MMIO16(DEV0_BASE | 0x6400e8)
#define SYS573D_FPGA_DS2401 _MMIO16(DEV0_BASE | 0x6400ee) #define SYS573D_FPGA_MP3_KEY2 _MMIO16(DEV0_BASE | 0x6400ea)
#define SYS573D_FPGA_MP3_KEY3 _MMIO16(DEV0_BASE | 0x6400ec)
#define SYS573D_FPGA_DS_BUS _MMIO16(DEV0_BASE | 0x6400ee)
#define SYS573D_CPLD_UNK_RESET _MMIO16(DEV0_BASE | 0x6400f4) #define SYS573D_CPLD_UNK_RESET _MMIO16(DEV0_BASE | 0x6400f4)
#define SYS573D_CPLD_STAT _MMIO16(DEV0_BASE | 0x6400f6) #define SYS573D_CPLD_STAT _MMIO16(DEV0_BASE | 0x6400f6)
#define SYS573D_CPLD_CTRL _MMIO16(DEV0_BASE | 0x6400f6) #define SYS573D_CPLD_CTRL _MMIO16(DEV0_BASE | 0x6400f6)
#define SYS573D_CPLD_BITSTREAM _MMIO16(DEV0_BASE | 0x6400f8) #define SYS573D_CPLD_BITSTREAM _MMIO16(DEV0_BASE | 0x6400f8)
#define SYS573D_CPLD_LIGHTS_C0 _MMIO16(DEV0_BASE | 0x6400fa) #define SYS573D_CPLD_LIGHTS_CL _MMIO16(DEV0_BASE | 0x6400fa)
#define SYS573D_CPLD_LIGHTS_C1 _MMIO16(DEV0_BASE | 0x6400fc) #define SYS573D_CPLD_LIGHTS_CH _MMIO16(DEV0_BASE | 0x6400fc)
#define SYS573D_CPLD_LIGHTS_B0 _MMIO16(DEV0_BASE | 0x6400fe) #define SYS573D_CPLD_LIGHTS_BL _MMIO16(DEV0_BASE | 0x6400fe)