mirror of
https://github.com/spicyjpeg/573in1.git
synced 2025-03-01 07:20:42 +01:00
Fix FPGA bitstream, rewrite I2C and 1-wire drivers
This commit is contained in:
parent
84985785c8
commit
3a340da8c7
BIN
data/fpga.bit
BIN
data/fpga.bit
Binary file not shown.
366
fpga/fpga.ucf
366
fpga/fpga.ucf
@ -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
|
||||
|
||||
|
35
fpga/fpga.ys
35
fpga/fpga.ys
@ -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
|
||||
|
@ -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 ^
|
||||
|
328
fpga/src/main.v
328
fpga/src/main.v
@ -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
|
||||
|
@ -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
37
fpga/src/spartanxl/map.v
Normal 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
|
551
fpga/src/spartanxl/primitives.lib
Normal file
551
fpga/src/spartanxl/primitives.lib
Normal 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)"; }
|
||||
}
|
||||
}
|
646
fpga/src/spartanxl/primitives.v
Normal file
646
fpga/src/spartanxl/primitives.v
Normal 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
|
@ -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
|
@ -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;
|
||||
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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)
|
||||
|
Loading…
x
Reference in New Issue
Block a user