Fix FPGA bitstream, rewrite I2C and 1-wire drivers

This commit is contained in:
spicyjpeg 2024-07-10 18:13:03 +02:00
parent 84985785c8
commit 3a340da8c7
No known key found for this signature in database
GPG Key ID: 5CC87404C01DF393
18 changed files with 2098 additions and 1056 deletions

Binary file not shown.

View File

@ -8,151 +8,262 @@ CONFIG PROHIBIT = "P154"; # DOUT
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 "clock29M" TNM = "clock29M";
#NET "clockIn19M" LOC = "P207";
#NET "clock19M" TNM = "clock19M";
NET "clockIn29M" LOC = "P160";
NET "clock29M" TNM_NET = "clock29M";
NET "clockIn19M" LOC = "P207";
#NET "clock19M" TNM_NET = "clock19M";
## Host interface
NET "nHostRead" LOC = "P146";
NET "nHostWrite" LOC = "P145";
NET "nHostEnable" LOC = "P142";
TIMESPEC "TS_hostAddress" = FROM "hostAddress" TO "FFS" "TS_clock29M" / 1;
TIMESPEC "TS_hostDataIn" = FROM "hostData" TO "FFS" "TS_clock29M" / 1;
TIMESPEC "TS_hostDataOut" = FROM "FFS" TO "hostData" "TS_clock29M" / 1;
NET "hostAddress[0]" LOC = "P117";
NET "hostAddress[1]" LOC = "P116";
NET "hostAddress[2]" LOC = "P115";
NET "hostAddress[3]" LOC = "P114";
NET "hostAddress[4]" LOC = "P113";
NET "hostAddress[5]" LOC = "P112";
NET "hostAddress[6]" LOC = "P110";
NET "nHostRead" LOC = "P146";
NET "nHostRead" TNM_NET = "hostControl";
NET "nHostWrite" LOC = "P145";
NET "nHostWrite" TNM_NET = "hostControl";
NET "nHostEnable" LOC = "P142";
NET "nHostEnable" TNM_NET = "hostControl";
NET "hostData[0]" LOC = "P138";
NET "hostData[1]" LOC = "P137";
NET "hostData[2]" LOC = "P136";
NET "hostData[3]" LOC = "P135";
NET "hostData[4]" LOC = "P134";
NET "hostData[5]" LOC = "P133";
NET "hostData[6]" LOC = "P132";
NET "hostData[7]" LOC = "P129";
NET "hostData[8]" LOC = "P128";
NET "hostData[9]" LOC = "P127";
NET "hostData[10]" LOC = "P126";
NET "hostData[11]" LOC = "P125";
NET "hostData[12]" LOC = "P124";
NET "hostData[13]" LOC = "P123";
NET "hostData[14]" LOC = "P122";
NET "hostData[15]" LOC = "P120";
NET "hostAddress[0]" LOC = "P117";
NET "hostAddress[0]" TNM_NET = "hostAddress";
NET "hostAddress[1]" LOC = "P116";
NET "hostAddress[1]" TNM_NET = "hostAddress";
NET "hostAddress[2]" LOC = "P115";
NET "hostAddress[2]" TNM_NET = "hostAddress";
NET "hostAddress[3]" LOC = "P114";
NET "hostAddress[3]" TNM_NET = "hostAddress";
NET "hostAddress[4]" LOC = "P113";
NET "hostAddress[4]" TNM_NET = "hostAddress";
NET "hostAddress[5]" LOC = "P112";
NET "hostAddress[5]" TNM_NET = "hostAddress";
NET "hostAddress[6]" LOC = "P110";
NET "hostAddress[6]" TNM_NET = "hostAddress";
NET "hostData[0]" LOC = "P138";
NET "hostData[0]" TNM_NET = "hostData";
NET "hostData[1]" LOC = "P137";
NET "hostData[1]" TNM_NET = "hostData";
NET "hostData[2]" LOC = "P136";
NET "hostData[2]" TNM_NET = "hostData";
NET "hostData[3]" LOC = "P135";
NET "hostData[3]" TNM_NET = "hostData";
NET "hostData[4]" LOC = "P134";
NET "hostData[4]" TNM_NET = "hostData";
NET "hostData[5]" LOC = "P133";
NET "hostData[5]" TNM_NET = "hostData";
NET "hostData[6]" LOC = "P132";
NET "hostData[6]" TNM_NET = "hostData";
NET "hostData[7]" LOC = "P129";
NET "hostData[7]" TNM_NET = "hostData";
NET "hostData[8]" LOC = "P128";
NET "hostData[8]" TNM_NET = "hostData";
NET "hostData[9]" LOC = "P127";
NET "hostData[9]" TNM_NET = "hostData";
NET "hostData[10]" LOC = "P126";
NET "hostData[10]" TNM_NET = "hostData";
NET "hostData[11]" LOC = "P125";
NET "hostData[11]" TNM_NET = "hostData";
NET "hostData[12]" LOC = "P124";
NET "hostData[12]" TNM_NET = "hostData";
NET "hostData[13]" LOC = "P123";
NET "hostData[13]" TNM_NET = "hostData";
NET "hostData[14]" LOC = "P122";
NET "hostData[14]" TNM_NET = "hostData";
NET "hostData[15]" LOC = "P120";
NET "hostData[15]" TNM_NET = "hostData";
## SRAM interface
NET "nSRAMRead" LOC = "P40";
NET "nSRAMRead" LOC = "P40";
NET "nSRAMRead" TNM_NET = "sramControl";
NET "nSRAMRead" FAST;
NET "nSRAMWrite" LOC = "P55";
NET "nSRAMWrite" LOC = "P55";
NET "nSRAMWrite" TNM_NET = "sramControl";
NET "nSRAMWrite" FAST;
NET "nSRAMEnable" LOC = "P34";
NET "nSRAMEnable" LOC = "P34";
NET "nSRAMEnable" TNM_NET = "sramControl";
NET "nSRAMEnable" FAST;
NET "sramAddress[0]" LOC = "P30";
NET "sramAddress[1]" LOC = "P32";
NET "sramAddress[2]" LOC = "P35";
NET "sramAddress[3]" LOC = "P37";
NET "sramAddress[4]" LOC = "P41";
NET "sramAddress[5]" LOC = "P43";
NET "sramAddress[6]" LOC = "P45";
NET "sramAddress[7]" LOC = "P47";
NET "sramAddress[8]" LOC = "P46";
NET "sramAddress[9]" LOC = "P44";
NET "sramAddress[10]" LOC = "P36";
NET "sramAddress[11]" LOC = "P42";
NET "sramAddress[12]" LOC = "P49";
NET "sramAddress[13]" LOC = "P48";
NET "sramAddress[14]" LOC = "P56";
NET "sramAddress[15]" LOC = "P58";
NET "sramAddress[16]" LOC = "P57";
NET "sramAddress[0]" LOC = "P30";
NET "sramAddress[0]" TNM_NET = "sramAddress";
NET "sramAddress[1]" LOC = "P32";
NET "sramAddress[0]" TNM_NET = "sramAddress";
NET "sramAddress[2]" LOC = "P35";
NET "sramAddress[0]" TNM_NET = "sramAddress";
NET "sramAddress[3]" LOC = "P37";
NET "sramAddress[0]" TNM_NET = "sramAddress";
NET "sramAddress[4]" LOC = "P41";
NET "sramAddress[0]" TNM_NET = "sramAddress";
NET "sramAddress[5]" LOC = "P43";
NET "sramAddress[0]" TNM_NET = "sramAddress";
NET "sramAddress[6]" LOC = "P45";
NET "sramAddress[0]" TNM_NET = "sramAddress";
NET "sramAddress[7]" LOC = "P47";
NET "sramAddress[0]" TNM_NET = "sramAddress";
NET "sramAddress[8]" LOC = "P46";
NET "sramAddress[0]" TNM_NET = "sramAddress";
NET "sramAddress[9]" LOC = "P44";
NET "sramAddress[0]" TNM_NET = "sramAddress";
NET "sramAddress[10]" LOC = "P36";
NET "sramAddress[10]" TNM_NET = "sramAddress";
NET "sramAddress[11]" LOC = "P42";
NET "sramAddress[11]" TNM_NET = "sramAddress";
NET "sramAddress[12]" LOC = "P49";
NET "sramAddress[12]" TNM_NET = "sramAddress";
NET "sramAddress[13]" LOC = "P48";
NET "sramAddress[13]" TNM_NET = "sramAddress";
NET "sramAddress[14]" LOC = "P56";
NET "sramAddress[14]" TNM_NET = "sramAddress";
NET "sramAddress[15]" LOC = "P58";
NET "sramAddress[15]" TNM_NET = "sramAddress";
NET "sramAddress[16]" LOC = "P57";
NET "sramAddress[16]" TNM_NET = "sramAddress";
NET "sramData[0]" LOC = "P28";
NET "sramData[1]" LOC = "P24";
NET "sramData[2]" LOC = "P22";
NET "sramData[3]" LOC = "P21";
NET "sramData[4]" LOC = "P23";
NET "sramData[5]" LOC = "P27";
NET "sramData[6]" LOC = "P29";
NET "sramData[7]" LOC = "P31";
NET "sramData[0]" LOC = "P28";
NET "sramData[0]" TNM_NET = "sramData";
NET "sramData[1]" LOC = "P24";
NET "sramData[1]" TNM_NET = "sramData";
NET "sramData[2]" LOC = "P22";
NET "sramData[2]" TNM_NET = "sramData";
NET "sramData[3]" LOC = "P21";
NET "sramData[3]" TNM_NET = "sramData";
NET "sramData[4]" LOC = "P23";
NET "sramData[4]" TNM_NET = "sramData";
NET "sramData[5]" LOC = "P27";
NET "sramData[5]" TNM_NET = "sramData";
NET "sramData[6]" LOC = "P29";
NET "sramData[6]" TNM_NET = "sramData";
NET "sramData[7]" LOC = "P31";
NET "sramData[7]" TNM_NET = "sramData";
## DRAM interface
# 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 "dramControl[0]" LOC = "P188";
NET "dramControl[0]" TNM_NET = "dramControl";
NET "dramControl[1]" LOC = "P189";
NET "dramControl[1]" TNM_NET = "dramControl";
NET "dramControl[2]" LOC = "P190";
NET "dramControl[2]" TNM_NET = "dramControl";
NET "dramControl[3]" LOC = "P191";
NET "dramControl[3]" TNM_NET = "dramControl";
NET "dramControl[4]" LOC = "P193";
NET "dramControl[4]" TNM_NET = "dramControl";
NET "dramControl[5]" LOC = "P194";
NET "dramControl[5]" TNM_NET = "dramControl";
NET "dramControl[6]" LOC = "P196";
NET "dramControl[6]" TNM_NET = "dramControl";
NET "dramControl[7]" LOC = "P197";
NET "dramControl[7]" TNM_NET = "dramControl";
NET "dramControl[8]" LOC = "P198";
NET "dramControl[8]" TNM_NET = "dramControl";
NET "dramControl[9]" LOC = "P199";
NET "dramControl[9]" TNM_NET = "dramControl";
NET "dramControl[10]" LOC = "P200";
NET "dramControl[10]" TNM_NET = "dramControl";
NET "dramControl[11]" LOC = "P201";
NET "dramControl[11]" TNM_NET = "dramControl";
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 "dramAddress[0]" LOC = "P186";
NET "dramAddress[0]" TNM_NET = "dramAddress";
NET "dramAddress[1]" LOC = "P184";
NET "dramAddress[1]" TNM_NET = "dramAddress";
NET "dramAddress[2]" LOC = "P180";
NET "dramAddress[2]" TNM_NET = "dramAddress";
NET "dramAddress[3]" LOC = "P178";
NET "dramAddress[3]" TNM_NET = "dramAddress";
NET "dramAddress[4]" LOC = "P176";
NET "dramAddress[4]" TNM_NET = "dramAddress";
NET "dramAddress[5]" LOC = "P174";
NET "dramAddress[5]" TNM_NET = "dramAddress";
NET "dramAddress[6]" LOC = "P175";
NET "dramAddress[6]" TNM_NET = "dramAddress";
NET "dramAddress[7]" LOC = "P177";
NET "dramAddress[7]" TNM_NET = "dramAddress";
NET "dramAddress[8]" LOC = "P179";
NET "dramAddress[8]" TNM_NET = "dramAddress";
NET "dramAddress[9]" LOC = "P181";
NET "dramAddress[9]" TNM_NET = "dramAddress";
NET "dramAddress[10]" LOC = "P185";
NET "dramAddress[10]" TNM_NET = "dramAddress";
NET "dramAddress[11]" LOC = "P187";
NET "dramAddress[11]" TNM_NET = "dramAddress";
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";
NET "dramData[0]" LOC = "P15";
NET "dramData[0]" TNM_NET = "dramData";
NET "dramData[1]" LOC = "P14";
NET "dramData[1]" TNM_NET = "dramData";
NET "dramData[2]" LOC = "P10";
NET "dramData[2]" TNM_NET = "dramData";
NET "dramData[3]" LOC = "P8";
NET "dramData[3]" TNM_NET = "dramData";
NET "dramData[4]" LOC = "P2";
NET "dramData[4]" TNM_NET = "dramData";
NET "dramData[5]" LOC = "P206";
NET "dramData[5]" TNM_NET = "dramData";
NET "dramData[6]" LOC = "P205";
NET "dramData[6]" TNM_NET = "dramData";
NET "dramData[7]" LOC = "P204";
NET "dramData[7]" TNM_NET = "dramData";
NET "dramData[8]" LOC = "P3";
NET "dramData[8]" TNM_NET = "dramData";
NET "dramData[9]" LOC = "P4";
NET "dramData[9]" TNM_NET = "dramData";
NET "dramData[10]" LOC = "P5";
NET "dramData[10]" TNM_NET = "dramData";
NET "dramData[11]" LOC = "P9";
NET "dramData[11]" TNM_NET = "dramData";
NET "dramData[12]" LOC = "P11";
NET "dramData[12]" TNM_NET = "dramData";
NET "dramData[13]" LOC = "P17";
NET "dramData[13]" TNM_NET = "dramData";
NET "dramData[14]" LOC = "P19";
NET "dramData[14]" TNM_NET = "dramData";
NET "dramData[15]" LOC = "P20";
NET "dramData[15]" TNM_NET = "dramData";
## 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 "mp3ClockIn" LOC = "P163";
NET "mp3ClockIn" TNM_NET = "mp3Clock";
NET "mp3ClockOut" LOC = "P162";
NET "mp3ClockOut" TNM_NET = "mp3Clock";
NET "mp3Reset" LOC = "P152";
NET "mp3Ready" LOC = "P159";
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";
NET "mp3InSDIN" LOC = "P167";
NET "mp3InSDIN" TNM_NET = "mp3Data";
NET "mp3InBCLK" LOC = "P164";
NET "mp3InBCLK" TNM_NET = "mp3Data";
NET "mp3InLRCK" LOC = "P166";
NET "mp3InLRCK" TNM_NET = "mp3Data";
NET "mp3OutSDOUT" LOC = "P172";
NET "mp3OutSDOUT" TNM_NET = "mp3Data";
NET "mp3OutBCLK" LOC = "P169";
NET "mp3OutBCLK" TNM_NET = "mp3Data";
NET "mp3OutLRCK" LOC = "P171";
NET "mp3OutLRCK" TNM_NET = "mp3Data";
## I2S audio output
NET "dacSDIN" LOC = "P96";
NET "dacBCLK" LOC = "P94";
NET "dacLRCK" LOC = "P95";
NET "dacMCLK" LOC = "P97";
NET "dacSDIN" LOC = "P96";
NET "dacSDIN" TNM_NET = "dacData";
NET "dacBCLK" LOC = "P94";
NET "dacBCLK" TNM_NET = "dacData";
NET "dacLRCK" LOC = "P95";
NET "dacLRCK" TNM_NET = "dacData";
NET "dacMCLK" LOC = "P97";
NET "dacMCLK" TNM_NET = "dacData";
## Light outputs
@ -186,16 +297,25 @@ NET "lightBankD[3]" LOC = "P59";
## Serial interfaces
# TODO: are pins 98 and 99 swapped?
NET "networkTXEnable" LOC = "P98";
NET "networkTX" LOC = "P99";
NET "networkRX" LOC = "P100";
NET "networkTXEnable" LOC = "P98";
NET "networkTXEnable" TNM_NET = "network";
NET "networkTX" LOC = "P99";
NET "networkTX" TNM_NET = "network";
NET "networkRX" LOC = "P100";
NET "networkRX" TNM_NET = "network";
NET "serialTX" LOC = "P89";
NET "serialRX" LOC = "P88";
NET "serialRTS" LOC = "P93";
NET "serialCTS" LOC = "P90";
NET "serialDTR" LOC = "P87";
NET "serialDSR" LOC = "P85";
NET "serialTX" LOC = "P89";
NET "serialTX" TNM_NET = "serial";
NET "serialRX" LOC = "P88";
NET "serialRX" TNM_NET = "serial";
NET "serialRTS" LOC = "P93";
NET "serialRTS" TNM_NET = "serial";
NET "serialCTS" LOC = "P90";
NET "serialCTS" TNM_NET = "serial";
NET "serialDTR" LOC = "P87";
NET "serialDTR" TNM_NET = "serial";
NET "serialDSR" LOC = "P85";
NET "serialDSR" TNM_NET = "serial";
## 1-wire bus

View File

@ -1,16 +1,17 @@
# This script is roughly similar to the built-in synth_xilinx command, with the
# appropriate modifications made in order to output gate netlists rather than
# precompiled LUTs. Note that more advanced features such as fast carry or
# distributed LUT RAM are not yet supported.
# precompiled LUTs (which are not supported by the ISE mapper for Spartan-XL
# devices). Note that more advanced features such as fast carry or distributed
# LUT RAMs are not yet supported.
## Input and preliminary optimization
read_verilog src/main.v
read_verilog src/spartanxl.v
read_verilog src/spartanxl/primitives.v
hierarchy -check -top FPGA
proc
flatten -noscopeinfo
flatten
tribuf -logic
deminout
opt_expr
@ -25,15 +26,16 @@ opt_clean
## Conversion to gate-level representation
techmap -D LUT_WIDTH=4 -map +/cmp2lut.v -map +/cmp2lcu.v
alumacc
share
opt
memory -nomap
opt_clean
memory_map
opt -full
simplemap
techmap -D NOLUT -D LUT_SIZE=4 -map +/techmap.v -map +/xilinx/arith_map.v
techmap -map +/techmap.v
opt -fast
clean
@ -41,25 +43,26 @@ clean
dfflegalize -cell $_DFFE_PP?P_ r -cell $_DLATCH_PP?_ r
opt_expr -mux_undef -noclkinv
abc -g gates
xilinx_dffopt -lut4
abc -liberty src/spartanxl/primitives.lib
clean
#clkbufmap -buf BUFGLS O:I
#hilomap -hicell VCC P -locell GND G
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
techmap -map src/techmap.v
iopadmap -bits -outpad OBUF I:O -toutpad OBUFE E:I:O -tinoutpad IOBUFE E:O:I:IO -ignore IPAD IPAD -ignore OPAD OPAD -ignore IOPAD IOPAD -ignore OFDX Q -ignore OFDXI Q -ignore OFDTX O -ignore OFDTXI O
clkbufmap -buf BUFGLS O:I
#extractinv -inv INV O:I
techmap -map src/spartanxl/map.v
clean
## Output
# FIXME: for some reason invoking hierarchy here results in $or/$reduce_or
# primitives being added back when using wired-or
#hierarchy -check
hierarchy -check
autoname
stat -tech xilinx
check -noinit
blackbox =A:whitebox
show -notitle -colors 1 -format dot -viewer none -prefix build/synth
write_verilog -noattr build/synth.v
write_edif -top FPGA -pvector bra -lsbidx build/synth.edf

View File

@ -2,9 +2,9 @@
setlocal
set TARGET=xcs40xl-pq208-4
set COVER_MODE=area
set COVER_MODE=speed
set OPTIMIZATION_MODE=speed
set OPTIMIZATION_LEVEL=high
set OPTIMIZATION_LEVEL=normal
if not exist "%XILINX%\bin\nt\" (
echo The XILINX environment variable must be set to the root of a valid ^

View File

@ -22,10 +22,11 @@ module FPGA (
output [11:0] dramAddress,
inout [15:0] dramData,
output mp3Reset,
input mp3Ready,
output mp3ClockIn,
input mp3ClockOut,
output mp3Reset,
input mp3Ready,
inout mp3SDA,
inout mp3SCL,
@ -69,113 +70,99 @@ module FPGA (
/* Register definitions */
localparam SYS573D_FPGA_MAGIC = 8'h80;
function automatic [5:0] _hostReg (input [7:0] address);
_hostReg = address[6:1];
endfunction
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_MAGIC = _hostReg(8'h80);
localparam SYS573D_FPGA_VERSION = _hostReg(8'h82);
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_MP3_PTR_H = _hostReg(8'ha0);
localparam SYS573D_FPGA_MP3_PTR_L = _hostReg(8'ha2);
localparam SYS573D_FPGA_MP3_ENDPTR_H = _hostReg(8'ha4);
localparam SYS573D_FPGA_MP3_ENDPTR_L = _hostReg(8'ha6);
localparam SYS573D_FPGA_MP3_COUNTER = _hostReg(8'ha8);
localparam SYS573D_FPGA_MP3_KEY1 = _hostReg(8'ha8);
localparam SYS573D_FPGA_MP3_FEED_STAT = _hostReg(8'haa);
localparam SYS573D_FPGA_MP3_I2C = _hostReg(8'hac);
localparam SYS573D_FPGA_MP3_FEED_CTRL = _hostReg(8'hae);
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_DRAM_WRPTR_H = _hostReg(8'hb0);
localparam SYS573D_FPGA_DRAM_WRPTR_L = _hostReg(8'hb2);
localparam SYS573D_FPGA_DRAM_DATA = _hostReg(8'hb4);
localparam SYS573D_FPGA_DRAM_RDPTR_H = _hostReg(8'hb6);
localparam SYS573D_FPGA_DRAM_RDPTR_L = _hostReg(8'hb8);
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;
localparam SYS573D_FPGA_NET_DATA = _hostReg(8'hc0);
localparam SYS573D_FPGA_DAC_COUNTER_H = _hostReg(8'hca);
localparam SYS573D_FPGA_DAC_COUNTER_L = _hostReg(8'hcc);
localparam SYS573D_FPGA_DAC_COUNTER_D = _hostReg(8'hce);
localparam SYS573D_FPGA_LIGHTS_AH = _hostReg(8'he0);
localparam SYS573D_FPGA_LIGHTS_AL = _hostReg(8'he2);
localparam SYS573D_FPGA_LIGHTS_BH = _hostReg(8'he4);
localparam SYS573D_FPGA_LIGHTS_D = _hostReg(8'he6);
localparam SYS573D_FPGA_INIT = _hostReg(8'he8);
localparam SYS573D_FPGA_MP3_KEY2 = _hostReg(8'hea);
localparam SYS573D_FPGA_MP3_KEY3 = _hostReg(8'hec);
localparam SYS573D_FPGA_DS_BUS = _hostReg(8'hee);
/* System clocks */
wire clock29M, clock19M;
// ISE rejects global buffer primitives unless they are wired either to an
// IBUF (which results in suboptimal routing, as the dedicated IOB clock
// output is left unused) or directly to a pad primitive.
IPAD clockPad29M (.IPAD(clockIn29M));
IPAD clockPad19M (.IPAD(clockIn19M));
BUFGLS clockBuf29M (.I(clockIn29M), .O(clock29M));
BUFGLS clockBuf19M (.I(clockIn19M), .O(clock19M));
wire clock29M;
IPAD _clockPad29M (.IPAD(clockIn29M));
BUFGLS _clockBuf29M (.I(clockIn29M), .O(clock29M));
/* Host address decoding */
wire clock19M;
IPAD _clockPad19M (.IPAD(clockIn19M));
BUFGLS _clockBuf19M (.I(clockIn19M), .O(clock19M));
/* Host interface */
wire _hostWriteLatchIn = ~nHostWrite & ~nHostEnable;
wire _hostWriteLatch;
BUFGLS _hostWriteLatchBuf (.I(_hostWriteLatchIn), .O(_hostWriteLatch));
reg [6:0] hostRegAddress;
reg [15:0] hostReadData;
reg [15:0] hostWriteData;
always @(posedge clock29M)
hostRegAddress <= hostAddress;
always @(negedge _hostWriteLatch)
hostWriteData <= hostData;
/* Read/write strobe edge detector */
reg [1:0] _hostReadState = 2'b00;
reg [1:0] _hostWriteState = 2'b00;
always @(posedge clock29M) begin
_hostReadState <= { _hostReadState[0], ~nHostRead & ~nHostEnable };
_hostWriteState <= { _hostWriteState[0], ~nHostWrite & ~nHostEnable };
end
wire hostReadAsserted = (_hostReadState == 2'b01);
wire hostReadReleased = (_hostReadState == 2'b10);
wire hostWriteAsserted = (_hostWriteState == 2'b01);
wire hostWriteReleased = (_hostWriteState == 2'b10);
// 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;
reg _hostDataDir = 1'b0;
assign hostData = _hostDataDir ? hostReadData : 16'hzzzz;
wire [7:0] hostRegister = { 1'b1, hostAddress[5:0], 1'b0 };
/* Host interface */
reg [2:0] _delayedHostRegRead = 3'b000;
wire _hostDataInClock;
wire [15:0] hostDataIn;
wor [15:0] hostDataOut;
reg hostDataInValid = 1'b0;
reg hostDataOutValid = 1'b0;
// Data is latched in the input flip flops once the 573 *deasserts* either
// 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
for (i = 0; i < 16; i = i + 1) begin
IFDX hostDataInReg (
.D(hostData[i]),
.C(~_hostDataInClock),
.CE(1'b1),
.Q(hostDataIn[i])
);
OFDTX hostDataOutReg (
.D(hostDataOut[i]),
.C(clock29M),
.CE(~_delayedHostRegRead[2]),
.T(~hostDataOutValid),
.O(hostData[i])
);
end
endgenerate
always @(posedge clock29M)
_hostDataDir <= 1'b1
& ~nHostRead
& ~nHostEnable
& hostAddress[6]
& (hostAddress[5:3] != 3'b111);
/* SRAM interface (currently unused) */
@ -191,29 +178,26 @@ module FPGA (
/* MP3 decoder interface (currently unused) */
assign mp3Reset = 1'b1;
reg mp3SDAIn;
reg mp3SDAOut = 1'b1;
reg mp3SCLIn;
reg mp3SCLOut = 1'b1;
assign mp3ClockIn = 1'b1;
assign mp3Reset = 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;
assign mp3SDA = mp3SDAOut ? 1'bz : 1'b0;
assign mp3SCL = mp3SCLOut ? 1'bz : 1'b0;
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;
always @(posedge clock29M) begin
mp3SDAIn <= mp3SDA;
mp3SCLIn <= mp3SCL;
end
/* I2S audio output */
@ -222,39 +206,23 @@ module FPGA (
assign dacLRCK = mp3OutLRCK;
assign dacMCLK = mp3ClockOut;
/* Magic number */
assign hostDataOut = (hostRegister == SYS573D_FPGA_MAGIC)
? 16'h573f
: 16'h0000;
/* Light outputs */
reg [3:0] lightBankAHState = 4'b1111;
reg [3:0] lightBankALState = 4'b1111;
reg [3:0] lightBankBHState = 4'b1111;
reg [3:0] lightBankDState = 4'b1111;
generate
for (i = 0; i < 4; i = i + 1) begin
reg [3:0] lightBankState = 4'b1111;
wire dataIn = hostDataIn[i + 12];
always @(posedge clock29M)
if (hostDataInPending)
case (hostRegister)
SYS573D_FPGA_LIGHTS_AH:
lightBankState[0] <= dataIn;
SYS573D_FPGA_LIGHTS_AL:
lightBankState[1] <= dataIn;
SYS573D_FPGA_LIGHTS_BH:
lightBankState[2] <= dataIn;
SYS573D_FPGA_LIGHTS_D:
lightBankState[3] <= dataIn;
endcase
// 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;
// Note that XCS40XL IOBs actually have a built-in tristate flip
// flop, but ISE will not use it here as it does not have a clock
// enable input (used to gate writes to the state registers) and
// cannot be read back nor configured to be set on startup.
assign lightBankAH[i] = lightBankAHState[i] ? 1'bz : 1'b0;
assign lightBankAL[i] = lightBankALState[i] ? 1'bz : 1'b0;
assign lightBankBH[i] = lightBankBHState[i] ? 1'bz : 1'b0;
assign lightBankD[i] = lightBankDState[i] ? 1'bz : 1'b0;
end
endgenerate
@ -269,21 +237,81 @@ module FPGA (
/* 1-wire bus */
assign hostDataOut = (hostRegister == SYS573D_FPGA_DS_BUS)
? { 3'h0, ds2401, 3'h0, ds2433, 8'h00 }
: 16'h0000;
reg ds2433State = 1'b0;
reg ds2401State = 1'b0;
always @(posedge clock29M)
if (hostDataInPending & (hostRegister == SYS573D_FPGA_DS_BUS)) begin
ds2433State <= hostDataIn[8];
ds2401State <= hostDataIn[12];
end
reg ds2433In;
reg ds2433Out = 1'b0;
reg ds2401In;
reg ds2401Out = 1'b0;
// The 1-wire pins are pulled low by writing 1 (rather than 0) to the
// respective register bits, but not inverted when read.
assign ds2433 = ds2433State ? 1'b0 : 1'bz;
assign ds2401 = ds2401State ? 1'b0 : 1'bz;
assign ds2433 = ds2433Out ? 1'b0 : 1'bz;
assign ds2401 = ds2401Out ? 1'b0 : 1'bz;
always @(posedge clock29M) begin
ds2433In <= ds2433;
ds2401In <= ds2401;
end
/* Host registers */
always @(posedge clock29M)
case (hostRegAddress[5:0])
SYS573D_FPGA_MAGIC: begin
hostReadData <= 16'h573f;
end
SYS573D_FPGA_VERSION: begin
hostReadData <= 16'h0001;
end
SYS573D_FPGA_MP3_I2C: begin
hostReadData <= { 2'h0, mp3SCLIn, mp3SDAIn, 12'h000 };
if (hostWriteReleased) begin
mp3SDAOut <= hostWriteData[12];
mp3SCLOut <= hostWriteData[13];
end
end
SYS573D_FPGA_LIGHTS_AH: begin
hostReadData <= { lightBankAHState, 12'h000 };
if (hostWriteReleased)
lightBankAHState <= hostWriteData[15:12];
end
SYS573D_FPGA_LIGHTS_AL: begin
hostReadData <= { lightBankALState, 12'h000 };
if (hostWriteReleased)
lightBankALState <= hostWriteData[15:12];
end
SYS573D_FPGA_LIGHTS_BH: begin
hostReadData <= { lightBankBHState, 12'h000 };
if (hostWriteReleased)
lightBankBHState <= hostWriteData[15:12];
end
SYS573D_FPGA_LIGHTS_D: begin
hostReadData <= { lightBankDState, 12'h000 };
if (hostWriteReleased)
lightBankDState <= hostWriteData[15:12];
end
SYS573D_FPGA_DS_BUS: begin
hostReadData <= { 3'h0, ds2401In, 3'h0, ds2433In, 8'h00 };
if (hostWriteReleased) begin
ds2433Out <= hostWriteData[8];
ds2401Out <= hostWriteData[12];
end
end
default: begin
hostReadData <= 16'hxxxx;
end
endcase
endmodule

View File

@ -1,368 +0,0 @@
/* 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

37
fpga/src/spartanxl/map.v Normal file
View File

@ -0,0 +1,37 @@
/* I/O cells */
module OBUFE (input I, input E, output O);
wire T;
INV _TECHMAP_REPLACE_.inv (.I(E), .O(T));
OBUFT _TECHMAP_REPLACE_.obuf (.I(I), .T(T), .O(O));
endmodule
module IOBUFE (input I, input E, output O, inout IO);
wire T;
INV _TECHMAP_REPLACE_.inv (.I(E), .O(T));
OBUFT _TECHMAP_REPLACE_.obuf (.I(I), .T(T), .O(IO));
IBUF _TECHMAP_REPLACE_.ibuf (.I(IO), .O(O));
endmodule
/* Flip flops and latches */
// The dfflibmap command does not currently support mapping memory cells with an
// enable input, so these have to be declared here rather than in spartanxl.lib.
module \$_DFFE_PP0P_ (input D, input C, input R, input E, output Q);
FDCE _TECHMAP_REPLACE_ (.D(D), .C(C), .CLR(R), .CE(E), .Q(Q));
endmodule
module \$_DFFE_PP1P_ (input D, input C, input R, input E, output Q);
FDPE _TECHMAP_REPLACE_ (.D(D), .C(C), .PRE(R), .CE(E), .Q(Q));
endmodule
module \$_DLATCH_PP0_ (input E, input R, input D, output Q);
LDCE_1 _TECHMAP_REPLACE_ (.D(D), .G(E), .CLR(R), .GE(1'b1), .Q(Q));
endmodule
module \$_DLATCH_PP1_ (input E, input R, input D, output Q);
LDPE_1 _TECHMAP_REPLACE_ (.D(D), .G(E), .PRE(R), .GE(1'b1), .Q(Q));
endmodule

View File

@ -0,0 +1,551 @@
library(spartanxl) {
/* Buffers */
cell(BUF) {
area: 1;
pin(I) { direction: input; }
pin(O) { direction: output; function: "I"; }
}
cell(INV) {
area: 1;
pin(I) { direction: input; }
pin(O) { direction: output; function: "!I"; }
}
/* AND gates */
cell(AND2) {
area: 1;
pin(I0) { direction: input; }
pin(I1) { direction: input; }
pin(O) { direction: output; function: "I0*I1"; }
}
cell(AND2B1) {
area: 1;
pin(I0) { direction: input; }
pin(I1) { direction: input; }
pin(O) { direction: output; function: "!I0*I1"; }
}
cell(AND3) {
area: 1;
pin(I0) { direction: input; }
pin(I1) { direction: input; }
pin(I2) { direction: input; }
pin(O) { direction: output; function: "I0*I1*I2"; }
}
cell(AND3B1) {
area: 1;
pin(I0) { direction: input; }
pin(I1) { direction: input; }
pin(I2) { direction: input; }
pin(O) { direction: output; function: "!I0*I1*I2"; }
}
cell(AND3B2) {
area: 1;
pin(I0) { direction: input; }
pin(I1) { direction: input; }
pin(I2) { direction: input; }
pin(O) { direction: output; function: "!I0*!I1*I2"; }
}
cell(AND4) {
area: 1;
pin(I0) { direction: input; }
pin(I1) { direction: input; }
pin(I2) { direction: input; }
pin(I3) { direction: input; }
pin(O) { direction: output; function: "I0*I1*I2*I3"; }
}
cell(AND4B1) {
area: 1;
pin(I0) { direction: input; }
pin(I1) { direction: input; }
pin(I2) { direction: input; }
pin(I3) { direction: input; }
pin(O) { direction: output; function: "!I0*I1*I2*I3"; }
}
cell(AND4B2) {
area: 1;
pin(I0) { direction: input; }
pin(I1) { direction: input; }
pin(I2) { direction: input; }
pin(I3) { direction: input; }
pin(O) { direction: output; function: "!I0*!I1*I2*I3"; }
}
cell(AND4B3) {
area: 1;
pin(I0) { direction: input; }
pin(I1) { direction: input; }
pin(I2) { direction: input; }
pin(I3) { direction: input; }
pin(O) { direction: output; function: "!I0*!I1*!I2*I3"; }
}
cell(AND5) {
area: 1;
pin(I0) { direction: input; }
pin(I1) { direction: input; }
pin(I2) { direction: input; }
pin(I3) { direction: input; }
pin(I4) { direction: input; }
pin(O) { direction: output; function: "I0*I1*I2*I3*I4"; }
}
cell(AND5B1) {
area: 1;
pin(I0) { direction: input; }
pin(I1) { direction: input; }
pin(I2) { direction: input; }
pin(I3) { direction: input; }
pin(I4) { direction: input; }
pin(O) { direction: output; function: "!I0*I1*I2*I3*I4"; }
}
cell(AND5B2) {
area: 1;
pin(I0) { direction: input; }
pin(I1) { direction: input; }
pin(I2) { direction: input; }
pin(I3) { direction: input; }
pin(I4) { direction: input; }
pin(O) { direction: output; function: "!I0*!I1*I2*I3*I4"; }
}
cell(AND5B3) {
area: 1;
pin(I0) { direction: input; }
pin(I1) { direction: input; }
pin(I2) { direction: input; }
pin(I3) { direction: input; }
pin(I4) { direction: input; }
pin(O) { direction: output; function: "!I0*!I1*!I2*I3*I4"; }
}
cell(AND5B4) {
area: 1;
pin(I0) { direction: input; }
pin(I1) { direction: input; }
pin(I2) { direction: input; }
pin(I3) { direction: input; }
pin(I4) { direction: input; }
pin(O) { direction: output; function: "!I0*!I1*!I2*!I3*I4"; }
}
/* NAND gates */
cell(NAND2) {
area: 1;
pin(I0) { direction: input; }
pin(I1) { direction: input; }
pin(O) { direction: output; function: "!(I0*I1)"; }
}
cell(NAND2B1) {
area: 1;
pin(I0) { direction: input; }
pin(I1) { direction: input; }
pin(O) { direction: output; function: "!(!I0*I1)"; }
}
cell(NAND3) {
area: 1;
pin(I0) { direction: input; }
pin(I1) { direction: input; }
pin(I2) { direction: input; }
pin(O) { direction: output; function: "!(I0*I1*I2)"; }
}
cell(NAND3B1) {
area: 1;
pin(I0) { direction: input; }
pin(I1) { direction: input; }
pin(I2) { direction: input; }
pin(O) { direction: output; function: "!(!I0*I1*I2)"; }
}
cell(NAND3B2) {
area: 1;
pin(I0) { direction: input; }
pin(I1) { direction: input; }
pin(I2) { direction: input; }
pin(O) { direction: output; function: "!(!I0*!I1*I2)"; }
}
cell(NAND4) {
area: 1;
pin(I0) { direction: input; }
pin(I1) { direction: input; }
pin(I2) { direction: input; }
pin(I3) { direction: input; }
pin(O) { direction: output; function: "!(I0*I1*I2*I3)"; }
}
cell(NAND4B1) {
area: 1;
pin(I0) { direction: input; }
pin(I1) { direction: input; }
pin(I2) { direction: input; }
pin(I3) { direction: input; }
pin(O) { direction: output; function: "!(!I0*I1*I2*I3)"; }
}
cell(NAND4B2) {
area: 1;
pin(I0) { direction: input; }
pin(I1) { direction: input; }
pin(I2) { direction: input; }
pin(I3) { direction: input; }
pin(O) { direction: output; function: "!(!I0*!I1*I2*I3)"; }
}
cell(NAND4B3) {
area: 1;
pin(I0) { direction: input; }
pin(I1) { direction: input; }
pin(I2) { direction: input; }
pin(I3) { direction: input; }
pin(O) { direction: output; function: "!(!I0*!I1*!I2*I3)"; }
}
cell(NAND5) {
area: 1;
pin(I0) { direction: input; }
pin(I1) { direction: input; }
pin(I2) { direction: input; }
pin(I3) { direction: input; }
pin(I4) { direction: input; }
pin(O) { direction: output; function: "!(I0*I1*I2*I3*I4)"; }
}
cell(NAND5B1) {
area: 1;
pin(I0) { direction: input; }
pin(I1) { direction: input; }
pin(I2) { direction: input; }
pin(I3) { direction: input; }
pin(I4) { direction: input; }
pin(O) { direction: output; function: "!(!I0*I1*I2*I3*I4)"; }
}
cell(NAND5B2) {
area: 1;
pin(I0) { direction: input; }
pin(I1) { direction: input; }
pin(I2) { direction: input; }
pin(I3) { direction: input; }
pin(I4) { direction: input; }
pin(O) { direction: output; function: "!(!I0*!I1*I2*I3*I4)"; }
}
cell(NAND5B3) {
area: 1;
pin(I0) { direction: input; }
pin(I1) { direction: input; }
pin(I2) { direction: input; }
pin(I3) { direction: input; }
pin(I4) { direction: input; }
pin(O) { direction: output; function: "!(!I0*!I1*!I2*I3*I4)"; }
}
cell(NAND5B4) {
area: 1;
pin(I0) { direction: input; }
pin(I1) { direction: input; }
pin(I2) { direction: input; }
pin(I3) { direction: input; }
pin(I4) { direction: input; }
pin(O) { direction: output; function: "!(!I0*!I1*!I2*!I3*I4)"; }
}
/* OR gates */
cell(OR2) {
area: 1;
pin(I0) { direction: input; }
pin(I1) { direction: input; }
pin(O) { direction: output; function: "I0+I1"; }
}
cell(OR2B1) {
area: 1;
pin(I0) { direction: input; }
pin(I1) { direction: input; }
pin(O) { direction: output; function: "!I0+I1"; }
}
cell(OR3) {
area: 1;
pin(I0) { direction: input; }
pin(I1) { direction: input; }
pin(I2) { direction: input; }
pin(O) { direction: output; function: "I0+I1+I2"; }
}
cell(OR3B1) {
area: 1;
pin(I0) { direction: input; }
pin(I1) { direction: input; }
pin(I2) { direction: input; }
pin(O) { direction: output; function: "!I0+I1+I2"; }
}
cell(OR3B2) {
area: 1;
pin(I0) { direction: input; }
pin(I1) { direction: input; }
pin(I2) { direction: input; }
pin(O) { direction: output; function: "!I0+!I1+I2"; }
}
cell(OR4) {
area: 1;
pin(I0) { direction: input; }
pin(I1) { direction: input; }
pin(I2) { direction: input; }
pin(I3) { direction: input; }
pin(O) { direction: output; function: "I0+I1+I2+I3"; }
}
cell(OR4B1) {
area: 1;
pin(I0) { direction: input; }
pin(I1) { direction: input; }
pin(I2) { direction: input; }
pin(I3) { direction: input; }
pin(O) { direction: output; function: "!I0+I1+I2+I3"; }
}
cell(OR4B2) {
area: 1;
pin(I0) { direction: input; }
pin(I1) { direction: input; }
pin(I2) { direction: input; }
pin(I3) { direction: input; }
pin(O) { direction: output; function: "!I0+!I1+I2+I3"; }
}
cell(OR4B3) {
area: 1;
pin(I0) { direction: input; }
pin(I1) { direction: input; }
pin(I2) { direction: input; }
pin(I3) { direction: input; }
pin(O) { direction: output; function: "!I0+!I1+!I2+I3"; }
}
cell(OR5) {
area: 1;
pin(I0) { direction: input; }
pin(I1) { direction: input; }
pin(I2) { direction: input; }
pin(I3) { direction: input; }
pin(I4) { direction: input; }
pin(O) { direction: output; function: "I0+I1+I2+I3+I4"; }
}
cell(OR5B1) {
area: 1;
pin(I0) { direction: input; }
pin(I1) { direction: input; }
pin(I2) { direction: input; }
pin(I3) { direction: input; }
pin(I4) { direction: input; }
pin(O) { direction: output; function: "!I0+I1+I2+I3+I4"; }
}
cell(OR5B2) {
area: 1;
pin(I0) { direction: input; }
pin(I1) { direction: input; }
pin(I2) { direction: input; }
pin(I3) { direction: input; }
pin(I4) { direction: input; }
pin(O) { direction: output; function: "!I0+!I1+I2+I3+I4"; }
}
cell(OR5B3) {
area: 1;
pin(I0) { direction: input; }
pin(I1) { direction: input; }
pin(I2) { direction: input; }
pin(I3) { direction: input; }
pin(I4) { direction: input; }
pin(O) { direction: output; function: "!I0+!I1+!I2+I3+I4"; }
}
cell(OR5B4) {
area: 1;
pin(I0) { direction: input; }
pin(I1) { direction: input; }
pin(I2) { direction: input; }
pin(I3) { direction: input; }
pin(I4) { direction: input; }
pin(O) { direction: output; function: "!I0+!I1+!I2+!I3+I4"; }
}
/* NOR gates */
cell(NOR2) {
area: 1;
pin(I0) { direction: input; }
pin(I1) { direction: input; }
pin(O) { direction: output; function: "!(I0+I1)"; }
}
cell(NOR2B1) {
area: 1;
pin(I0) { direction: input; }
pin(I1) { direction: input; }
pin(O) { direction: output; function: "!(!I0+I1)"; }
}
cell(NOR3) {
area: 1;
pin(I0) { direction: input; }
pin(I1) { direction: input; }
pin(I2) { direction: input; }
pin(O) { direction: output; function: "!(I0+I1+I2)"; }
}
cell(NOR3B1) {
area: 1;
pin(I0) { direction: input; }
pin(I1) { direction: input; }
pin(I2) { direction: input; }
pin(O) { direction: output; function: "!(!I0+I1+I2)"; }
}
cell(NOR3B2) {
area: 1;
pin(I0) { direction: input; }
pin(I1) { direction: input; }
pin(I2) { direction: input; }
pin(O) { direction: output; function: "!(!I0+!I1+I2)"; }
}
cell(NOR4) {
area: 1;
pin(I0) { direction: input; }
pin(I1) { direction: input; }
pin(I2) { direction: input; }
pin(I3) { direction: input; }
pin(O) { direction: output; function: "!(I0+I1+I2+I3)"; }
}
cell(NOR4B1) {
area: 1;
pin(I0) { direction: input; }
pin(I1) { direction: input; }
pin(I2) { direction: input; }
pin(I3) { direction: input; }
pin(O) { direction: output; function: "!(!I0+I1+I2+I3)"; }
}
cell(NOR4B2) {
area: 1;
pin(I0) { direction: input; }
pin(I1) { direction: input; }
pin(I2) { direction: input; }
pin(I3) { direction: input; }
pin(O) { direction: output; function: "!(!I0+!I1+I2+I3)"; }
}
cell(NOR4B3) {
area: 1;
pin(I0) { direction: input; }
pin(I1) { direction: input; }
pin(I2) { direction: input; }
pin(I3) { direction: input; }
pin(O) { direction: output; function: "!(!I0+!I1+!I2+I3)"; }
}
cell(NOR5) {
area: 1;
pin(I0) { direction: input; }
pin(I1) { direction: input; }
pin(I2) { direction: input; }
pin(I3) { direction: input; }
pin(I4) { direction: input; }
pin(O) { direction: output; function: "!(I0+I1+I2+I3+I4)"; }
}
cell(NOR5B1) {
area: 1;
pin(I0) { direction: input; }
pin(I1) { direction: input; }
pin(I2) { direction: input; }
pin(I3) { direction: input; }
pin(I4) { direction: input; }
pin(O) { direction: output; function: "!(!I0+I1+I2+I3+I4)"; }
}
cell(NOR5B2) {
area: 1;
pin(I0) { direction: input; }
pin(I1) { direction: input; }
pin(I2) { direction: input; }
pin(I3) { direction: input; }
pin(I4) { direction: input; }
pin(O) { direction: output; function: "!(!I0+!I1+I2+I3+I4)"; }
}
cell(NOR5B3) {
area: 1;
pin(I0) { direction: input; }
pin(I1) { direction: input; }
pin(I2) { direction: input; }
pin(I3) { direction: input; }
pin(I4) { direction: input; }
pin(O) { direction: output; function: "!(!I0+!I1+!I2+I3+I4)"; }
}
cell(NOR5B4) {
area: 1;
pin(I0) { direction: input; }
pin(I1) { direction: input; }
pin(I2) { direction: input; }
pin(I3) { direction: input; }
pin(I4) { direction: input; }
pin(O) { direction: output; function: "!(!I0+!I1+!I2+!I3+I4)"; }
}
/* XOR gates */
cell(XOR2) {
area: 1;
pin(I0) { direction: input; }
pin(I1) { direction: input; }
pin(O) { direction: output; function: "I0^I1"; }
}
cell(XOR3) {
area: 1;
pin(I0) { direction: input; }
pin(I1) { direction: input; }
pin(I2) { direction: input; }
pin(O) { direction: output; function: "I0^I1^I2"; }
}
cell(XOR4) {
area: 1;
pin(I0) { direction: input; }
pin(I1) { direction: input; }
pin(I2) { direction: input; }
pin(I3) { direction: input; }
pin(O) { direction: output; function: "I0^I1^I2^I3"; }
}
cell(XOR5) {
area: 1;
pin(I0) { direction: input; }
pin(I1) { direction: input; }
pin(I2) { direction: input; }
pin(I3) { direction: input; }
pin(I4) { direction: input; }
pin(O) { direction: output; function: "I0^I1^I2^I3^I4"; }
}
/* XNOR gates */
cell(XNOR2) {
area: 1;
pin(I0) { direction: input; }
pin(I1) { direction: input; }
pin(O) { direction: output; function: "!(I0^I1)"; }
}
cell(XNOR3) {
area: 1;
pin(I0) { direction: input; }
pin(I1) { direction: input; }
pin(I2) { direction: input; }
pin(O) { direction: output; function: "!(I0^I1^I2)"; }
}
cell(XNOR4) {
area: 1;
pin(I0) { direction: input; }
pin(I1) { direction: input; }
pin(I2) { direction: input; }
pin(I3) { direction: input; }
pin(O) { direction: output; function: "!(I0^I1^I2^I3)"; }
}
cell(XNOR5) {
area: 1;
pin(I0) { direction: input; }
pin(I1) { direction: input; }
pin(I2) { direction: input; }
pin(I3) { direction: input; }
pin(I4) { direction: input; }
pin(O) { direction: output; function: "!(I0^I1^I2^I3^I4)"; }
}
}

View File

@ -0,0 +1,646 @@
/* Constants */
module VCC (output P);
`ifndef SYNTHESIS
assign P = 1'b1;
`endif
endmodule
module GND (output G);
`ifndef SYNTHESIS
assign G = 1'b0;
`endif
endmodule
/* Buffers */
module BUF (input I, output O);
`ifndef SYNTHESIS
assign O = I;
`endif
endmodule
module BUFT (input I, input T, output O);
`ifndef SYNTHESIS
assign O = T ? 1'bz : I;
`endif
endmodule
module INV (input I, output O);
`ifndef SYNTHESIS
assign O = ~I;
`endif
endmodule
/* AND gates */
module AND2 (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 AND3 (input I0, input I1, input I2, output O);
`ifndef SYNTHESIS
assign O = I0 & I1 & I2;
`endif
endmodule
module AND3B1 (input I0, input I1, input I2, output O);
`ifndef SYNTHESIS
assign O = ~I0 & I1 & I2;
`endif
endmodule
module AND3B2 (input I0, input I1, input I2, output O);
`ifndef SYNTHESIS
assign O = ~I0 & ~I1 & I2;
`endif
endmodule
module AND4 (input I0, input I1, input I2, input I3, output O);
`ifndef SYNTHESIS
assign O = I0 & I1 & I2 & I3;
`endif
endmodule
module AND4B1 (input I0, input I1, input I2, input I3, output O);
`ifndef SYNTHESIS
assign O = ~I0 & I1 & I2 & I3;
`endif
endmodule
module AND4B2 (input I0, input I1, input I2, input I3, output O);
`ifndef SYNTHESIS
assign O = ~I0 & ~I1 & I2 & I3;
`endif
endmodule
module AND4B3 (input I0, input I1, input I2, input I3, output O);
`ifndef SYNTHESIS
assign O = ~I0 & ~I1 & ~I2 & I3;
`endif
endmodule
module AND5 (input I0, input I1, input I2, input I3, input I4, output O);
`ifndef SYNTHESIS
assign O = I0 & I1 & I2 & I3 & I4;
`endif
endmodule
module AND5B1 (input I0, input I1, input I2, input I3, input I4, output O);
`ifndef SYNTHESIS
assign O = ~I0 & I1 & I2 & I3 & I4;
`endif
endmodule
module AND5B2 (input I0, input I1, input I2, input I3, input I4, output O);
`ifndef SYNTHESIS
assign O = ~I0 & ~I1 & I2 & I3 & I4;
`endif
endmodule
module AND5B3 (input I0, input I1, input I2, input I3, input I4, output O);
`ifndef SYNTHESIS
assign O = ~I0 & ~I1 & ~I2 & I3 & I4;
`endif
endmodule
module AND5B4 (input I0, input I1, input I2, input I3, input I4, output O);
`ifndef SYNTHESIS
assign O = ~I0 & ~I1 & ~I2 & ~I3 & I4;
`endif
endmodule
/* NAND gates */
module NAND2 (input I0, input I1, output O);
`ifndef SYNTHESIS
assign O = ~(I0 & I1);
`endif
endmodule
module NAND2B1 (input I0, input I1, output O);
`ifndef SYNTHESIS
assign O = ~(~I0 & I1);
`endif
endmodule
module NAND3 (input I0, input I1, input I2, output O);
`ifndef SYNTHESIS
assign O = ~(I0 & I1 & I2);
`endif
endmodule
module NAND3B1 (input I0, input I1, input I2, output O);
`ifndef SYNTHESIS
assign O = ~(~I0 & I1 & I2);
`endif
endmodule
module NAND3B2 (input I0, input I1, input I2, output O);
`ifndef SYNTHESIS
assign O = ~(~I0 & ~I1 & I2);
`endif
endmodule
module NAND4 (input I0, input I1, input I2, input I3, output O);
`ifndef SYNTHESIS
assign O = ~(I0 & I1 & I2 & I3);
`endif
endmodule
module NAND4B1 (input I0, input I1, input I2, input I3, output O);
`ifndef SYNTHESIS
assign O = ~(~I0 & I1 & I2 & I3);
`endif
endmodule
module NAND4B2 (input I0, input I1, input I2, input I3, output O);
`ifndef SYNTHESIS
assign O = ~(~I0 & ~I1 & I2 & I3);
`endif
endmodule
module NAND4B3 (input I0, input I1, input I2, input I3, output O);
`ifndef SYNTHESIS
assign O = ~(~I0 & ~I1 & ~I2 & I3);
`endif
endmodule
module NAND5 (input I0, input I1, input I2, input I3, input I4, output O);
`ifndef SYNTHESIS
assign O = ~(I0 & I1 & I2 & I3 & I4);
`endif
endmodule
module NAND5B1 (input I0, input I1, input I2, input I3, input I4, output O);
`ifndef SYNTHESIS
assign O = ~(~I0 & I1 & I2 & I3 & I4);
`endif
endmodule
module NAND5B2 (input I0, input I1, input I2, input I3, input I4, output O);
`ifndef SYNTHESIS
assign O = ~(~I0 & ~I1 & I2 & I3 & I4);
`endif
endmodule
module NAND5B3 (input I0, input I1, input I2, input I3, input I4, output O);
`ifndef SYNTHESIS
assign O = ~(~I0 & ~I1 & ~I2 & I3 & I4);
`endif
endmodule
module NAND5B4 (input I0, input I1, input I2, input I3, input I4, output O);
`ifndef SYNTHESIS
assign O = ~(~I0 & ~I1 & ~I2 & ~I3 & I4);
`endif
endmodule
/* OR gates */
module OR2 (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 OR3 (input I0, input I1, input I2, output O);
`ifndef SYNTHESIS
assign O = I0 | I1 | I2;
`endif
endmodule
module OR3B1 (input I0, input I1, input I2, output O);
`ifndef SYNTHESIS
assign O = ~I0 | I1 | I2;
`endif
endmodule
module OR3B2 (input I0, input I1, input I2, output O);
`ifndef SYNTHESIS
assign O = ~I0 | ~I1 | I2;
`endif
endmodule
module OR4 (input I0, input I1, input I2, input I3, output O);
`ifndef SYNTHESIS
assign O = I0 | I1 | I2 | I3;
`endif
endmodule
module OR4B1 (input I0, input I1, input I2, input I3, output O);
`ifndef SYNTHESIS
assign O = ~I0 | I1 | I2 | I3;
`endif
endmodule
module OR4B2 (input I0, input I1, input I2, input I3, output O);
`ifndef SYNTHESIS
assign O = ~I0 | ~I1 | I2 | I3;
`endif
endmodule
module OR4B3 (input I0, input I1, input I2, input I3, output O);
`ifndef SYNTHESIS
assign O = ~I0 | ~I1 | ~I2 | I3;
`endif
endmodule
module OR5 (input I0, input I1, input I2, input I3, input I4, output O);
`ifndef SYNTHESIS
assign O = I0 | I1 | I2 | I3 | I4;
`endif
endmodule
module OR5B1 (input I0, input I1, input I2, input I3, input I4, output O);
`ifndef SYNTHESIS
assign O = ~I0 | I1 | I2 | I3 | I4;
`endif
endmodule
module OR5B2 (input I0, input I1, input I2, input I3, input I4, output O);
`ifndef SYNTHESIS
assign O = ~I0 | ~I1 | I2 | I3 | I4;
`endif
endmodule
module OR5B3 (input I0, input I1, input I2, input I3, input I4, output O);
`ifndef SYNTHESIS
assign O = ~I0 | ~I1 | ~I2 | I3 | I4;
`endif
endmodule
module OR5B4 (input I0, input I1, input I2, input I3, input I4, output O);
`ifndef SYNTHESIS
assign O = ~I0 | ~I1 | ~I2 | ~I3 | I4;
`endif
endmodule
/* NOR gates */
module NOR2 (input I0, input I1, output O);
`ifndef SYNTHESIS
assign O = ~(I0 | I1);
`endif
endmodule
module NOR2B1 (input I0, input I1, output O);
`ifndef SYNTHESIS
assign O = ~(~I0 | I1);
`endif
endmodule
module NOR3 (input I0, input I1, input I2, output O);
`ifndef SYNTHESIS
assign O = ~(I0 | I1 | I2);
`endif
endmodule
module NOR3B1 (input I0, input I1, input I2, output O);
`ifndef SYNTHESIS
assign O = ~(~I0 | I1 | I2);
`endif
endmodule
module NOR3B2 (input I0, input I1, input I2, output O);
`ifndef SYNTHESIS
assign O = ~(~I0 | ~I1 | I2);
`endif
endmodule
module NOR4 (input I0, input I1, input I2, input I3, output O);
`ifndef SYNTHESIS
assign O = ~(I0 | I1 | I2 | I3);
`endif
endmodule
module NOR4B1 (input I0, input I1, input I2, input I3, output O);
`ifndef SYNTHESIS
assign O = ~(~I0 | I1 | I2 | I3);
`endif
endmodule
module NOR4B2 (input I0, input I1, input I2, input I3, output O);
`ifndef SYNTHESIS
assign O = ~(~I0 | ~I1 | I2 | I3);
`endif
endmodule
module NOR4B3 (input I0, input I1, input I2, input I3, output O);
`ifndef SYNTHESIS
assign O = ~(~I0 | ~I1 | ~I2 | I3);
`endif
endmodule
module NOR5 (input I0, input I1, input I2, input I3, input I4, output O);
`ifndef SYNTHESIS
assign O = ~(I0 | I1 | I2 | I3 | I4);
`endif
endmodule
module NOR5B1 (input I0, input I1, input I2, input I3, input I4, output O);
`ifndef SYNTHESIS
assign O = ~(~I0 | I1 | I2 | I3 | I4);
`endif
endmodule
module NOR5B2 (input I0, input I1, input I2, input I3, input I4, output O);
`ifndef SYNTHESIS
assign O = ~(~I0 | ~I1 | I2 | I3 | I4);
`endif
endmodule
module NOR5B3 (input I0, input I1, input I2, input I3, input I4, output O);
`ifndef SYNTHESIS
assign O = ~(~I0 | ~I1 | ~I2 | I3 | I4);
`endif
endmodule
module NOR5B4 (input I0, input I1, input I2, input I3, input I4, output O);
`ifndef SYNTHESIS
assign O = ~(~I0 | ~I1 | ~I2 | ~I3 | I4);
`endif
endmodule
/* XOR gates */
module XOR2 (input I0, input I1, output O);
`ifndef SYNTHESIS
assign O = I0 ^ I1;
`endif
endmodule
module XOR3 (input I0, input I1, input I2, output O);
`ifndef SYNTHESIS
assign O = I0 ^ I1 ^ I2;
`endif
endmodule
module XOR4 (input I0, input I1, input I2, input I3, output O);
`ifndef SYNTHESIS
assign O = I0 ^ I1 ^ I2 ^ I3;
`endif
endmodule
module XOR5 (input I0, input I1, input I2, input I3, input I4, output O);
`ifndef SYNTHESIS
assign O = I0 ^ I1 ^ I2 ^ I3 ^ I4;
`endif
endmodule
/* XNOR gates */
module XNOR2 (input I0, input I1, output O);
`ifndef SYNTHESIS
assign O = ~(I0 ^ I1);
`endif
endmodule
module XNOR3 (input I0, input I1, input I2, output O);
`ifndef SYNTHESIS
assign O = ~(I0 ^ I1 ^ I2);
`endif
endmodule
module XNOR4 (input I0, input I1, input I2, input I3, output O);
`ifndef SYNTHESIS
assign O = ~(I0 ^ I1 ^ I2 ^ I3);
`endif
endmodule
module XNOR5 (input I0, input I1, input I2, input I3, input I4, output O);
`ifndef SYNTHESIS
assign O = ~(I0 ^ I1 ^ I2 ^ I3 ^ I4);
`endif
endmodule
/* Flip flops */
module FDCE (input D, input C, input CLR, input CE, output Q);
`ifndef SYNTHESIS
reg _Q = 1'b0;
assign Q = _Q;
always @(posedge C, CLR)
if (CLR)
_Q <= 1'b0;
else if (CE)
_Q <= D;
`endif
endmodule
module FDPE (input D, input C, input PRE, input CE, output Q);
`ifndef SYNTHESIS
reg _Q = 1'b1;
assign Q = _Q;
always @(posedge C, PRE)
if (PRE)
_Q <= 1'b1;
else if (CE)
_Q <= D;
`endif
endmodule
/* Latches */
module LDCE_1 (input D, input G, input CLR, input GE, output Q);
`ifndef SYNTHESIS
reg _Q = 1'b0;
assign Q = _Q;
always @*
if (CLR)
_Q <= 1'b0;
else if (GE)
_Q <= D;
`endif
endmodule
module LDPE_1 (input D, input G, input PRE, input GE, output Q);
`ifndef SYNTHESIS
reg _Q = 1'b1;
assign Q = _Q;
always @*
if (PRE)
_Q <= 1'b1;
else if (GE)
_Q <= D;
`endif
endmodule
/* CLB placement control primitives */
module FMAP (input I1, input I2, input I3, input I4, input O);
endmodule
module HMAP (input I1, input I2, input I3, input O);
endmodule
/* I/O buffers */
module BUFGLS (input I, output O);
`ifndef SYNTHESIS
assign O = I;
`endif
endmodule
module IBUF (input I, output O);
`ifndef SYNTHESIS
assign O = I;
`endif
endmodule
module OBUF (input I, output O);
`ifndef SYNTHESIS
assign O = I;
`endif
endmodule
module OBUFT (input I, input T, output O);
`ifndef SYNTHESIS
assign O = T ? 1'bz : I;
`endif
endmodule
/* I/O flip flops */
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
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
module OFDX (input D, input C, input CE, output Q);
`ifndef SYNTHESIS
IFDX ff (.D(D), .C(C), .CE(CE), .Q(Q));
`endif
endmodule
module OFDXI (input D, input C, input CE, output Q);
`ifndef SYNTHESIS
IFDXI ff (.D(D), .C(C), .CE(CE), .Q(Q));
`endif
endmodule
module OFDTX (input D, input C, input CE, input T, output O);
`ifndef SYNTHESIS
wire Q;
assign O = T ? 1'bz : Q;
IFDX ff (.D(D), .C(C), .CE(CE), .Q(Q));
`endif
endmodule
module OFDTXI (input D, input C, input CE, input T, output O);
`ifndef SYNTHESIS
wire Q;
assign O = T ? 1'bz : Q;
IFDXI ff (.D(D), .C(C), .CE(CE), .Q(Q));
`endif
endmodule
/* I/O pads */
module IPAD (output IPAD);
endmodule
module OPAD (input OPAD);
endmodule
module IOPAD (inout IOPAD);
endmodule
module UPAD (inout UPAD);
endmodule
module TDI (inout I);
endmodule
module TDO (input O);
endmodule
module TCK (inout I);
endmodule
module TMS (inout I);
endmodule
/* Fixed-function blocks */
module STARTUP (
input GSR,
input GTS,
input CLK,
output DONEIN,
output Q1Q4,
output Q2,
output Q3
);
endmodule
module OSC4 (
output F8M,
output F500K,
output F16K,
output F490,
output F15
);
endmodule
module BSCAN(
input TDI,
input TDO1,
input TDO2,
input TCK,
input TMS,
output TDO,
output DRCK,
output IDLE,
output SEL1,
output SEL2
);
endmodule
module RDBK (input TRIG, output DATA, output RIP);
endmodule
module RDCLK (input I);
endmodule

View File

@ -1,90 +0,0 @@
/*
* This file is used by Yosys to map its internal gate representations to the
* respective primitives supported by ISE's mapping tools. Note that ISE does
* not expose LUT primitives for Spartan-XL devices, so LUT-based synthesis and
* the synth_xilinx command built into Yosys cannot be used.
*/
(* techmap_celltype = "IOBUFT" *)
module _ISE_IOBUFT (input I, input T, output O, inout IO);
IBUF _TECHMAP_REPLACE_.ibuf (.I(IO), .O(O));
OBUFT _TECHMAP_REPLACE_.obuf (.O(IO), .I(I), .T(T));
endmodule
(* techmap_celltype = "$_BUF_" *)
module _ISE_BUF (input A, output Y);
BUF _TECHMAP_REPLACE_ (.I(A), .O(Y));
endmodule
(* techmap_celltype = "$_NOT_" *)
module _ISE_INV (input A, output Y);
INV _TECHMAP_REPLACE_ (.I(A), .O(Y));
endmodule
(* techmap_celltype = "$_AND_" *)
module _ISE_AND2 (input A, input B, output Y);
AND2 _TECHMAP_REPLACE_ (.I0(A), .I1(B), .O(Y));
endmodule
(* techmap_celltype = "$_NAND_" *)
module _ISE_NAND2 (input A, input B, output Y);
NAND2 _TECHMAP_REPLACE_ (.I0(A), .I1(B), .O(Y));
endmodule
(* techmap_celltype = "$_ANDNOT_" *)
module _ISE_AND2B1 (input A, input B, output Y);
AND2B1 _TECHMAP_REPLACE_ (.I0(A), .I1(B), .O(Y));
endmodule
(* techmap_celltype = "$_OR_" *)
module _ISE_OR2 (input A, input B, output Y);
OR2 _TECHMAP_REPLACE_ (.I0(A), .I1(B), .O(Y));
endmodule
(* techmap_celltype = "$_NOR_" *)
module _ISE_NOR2 (input A, input B, output Y);
NOR2 _TECHMAP_REPLACE_ (.I0(A), .I1(B), .O(Y));
endmodule
(* techmap_celltype = "$_ORNOT_" *)
module _ISE_OR2B1 (input A, input B, output Y);
OR2B1 _TECHMAP_REPLACE_ (.I0(A), .I1(B), .O(Y));
endmodule
(* techmap_celltype = "$_XOR_" *)
module _ISE_XOR2 (input A, input B, output Y);
XOR2 _TECHMAP_REPLACE_ (.I0(A), .I1(B), .O(Y));
endmodule
(* techmap_celltype = "$_XNOR_" *)
module _ISE_XNOR2 (input A, input B, output Y);
XNOR2 _TECHMAP_REPLACE_ (.I0(A), .I1(B), .O(Y));
endmodule
(* techmap_celltype = "$_TBUF_" *)
module _ISE_BUFT (input A, input E, output Y);
wire T;
INV _TECHMAP_REPLACE_.inv (.I(E), .O(T));
BUFT _TECHMAP_REPLACE_.buffer (.I(A), .T(T), .O(Y));
endmodule
(* techmap_celltype = "$_DFFE_PP0P_" *)
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));
endmodule
(* techmap_celltype = "$_DFFE_PP1P_" *)
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));
endmodule
(* techmap_celltype = "$_DLATCH_PP0_" *)
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));
endmodule
(* techmap_celltype = "$_DLATCH_PP1_" *)
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));
endmodule

View File

@ -9,7 +9,8 @@
namespace io {
uint16_t _bankSwitchReg, _cartOutputReg, _miscOutputReg;
uint16_t _bankSwitchReg, _cartOutputReg, _miscOutputReg;
static uint16_t _digitalIOI2CReg, _digitalIODSBusReg;
/* System initialization */
@ -50,9 +51,9 @@ void init(void) {
_bankSwitchReg = 0;
_cartOutputReg = 0;
_miscOutputReg = 0
| SYS573_MISC_OUT_ADC_MOSI
| SYS573_MISC_OUT_ADC_DI
| SYS573_MISC_OUT_ADC_CS
| SYS573_MISC_OUT_ADC_SCK
| SYS573_MISC_OUT_ADC_CLK
| SYS573_MISC_OUT_JVS_RESET;
SYS573_BANK_CTRL = _bankSwitchReg;
@ -181,7 +182,13 @@ static void _writeBitstreamMSB(const uint8_t *data, size_t length) {
}
}
bool loadBitstream(const uint8_t *data, size_t length) {
bool isDigitalIOPresent(void) {
const uint16_t mask = SYS573D_CPLD_STAT_ID1 | SYS573D_CPLD_STAT_ID2;
return ((SYS573D_CPLD_STAT & mask) == SYS573D_CPLD_STAT_ID2);
}
bool loadDigitalIOBitstream(const uint8_t *data, size_t length) {
// Konami's bitstreams are always stored LSB-first and with no headers,
// however Xilinx tools export .bit files which contain MSB-first bitstreams
// wrapped in a TLV container. In order to upload the bitstream properly,
@ -189,7 +196,7 @@ bool loadBitstream(const uint8_t *data, size_t length) {
// https://www.fpga-faq.com/FAQ_Pages/0026_Tell_me_about_bit_files.htm and
// the "Data Stream Format" section in the XCS40XL datasheet for details.
if (data[0] == 0xff)
return loadRawBitstream(data, length);
return loadDigitalIORawBitstream(data, length);
auto dataEnd = &data[length];
uint16_t headerLength = (data[0] << 8) | data[1];
@ -208,7 +215,7 @@ bool loadBitstream(const uint8_t *data, size_t length) {
| data[4];
data += 5;
return loadRawBitstream(data, tagLength);
return loadDigitalIORawBitstream(data, tagLength);
default:
tagLength = (data[1] << 8) | data[2];
@ -221,7 +228,7 @@ bool loadBitstream(const uint8_t *data, size_t length) {
return false;
}
bool loadRawBitstream(const uint8_t *data, size_t length) {
bool loadDigitalIORawBitstream(const uint8_t *data, size_t length) {
if (data[0] != 0xff)
return false;
@ -266,7 +273,7 @@ bool loadRawBitstream(const uint8_t *data, size_t length) {
return false;
}
void initKonamiBitstream(void) {
void initDigitalIOFPGA(void) {
SYS573D_FPGA_INIT = 0xf000;
SYS573D_FPGA_INIT = 0x0000;
delayMicroseconds(_FPGA_INIT_REG_DELAY);
@ -282,6 +289,16 @@ void initKonamiBitstream(void) {
SYS573D_CPLD_LIGHTS_CL = 0xf000;
SYS573D_CPLD_LIGHTS_CH = 0xf000;
SYS573D_FPGA_LIGHTS_D = 0xf000;
_digitalIOI2CReg = 0
| SYS573D_FPGA_MP3_I2C_SDA
| SYS573D_FPGA_MP3_I2C_SCL;
_digitalIODSBusReg = 0
| SYS573D_FPGA_DS_BUS_DS2401
| SYS573D_FPGA_DS_BUS_DS2433;
SYS573D_FPGA_MP3_I2C = _digitalIOI2CReg;
SYS573D_FPGA_DS_BUS = _digitalIODSBusReg;
}
/* I2C driver */
@ -289,173 +306,204 @@ void initKonamiBitstream(void) {
static constexpr int _I2C_BUS_DELAY = 50;
static constexpr int _I2C_RESET_DELAY = 500;
// SDA is open-drain so it is toggled by changing pin direction.
#define _SDA(value) setCartSDADir(!(value))
#define SDA(value) _SDA(value), delayMicroseconds(_I2C_BUS_DELAY)
#define _SCL(value) setCartOutput(OUT_SCL, value)
#define SCL(value) _SCL(value), delayMicroseconds(_I2C_BUS_DELAY)
#define _CS(value) setCartOutput(OUT_CS, value)
#define CS(value) _CS(value), delayMicroseconds(_I2C_BUS_DELAY)
#define _RESET(value) setCartOutput(OUT_RESET, value)
#define RESET(value) _RESET(value), delayMicroseconds(_I2C_BUS_DELAY)
void I2CDriver::start(void) const {
_setSDA(true);
_setSCL(true, _I2C_BUS_DELAY);
void i2cStart(void) {
_SDA(true);
SCL(true);
SDA(false); // START: SDA falling, SCL high
SCL(false);
_setSDA(false, _I2C_BUS_DELAY); // START: SDA falling, SCL high
_setSCL(false, _I2C_BUS_DELAY);
}
void i2cStartWithCS(int csDelay) {
_SDA(true);
_SCL(false);
CS(true);
void I2CDriver::startWithCS(int csDelay) const {
_setSDA(true);
_setSCL(false);
_setCS(true, _I2C_BUS_DELAY);
CS(false);
delayMicroseconds(csDelay);
SCL(true);
_setCS(false, _I2C_BUS_DELAY + csDelay);
_setSCL(true, _I2C_BUS_DELAY);
SDA(false); // START: SDA falling, SCL high
SCL(false);
_setSDA(false, _I2C_BUS_DELAY); // START: SDA falling, SCL high
_setSCL(false, _I2C_BUS_DELAY);
}
void i2cStop(void) {
_SDA(false);
SCL(true);
void I2CDriver::stop(void) const {
_setSDA(false);
SDA(true); // STOP: SDA rising, SCL high
_setSCL(true, _I2C_BUS_DELAY);
_setSDA(true, _I2C_BUS_DELAY); // STOP: SDA rising, SCL high
}
void i2cStopWithCS(int csDelay) {
_SDA(false);
SCL(true);
void I2CDriver::stopWithCS(int csDelay) const {
_setSDA(false);
SDA(true); // STOP: SDA rising, SCL high
_setSCL(true, _I2C_BUS_DELAY);
_setSDA(true, _I2C_BUS_DELAY); // STOP: SDA rising, SCL high
SCL(false);
delayMicroseconds(csDelay);
CS(true);
_setSCL(false, _I2C_BUS_DELAY + csDelay);
_setCS(true, _I2C_BUS_DELAY);
}
uint8_t i2cReadByte(void) {
bool I2CDriver::getACK(void) const {
delayMicroseconds(_I2C_BUS_DELAY); // Required for ZS01
_setSCL(true, _I2C_BUS_DELAY);
bool ack = _getSDA();
_setSCL(false, _I2C_BUS_DELAY * 2);
return ack ^ 1;
}
void I2CDriver::sendACK(bool ack) const {
_setSDA(ack ^ 1);
_setSCL(true, _I2C_BUS_DELAY);
_setSCL(false, _I2C_BUS_DELAY);
_setSDA(true, _I2C_BUS_DELAY);
}
uint8_t I2CDriver::readByte(void) const {
uint8_t value = 0;
for (int bit = 7; bit >= 0; bit--) { // MSB first
SCL(true);
if (getCartSDA())
value |= (1 << bit);
SCL(false);
for (int i = 7; i >= 0; i--) { // MSB first
_setSCL(true, _I2C_BUS_DELAY);
value |= _getSDA() << i;
_setSCL(false, _I2C_BUS_DELAY);
}
delayMicroseconds(_I2C_BUS_DELAY);
return value;
}
void i2cWriteByte(uint8_t value) {
for (int bit = 7; bit >= 0; bit--) { // MSB first
_SDA(value & (1 << bit));
SCL(true);
SCL(false);
void I2CDriver::writeByte(uint8_t value) const {
for (int i = 7; i >= 0; i--) { // MSB first
_setSDA((value >> i) & 1);
_setSCL(true, _I2C_BUS_DELAY);
_setSCL(false, _I2C_BUS_DELAY);
}
SDA(true);
_setSDA(true, _I2C_BUS_DELAY);
}
void i2cSendACK(bool ack) {
_SDA(!ack);
SCL(true);
SCL(false);
SDA(true);
}
bool i2cGetACK(void) {
delayMicroseconds(_I2C_BUS_DELAY); // Required for ZS01
SCL(true);
bool ack = !getCartSDA();
SCL(false);
delayMicroseconds(_I2C_BUS_DELAY);
return ack;
}
void i2cReadBytes(uint8_t *data, size_t length) {
void I2CDriver::readBytes(uint8_t *data, size_t length) const {
for (; length; length--) {
*(data++) = i2cReadByte();
*(data++) = readByte();
if (length > 1)
i2cSendACK(true);
sendACK(true);
}
}
bool i2cWriteBytes(const uint8_t *data, size_t length, int lastACKDelay) {
bool I2CDriver::writeBytes(
const uint8_t *data, size_t length, int lastACKDelay
) const {
for (; length; length--) {
i2cWriteByte(*(data++));
writeByte(*(data++));
if (length == 1)
delayMicroseconds(lastACKDelay);
if (!i2cGetACK())
if (!getACK())
return false;
}
return true;
}
uint32_t i2cResetX76(void) {
uint32_t I2CDriver::resetX76(void) const {
uint32_t value = 0;
_SDA(true);
_SCL(false);
_CS(false);
_RESET(false);
_setSDA(true);
_setSCL(false);
_setCS(false);
_setReset(false);
RESET(true);
SCL(true);
SCL(false);
RESET(false);
delayMicroseconds(_I2C_RESET_DELAY);
_setReset(true, _I2C_RESET_DELAY);
_setSCL(true, _I2C_BUS_DELAY);
_setSCL(false, _I2C_BUS_DELAY);
_setReset(false, _I2C_RESET_DELAY);
for (int bit = 0; bit < 32; bit++) { // LSB first
SCL(true);
if (getCartSDA())
value |= (1 << bit);
SCL(false);
for (int i = 0; i < 32; i++) { // LSB first
_setSCL(true, _I2C_BUS_DELAY);
value |= _getSDA() << i;
_setSCL(false, _I2C_BUS_DELAY);
}
CS(true);
SCL(true);
_setCS(true, _I2C_BUS_DELAY);
_setSCL(true, _I2C_BUS_DELAY);
return value;
}
// For whatever reason the ZS01 does not implement the exact same response to
// reset protocol as the X76 chips. The reset pin is also active-low rather
// than active-high, and CS is ignored.
uint32_t i2cResetZS01(void) {
uint32_t I2CDriver::resetZS01(void) const {
uint32_t value = 0;
_SDA(true);
_SCL(false);
_CS(false);
_RESET(true);
_setSDA(true);
_setSCL(false);
_setCS(false);
_setReset(true);
RESET(false);
RESET(true);
delayMicroseconds(_I2C_RESET_DELAY);
_setReset(false, _I2C_RESET_DELAY);
_setReset(true, _I2C_RESET_DELAY);
_setSCL(true, _I2C_BUS_DELAY);
_setSCL(false, _I2C_BUS_DELAY);
SCL(true);
SCL(false);
for (int bit = 31; bit >= 0; bit--) { // MSB first
if (getCartSDA())
value |= (1 << bit);
SCL(true);
SCL(false);
for (int i = 31; i >= 0; i--) { // MSB first
value |= _getSDA() << i;
_setSCL(true, _I2C_BUS_DELAY);
_setSCL(false, _I2C_BUS_DELAY);
}
SCL(true);
_setSCL(true, _I2C_BUS_DELAY);
return value;
}
bool CartI2CDriver::_getSDA(void) const {
return (SYS573_MISC_IN / SYS573_MISC_IN_CART_SDA) & 1;
}
void CartI2CDriver::_setSDA(bool value) const {
// SDA is open-drain so it is toggled by tristating the pin.
setCartOutput(CART_OUTPUT_SDA, false);
setCartSDADirection(value ^ 1);
}
void CartI2CDriver::_setSCL(bool value) const {
setCartOutput(CART_OUTPUT_SCL, value);
}
void CartI2CDriver::_setCS(bool value) const {
setCartOutput(CART_OUTPUT_CS, value);
}
void CartI2CDriver::_setReset(bool value) const {
setCartOutput(CART_OUTPUT_RESET, value);
}
bool DigitalIOI2CDriver::_getSDA(void) const {
return (SYS573D_FPGA_MP3_I2C / SYS573D_FPGA_MP3_I2C_SDA) & 1;
}
void DigitalIOI2CDriver::_setSDA(bool value) const {
if (value)
_digitalIOI2CReg |= SYS573D_FPGA_MP3_I2C_SDA;
else
_digitalIOI2CReg &= ~SYS573D_FPGA_MP3_I2C_SCL;
SYS573D_FPGA_MP3_I2C = _digitalIOI2CReg;
}
void DigitalIOI2CDriver::_setSCL(bool value) const {
if (value)
_digitalIOI2CReg |= SYS573D_FPGA_MP3_I2C_SDA;
else
_digitalIOI2CReg &= ~SYS573D_FPGA_MP3_I2C_SCL;
SYS573D_FPGA_MP3_I2C = _digitalIOI2CReg;
}
const CartI2CDriver cartI2C;
const DigitalIOI2CDriver digitalIOI2C;
/* 1-wire driver */
static constexpr int _DS_RESET_LOW_TIME = 480;
@ -471,95 +519,76 @@ static constexpr int _DS_ZERO_HIGH_TIME = 5;
static constexpr int _DS_ONE_LOW_TIME = 10;
static constexpr int _DS_ONE_HIGH_TIME = 55;
#define _CART1WIRE(value) setCartOutput(OUT_1WIRE, !(value))
#define _DIO1WIRE(value) setDIO1Wire(value)
bool OneWireDriver::reset(void) const {
_set(false, _DS_RESET_LOW_TIME);
_set(true, _DS_RESET_SAMPLE_DELAY);
bool present = _get();
bool dsCartReset(void) {
_CART1WIRE(false);
delayMicroseconds(_DS_RESET_LOW_TIME);
_CART1WIRE(true);
delayMicroseconds(_DS_RESET_SAMPLE_DELAY);
bool present = !getCartInput(IN_1WIRE);
delayMicroseconds(_DS_RESET_DELAY);
return present;
return present ^ 1;
}
bool dsDIOReset(void) {
_DIO1WIRE(false);
delayMicroseconds(_DS_RESET_LOW_TIME);
_DIO1WIRE(true);
delayMicroseconds(_DS_RESET_SAMPLE_DELAY);
bool present = !getDIO1Wire();
delayMicroseconds(_DS_RESET_DELAY);
return present;
}
uint8_t dsCartReadByte(void) {
uint8_t OneWireDriver::readByte(void) const {
uint8_t value = 0;
for (int bit = 0; bit < 8; bit++) { // LSB first
_CART1WIRE(false);
delayMicroseconds(_DS_READ_LOW_TIME);
_CART1WIRE(true);
delayMicroseconds(_DS_READ_SAMPLE_DELAY);
if (getCartInput(IN_1WIRE))
value |= (1 << bit);
for (int i = 0; i < 8; i++) { // LSB first
_set(false, _DS_READ_LOW_TIME);
_set(true, _DS_READ_SAMPLE_DELAY);
value |= _get() << i;
delayMicroseconds(_DS_READ_DELAY);
}
return value;
}
uint8_t dsDIOReadByte(void) {
uint8_t value = 0;
for (int bit = 0; bit < 8; bit++) { // LSB first
_DIO1WIRE(false);
delayMicroseconds(_DS_READ_LOW_TIME);
_DIO1WIRE(true);
delayMicroseconds(_DS_READ_SAMPLE_DELAY);
if (getDIO1Wire())
value |= (1 << bit);
delayMicroseconds(_DS_READ_DELAY);
}
return value;
}
void dsCartWriteByte(uint8_t value) {
for (int bit = 0; bit < 8; bit++) { // LSB first
if (value & (1 << bit)) {
_CART1WIRE(false);
delayMicroseconds(_DS_ONE_LOW_TIME);
_CART1WIRE(true);
delayMicroseconds(_DS_ONE_HIGH_TIME);
void OneWireDriver::writeByte(uint8_t value) const {
for (int i = 8; i; i--, value >>= 1) { // LSB first
if (value & 1) {
_set(false, _DS_ONE_LOW_TIME);
_set(true, _DS_ONE_HIGH_TIME);
} else {
_CART1WIRE(false);
delayMicroseconds(_DS_ZERO_LOW_TIME);
_CART1WIRE(true);
delayMicroseconds(_DS_ZERO_HIGH_TIME);
_set(false, _DS_ZERO_LOW_TIME);
_set(true, _DS_ZERO_HIGH_TIME);
}
}
}
void dsDIOWriteByte(uint8_t value) {
for (int bit = 0; bit < 8; bit++) { // LSB first
if (value & (1 << bit)) {
_DIO1WIRE(false);
delayMicroseconds(_DS_ONE_LOW_TIME);
_DIO1WIRE(true);
delayMicroseconds(_DS_ONE_HIGH_TIME);
} else {
_DIO1WIRE(false);
delayMicroseconds(_DS_ZERO_LOW_TIME);
_DIO1WIRE(true);
delayMicroseconds(_DS_ZERO_HIGH_TIME);
}
}
bool CartDS2401Driver::_get(void) const {
return getCartInput(CART_INPUT_DS2401);
}
void CartDS2401Driver::_set(bool value) const {
setCartOutput(CART_OUTPUT_DS2401, value ^ 1);
}
bool DigitalIODS2401Driver::_get(void) const {
return (SYS573D_FPGA_DS_BUS / SYS573D_FPGA_DS_BUS_DS2401) & 1;
}
void DigitalIODS2401Driver::_set(bool value) const {
if (value)
_digitalIODSBusReg &= ~SYS573D_FPGA_DS_BUS_DS2401;
else
_digitalIODSBusReg |= SYS573D_FPGA_DS_BUS_DS2401;
SYS573D_FPGA_DS_BUS = _digitalIODSBusReg;
}
bool DigitalIODS2433Driver::_get(void) const {
return (SYS573D_FPGA_DS_BUS / SYS573D_FPGA_DS_BUS_DS2433) & 1;
}
void DigitalIODS2433Driver::_set(bool value) const {
if (value)
_digitalIODSBusReg &= ~SYS573D_FPGA_DS_BUS_DS2433;
else
_digitalIODSBusReg |= SYS573D_FPGA_DS_BUS_DS2433;
SYS573D_FPGA_DS_BUS = _digitalIODSBusReg;
}
const CartDS2401Driver cartDS2401;
const DigitalIODS2401Driver digitalIODS2401;
const DigitalIODS2433Driver digitalIODS2433;
}

View File

@ -7,6 +7,7 @@
#include "common/util.hpp"
#include "ps1/registers.h"
#include "ps1/registers573.h"
#include "ps1/system.h"
namespace io {
@ -52,27 +53,27 @@ enum JAMMAInput : uint32_t {
};
enum CartInputPin {
IN_1WIRE = 6
CART_INPUT_DS2401 = 6
};
enum CartOutputPin {
OUT_SDA = 0,
OUT_SCL = 1,
OUT_CS = 2,
OUT_RESET = 3,
OUT_1WIRE = 4
CART_OUTPUT_SDA = 0,
CART_OUTPUT_SCL = 1,
CART_OUTPUT_CS = 2,
CART_OUTPUT_RESET = 3,
CART_OUTPUT_DS2401 = 4
};
enum MiscOutputPin {
MISC_ADC_MOSI = 0,
MISC_ADC_CS = 1,
MISC_ADC_SCK = 2,
MISC_COIN_COUNT1 = 3,
MISC_COIN_COUNT2 = 4,
MISC_AMP_ENABLE = 5,
MISC_CDDA_ENABLE = 6,
MISC_SPU_ENABLE = 7,
MISC_JVS_RESET = 8
MISC_OUT_ADC_DI = 0,
MISC_OUT_ADC_CS = 1,
MISC_OUT_ADC_CLK = 2,
MISC_OUT_COIN_COUNT1 = 3,
MISC_OUT_COIN_COUNT2 = 4,
MISC_OUT_AMP_ENABLE = 5,
MISC_OUT_CDDA_ENABLE = 6,
MISC_OUT_SPU_ENABLE = 7,
MISC_OUT_JVS_RESET = 8
};
/* Inputs */
@ -106,10 +107,6 @@ static inline bool getCartInput(CartInputPin pin) {
return (SYS573_DIP_CART >> (8 + pin)) & 1;
}
static inline bool getCartSDA(void) {
return (SYS573_MISC_IN / SYS573_MISC_IN_CART_SDA) & 1;
}
static inline void setCartOutput(CartOutputPin pin, bool value) {
if (value)
_cartOutputReg |= 1 << pin;
@ -125,7 +122,7 @@ static inline void setFlashBank(int bank) {
SYS573_BANK_CTRL = _bankSwitchReg;
}
static inline void setCartSDADir(bool dir) {
static inline void setCartSDADirection(bool dir) {
if (dir)
_bankSwitchReg |= 1 << 6;
else
@ -143,22 +140,112 @@ static inline void setMiscOutput(MiscOutputPin pin, bool value) {
SYS573_MISC_OUT = _miscOutputReg;
}
/* Digital I/O board driver */
/* I2C driver */
static inline bool isDigitalIOPresent(void) {
return (
(SYS573D_CPLD_STAT & (SYS573D_CPLD_STAT_ID1 | SYS573D_CPLD_STAT_ID2)) ==
SYS573D_CPLD_STAT_ID2
);
}
class I2CDriver {
private:
inline void _setSDA(bool value, int delay) const {
_setSDA(value);
delayMicroseconds(delay);
}
inline void _setSCL(bool value, int delay) const {
_setSCL(value);
delayMicroseconds(delay);
}
inline void _setCS(bool value, int delay) const {
_setCS(value);
delayMicroseconds(delay);
}
inline void _setReset(bool value, int delay) const {
_setReset(value);
delayMicroseconds(delay);
}
static inline bool getDIO1Wire(void) {
return (SYS573D_FPGA_DS_BUS / SYS573D_FPGA_DS_BUS_DS2401) & 1;
}
virtual bool _getSDA(void) const { return true; }
virtual void _setSDA(bool value) const {}
virtual void _setSCL(bool value) const {}
virtual void _setCS(bool value) const {}
virtual void _setReset(bool value) const {}
static inline void setDIO1Wire(bool value) {
SYS573D_FPGA_DS_BUS = (value ^ 1) * SYS573D_FPGA_DS_BUS_DS2401;
}
public:
void start(void) const;
void startWithCS(int csDelay = 0) const;
void stop(void) const;
void stopWithCS(int csDelay = 0) const;
bool getACK(void) const;
void sendACK(bool value) const;
uint8_t readByte(void) const;
void writeByte(uint8_t value) const;
void readBytes(uint8_t *data, size_t length) const;
bool writeBytes(
const uint8_t *data, size_t length, int lastACKDelay = 0
) const;
uint32_t resetX76(void) const;
uint32_t resetZS01(void) const;
};
class CartI2CDriver : public I2CDriver {
private:
bool _getSDA(void) const;
void _setSDA(bool value) const;
void _setSCL(bool value) const;
void _setCS(bool value) const;
void _setReset(bool value) const;
};
class DigitalIOI2CDriver : public I2CDriver {
private:
bool _getSDA(void) const;
void _setSDA(bool value) const;
void _setSCL(bool value) const;
};
extern const CartI2CDriver cartI2C;
extern const DigitalIOI2CDriver digitalIOI2C;
/* 1-wire driver */
class OneWireDriver {
private:
inline void _set(bool value, int delay) const {
_set(value);
delayMicroseconds(delay);
}
virtual bool _get(void) const { return true; }
virtual void _set(bool value) const {}
public:
bool reset(void) const;
uint8_t readByte(void) const;
void writeByte(uint8_t value) const;
};
class CartDS2401Driver : public OneWireDriver {
private:
bool _get(void) const;
void _set(bool value) const;
};
class DigitalIODS2401Driver : public OneWireDriver {
private:
bool _get(void) const;
void _set(bool value) const;
};
class DigitalIODS2433Driver : public OneWireDriver {
private:
bool _get(void) const;
void _set(bool value) const;
};
extern const CartDS2401Driver cartDS2401;
extern const DigitalIODS2401Driver digitalIODS2401;
extern const DigitalIODS2433Driver digitalIODS2433;
/* Other APIs */
@ -171,30 +258,9 @@ void getRTCTime(util::Date &output);
void setRTCTime(const util::Date &value, bool stop = false);
bool isRTCBatteryLow(void);
bool loadBitstream(const uint8_t *data, size_t length);
bool loadRawBitstream(const uint8_t *data, size_t length);
void initKonamiBitstream(void);
void i2cStart(void);
void i2cStartWithCS(int csDelay = 0);
void i2cStop(void);
void i2cStopWithCS(int csDelay = 0);
uint8_t i2cReadByte(void);
void i2cWriteByte(uint8_t value);
void i2cSendACK(bool ack);
bool i2cGetACK(void);
void i2cReadBytes(uint8_t *data, size_t length);
bool i2cWriteBytes(const uint8_t *data, size_t length, int lastACKDelay = 0);
uint32_t i2cResetX76(void);
uint32_t i2cResetZS01(void);
bool dsCartReset(void);
bool dsDIOReset(void);
uint8_t dsCartReadByte(void);
uint8_t dsDIOReadByte(void);
void dsCartWriteByte(uint8_t value);
void dsDIOWriteByte(uint8_t value);
bool isDigitalIOPresent(void);
bool loadDigitalIOBitstream(const uint8_t *data, size_t length);
bool loadDigitalIORawBitstream(const uint8_t *data, size_t length);
void initDigitalIOFPGA(void);
}

View File

@ -224,8 +224,12 @@ const util::ExecutableHeader *FlashRegion::getBootExecutableHeader(void) const {
for (size_t i = 1; i < length; i <<= 1)
crc = (crc >> 8) ^ table[(crc ^ data[i]) & 0xff];
if (~crc != *crcPtr)
if (~crc != *crcPtr) {
LOG_ROM("CRC32 mismatch");
LOG_ROM("exp=0x%08x", ~crc);
LOG_ROM("got=0x%08x", *crcPtr);
return nullptr;
}
return header;
}

View File

@ -98,7 +98,9 @@ _cartInitDone:
return true;
}
ready = io::loadBitstream(bitstream.as<uint8_t>(), bitstream.length);
ready = io::loadDigitalIOBitstream(
bitstream.as<uint8_t>(), bitstream.length
);
bitstream.destroy();
if (!ready) {
@ -107,7 +109,7 @@ _cartInitDone:
}
delayMicroseconds(5000); // Probably not necessary
io::initKonamiBitstream();
io::initDigitalIOFPGA();
auto error = _cartDriver->readSystemID();

View File

@ -205,19 +205,19 @@ void AudioTestScreen::playBoth(ui::Context &ctx) {
}
void AudioTestScreen::enableAmp(ui::Context &ctx) {
io::setMiscOutput(io::MISC_AMP_ENABLE, true);
io::setMiscOutput(io::MISC_OUT_AMP_ENABLE, true);
}
void AudioTestScreen::disableAmp(ui::Context &ctx) {
io::setMiscOutput(io::MISC_AMP_ENABLE, false);
io::setMiscOutput(io::MISC_OUT_AMP_ENABLE, false);
}
void AudioTestScreen::enableCDDA(ui::Context &ctx) {
io::setMiscOutput(io::MISC_CDDA_ENABLE, true);
io::setMiscOutput(io::MISC_OUT_CDDA_ENABLE, true);
}
void AudioTestScreen::disableCDDA(ui::Context &ctx) {
io::setMiscOutput(io::MISC_CDDA_ENABLE, false);
io::setMiscOutput(io::MISC_OUT_CDDA_ENABLE, false);
}
void AudioTestScreen::show(ui::Context &ctx, bool goBack) {
@ -236,8 +236,8 @@ void AudioTestScreen::update(ui::Context &ctx) {
if (ctx.buttons.pressed(ui::BTN_START)) {
if (ctx.buttons.held(ui::BTN_LEFT) || ctx.buttons.held(ui::BTN_RIGHT)) {
#if 0
io::setMiscOutput(io::MISC_AMP_ENABLE, false);
io::setMiscOutput(io::MISC_CDDA_ENABLE, false);
io::setMiscOutput(io::MISC_OUT_AMP_ENABLE, false);
io::setMiscOutput(io::MISC_OUT_CDDA_ENABLE, false);
#endif
ctx.show(APP->_testMenuScreen, true, true);

View File

@ -117,6 +117,13 @@ DriverError DummyDriver::setDataKey(const uint8_t *key) {
/* Functions common to all cartridge drivers */
enum DS2401Command : uint8_t {
_DS2401_READ_ROM = 0x33,
_DS2401_MATCH_ROM = 0x55,
_DS2401_SKIP_ROM = 0xcc,
_DS2401_SEARCH_ROM = 0xf0
};
// TODO: _ZS01_SEND_DELAY and _ZS01_PACKET_DELAY could be tweaked to make the
// tool faster, however setting both to 30000 results in bricked carts when
// attempting to reflash.
@ -129,7 +136,7 @@ static constexpr int _ZS01_PACKET_DELAY = 300000;
DriverError CartDriver::readSystemID(void) {
auto enable = disableInterrupts();
if (!io::dsDIOReset()) {
if (!io::digitalIODS2401.reset()) {
if (enable)
enableInterrupts();
@ -139,9 +146,9 @@ DriverError CartDriver::readSystemID(void) {
_dump.flags |= DUMP_HAS_SYSTEM_ID;
io::dsDIOWriteByte(0x33);
io::digitalIODS2401.writeByte(_DS2401_READ_ROM);
for (int i = 0; i < 8; i++)
_dump.systemID.data[i] = io::dsDIOReadByte();
_dump.systemID.data[i] = io::digitalIODS2401.readByte();
if (enable)
enableInterrupts();
@ -155,7 +162,7 @@ DriverError CartDriver::readSystemID(void) {
DriverError X76Driver::readCartID(void) {
auto enable = disableInterrupts();
if (!io::dsCartReset()) {
if (!io::cartDS2401.reset()) {
if (enable)
enableInterrupts();
@ -165,9 +172,9 @@ DriverError X76Driver::readCartID(void) {
_dump.flags |= DUMP_HAS_CART_ID;
io::dsCartWriteByte(0x33);
io::cartDS2401.writeByte(_DS2401_READ_ROM);
for (int i = 0; i < 8; i++)
_dump.cartID.data[i] = io::dsCartReadByte();
_dump.cartID.data[i] = io::cartDS2401.readByte();
if (enable)
enableInterrupts();
@ -182,26 +189,26 @@ DriverError X76Driver::_x76Command(
uint8_t pollByte, uint8_t cmd, int param
) const {
delayMicroseconds(_X76_PACKET_DELAY);
io::i2cStartWithCS();
io::cartI2C.startWithCS();
io::i2cWriteByte(cmd);
if (!io::i2cGetACK()) {
io::i2cStopWithCS();
io::cartI2C.writeByte(cmd);
if (!io::cartI2C.getACK()) {
io::cartI2C.stopWithCS();
LOG_CART_IO("NACK while sending cmd=0x%02x", cmd);
return X76_NACK;
}
if (param >= 0) {
io::i2cWriteByte(param);
if (!io::i2cGetACK()) {
io::i2cStopWithCS();
io::cartI2C.writeByte(param);
if (!io::cartI2C.getACK()) {
io::cartI2C.stopWithCS();
LOG_CART_IO("NACK while sending param=0x%02x", param);
return X76_NACK;
}
}
if (!io::i2cWriteBytes(_dump.dataKey, sizeof(_dump.dataKey))) {
io::i2cStopWithCS();
if (!io::cartI2C.writeBytes(_dump.dataKey, sizeof(_dump.dataKey))) {
io::cartI2C.stopWithCS();
LOG_CART_IO("NACK while sending data key");
return X76_NACK;
}
@ -218,13 +225,13 @@ DriverError X76Driver::_x76Command(
for (int i = _X76_MAX_ACK_POLLS; i; i--) {
delayMicroseconds(_X76_WRITE_DELAY);
io::i2cStart();
io::i2cWriteByte(pollByte);
if (io::i2cGetACK())
io::cartI2C.start();
io::cartI2C.writeByte(pollByte);
if (io::cartI2C.getACK())
return NO_ERROR;
}
io::i2cStopWithCS();
io::cartI2C.stopWithCS();
LOG_CART_IO("ACK polling timeout (wrong key?)");
return X76_POLL_FAIL;
}
@ -255,18 +262,18 @@ DriverError X76F041Driver::readPrivateData(void) {
if (error)
return error;
io::i2cReadByte(); // Ignore "secure read setup" byte
io::i2cStart();
io::cartI2C.readByte(); // Ignore "secure read setup" byte
io::cartI2C.start();
io::i2cWriteByte(i & 0xff);
if (!io::i2cGetACK()) {
io::i2cStopWithCS();
io::cartI2C.writeByte(i & 0xff);
if (!io::cartI2C.getACK()) {
io::cartI2C.stopWithCS();
LOG_CART_IO("NACK after resending addr=0x%02x", i & 0xff);
return X76_NACK;
}
io::i2cReadBytes(&_dump.data[i], 128);
io::i2cStopWithCS();
io::cartI2C.readBytes(&_dump.data[i], 128);
io::cartI2C.stopWithCS();
}
_dump.flags |= DUMP_PRIVATE_DATA_OK;
@ -278,8 +285,8 @@ DriverError X76F041Driver::readPrivateData(void) {
return error;
util::clear(_dump.config);
io::i2cReadBytes(_dump.config, 5);
io::i2cStopWithCS();
io::cartI2C.readBytes(_dump.config, 5);
io::cartI2C.stopWithCS();
_dump.flags |= DUMP_CONFIG_OK;
return NO_ERROR;
@ -294,8 +301,8 @@ DriverError X76F041Driver::writeData(void) {
if (error)
return error;
auto ok = io::i2cWriteBytes(&_dump.data[i], 8);
io::i2cStopWithCS(_X76_WRITE_DELAY);
auto ok = io::cartI2C.writeBytes(&_dump.data[i], 8);
io::cartI2C.stopWithCS(_X76_WRITE_DELAY);
if (!ok) {
LOG_CART_IO("NACK while sending data bytes");
@ -309,8 +316,8 @@ DriverError X76F041Driver::writeData(void) {
if (error)
return error;
auto ok = io::i2cWriteBytes(_dump.config, 5);
io::i2cStopWithCS(_X76_WRITE_DELAY);
auto ok = io::cartI2C.writeBytes(_dump.config, 5);
io::cartI2C.stopWithCS(_X76_WRITE_DELAY);
if (!ok) {
LOG_CART_IO("NACK while sending config registers");
@ -327,7 +334,7 @@ DriverError X76F041Driver::erase(void) {
if (error)
return error;
io::i2cStopWithCS(_X76_WRITE_DELAY);
io::cartI2C.stopWithCS(_X76_WRITE_DELAY);
util::clear(_dump.dataKey);
return NO_ERROR;
@ -343,14 +350,14 @@ DriverError X76F041Driver::setDataKey(const uint8_t *key) {
// The X76F041 requires the key to be sent twice as a way of ensuring it
// gets received correctly.
for (int i = 2; i; i--) {
if (!io::i2cWriteBytes(key, sizeof(_dump.dataKey))) {
io::i2cStopWithCS(_X76_WRITE_DELAY);
if (!io::cartI2C.writeBytes(key, sizeof(_dump.dataKey))) {
io::cartI2C.stopWithCS(_X76_WRITE_DELAY);
LOG_CART_IO("NACK while setting new data key");
return X76_NACK;
}
}
io::i2cStopWithCS(_X76_WRITE_DELAY);
io::cartI2C.stopWithCS(_X76_WRITE_DELAY);
_dump.copyKeyFrom(key);
return NO_ERROR;
@ -370,9 +377,9 @@ DriverError X76F100Driver::readPrivateData(void) {
if (error)
return error;
//io::i2cStart();
io::i2cReadBytes(_dump.data, 112);
io::i2cStopWithCS();
//io::cartI2C.Start();
io::cartI2C.readBytes(_dump.data, 112);
io::cartI2C.stopWithCS();
_dump.flags |= DUMP_PRIVATE_DATA_OK;
return NO_ERROR;
@ -387,8 +394,8 @@ DriverError X76F100Driver::writeData(void) {
if (error)
return error;
auto ok = io::i2cWriteBytes(&_dump.data[i], 8);
io::i2cStopWithCS(_X76_WRITE_DELAY);
auto ok = io::cartI2C.writeBytes(&_dump.data[i], 8);
io::cartI2C.stopWithCS(_X76_WRITE_DELAY);
if (!ok) {
LOG_CART_IO("NACK while sending data bytes");
@ -411,8 +418,8 @@ DriverError X76F100Driver::erase(void) {
if (error)
return error;
auto ok = io::i2cWriteBytes(dummy, 8);
io::i2cStopWithCS(_X76_WRITE_DELAY);
auto ok = io::cartI2C.writeBytes(dummy, 8);
io::cartI2C.stopWithCS(_X76_WRITE_DELAY);
if (!ok) {
LOG_CART_IO("NACK while sending data bytes");
@ -433,8 +440,8 @@ DriverError X76F100Driver::setDataKey(const uint8_t *key) {
if (error)
return error;
auto ok = io::i2cWriteBytes(key, sizeof(_dump.dataKey));
io::i2cStopWithCS(_X76_WRITE_DELAY);
auto ok = io::cartI2C.writeBytes(key, sizeof(_dump.dataKey));
io::cartI2C.stopWithCS(_X76_WRITE_DELAY);
if (!ok) {
LOG_CART_IO("NACK while setting new data key");
@ -450,7 +457,7 @@ DriverError X76F100Driver::setDataKey(const uint8_t *key) {
DriverError ZS01Driver::_transact(ZS01Packet &request, ZS01Packet &response) {
delayMicroseconds(_ZS01_PACKET_DELAY);
io::i2cStart();
io::cartI2C.start();
#if 0
char buffer[48];
@ -459,16 +466,16 @@ DriverError ZS01Driver::_transact(ZS01Packet &request, ZS01Packet &response) {
LOG_CART_IO("S: %s", buffer);
#endif
if (!io::i2cWriteBytes(
if (!io::cartI2C.writeBytes(
&request.command, sizeof(ZS01Packet), _ZS01_SEND_DELAY
)) {
io::i2cStop();
io::cartI2C.stop();
LOG_CART_IO("NACK while sending request packet");
return ZS01_NACK;
}
io::i2cReadBytes(&response.command, sizeof(ZS01Packet));
io::i2cStop();
io::cartI2C.readBytes(&response.command, sizeof(ZS01Packet));
io::cartI2C.stop();
#if 0
util::hexToString(buffer, &response.command, sizeof(ZS01Packet), ' ');
@ -651,14 +658,14 @@ CartDriver *newCartDriver(CartDump &dump) {
}
#ifdef ENABLE_ZS01_CART_DRIVER
uint32_t id1 = io::i2cResetZS01();
auto id1 = io::cartI2C.resetZS01();
LOG_CART_IO("detecting ZS01: 0x%08x", id1);
if (id1 == _ID_ZS01)
return new ZS01Driver(dump);
#endif
uint32_t id2 = io::i2cResetX76();
auto id2 = io::cartI2C.resetX76();
LOG_CART_IO("detecting X76: 0x%08x", id2);
switch (id2) {

View File

@ -41,7 +41,7 @@ int main(int argc, const char **argv) {
gpu::enableDisplay(true);
spu::setMasterVolume(spu::MAX_VOLUME / 2);
io::setMiscOutput(io::MISC_SPU_ENABLE, true);
io::setMiscOutput(io::MISC_OUT_SPU_ENABLE, true);
app->run(args.resourcePtr, args.resourceLength);

View File

@ -21,9 +21,9 @@
/* System 573 base hardware */
typedef enum {
SYS573_MISC_OUT_ADC_MOSI = 1 << 0,
SYS573_MISC_OUT_ADC_DI = 1 << 0,
SYS573_MISC_OUT_ADC_CS = 1 << 1,
SYS573_MISC_OUT_ADC_SCK = 1 << 2,
SYS573_MISC_OUT_ADC_CLK = 1 << 2,
SYS573_MISC_OUT_COIN_COUNT1 = 1 << 3,
SYS573_MISC_OUT_COIN_COUNT2 = 1 << 4,
SYS573_MISC_OUT_AMP_ENABLE = 1 << 5,
@ -33,7 +33,7 @@ typedef enum {
} Sys573MiscOutputFlag;
typedef enum {
SYS573_MISC_IN_ADC_MISO = 1 << 0,
SYS573_MISC_IN_ADC_DO = 1 << 0,
SYS573_MISC_IN_ADC_SARS = 1 << 1,
SYS573_MISC_IN_CART_SDA = 1 << 2,
SYS573_MISC_IN_JVS_SENSE = 1 << 3,
@ -137,6 +137,11 @@ typedef enum {
SYS573D_CPLD_CTRL_UNKNOWN = 1 << 15
} Sys573DCPLDControlFlag;
typedef enum {
SYS573D_FPGA_MP3_I2C_SDA = 1 << 12,
SYS573D_FPGA_MP3_I2C_SCL = 1 << 13
} Sys573DFPGAMP3I2CFlag;
typedef enum {
SYS573D_FPGA_DS_BUS_DS2433 = 1 << 8,
SYS573D_FPGA_DS_BUS_DS2401 = 1 << 12
@ -144,6 +149,8 @@ typedef enum {
#define SYS573D_FPGA_MAGIC _MMIO16(DEV0_BASE | 0x640080)
#define SYS573D_FPGA_NET_ID _MMIO16(DEV0_BASE | 0x640090)
#define SYS573D_FPGA_MP3_PTR_H _MMIO16(DEV0_BASE | 0x6400a0)
#define SYS573D_FPGA_MP3_PTR_L _MMIO16(DEV0_BASE | 0x6400a2)
#define SYS573D_FPGA_MP3_ENDPTR_H _MMIO16(DEV0_BASE | 0x6400a4)