Initial repo build
816
.gitignore
vendored
Normal file
@@ -0,0 +1,816 @@
|
|||||||
|
*.bin
|
||||||
|
build/ADV7123_TEST.qpf
|
||||||
|
build/ADV7123_TEST.qsf
|
||||||
|
build/ADV7123.vhd
|
||||||
|
build/A-Hdrive
|
||||||
|
build/audio_shifter.v
|
||||||
|
build/audio_top.v
|
||||||
|
build/Clock_50to100.BAK.vhd
|
||||||
|
build/constraints.sdc
|
||||||
|
build/db/
|
||||||
|
build/ddr2_sodimm.qpf
|
||||||
|
build/ddr2_sodimm.qpf.v1
|
||||||
|
build/ddr2_sodimm.qsf
|
||||||
|
build/ddr2_sodimm.qsf.v1
|
||||||
|
build/incremental_db/
|
||||||
|
build/KEY_TEST.qpf
|
||||||
|
build/KEY_TEST.qsf
|
||||||
|
build/KEY_TEST.v
|
||||||
|
build/ledwater.qpf
|
||||||
|
build/ledwater.qsf
|
||||||
|
build/ledwater.v
|
||||||
|
build/Makefile.1306
|
||||||
|
build/mypll.cmp
|
||||||
|
build/mypll.qip
|
||||||
|
build/mypll.vhd
|
||||||
|
build/output_files/
|
||||||
|
build/.qsys_edit/
|
||||||
|
build/serial.qpf
|
||||||
|
build/serial.qsf
|
||||||
|
build/serial.v
|
||||||
|
build/serv_req_info.txt
|
||||||
|
build/simulation/
|
||||||
|
build/template.qsf
|
||||||
|
build/unsaved/
|
||||||
|
build/unsaved.qsys
|
||||||
|
build/unsaved.sopcinfo
|
||||||
|
c5_pin_model_dump.txt
|
||||||
|
CPLD/build/db/
|
||||||
|
CPLD/build/incremental_db/
|
||||||
|
CPLD/build/output_files/
|
||||||
|
CPLD/build/simulation/
|
||||||
|
CPLD/build/tranZPUterSW_constraints.sdc.clk
|
||||||
|
CPLD/mz80b/
|
||||||
|
CPLD/v1.0.bak/
|
||||||
|
CPLD/v1.0/build/greybox_tmp/
|
||||||
|
CPLD/v1.0/MZ2000/build/db/
|
||||||
|
CPLD/v1.0/MZ2000/build/greybox_tmp/
|
||||||
|
CPLD/v1.0/MZ2000/build/incremental_db/
|
||||||
|
CPLD/v1.0/MZ2000/build/output_files/
|
||||||
|
CPLD/v1.0/MZ2000/build/simulation/
|
||||||
|
CPLD/v1.0/MZ2000/build/tranZPUterSW_constraints.sdc.clk
|
||||||
|
CPLD/v1.0/MZ2000/build/tzpuSW700 MZ2000.qsf
|
||||||
|
CPLD/v1.0/MZ2000/tranZPUterSW700.sav.bak
|
||||||
|
CPLD/v1.0/MZ2000/tranZPUterSW700_tidy.vhd
|
||||||
|
CPLD/v1.0/MZ2000/tranZPUterSW700.vhd.sav1
|
||||||
|
CPLD/v1.0/MZ2000/tranZPUterSW700.vhd.sav2
|
||||||
|
CPLD/v1.0/MZ2000/tranZPUterSW700.vhd.sav3
|
||||||
|
CPLD/v1.0/MZ2000/tranZPUterSW.sav2
|
||||||
|
CPLD/v1.0/MZ2000/tranZPUterSW.vhd.clk
|
||||||
|
CPLD/v1.0/MZ2000/tranZPUterSW.vhd.presweep
|
||||||
|
CPLD/v1.0/MZ700/build/db/
|
||||||
|
CPLD/v1.0/MZ700/build/greybox_tmp/
|
||||||
|
CPLD/v1.0/MZ700/build/incremental_db/
|
||||||
|
CPLD/v1.0/MZ700/build/output_files/
|
||||||
|
CPLD/v1.0/MZ700/build/simulation/
|
||||||
|
CPLD/v1.0/MZ700/build/tranZPUterSW_constraints.sdc.clk
|
||||||
|
CPLD/v1.0/MZ700/rr
|
||||||
|
CPLD/v1.0/MZ700/rtsd
|
||||||
|
CPLD/v1.0/MZ700/tranZPUterSW.sav2
|
||||||
|
CPLD/v1.0/MZ700/tranZPUterSW.vhd.clk
|
||||||
|
CPLD/v1.0/MZ700/tranZPUterSW.vhd.presweep
|
||||||
|
CPLD/v1.0/MZ700/working
|
||||||
|
CPLD/v1.0/MZ700/working2
|
||||||
|
CPLD/v1.0/MZ80A/build/db/
|
||||||
|
CPLD/v1.0/MZ80A/build/emuMZ_ClockII.qip
|
||||||
|
CPLD/v1.0/MZ80A/build/greybox_tmp/
|
||||||
|
CPLD/v1.0/MZ80A/build/incremental_db/
|
||||||
|
CPLD/v1.0/MZ80A/build/output_files/
|
||||||
|
CPLD/v1.0/MZ80A/build/simulation/
|
||||||
|
CPLD/v1.0/MZ80A/build/tranZPUterSW_constraints.sdc.clk
|
||||||
|
cpu/sav
|
||||||
|
cpu/zpu_core_evo.vhd.06052012
|
||||||
|
devices/sysbus/BRAM/TZSW_DualPort32-64BootBRAM.vhd
|
||||||
|
devices/sysbus/BRAM/TZSW_DualPort3264BootBRAM.vhd
|
||||||
|
devices/sysbus/TCPU/
|
||||||
|
.dm
|
||||||
|
*.dmp
|
||||||
|
docker/QuartusPrime/Dockerfile.13.0.1.old
|
||||||
|
docker/QuartusPrime/files/13.0/
|
||||||
|
docker/QuartusPrime/files/13.1/
|
||||||
|
docker/QuartusPrime/files/17.1/
|
||||||
|
docker/QuartusPrime/local/
|
||||||
|
docker/QuartusPrime/quartus_docker.sh
|
||||||
|
docker/QuartusPrime/Quartus-web-13.0.1.232-linux.tar
|
||||||
|
*.done
|
||||||
|
*.elf
|
||||||
|
.gradle
|
||||||
|
*.jdi
|
||||||
|
*.log
|
||||||
|
*.lss
|
||||||
|
Manuals/
|
||||||
|
*.map
|
||||||
|
.metadata
|
||||||
|
/.nb-gradle/
|
||||||
|
nohup.out
|
||||||
|
*.o
|
||||||
|
*/*/*/old/
|
||||||
|
*/*/old/
|
||||||
|
*/old/
|
||||||
|
old/
|
||||||
|
*.out.sdc
|
||||||
|
*.pin
|
||||||
|
*.pof
|
||||||
|
*.qdf
|
||||||
|
*.qws
|
||||||
|
*.rbf
|
||||||
|
/Releases
|
||||||
|
*.rpt
|
||||||
|
*.sav
|
||||||
|
schematics/previous
|
||||||
|
schematics/sep/
|
||||||
|
schematics/tranZPUter/
|
||||||
|
schematics/tranZPUter-SW/
|
||||||
|
SD/
|
||||||
|
*.sld
|
||||||
|
*.smsg
|
||||||
|
*.sof
|
||||||
|
software/apps/*/*_obj/
|
||||||
|
software/asm/cbios.asm.bak
|
||||||
|
software/asm/.cbiosII.asm.swo
|
||||||
|
software/asm/CPM22-BIOS.asm
|
||||||
|
software/asm/cpm22.mzf
|
||||||
|
software/asm/dz80.ini
|
||||||
|
software/asm/include/Definitions.asm.swo
|
||||||
|
software/asm/MZ80AFI.asm.bak
|
||||||
|
software/asm/new/
|
||||||
|
software/asm/old/
|
||||||
|
software/asm/rfs_bank2.prewriteread
|
||||||
|
software/asm/sav/
|
||||||
|
software/asm/savit
|
||||||
|
software.bak/
|
||||||
|
software/BAS
|
||||||
|
software/build/
|
||||||
|
software/CAS
|
||||||
|
software/CPM
|
||||||
|
software/CPM/1M44/DSK
|
||||||
|
software/CPM/1M44/DSK/CPM_1M44_RFS_1.DSK
|
||||||
|
software/CPM/1M44/DSK/CPM_1M44_RFS_2.DSK
|
||||||
|
software/CPM/1M44/RAW
|
||||||
|
software/CPM/1M44/RAW/CPM_1M44_RFS_1.RAW
|
||||||
|
software/CPM/1M44/RAW/CPM_1M44_RFS_2.RAW
|
||||||
|
software/CPM/320K/DSK
|
||||||
|
software/CPM/320K/RAW
|
||||||
|
software/CPM/720K/DSK
|
||||||
|
software/CPM/720K/RAW
|
||||||
|
software/CPM/CPM00_MZ800
|
||||||
|
software/CPM/CPM00_SYSTEM
|
||||||
|
software/CPM/CPM01_TURBOP
|
||||||
|
software/CPM/CPM02_HI_C
|
||||||
|
software/CPM/CPM03_FORTRAN80
|
||||||
|
software/CPM/CPM04_MBASIC
|
||||||
|
software/CPM/CPM05_COBOL80_v13
|
||||||
|
software/CPM/CPM06_COBOL80_v20
|
||||||
|
software/CPM/CPM07_COBOL80
|
||||||
|
software/CPM/CPM08_Z80FORTH
|
||||||
|
software/CPM/CPM09_CPMTEX
|
||||||
|
software/CPM/CPM10_DISKUTILFUNC5
|
||||||
|
software/CPM/CPM11_MAC80
|
||||||
|
software/CPM/CPM12_PASCALMTP_v561
|
||||||
|
software/CPM/CPM13_MTPUG_01
|
||||||
|
software/CPM/CPM14_MTPUG_02
|
||||||
|
software/CPM/CPM15_MTPUG_03
|
||||||
|
software/CPM/CPM16_MTPUG_04
|
||||||
|
software/CPM/CPM17_MTPUG_05
|
||||||
|
software/CPM/CPM18_MTPUG_06
|
||||||
|
software/CPM/CPM19_MTPUG_07
|
||||||
|
software/CPM/CPM20_MTPUG_08
|
||||||
|
software/CPM/CPM21_MTPUG_09
|
||||||
|
software/CPM/CPM22_MTPUG_10
|
||||||
|
software/CPM/CPM23_PLI
|
||||||
|
software/CPM/CPM24_PLI80_v13
|
||||||
|
software/CPM/CPM25_PLI80_v14
|
||||||
|
software/CPM/CPM26_TPASCAL_v300a
|
||||||
|
software/CPM/CPM27_WORDSTAR_v30
|
||||||
|
software/CPM/CPM28_PLM80
|
||||||
|
software/CPM/CPM29_ZSID_v14
|
||||||
|
software/CPM/CPM30_WORDSTAR_v400
|
||||||
|
software/CPM/CPM31_WORDSTAR_v330
|
||||||
|
software/CPM/CPM32_ZCPR3
|
||||||
|
software/CPM/CPM33_ZCPR3_COMMON
|
||||||
|
software/CPM/cpm3/on2
|
||||||
|
software/CPM/CPM_MC_5
|
||||||
|
software/CPM/CPM_MC_C0
|
||||||
|
software/CPM/CPM_MC_C1
|
||||||
|
software/CPM/CPM_MC_C2
|
||||||
|
software/CPM/CPM_MC_C3
|
||||||
|
software/CPM/CPM_MC_C4
|
||||||
|
software/CPM/CPM_MC_C5
|
||||||
|
software/CPM/CPM_MC_C6
|
||||||
|
software/CPM/CPM_MC_C7
|
||||||
|
software/CPM/CPM_MC_C8
|
||||||
|
software/CPM/CPM_MC_C9
|
||||||
|
software/CPM/CPM_MC_D0
|
||||||
|
software/CPM/CPM_MC_D1
|
||||||
|
software/CPM/CPM_MC_D2
|
||||||
|
software/CPM/CPM_MC_D3
|
||||||
|
software/CPM/CPM_MC_D4
|
||||||
|
software/CPM/CPM_MC_D5
|
||||||
|
software/CPM/CPM_MC_D6
|
||||||
|
software/CPM/CPM_MC_D7
|
||||||
|
software/CPM/CPM_MC_D8
|
||||||
|
software/CPM/CPM_MC_D9
|
||||||
|
software/CPM/CPM_MC_E0
|
||||||
|
software/CPM/CPM_MC_E1
|
||||||
|
software/CPM/CPM_MC_E2
|
||||||
|
software/CPM/CPM_MC_E3
|
||||||
|
software/CPM/CPM_MC_E4
|
||||||
|
software/CPM/CPM_MC_E5
|
||||||
|
software/CPM/CPM_MC_E6
|
||||||
|
software/CPM/CPM_MC_E7
|
||||||
|
software/CPM/CPM_MC_E8
|
||||||
|
software/CPM/CPM_MC_E9
|
||||||
|
software/CPM/CPM_MC_F0
|
||||||
|
software/CPM/CPM_MC_F1
|
||||||
|
software/CPM/CPM_MC_F2
|
||||||
|
software/CPM/CPM_MC_F3
|
||||||
|
software/CPM/CPM_MC_F4
|
||||||
|
software/CPM/CPM_MC_F5
|
||||||
|
software/CPM/CPM_MC_F6
|
||||||
|
software/CPM/CPM_MC_F7
|
||||||
|
software/CPM/CPM_MC_F8
|
||||||
|
software/CPM/CPM_MC_F9
|
||||||
|
software/CPM/CPM_MULTICOMP_contents.txt
|
||||||
|
software/CPM/CPM_RFS_1
|
||||||
|
software/CPM/CPM_RFS_2
|
||||||
|
software/CPM/PLM80
|
||||||
|
software/CPM/SDC16M/
|
||||||
|
software/CPM/tools/
|
||||||
|
software/CPM/tosort
|
||||||
|
software/disks
|
||||||
|
software/DSK
|
||||||
|
software/dz80.ini
|
||||||
|
software/full.asm
|
||||||
|
software/howto
|
||||||
|
software/iocp/iocp_obj/
|
||||||
|
software/mif/monitor_SA1510.mif.bak
|
||||||
|
software/mif/monitor_SA1510.mif.tst
|
||||||
|
software/MZ800_IOCS.ref
|
||||||
|
software/MZB
|
||||||
|
software/MZF
|
||||||
|
software/NASCAS
|
||||||
|
software/rfs_bank2.asm.1703.2200
|
||||||
|
software/roms/bios.rom
|
||||||
|
software/roms/cbios_bank5.rom
|
||||||
|
software/roms/cbios_bank6.rom
|
||||||
|
software/roms/cbios_bank7.rom
|
||||||
|
software/roms/cbios_bank8.rom
|
||||||
|
software/roms/cmp
|
||||||
|
software/roms/cpm22.rom
|
||||||
|
software/roms/data
|
||||||
|
software/roms/fill
|
||||||
|
software/roms/keymap_readme.txt
|
||||||
|
software/roms/MZ80AFI.BIN
|
||||||
|
software/roms/MZ80AFI.rom
|
||||||
|
software/roms/SA1510.orig
|
||||||
|
software/roms/SHARP_MZ80A_RFS_CPM_IMAGE_1.img
|
||||||
|
software/roms/SHARP_MZ80A_RFS_IMAGE_1.img
|
||||||
|
software/roms/split
|
||||||
|
software/roms/x
|
||||||
|
software/src/FatFS
|
||||||
|
software/src/sav
|
||||||
|
software/src/sdtest.c
|
||||||
|
software/src/tools/.flashmmcfg.c.swo
|
||||||
|
software/src/tools/x
|
||||||
|
software/tmp/
|
||||||
|
software/x/
|
||||||
|
software/zputa/zpu_obj/
|
||||||
|
*.srec
|
||||||
|
*.srf
|
||||||
|
*.summary
|
||||||
|
*.swo
|
||||||
|
*.swp
|
||||||
|
tools/assemble_rfs.sh
|
||||||
|
tools/Mars4_5.jar
|
||||||
|
tools/Master0.z80
|
||||||
|
tools/Master1.z80
|
||||||
|
*.zpu
|
||||||
|
./.git
|
||||||
|
./.git/refs
|
||||||
|
./.git/refs/tags
|
||||||
|
./.git/refs/heads
|
||||||
|
./.git/info
|
||||||
|
./.git/hooks
|
||||||
|
./.git/branches
|
||||||
|
./.git/objects
|
||||||
|
./.git/objects/72
|
||||||
|
./.git/objects/bd
|
||||||
|
./.git/objects/c0
|
||||||
|
./.git/objects/98
|
||||||
|
./.git/objects/f6
|
||||||
|
./.git/objects/58
|
||||||
|
./.git/objects/9a
|
||||||
|
./.git/objects/a7
|
||||||
|
./.git/objects/4f
|
||||||
|
./.git/objects/b3
|
||||||
|
./.git/objects/99
|
||||||
|
./.git/objects/c4
|
||||||
|
./.git/objects/eb
|
||||||
|
./.git/objects/2b
|
||||||
|
./.git/objects/ca
|
||||||
|
./.git/objects/75
|
||||||
|
./.git/objects/3f
|
||||||
|
./.git/objects/52
|
||||||
|
./.git/objects/bb
|
||||||
|
./.git/objects/c2
|
||||||
|
./.git/objects/f0
|
||||||
|
./.git/objects/49
|
||||||
|
./.git/objects/50
|
||||||
|
./.git/objects/94
|
||||||
|
./.git/objects/82
|
||||||
|
./.git/objects/0a
|
||||||
|
./.git/objects/3e
|
||||||
|
./.git/objects/1c
|
||||||
|
./.git/objects/a1
|
||||||
|
./.git/objects/cf
|
||||||
|
./.git/objects/41
|
||||||
|
./.git/objects/22
|
||||||
|
./.git/objects/8e
|
||||||
|
./.git/objects/19
|
||||||
|
./.git/objects/a8
|
||||||
|
./.git/objects/4e
|
||||||
|
./.git/objects/69
|
||||||
|
./.git/objects/10
|
||||||
|
./.git/objects/06
|
||||||
|
./.git/objects/1a
|
||||||
|
./.git/objects/e1
|
||||||
|
./.git/objects/47
|
||||||
|
./.git/objects/fe
|
||||||
|
./.git/objects/9d
|
||||||
|
./.git/objects/86
|
||||||
|
./.git/objects/7d
|
||||||
|
./.git/objects/91
|
||||||
|
./.git/objects/57
|
||||||
|
./.git/objects/e3
|
||||||
|
./.git/objects/f7
|
||||||
|
./.git/objects/ce
|
||||||
|
./.git/objects/00
|
||||||
|
./.git/objects/25
|
||||||
|
./.git/objects/87
|
||||||
|
./.git/objects/51
|
||||||
|
./.git/objects/60
|
||||||
|
./.git/objects/d3
|
||||||
|
./.git/objects/73
|
||||||
|
./.git/objects/dc
|
||||||
|
./.git/objects/63
|
||||||
|
./.git/objects/5e
|
||||||
|
./.git/objects/48
|
||||||
|
./.git/objects/cb
|
||||||
|
./.git/objects/04
|
||||||
|
./.git/objects/e7
|
||||||
|
./.git/objects/54
|
||||||
|
./.git/objects/37
|
||||||
|
./.git/objects/65
|
||||||
|
./.git/objects/6b
|
||||||
|
./.git/objects/53
|
||||||
|
./.git/objects/bc
|
||||||
|
./.git/objects/02
|
||||||
|
./.git/objects/d9
|
||||||
|
./.git/objects/95
|
||||||
|
./.git/objects/ec
|
||||||
|
./.git/objects/5b
|
||||||
|
./.git/objects/be
|
||||||
|
./.git/objects/b1
|
||||||
|
./.git/objects/e0
|
||||||
|
./.git/objects/15
|
||||||
|
./.git/objects/9b
|
||||||
|
./.git/objects/0c
|
||||||
|
./.git/objects/f1
|
||||||
|
./.git/objects/30
|
||||||
|
./.git/objects/27
|
||||||
|
./.git/objects/96
|
||||||
|
./.git/objects/a5
|
||||||
|
./.git/objects/78
|
||||||
|
./.git/objects/90
|
||||||
|
./.git/objects/68
|
||||||
|
./.git/objects/11
|
||||||
|
./.git/objects/59
|
||||||
|
./.git/objects/79
|
||||||
|
./.git/objects/92
|
||||||
|
./.git/objects/8f
|
||||||
|
./.git/objects/3d
|
||||||
|
./.git/objects/28
|
||||||
|
./.git/objects/ac
|
||||||
|
./.git/objects/a6
|
||||||
|
./.git/objects/f4
|
||||||
|
./.git/objects/f5
|
||||||
|
./.git/objects/cc
|
||||||
|
./.git/objects/08
|
||||||
|
./.git/objects/ba
|
||||||
|
./.git/objects/77
|
||||||
|
./.git/objects/a9
|
||||||
|
./.git/objects/ff
|
||||||
|
./.git/objects/db
|
||||||
|
./.git/objects/d8
|
||||||
|
./.git/objects/ed
|
||||||
|
./.git/objects/6c
|
||||||
|
./.git/objects/7a
|
||||||
|
./.git/objects/ee
|
||||||
|
./.git/objects/2f
|
||||||
|
./.git/objects/44
|
||||||
|
./.git/objects/7f
|
||||||
|
./.git/objects/9e
|
||||||
|
./.git/objects/cd
|
||||||
|
./.git/objects/12
|
||||||
|
./.git/objects/de
|
||||||
|
./.git/objects/e9
|
||||||
|
./.git/objects/4b
|
||||||
|
./.git/objects/a3
|
||||||
|
./.git/objects/39
|
||||||
|
./.git/objects/d5
|
||||||
|
./.git/objects/b6
|
||||||
|
./.git/objects/8b
|
||||||
|
./.git/objects/83
|
||||||
|
./.git/objects/f2
|
||||||
|
./.git/objects/76
|
||||||
|
./.git/objects/af
|
||||||
|
./.git/objects/pack
|
||||||
|
./.git/objects/3a
|
||||||
|
./.git/objects/9c
|
||||||
|
./.git/objects/ad
|
||||||
|
./.git/objects/61
|
||||||
|
./.git/objects/fa
|
||||||
|
./.git/objects/ef
|
||||||
|
./.git/objects/42
|
||||||
|
./.git/objects/d6
|
||||||
|
./.git/objects/2d
|
||||||
|
./.git/objects/17
|
||||||
|
./.git/objects/1d
|
||||||
|
./.git/objects/b8
|
||||||
|
./.git/objects/c3
|
||||||
|
./.git/objects/c9
|
||||||
|
./.git/objects/7e
|
||||||
|
./.git/objects/8d
|
||||||
|
./.git/objects/55
|
||||||
|
./.git/objects/46
|
||||||
|
./.git/objects/5f
|
||||||
|
./.git/objects/67
|
||||||
|
./.git/objects/6f
|
||||||
|
./.git/objects/d7
|
||||||
|
./.git/objects/38
|
||||||
|
./.git/objects/05
|
||||||
|
./.git/objects/2e
|
||||||
|
./.git/objects/b0
|
||||||
|
./.git/objects/0b
|
||||||
|
./.git/objects/info
|
||||||
|
./.git/objects/6e
|
||||||
|
./.git/objects/74
|
||||||
|
./.git/objects/c6
|
||||||
|
./.git/objects/f8
|
||||||
|
./.git/objects/0d
|
||||||
|
./.git/objects/33
|
||||||
|
./.git/objects/88
|
||||||
|
./.git/objects/df
|
||||||
|
./.git/objects/d1
|
||||||
|
./.git/objects/aa
|
||||||
|
./.git/objects/8c
|
||||||
|
./.git/objects/8a
|
||||||
|
./.git/objects/e2
|
||||||
|
./.git/objects/7c
|
||||||
|
./.git/objects/6a
|
||||||
|
./.git/objects/e5
|
||||||
|
./.git/objects/a2
|
||||||
|
./.git/objects/ae
|
||||||
|
./.git/objects/c1
|
||||||
|
./.git/objects/80
|
||||||
|
./.git/objects/71
|
||||||
|
./.git/objects/d2
|
||||||
|
./.git/objects/31
|
||||||
|
./.git/objects/0f
|
||||||
|
./.git/objects/c8
|
||||||
|
./.git/objects/43
|
||||||
|
./.git/objects/2a
|
||||||
|
./.git/objects/a4
|
||||||
|
./.git/objects/21
|
||||||
|
./.git/objects/13
|
||||||
|
./.git/objects/26
|
||||||
|
./.git/objects/64
|
||||||
|
./.git/objects/d0
|
||||||
|
./.git/objects/b7
|
||||||
|
./.git/objects/0e
|
||||||
|
./.git/objects/2c
|
||||||
|
./.git/objects/a0
|
||||||
|
./.git/objects/4d
|
||||||
|
./.git/objects/e4
|
||||||
|
./.git/objects/5a
|
||||||
|
./.git/objects/dd
|
||||||
|
./.git/objects/16
|
||||||
|
./.git/objects/b4
|
||||||
|
./.git/objects/07
|
||||||
|
./.git/objects/24
|
||||||
|
./.git/objects/93
|
||||||
|
./.git/objects/fc
|
||||||
|
./.git/objects/09
|
||||||
|
./.git/objects/5c
|
||||||
|
./.git/objects/18
|
||||||
|
./.git/objects/6d
|
||||||
|
./.git/objects/40
|
||||||
|
./.git/objects/e6
|
||||||
|
./.git/objects/03
|
||||||
|
./.git/objects/d4
|
||||||
|
./.git/objects/14
|
||||||
|
./.git/objects/70
|
||||||
|
./.git/objects/01
|
||||||
|
./.git/objects/89
|
||||||
|
./.git/objects/b9
|
||||||
|
./.git/objects/f9
|
||||||
|
./.git/objects/35
|
||||||
|
./.git/objects/fb
|
||||||
|
./docs
|
||||||
|
./CPLD
|
||||||
|
./CPLD/v1.0
|
||||||
|
./CPLD/v1.0/MZ700
|
||||||
|
./CPLD/v1.0/MZ700/build
|
||||||
|
./CPLD/v1.0/MZ700/build/incremental_db
|
||||||
|
./CPLD/v1.0/MZ700/build/incremental_db/compiled_partitions
|
||||||
|
./CPLD/v1.0/MZ700/build/output_files
|
||||||
|
./CPLD/v1.0/MZ700/build/output_files/output_files
|
||||||
|
./CPLD/v1.0/MZ700/build/db
|
||||||
|
./CPLD/v1.0/MZ700/build/simulation
|
||||||
|
./CPLD/v1.0/MZ700/build/simulation/modelsim
|
||||||
|
./CPLD/v1.0/MZ700/build/greybox_tmp
|
||||||
|
./CPLD/v1.0/MZ2000
|
||||||
|
./CPLD/v1.0/MZ2000/build
|
||||||
|
./CPLD/v1.0/MZ2000/build/incremental_db
|
||||||
|
./CPLD/v1.0/MZ2000/build/output_files
|
||||||
|
./CPLD/v1.0/MZ2000/build/simulation
|
||||||
|
./CPLD/v1.0/MZ2000/build/greybox_tmp
|
||||||
|
./CPLD/v1.0/MZ80A
|
||||||
|
./CPLD/v1.0/MZ80A/build
|
||||||
|
./CPLD/v1.0/MZ80A/build/incremental_db
|
||||||
|
./CPLD/v1.0/MZ80A/build/output_files
|
||||||
|
./CPLD/v1.0/MZ80A/build/simulation
|
||||||
|
./CPLD/v1.0/MZ80A/build/greybox_tmp
|
||||||
|
./tools
|
||||||
|
./SD
|
||||||
|
./SD/K64F
|
||||||
|
./SD/K64F/CPM
|
||||||
|
./SD/K64F/MZF
|
||||||
|
./SD/K64F/CAS
|
||||||
|
./SD/K64F/TZFS
|
||||||
|
./SD/K64F/BAS
|
||||||
|
./datasheets
|
||||||
|
./software
|
||||||
|
./software/WebServer
|
||||||
|
./software/WebServer/webfs
|
||||||
|
./software/WebServer/webfs/images
|
||||||
|
./software/WebServer/webfs/css
|
||||||
|
./software/WebServer/webfs/font-awesome
|
||||||
|
./software/WebServer/webfs/font-awesome/css
|
||||||
|
./software/WebServer/webfs/font-awesome/fonts
|
||||||
|
./software/WebServer/webfs/js
|
||||||
|
./software/WebServer/webserver
|
||||||
|
./software/WebServer/webserver/images
|
||||||
|
./software/WebServer/webserver/css
|
||||||
|
./software/WebServer/webserver/font-awesome
|
||||||
|
./software/WebServer/webserver/font-awesome/css
|
||||||
|
./software/WebServer/webserver/font-awesome/fonts
|
||||||
|
./software/WebServer/webserver/js
|
||||||
|
./software/WebServer/conf
|
||||||
|
./software/WebServer/old
|
||||||
|
./software/WebServer/old/embed_certificate
|
||||||
|
./software/hdr
|
||||||
|
./software/FusionX
|
||||||
|
./software/FusionX/bin
|
||||||
|
./software/FusionX/src
|
||||||
|
./software/FusionX/src/hello
|
||||||
|
|
||||||
|
./software/FusionX/src/driver
|
||||||
|
./software/FusionX/src/driver/.tmp_versions
|
||||||
|
./software/FusionX/src/driver/Z80
|
||||||
|
./software/FusionX/src/driver/build
|
||||||
|
./software/FusionX/src/cmake-kernel-module
|
||||||
|
./software/FusionX/src/spitools
|
||||||
|
./software/FusionX/src/spitools/hold
|
||||||
|
./software/dis
|
||||||
|
|
||||||
|
./software/src
|
||||||
|
./software/config
|
||||||
|
./software/Z80emu
|
||||||
|
./software/mif
|
||||||
|
./software/rt-tests
|
||||||
|
./software/tmp
|
||||||
|
./software/roms
|
||||||
|
./software/linux
|
||||||
|
./software/tools
|
||||||
|
./software/asm
|
||||||
|
./software/Linux_Driver_Tutorial
|
||||||
|
./software/exploringBB
|
||||||
|
./software/linux-kernel-module
|
||||||
|
|
||||||
|
pcb/FusionX/v1.0/tzpuFusionX_v1_0-B_Adhesive.gbr
|
||||||
|
pcb/FusionX/v1.0/tzpuFusionX_v1_0-B_Courtyard.gbr
|
||||||
|
pcb/FusionX/v1.0/tzpuFusionX_v1_0-B_Cu.gbr
|
||||||
|
pcb/FusionX/v1.0/tzpuFusionX_v1_0-B_Fab.gbr
|
||||||
|
pcb/FusionX/v1.0/tzpuFusionX_v1_0-B_Mask.gbr
|
||||||
|
pcb/FusionX/v1.0/tzpuFusionX_v1_0-B_Paste.gbr
|
||||||
|
pcb/FusionX/v1.0/tzpuFusionX_v1_0-B_Silkscreen.gbr
|
||||||
|
pcb/FusionX/v1.0/tzpuFusionX_v1_0-Edge_Cuts.gbr
|
||||||
|
pcb/FusionX/v1.0/tzpuFusionX_v1_0-F_Adhesive.gbr
|
||||||
|
pcb/FusionX/v1.0/tzpuFusionX_v1_0-F_Courtyard.gbr
|
||||||
|
pcb/FusionX/v1.0/tzpuFusionX_v1_0-F_Cu.gbr
|
||||||
|
pcb/FusionX/v1.0/tzpuFusionX_v1_0-F_Fab.gbr
|
||||||
|
pcb/FusionX/v1.0/tzpuFusionX_v1_0-F_Mask.gbr
|
||||||
|
pcb/FusionX/v1.0/tzpuFusionX_v1_0-F_Paste.gbr
|
||||||
|
pcb/FusionX/v1.0/tzpuFusionX_v1_0-F_Silkscreen.gbr
|
||||||
|
pcb/FusionX/v1.0/tzpuFusionX_v1_0-In1_Cu.gbr
|
||||||
|
pcb/FusionX/v1.0/tzpuFusionX_v1_0-In2_Cu.gbr
|
||||||
|
pcb/FusionX/v1.0/tzpuFusionX_v1_0-Margin.gbr
|
||||||
|
pcb/FusionX/v1.0/tzpuFusionX_v1_0-NPTH-drl_map.gbr
|
||||||
|
pcb/FusionX/v1.0/tzpuFusionX_v1_0-NPTH.drl
|
||||||
|
pcb/FusionX/v1.0/tzpuFusionX_v1_0-PTH-drl_map.gbr
|
||||||
|
pcb/FusionX/v1.0/tzpuFusionX_v1_0-PTH.drl
|
||||||
|
pcb/FusionX/v1.0/tzpuFusionX_v1_0-User_Comments.gbr
|
||||||
|
pcb/FusionX/v1.0/tzpuFusionX_v1_0-User_Drawings.gbr
|
||||||
|
pcb/FusionX/v1.0/tzpuFusionX_v1_0-User_Eco1.gbr
|
||||||
|
pcb/FusionX/v1.0/tzpuFusionX_v1_0-User_Eco2.gbr
|
||||||
|
pcb/FusionX/v1.0/tzpuFusionX_v1_0_Schematics.pdf
|
||||||
|
pcb/FusionX/v1.0/tzpuFusionX_v1_0_layout.png
|
||||||
|
pcb/VideoInterface/MZ2000/v1.0/VideoInterface_MZ2000-B_Adhesive.gbr
|
||||||
|
pcb/VideoInterface/MZ2000/v1.0/VideoInterface_MZ2000-B_Courtyard.gbr
|
||||||
|
pcb/VideoInterface/MZ2000/v1.0/VideoInterface_MZ2000-B_Cu.gbr
|
||||||
|
pcb/VideoInterface/MZ2000/v1.0/VideoInterface_MZ2000-B_Fab.gbr
|
||||||
|
pcb/VideoInterface/MZ2000/v1.0/VideoInterface_MZ2000-B_Mask.gbr
|
||||||
|
pcb/VideoInterface/MZ2000/v1.0/VideoInterface_MZ2000-B_Paste.gbr
|
||||||
|
pcb/VideoInterface/MZ2000/v1.0/VideoInterface_MZ2000-B_Silkscreen.gbr
|
||||||
|
pcb/VideoInterface/MZ2000/v1.0/VideoInterface_MZ2000-Edge_Cuts.gbr
|
||||||
|
pcb/VideoInterface/MZ2000/v1.0/VideoInterface_MZ2000-F_Adhesive.gbr
|
||||||
|
pcb/VideoInterface/MZ2000/v1.0/VideoInterface_MZ2000-F_Courtyard.gbr
|
||||||
|
pcb/VideoInterface/MZ2000/v1.0/VideoInterface_MZ2000-F_Cu.gbr
|
||||||
|
pcb/VideoInterface/MZ2000/v1.0/VideoInterface_MZ2000-F_Fab.gbr
|
||||||
|
pcb/VideoInterface/MZ2000/v1.0/VideoInterface_MZ2000-F_Mask.gbr
|
||||||
|
pcb/VideoInterface/MZ2000/v1.0/VideoInterface_MZ2000-F_Paste.gbr
|
||||||
|
pcb/VideoInterface/MZ2000/v1.0/VideoInterface_MZ2000-F_Silkscreen.gbr
|
||||||
|
pcb/VideoInterface/MZ2000/v1.0/VideoInterface_MZ2000-Margin.gbr
|
||||||
|
pcb/VideoInterface/MZ2000/v1.0/VideoInterface_MZ2000-NPTH-drl_map.gbr
|
||||||
|
pcb/VideoInterface/MZ2000/v1.0/VideoInterface_MZ2000-NPTH.drl
|
||||||
|
pcb/VideoInterface/MZ2000/v1.0/VideoInterface_MZ2000-PTH-drl_map.gbr
|
||||||
|
pcb/VideoInterface/MZ2000/v1.0/VideoInterface_MZ2000-PTH.drl
|
||||||
|
pcb/VideoInterface/MZ2000/v1.0/VideoInterface_MZ2000-job.gbrjob
|
||||||
|
pcb/VideoInterface/MZ2000/v1.0/VideoInterface_MZ2000_V1_0_layout.png
|
||||||
|
pcb/VideoInterface/MZ2000/v1.0/VideoInterface_MZ2000_v1_0_Schematics.pdf
|
||||||
|
pcb/VideoInterface/MZ700/v1.0/VideoInterface_MZ700-B_Adhesive.gbr
|
||||||
|
pcb/VideoInterface/MZ700/v1.0/VideoInterface_MZ700-B_Courtyard.gbr
|
||||||
|
pcb/VideoInterface/MZ700/v1.0/VideoInterface_MZ700-B_Cu.gbr
|
||||||
|
pcb/VideoInterface/MZ700/v1.0/VideoInterface_MZ700-B_Fab.gbr
|
||||||
|
pcb/VideoInterface/MZ700/v1.0/VideoInterface_MZ700-B_Mask.gbr
|
||||||
|
pcb/VideoInterface/MZ700/v1.0/VideoInterface_MZ700-B_Paste.gbr
|
||||||
|
pcb/VideoInterface/MZ700/v1.0/VideoInterface_MZ700-B_Silkscreen.gbr
|
||||||
|
pcb/VideoInterface/MZ700/v1.0/VideoInterface_MZ700-Edge_Cuts.gbr
|
||||||
|
pcb/VideoInterface/MZ700/v1.0/VideoInterface_MZ700-F_Adhesive.gbr
|
||||||
|
pcb/VideoInterface/MZ700/v1.0/VideoInterface_MZ700-F_Courtyard.gbr
|
||||||
|
pcb/VideoInterface/MZ700/v1.0/VideoInterface_MZ700-F_Cu.gbr
|
||||||
|
pcb/VideoInterface/MZ700/v1.0/VideoInterface_MZ700-F_Fab.gbr
|
||||||
|
pcb/VideoInterface/MZ700/v1.0/VideoInterface_MZ700-F_Mask.gbr
|
||||||
|
pcb/VideoInterface/MZ700/v1.0/VideoInterface_MZ700-F_Paste.gbr
|
||||||
|
pcb/VideoInterface/MZ700/v1.0/VideoInterface_MZ700-F_Silkscreen.gbr
|
||||||
|
pcb/VideoInterface/MZ700/v1.0/VideoInterface_MZ700-Margin.gbr
|
||||||
|
pcb/VideoInterface/MZ700/v1.0/VideoInterface_MZ700-NPTH-drl_map.gbr
|
||||||
|
pcb/VideoInterface/MZ700/v1.0/VideoInterface_MZ700-NPTH.drl
|
||||||
|
pcb/VideoInterface/MZ700/v1.0/VideoInterface_MZ700-PTH-drl_map.gbr
|
||||||
|
pcb/VideoInterface/MZ700/v1.0/VideoInterface_MZ700-PTH.drl
|
||||||
|
pcb/VideoInterface/MZ700/v1.0/VideoInterface_MZ700-job.gbrjob
|
||||||
|
pcb/VideoInterface/MZ700/v1.0/VideoInterface_MZ700_V1_0_Schematics.pdf
|
||||||
|
pcb/VideoInterface/MZ700/v1.0/VideoInterface_MZ700_v1_0_layout.png
|
||||||
|
pcb/VideoInterface/MZ80A/v1.0/VideoInterface_MZ80A-B_Adhesive.gbr
|
||||||
|
pcb/VideoInterface/MZ80A/v1.0/VideoInterface_MZ80A-B_Courtyard.gbr
|
||||||
|
pcb/VideoInterface/MZ80A/v1.0/VideoInterface_MZ80A-B_Cu.gbr
|
||||||
|
pcb/VideoInterface/MZ80A/v1.0/VideoInterface_MZ80A-B_Fab.gbr
|
||||||
|
pcb/VideoInterface/MZ80A/v1.0/VideoInterface_MZ80A-B_Mask.gbr
|
||||||
|
pcb/VideoInterface/MZ80A/v1.0/VideoInterface_MZ80A-B_Paste.gbr
|
||||||
|
pcb/VideoInterface/MZ80A/v1.0/VideoInterface_MZ80A-B_Silkscreen.gbr
|
||||||
|
pcb/VideoInterface/MZ80A/v1.0/VideoInterface_MZ80A-Edge_Cuts.gbr
|
||||||
|
pcb/VideoInterface/MZ80A/v1.0/VideoInterface_MZ80A-F_Adhesive.gbr
|
||||||
|
pcb/VideoInterface/MZ80A/v1.0/VideoInterface_MZ80A-F_Courtyard.gbr
|
||||||
|
pcb/VideoInterface/MZ80A/v1.0/VideoInterface_MZ80A-F_Cu.gbr
|
||||||
|
pcb/VideoInterface/MZ80A/v1.0/VideoInterface_MZ80A-F_Fab.gbr
|
||||||
|
pcb/VideoInterface/MZ80A/v1.0/VideoInterface_MZ80A-F_Mask.gbr
|
||||||
|
pcb/VideoInterface/MZ80A/v1.0/VideoInterface_MZ80A-F_Paste.gbr
|
||||||
|
pcb/VideoInterface/MZ80A/v1.0/VideoInterface_MZ80A-F_Silkscreen.gbr
|
||||||
|
pcb/VideoInterface/MZ80A/v1.0/VideoInterface_MZ80A-Margin.gbr
|
||||||
|
pcb/VideoInterface/MZ80A/v1.0/VideoInterface_MZ80A-NPTH-drl_map.gbr
|
||||||
|
pcb/VideoInterface/MZ80A/v1.0/VideoInterface_MZ80A-NPTH.drl
|
||||||
|
pcb/VideoInterface/MZ80A/v1.0/VideoInterface_MZ80A-PTH-drl_map.gbr
|
||||||
|
pcb/VideoInterface/MZ80A/v1.0/VideoInterface_MZ80A-PTH.drl
|
||||||
|
pcb/VideoInterface/MZ80A/v1.0/VideoInterface_MZ80A-job.gbrjob
|
||||||
|
pcb/VideoInterface/MZ80A/v1.0/VideoInterface_MZ80A_V1_0_layout.png
|
||||||
|
pcb/VideoInterface/MZ80A/v1.0/VideoInterface_MZ80A_v1_0_Schematics.pdf
|
||||||
|
|
||||||
|
schematics/FusionX/v1.0/09082020_1141.kicad_pcb
|
||||||
|
schematics/FusionX/v1.0/BGA_24Pin_6x8x1.00.kicad_mod
|
||||||
|
schematics/FusionX/v1.0/BGA_48Pin_6x8x0.75.kicad_mod
|
||||||
|
schematics/FusionX/v1.0/Custom.kicad_sym
|
||||||
|
schematics/FusionX/v1.0/Custom.pretty/
|
||||||
|
schematics/FusionX/v1.0/Custom/
|
||||||
|
schematics/FusionX/v1.0/Espressif.pretty/
|
||||||
|
schematics/FusionX/v1.0/MZ80FPGA.pretty/
|
||||||
|
schematics/FusionX/v1.0/ssd20x-SchLib-cache.lib
|
||||||
|
schematics/FusionX/v1.0/ssd20x.PcbLib
|
||||||
|
schematics/FusionX/v1.0/ssd20x.SchLib
|
||||||
|
schematics/FusionX/v1.0/ssd20x.kicad_sym
|
||||||
|
schematics/FusionX/v1.0/ssd20x.lib
|
||||||
|
schematics/FusionX/v1.0/tranZPUter-SW-700_v1_2-rescue.lib
|
||||||
|
schematics/FusionX/v1.0/tranZPUter-SW-700_v1_3-rescue.lib
|
||||||
|
schematics/FusionX/v1.0/tzpuFusion-cache_v1_0.lib
|
||||||
|
schematics/FusionX/v1.0/tzpuFusionX_CPLDFPGA_Programming_v1_0.kicad_sch
|
||||||
|
schematics/FusionX/v1.0/tzpuFusionX_CPU_Interface_v1_0.kicad_sch
|
||||||
|
schematics/FusionX/v1.0/tzpuFusionX_FPGA_CPU_Memory_v1_0.kicad_sch
|
||||||
|
schematics/FusionX/v1.0/tzpuFusionX_FPGA_CPU_v1_0.kicad_sch
|
||||||
|
schematics/FusionX/v1.0/tzpuFusionX_FPGA_Video_v1_0.kicad_sch
|
||||||
|
schematics/FusionX/v1.0/tzpuFusionX_PowerSupply_v1_0.kicad_sch
|
||||||
|
schematics/FusionX/v1.0/tzpuFusionX_k64fx512_v1_0.kicad_sch
|
||||||
|
schematics/FusionX/v1.0/tzpuFusionX_v1_0.dsn
|
||||||
|
schematics/FusionX/v1.0/tzpuFusionX_v1_0.kicad_pcb
|
||||||
|
schematics/FusionX/v1.0/tzpuFusionX_v1_0.kicad_prl
|
||||||
|
schematics/FusionX/v1.0/tzpuFusionX_v1_0.kicad_pro
|
||||||
|
schematics/FusionX/v1.0/tzpuFusionX_v1_0.kicad_sch
|
||||||
|
schematics/FusionX/v1.0/tzpuFusionX_v1_0.ses
|
||||||
|
schematics/VideoInterface/MZ2000/v1.0/09082020_1141.kicad_pcb
|
||||||
|
schematics/VideoInterface/MZ2000/v1.0/BGA_24Pin_6x8x1.00.kicad_mod
|
||||||
|
schematics/VideoInterface/MZ2000/v1.0/BGA_48Pin_6x8x0.75.kicad_mod
|
||||||
|
schematics/VideoInterface/MZ2000/v1.0/Custom.kicad_sym
|
||||||
|
schematics/VideoInterface/MZ2000/v1.0/Custom.pretty/
|
||||||
|
schematics/VideoInterface/MZ2000/v1.0/Custom/
|
||||||
|
schematics/VideoInterface/MZ2000/v1.0/Espressif.pretty/
|
||||||
|
schematics/VideoInterface/MZ2000/v1.0/MZ80FPGA.pretty/
|
||||||
|
schematics/VideoInterface/MZ2000/v1.0/VideoInterface_MZ2000.dsn
|
||||||
|
schematics/VideoInterface/MZ2000/v1.0/VideoInterface_MZ2000.kicad_pcb
|
||||||
|
schematics/VideoInterface/MZ2000/v1.0/VideoInterface_MZ2000.kicad_prl
|
||||||
|
schematics/VideoInterface/MZ2000/v1.0/VideoInterface_MZ2000.kicad_pro
|
||||||
|
schematics/VideoInterface/MZ2000/v1.0/VideoInterface_MZ2000.kicad_sch
|
||||||
|
schematics/VideoInterface/MZ2000/v1.0/VideoInterface_MZ2000.rules
|
||||||
|
schematics/VideoInterface/MZ2000/v1.0/VideoInterface_MZ2000.ses
|
||||||
|
schematics/VideoInterface/MZ700/v1.0/09082020_1141.kicad_pcb
|
||||||
|
schematics/VideoInterface/MZ700/v1.0/BGA_24Pin_6x8x1.00.kicad_mod
|
||||||
|
schematics/VideoInterface/MZ700/v1.0/BGA_48Pin_6x8x0.75.kicad_mod
|
||||||
|
schematics/VideoInterface/MZ700/v1.0/Custom.kicad_sym
|
||||||
|
schematics/VideoInterface/MZ700/v1.0/Custom.pretty/
|
||||||
|
schematics/VideoInterface/MZ700/v1.0/Custom/
|
||||||
|
schematics/VideoInterface/MZ700/v1.0/Espressif.pretty/
|
||||||
|
schematics/VideoInterface/MZ700/v1.0/MZ80FPGA.pretty/
|
||||||
|
schematics/VideoInterface/MZ700/v1.0/VideoInterface_MZ700.dsn
|
||||||
|
schematics/VideoInterface/MZ700/v1.0/VideoInterface_MZ700.kicad_pcb
|
||||||
|
schematics/VideoInterface/MZ700/v1.0/VideoInterface_MZ700.kicad_prl
|
||||||
|
schematics/VideoInterface/MZ700/v1.0/VideoInterface_MZ700.kicad_pro
|
||||||
|
schematics/VideoInterface/MZ700/v1.0/VideoInterface_MZ700.kicad_sch
|
||||||
|
schematics/VideoInterface/MZ700/v1.0/VideoInterface_MZ700.ses
|
||||||
|
schematics/VideoInterface/MZ80A/v1.0/09082020_1141.kicad_pcb
|
||||||
|
schematics/VideoInterface/MZ80A/v1.0/BGA_24Pin_6x8x1.00.kicad_mod
|
||||||
|
schematics/VideoInterface/MZ80A/v1.0/BGA_48Pin_6x8x0.75.kicad_mod
|
||||||
|
schematics/VideoInterface/MZ80A/v1.0/Custom.kicad_sym
|
||||||
|
schematics/VideoInterface/MZ80A/v1.0/Custom.pretty/
|
||||||
|
schematics/VideoInterface/MZ80A/v1.0/Custom/
|
||||||
|
schematics/VideoInterface/MZ80A/v1.0/Espressif.pretty/
|
||||||
|
schematics/VideoInterface/MZ80A/v1.0/MZ80FPGA.pretty/
|
||||||
|
schematics/VideoInterface/MZ80A/v1.0/VideoInterface_MZ80A.dsn
|
||||||
|
schematics/VideoInterface/MZ80A/v1.0/VideoInterface_MZ80A.kicad_pcb
|
||||||
|
schematics/VideoInterface/MZ80A/v1.0/VideoInterface_MZ80A.kicad_prl
|
||||||
|
schematics/VideoInterface/MZ80A/v1.0/VideoInterface_MZ80A.kicad_pro
|
||||||
|
schematics/VideoInterface/MZ80A/v1.0/VideoInterface_MZ80A.kicad_sch
|
||||||
|
schematics/VideoInterface/MZ80A/v1.0/VideoInterface_MZ80A.pro
|
||||||
|
schematics/VideoInterface/MZ80A/v1.0/VideoInterface_MZ80A.ses
|
||||||
|
|
||||||
|
software/Basic
|
||||||
|
software/FusionX/src/cmake-kernel-module/
|
||||||
|
software/FusionX/src/driver/Kbuild.in
|
||||||
|
software/FusionX/src/driver/MZ2000/old/
|
||||||
|
software/FusionX/src/driver/MZ700/old/
|
||||||
|
software/FusionX/src/driver/MZ80A/
|
||||||
|
software/FusionX/src/driver/MZ80A/old/
|
||||||
|
software/FusionX/src/driver/Makefile1
|
||||||
|
software/FusionX/src/driver/Makefile3
|
||||||
|
software/FusionX/src/driver/Z80.c.old
|
||||||
|
software/FusionX/src/driver/Z80.rc.in
|
||||||
|
software/FusionX/src/driver/Z80/
|
||||||
|
software/FusionX/src/driver/build/
|
||||||
|
software/FusionX/src/driver/mz700.rom
|
||||||
|
software/FusionX/src/driver/test
|
||||||
|
software/FusionX/src/driver/x.mzf
|
||||||
|
software/FusionX/src/driver/z80ctrl
|
||||||
|
software/FusionX/src/spitools/Makefile.drv
|
||||||
|
software/FusionX/src/spitools/hold/
|
||||||
|
software/FusionX/src/spitools/mspi_main_0.08
|
||||||
|
software/FusionX/src/spitools/spi
|
||||||
|
software/FusionX/src/spitools/spi_0.08
|
||||||
|
software/old/
|
||||||
|
software/READ.ME
|
||||||
|
software/asm/
|
||||||
|
software/build.sh
|
||||||
|
software/config/
|
||||||
|
software/dis/
|
||||||
|
software/exploringBB/
|
||||||
|
software/hdr/
|
||||||
|
software/linux-kernel-module/
|
||||||
|
software/linux/
|
||||||
|
software/mif/
|
||||||
|
software/roms/
|
||||||
|
software/rt-tests/
|
||||||
|
software/src/
|
||||||
|
software/tools/
|
||||||
|
CPLD/v1.0/MZ2000/rrrr
|
||||||
|
_config.yml
|
||||||
|
software/WebServer/WebServer
|
||||||
|
software/WebServer/WebServer.cpp.sk
|
||||||
|
software/WebServer/WebServer.h.sk
|
||||||
|
software/WebServer/webfs/
|
||||||
|
|
||||||
30
CPLD/v1.0/MZ2000/build/tzpuFusionX_MZ2000.qpf
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
# -------------------------------------------------------------------------- #
|
||||||
|
#
|
||||||
|
# Copyright (C) 1991-2013 Altera Corporation
|
||||||
|
# Your use of Altera Corporation's design tools, logic functions
|
||||||
|
# and other software and tools, and its AMPP partner logic
|
||||||
|
# functions, and any output files from any of the foregoing
|
||||||
|
# (including device programming or simulation files), and any
|
||||||
|
# associated documentation or information are expressly subject
|
||||||
|
# to the terms and conditions of the Altera Program License
|
||||||
|
# Subscription Agreement, Altera MegaCore Function License
|
||||||
|
# Agreement, or other applicable license agreement, including,
|
||||||
|
# without limitation, that your use is for the sole purpose of
|
||||||
|
# programming logic devices manufactured by Altera and sold by
|
||||||
|
# Altera or its authorized distributors. Please refer to the
|
||||||
|
# applicable agreement for further details.
|
||||||
|
#
|
||||||
|
# -------------------------------------------------------------------------- #
|
||||||
|
#
|
||||||
|
# Quartus II 64-Bit
|
||||||
|
# Version 13.0.1 Build 232 06/12/2013 Service Pack 1 SJ Web Edition
|
||||||
|
# Date created = 16:29:32 June 24, 2020
|
||||||
|
#
|
||||||
|
# -------------------------------------------------------------------------- #
|
||||||
|
|
||||||
|
QUARTUS_VERSION = "13.0"
|
||||||
|
DATE = "16:29:32 September 10, 2021"
|
||||||
|
|
||||||
|
# Revisions
|
||||||
|
|
||||||
|
PROJECT_REVISION = "tzpuFusionX_MZ2000"
|
||||||
243
CPLD/v1.0/MZ2000/build/tzpuFusionX_MZ2000.qsf
Normal file
@@ -0,0 +1,243 @@
|
|||||||
|
# -------------------------------------------------------------------------- #
|
||||||
|
#
|
||||||
|
# Copyright (C) 1991-2013 Altera Corporation
|
||||||
|
# Your use of Altera Corporation's design tools, logic functions
|
||||||
|
# and other software and tools, and its AMPP partner logic
|
||||||
|
# functions, and any output files from any of the foregoing
|
||||||
|
# (including device programming or simulation files), and any
|
||||||
|
# associated documentation or information are expressly subject
|
||||||
|
# to the terms and conditions of the Altera Program License
|
||||||
|
# Subscription Agreement, Altera MegaCore Function License
|
||||||
|
# Agreement, or other applicable license agreement, including,
|
||||||
|
# without limitation, that your use is for the sole purpose of
|
||||||
|
# programming logic devices manufactured by Altera and sold by
|
||||||
|
# Altera or its authorized distributors. Please refer to the
|
||||||
|
# applicable agreement for further details.
|
||||||
|
#
|
||||||
|
# -------------------------------------------------------------------------- #
|
||||||
|
#
|
||||||
|
# Quartus II 64-Bit
|
||||||
|
# Version 13.0.1 Build 232 06/12/2013 Service Pack 1 SJ Web Edition
|
||||||
|
# Date created = 16:29:32 June 24, 2020
|
||||||
|
#
|
||||||
|
# -------------------------------------------------------------------------- #
|
||||||
|
#
|
||||||
|
# Notes:
|
||||||
|
#
|
||||||
|
# 1) The default values for assignments are stored in the file:
|
||||||
|
# tzpuFusionX.qdf
|
||||||
|
# If this file doesn't exist, see file:
|
||||||
|
# assignment_defaults.qdf
|
||||||
|
#
|
||||||
|
# 2) Altera recommends that you do not modify this file. This
|
||||||
|
# file is updated automatically by the Quartus II software
|
||||||
|
# and any changes you make may be lost or overwritten.
|
||||||
|
#
|
||||||
|
# -------------------------------------------------------------------------- #
|
||||||
|
|
||||||
|
|
||||||
|
set_global_assignment -name FAMILY MAX7000AE
|
||||||
|
set_global_assignment -name DEVICE "EPM7512AETC144-10"
|
||||||
|
set_global_assignment -name TOP_LEVEL_ENTITY tzpuFusionX_MZ2000
|
||||||
|
set_global_assignment -name ORIGINAL_QUARTUS_VERSION "13.0 SP1"
|
||||||
|
set_global_assignment -name PROJECT_CREATION_TIME_DATE "16:29:32 JUNE 24, 2020"
|
||||||
|
set_global_assignment -name LAST_QUARTUS_VERSION "13.0 SP1"
|
||||||
|
set_global_assignment -name PROJECT_OUTPUT_DIRECTORY output_files
|
||||||
|
set_global_assignment -name ERROR_CHECK_FREQUENCY_DIVISOR "-1"
|
||||||
|
set_global_assignment -name EDA_DESIGN_ENTRY_SYNTHESIS_TOOL "<None>"
|
||||||
|
set_global_assignment -name EDA_INPUT_VCC_NAME VCC -section_id eda_design_synthesis
|
||||||
|
set_global_assignment -name EDA_INPUT_DATA_FORMAT EDIF -section_id eda_design_synthesis
|
||||||
|
set_global_assignment -name EDA_SIMULATION_TOOL "ModelSim-Altera (VHDL)"
|
||||||
|
set_global_assignment -name EDA_OUTPUT_DATA_FORMAT VHDL -section_id eda_simulation
|
||||||
|
set_global_assignment -name OPTIMIZE_HOLD_TIMING OFF
|
||||||
|
set_global_assignment -name OPTIMIZE_MULTI_CORNER_TIMING OFF
|
||||||
|
set_global_assignment -name FITTER_EFFORT "STANDARD FIT"
|
||||||
|
set_global_assignment -name MAX7000_DEVICE_IO_STANDARD LVTTL
|
||||||
|
|
||||||
|
# Z80 Data Bus
|
||||||
|
# ============
|
||||||
|
set_location_assignment PIN_81 -to Z80_DATA[0]
|
||||||
|
set_location_assignment PIN_78 -to Z80_DATA[1]
|
||||||
|
set_location_assignment PIN_87 -to Z80_DATA[2]
|
||||||
|
set_location_assignment PIN_100 -to Z80_DATA[3]
|
||||||
|
set_location_assignment PIN_102 -to Z80_DATA[4]
|
||||||
|
set_location_assignment PIN_93 -to Z80_DATA[5]
|
||||||
|
set_location_assignment PIN_94 -to Z80_DATA[6]
|
||||||
|
set_location_assignment PIN_84 -to Z80_DATA[7]
|
||||||
|
|
||||||
|
# Z80 Control signals.
|
||||||
|
# ====================
|
||||||
|
set_location_assignment PIN_69 -to Z80_INTn
|
||||||
|
set_location_assignment PIN_70 -to Z80_NMIn
|
||||||
|
set_location_assignment PIN_71 -to Z80_HALTn
|
||||||
|
set_location_assignment PIN_68 -to Z80_MREQn
|
||||||
|
set_location_assignment PIN_65 -to Z80_IORQn
|
||||||
|
set_location_assignment PIN_67 -to Z80_RDn
|
||||||
|
set_location_assignment PIN_66 -to Z80_WRn
|
||||||
|
set_location_assignment PIN_63 -to Z80_BUSAKn
|
||||||
|
set_location_assignment PIN_62 -to Z80_WAITn
|
||||||
|
set_location_assignment PIN_61 -to Z80_BUSRQn
|
||||||
|
set_location_assignment PIN_79 -to Z80_RFSHn
|
||||||
|
set_location_assignment PIN_60 -to Z80_M1n
|
||||||
|
set_location_assignment PIN_56 -to Z80_RESETn
|
||||||
|
set_location_assignment PIN_101 -to Z80_CLK
|
||||||
|
|
||||||
|
# Z80 Address Bus
|
||||||
|
# ===============
|
||||||
|
set_location_assignment PIN_80 -to Z80_ADDR[0]
|
||||||
|
set_location_assignment PIN_90 -to Z80_ADDR[1]
|
||||||
|
set_location_assignment PIN_83 -to Z80_ADDR[2]
|
||||||
|
set_location_assignment PIN_86 -to Z80_ADDR[3]
|
||||||
|
set_location_assignment PIN_88 -to Z80_ADDR[4]
|
||||||
|
set_location_assignment PIN_91 -to Z80_ADDR[5]
|
||||||
|
set_location_assignment PIN_92 -to Z80_ADDR[6]
|
||||||
|
set_location_assignment PIN_96 -to Z80_ADDR[7]
|
||||||
|
set_location_assignment PIN_97 -to Z80_ADDR[8]
|
||||||
|
set_location_assignment PIN_98 -to Z80_ADDR[9]
|
||||||
|
set_location_assignment PIN_99 -to Z80_ADDR[10]
|
||||||
|
set_location_assignment PIN_110 -to Z80_ADDR[11]
|
||||||
|
set_location_assignment PIN_108 -to Z80_ADDR[12]
|
||||||
|
set_location_assignment PIN_107 -to Z80_ADDR[13]
|
||||||
|
set_location_assignment PIN_106 -to Z80_ADDR[14]
|
||||||
|
set_location_assignment PIN_103 -to Z80_ADDR[15]
|
||||||
|
|
||||||
|
# SOM SPI
|
||||||
|
# =======
|
||||||
|
set_location_assignment PIN_32 -to VSOM_SPI_CSn
|
||||||
|
set_location_assignment PIN_31 -to VSOM_SPI_CLK
|
||||||
|
set_location_assignment PIN_30 -to VSOM_SPI_MOSI
|
||||||
|
set_location_assignment PIN_29 -to VSOM_SPI_MISO
|
||||||
|
|
||||||
|
# SOM Parallel Bus
|
||||||
|
# ================
|
||||||
|
set_location_assignment PIN_41 -to VSOM_DATA_OUT[0]
|
||||||
|
set_location_assignment PIN_40 -to VSOM_DATA_OUT[1]
|
||||||
|
set_location_assignment PIN_39 -to VSOM_DATA_OUT[2]
|
||||||
|
set_location_assignment PIN_38 -to VSOM_DATA_OUT[3]
|
||||||
|
set_location_assignment PIN_37 -to VSOM_DATA_OUT[4]
|
||||||
|
set_location_assignment PIN_36 -to VSOM_DATA_OUT[5]
|
||||||
|
set_location_assignment PIN_35 -to VSOM_DATA_OUT[6]
|
||||||
|
set_location_assignment PIN_34 -to VSOM_DATA_OUT[7]
|
||||||
|
set_location_assignment PIN_132 -to VSOM_HBYTE
|
||||||
|
|
||||||
|
# SOM Reserved signals.
|
||||||
|
# =====================
|
||||||
|
set_location_assignment PIN_21 -to VSOM_RSV[1]
|
||||||
|
|
||||||
|
# SOM Control Signals
|
||||||
|
# ===================
|
||||||
|
set_location_assignment PIN_28 -to VSOM_READY
|
||||||
|
set_location_assignment PIN_18 -to VSOM_LTSTATE
|
||||||
|
set_location_assignment PIN_27 -to VSOM_BUSRQ
|
||||||
|
set_location_assignment PIN_26 -to VSOM_BUSACK
|
||||||
|
set_location_assignment PIN_19 -to VSOM_INT
|
||||||
|
set_location_assignment PIN_22 -to VSOM_NMI
|
||||||
|
set_location_assignment PIN_25 -to VSOM_WAIT
|
||||||
|
set_location_assignment PIN_23 -to VSOM_RESET
|
||||||
|
set_location_assignment PIN_16 -to PM_RESET
|
||||||
|
|
||||||
|
# VGA_Palette Control
|
||||||
|
# ===================
|
||||||
|
set_location_assignment PIN_133 -to VGA_R[7]
|
||||||
|
set_location_assignment PIN_137 -to VGA_R[8]
|
||||||
|
set_location_assignment PIN_140 -to VGA_R[9]
|
||||||
|
set_location_assignment PIN_134 -to VGA_G[7]
|
||||||
|
set_location_assignment PIN_138 -to VGA_G[8]
|
||||||
|
set_location_assignment PIN_141 -to VGA_G[9]
|
||||||
|
set_location_assignment PIN_136 -to VGA_B[8]
|
||||||
|
set_location_assignment PIN_139 -to VGA_B[9]
|
||||||
|
|
||||||
|
|
||||||
|
# VGA Control Signals
|
||||||
|
# ===================
|
||||||
|
set_location_assignment PIN_142 -to VGA_PXL_CLK
|
||||||
|
set_location_assignment PIN_14 -to VGA_DISPEN
|
||||||
|
set_location_assignment PIN_12 -to VGA_VSYNCn
|
||||||
|
set_location_assignment PIN_11 -to VGA_HSYNCn
|
||||||
|
set_location_assignment PIN_82 -to VGA_COLR
|
||||||
|
set_location_assignment PIN_109 -to VGA_CSYNCn
|
||||||
|
set_location_assignment PIN_143 -to VGA_BLANKn
|
||||||
|
|
||||||
|
# CRT Control Signals
|
||||||
|
# ===================
|
||||||
|
set_location_assignment PIN_15 -to MONO_PXL_CLK
|
||||||
|
set_location_assignment PIN_114 -to MONO_BLANKn
|
||||||
|
set_location_assignment PIN_113 -to MONO_CSYNCn
|
||||||
|
set_location_assignment PIN_116 -to MONO_RSV
|
||||||
|
|
||||||
|
# CRT Lower Chrominance Control
|
||||||
|
# =============================
|
||||||
|
set_location_assignment PIN_1 -to MONO_R[0]
|
||||||
|
set_location_assignment PIN_6 -to MONO_R[1]
|
||||||
|
set_location_assignment PIN_10 -to MONO_R[2]
|
||||||
|
set_location_assignment PIN_2 -to MONO_G[0]
|
||||||
|
set_location_assignment PIN_7 -to MONO_G[1]
|
||||||
|
set_location_assignment PIN_9 -to MONO_G[2]
|
||||||
|
set_location_assignment PIN_5 -to MONO_B[1]
|
||||||
|
set_location_assignment PIN_8 -to MONO_B[2]
|
||||||
|
|
||||||
|
# MUX Control Signals
|
||||||
|
# ===================
|
||||||
|
set_location_assignment PIN_72 -to VIDEO_SRC
|
||||||
|
set_location_assignment PIN_74 -to MONO_VIDEO_SRC
|
||||||
|
set_location_assignment PIN_77 -to AUDIO_SRC_L
|
||||||
|
set_location_assignment PIN_75 -to AUDIO_SRC_R
|
||||||
|
|
||||||
|
# Mainboard Reset Signals
|
||||||
|
# =======================
|
||||||
|
#set_location_assignment PIN_127 -to CPU_RESETn
|
||||||
|
set_location_assignment PIN_122 -to MB_RESETn
|
||||||
|
set_location_assignment PIN_111 -to MB_IPLn
|
||||||
|
|
||||||
|
# USB Power Control
|
||||||
|
# =================
|
||||||
|
set_location_assignment PIN_55 -to VBUS_EN
|
||||||
|
|
||||||
|
# Clocks
|
||||||
|
# ======
|
||||||
|
#set_location_assignment PIN_125 -to CPU_CLK
|
||||||
|
set_location_assignment PIN_128 -to CLK_50M
|
||||||
|
|
||||||
|
# Unused ports
|
||||||
|
# ============
|
||||||
|
#set_location_assignment PIN_42 -to
|
||||||
|
#set_location_assignment PIN_43 -to
|
||||||
|
#set_location_assignment PIN_44 -to
|
||||||
|
#set_location_assignment PIN_45 -to
|
||||||
|
#set_location_assignment PIN_112 -to
|
||||||
|
#set_location_assignment PIN_131 -to
|
||||||
|
#set_location_assignment PIN_117 -to
|
||||||
|
#set_location_assignment PIN_118 -to
|
||||||
|
#set_location_assignment PIN_119 -to
|
||||||
|
#set_location_assignment PIN_120 -to
|
||||||
|
#set_location_assignment PIN_121 -to
|
||||||
|
#set_location_assignment PIN_25 -to
|
||||||
|
#set_location_assignment PIN_53 -to
|
||||||
|
#set_location_assignment PIN_128 -to
|
||||||
|
#set_location_assignment PIN_47 -to
|
||||||
|
#set_location_assignment PIN_54 -to
|
||||||
|
#set_location_assignment PIN_127 -to
|
||||||
|
#set_location_assignment PIN_125 -to
|
||||||
|
#set_location_assignment PIN_48 -to
|
||||||
|
#set_location_assignment PIN_46 -to
|
||||||
|
#set_location_assignment PIN_49 -to
|
||||||
|
|
||||||
|
|
||||||
|
set_global_assignment -name VHDL_FILE ../tzpuFusionX_Toplevel.vhd
|
||||||
|
set_global_assignment -name VHDL_FILE ../tzpuFusionX_pkg.vhd
|
||||||
|
set_global_assignment -name VHDL_FILE ../tzpuFusionX.vhd
|
||||||
|
set_global_assignment -name SDC_FILE tzpuFusionX_MZ2000_constraints.sdc
|
||||||
|
|
||||||
|
set_global_assignment -name VHDL_INPUT_VERSION VHDL_2008
|
||||||
|
set_global_assignment -name VHDL_SHOW_LMF_MAPPING_MESSAGES OFF
|
||||||
|
|
||||||
|
set_global_assignment -name SYNTH_TIMING_DRIVEN_SYNTHESIS OFF
|
||||||
|
set_global_assignment -name MAX7000_OPTIMIZATION_TECHNIQUE AREA
|
||||||
|
set_global_assignment -name AUTO_RESOURCE_SHARING OFF
|
||||||
|
set_global_assignment -name PRE_MAPPING_RESYNTHESIS OFF
|
||||||
|
set_global_assignment -name USE_LOGICLOCK_CONSTRAINTS_IN_BALANCING OFF
|
||||||
|
|
||||||
|
set_global_assignment -name INFER_RAMS_FROM_RAW_LOGIC OFF
|
||||||
|
set_global_assignment -name AUTO_LCELL_INSERTION ON
|
||||||
|
|
||||||
|
set_global_assignment -name CDF_FILE output_files/tzpuFusionX_MZ2000.cdf
|
||||||
324
CPLD/v1.0/MZ2000/build/tzpuFusionX_MZ2000_constraints.sdc
Normal file
@@ -0,0 +1,324 @@
|
|||||||
|
## Generated SDC file "tzpuFusionX.out.sdc"
|
||||||
|
|
||||||
|
## Copyright (C) 1991-2013 Altera Corporation
|
||||||
|
## Your use of Altera Corporation's design tools, logic functions
|
||||||
|
## and other software and tools, and its AMPP partner logic
|
||||||
|
## functions, and any output files from any of the foregoing
|
||||||
|
## (including device programming or simulation files), and any
|
||||||
|
## associated documentation or information are expressly subject
|
||||||
|
## to the terms and conditions of the Altera Program License
|
||||||
|
## Subscription Agreement, Altera MegaCore Function License
|
||||||
|
## Agreement, or other applicable license agreement, including,
|
||||||
|
## without limitation, that your use is for the sole purpose of
|
||||||
|
## programming logic devices manufactured by Altera and sold by
|
||||||
|
## Altera or its authorized distributors. Please refer to the
|
||||||
|
## applicable agreement for further details.
|
||||||
|
|
||||||
|
|
||||||
|
## VENDOR "Altera"
|
||||||
|
## PROGRAM "Quartus II"
|
||||||
|
## VERSION "Version 13.0.1 Build 232 06/12/2013 Service Pack 1 SJ Web Edition"
|
||||||
|
|
||||||
|
## DATE "Fri Jun 26 22:10:05 2020"
|
||||||
|
|
||||||
|
##
|
||||||
|
## DEVICE "EPM7160STC100-10"
|
||||||
|
##
|
||||||
|
|
||||||
|
|
||||||
|
#**************************************************************
|
||||||
|
# Time Information
|
||||||
|
#**************************************************************
|
||||||
|
|
||||||
|
set_time_format -unit ns -decimal_places 3
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#**************************************************************
|
||||||
|
# Create Clock
|
||||||
|
#**************************************************************
|
||||||
|
|
||||||
|
# Standard mainboard clock. If using tzpuFusionX on a different host then set to the host frequency.
|
||||||
|
create_clock -name {Z80_CLK} -period 250.000 -waveform { 0.000 125.000 } [get_ports { Z80_CLK }]
|
||||||
|
|
||||||
|
# For 50MHz crystal.
|
||||||
|
create_clock -name {CLK_50M} -period 20.000 -waveform { 0.000 10.000 } [ get_ports { CLK_50M }]
|
||||||
|
|
||||||
|
# For SPI CSn
|
||||||
|
#create_clock -name {VSOM_SPI_CSn} -period 200.000 -waveform { 160.000 40.000 } [ get_ports { VSOM_SPI_CSn }]
|
||||||
|
|
||||||
|
# For SPI CLK
|
||||||
|
create_clock -name {VSOM_SPI_CLK} -period 14.000 -waveform { 0.000 7.000 } [ get_ports { VSOM_SPI_CLK }]
|
||||||
|
|
||||||
|
# For basic board with oscillator.
|
||||||
|
#create_clock -name {CTLCLK} -period 20.000 -waveform { 0.000 10.000 } [ get_ports { CTLCLK }]
|
||||||
|
#create_clock -name {cpld512:cpldl512Toplevel|CTLCLKi} -period 280.000 -waveform { 0.000 140.000 } [ get_keepers {cpld512:cpldl512Toplevel|CTLCLKi} ]
|
||||||
|
##create_clock -name {Z80_CLK} -period 50.000 -waveform { 0.000 25.000 } [get_ports { CTLCLK }]
|
||||||
|
|
||||||
|
|
||||||
|
#**************************************************************
|
||||||
|
# Create Generated Clock
|
||||||
|
#**************************************************************
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#**************************************************************
|
||||||
|
# Set Clock Latency
|
||||||
|
#**************************************************************
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#**************************************************************
|
||||||
|
# Set Clock Uncertainty
|
||||||
|
#**************************************************************
|
||||||
|
|
||||||
|
#derive_clock_uncertainty
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#**************************************************************
|
||||||
|
# Set Input Delay
|
||||||
|
#**************************************************************
|
||||||
|
|
||||||
|
#set_input_delay -add_delay -clock [get_clocks {SYSCLK}] 1.000 [get_ports {CTL_MBSEL}]
|
||||||
|
#set_input_delay -add_delay -clock [get_clocks {SYSCLK}] 1.000 [get_ports {CTL_BUSRQn}]
|
||||||
|
#set_input_delay -add_delay -clock [get_clocks {SYSCLK}] 1.000 [get_ports {CTL_WAITn}]
|
||||||
|
#set_input_delay -add_delay -clock [get_clocks {SYSCLK}] 1.000 [get_ports {SYS_BUSRQn}]
|
||||||
|
#set_input_delay -add_delay -clock [get_clocks {SYSCLK}] 1.000 [get_ports {SYS_WAITn}]
|
||||||
|
#set_input_delay -add_delay -clock [get_clocks {SYSCLK}] 1.000 [get_ports {Z80_ADDR[*]}]
|
||||||
|
#set_input_delay -add_delay -clock [get_clocks {SYSCLK}] 1.000 [get_ports {Z80_HI_ADDR[*]}]
|
||||||
|
#set_input_delay -add_delay -clock [get_clocks {SYSCLK}] 1.000 [get_ports {VZ80_ADDR[*]}]
|
||||||
|
#set_input_delay -add_delay -clock [get_clocks {SYSCLK}] 1.000 [get_ports {Z80_BUSACKn}]
|
||||||
|
#set_input_delay -add_delay -clock [get_clocks {SYSCLK}] 1.000 [get_ports {Z80_DATA[*]}]
|
||||||
|
#set_input_delay -add_delay -clock [get_clocks {SYSCLK}] 1.000 [get_ports {Z80_HALTn}]
|
||||||
|
#set_input_delay -add_delay -clock [get_clocks {SYSCLK}] 1.000 [get_ports {Z80_IORQn}]
|
||||||
|
#set_input_delay -add_delay -clock [get_clocks {SYSCLK}] 1.000 [get_ports {Z80_M1n}]
|
||||||
|
#set_input_delay -add_delay -clock [get_clocks {SYSCLK}] 1.000 [get_ports {Z80_MREQn}]
|
||||||
|
#set_input_delay -add_delay -clock [get_clocks {SYSCLK}] 1.000 [get_ports {Z80_RESETn}]
|
||||||
|
#set_input_delay -add_delay -clock [get_clocks {SYSCLK}] 1.000 [get_ports {Z80_RFSHn}]
|
||||||
|
#set_input_delay -add_delay -clock [get_clocks {SYSCLK}] 1.000 [get_ports {Z80_WRn}]
|
||||||
|
#set_input_delay -add_delay -clock [get_clocks {SYSCLK}] 1.000 [get_ports {Z80_RDn}]
|
||||||
|
#set_input_delay -add_delay -clock [get_clocks {SYSCLK}] 1.000 [get_ports {R_IN}]
|
||||||
|
#set_input_delay -add_delay -clock [get_clocks {SYSCLK}] 1.000 [get_ports {G_IN}]
|
||||||
|
#set_input_delay -add_delay -clock [get_clocks {SYSCLK}] 1.000 [get_ports {B_IN}]
|
||||||
|
#set_input_delay -add_delay -clock [get_clocks {SYSCLK}] 1.000 [get_ports {COLR_IN}]
|
||||||
|
#set_input_delay -add_delay -clock [get_clocks {SYSCLK}] 1.000 [get_ports {CSYNC_IN}]
|
||||||
|
##set_input_delay -add_delay -clock [get_clocks {SYSCLK}] 1.000 [get_ports {CVIDEO_IN}]
|
||||||
|
#set_input_delay -add_delay -clock [get_clocks {SYSCLK}] 1.000 [get_ports {HSYNC_IN}]
|
||||||
|
#set_input_delay -add_delay -clock [get_clocks {SYSCLK}] 1.000 [get_ports {VSYNC_IN}]
|
||||||
|
#set_input_delay -add_delay -clock [get_clocks {SYSCLK}] 1.000 [get_ports {VZ80_DATA[*]}]
|
||||||
|
#set_input_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {VZ80_MREQn}]
|
||||||
|
#set_input_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {VZ80_IORQn}]
|
||||||
|
#set_input_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {VZ80_WRn}]
|
||||||
|
#set_input_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {VZ80_RDn}]
|
||||||
|
#set_input_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {VZ80_M1n}]
|
||||||
|
#set_input_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {VZ80_BUSACKn}]
|
||||||
|
#set_input_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {Z80_INTn}]
|
||||||
|
#set_input_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {Z80_NMIn}]
|
||||||
|
#set_input_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {Z80_WAITn}]
|
||||||
|
#set_input_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {VWAITn_A21_V_CSYNC}]
|
||||||
|
#set_input_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {VZ80_A20_RFSHn_V_HSYNC}]
|
||||||
|
#set_input_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {VZ80_A19_HALTn_V_VSYNC}]
|
||||||
|
|
||||||
|
#**************************************************************
|
||||||
|
# Set Output Delay
|
||||||
|
#**************************************************************
|
||||||
|
|
||||||
|
#set_output_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {CTL_BUSACKn}]
|
||||||
|
#set_output_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {CTL_HALTn}]
|
||||||
|
#set_output_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {CTL_M1n}]
|
||||||
|
#set_output_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {CTL_RFSHn}]
|
||||||
|
#set_output_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {RAM_CSn}]
|
||||||
|
#set_output_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {RAM_CS2n}]
|
||||||
|
#set_output_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {RAM_OEn}]
|
||||||
|
#set_output_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {RAM_WEn}]
|
||||||
|
#set_output_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {SVCREQn}]
|
||||||
|
#set_output_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {SYS_BUSACKn}]
|
||||||
|
#set_output_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {Z80_BUSRQn}]
|
||||||
|
#set_output_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {Z80_DATA[*]}]
|
||||||
|
#set_output_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {Z80_ADDR[*]}]
|
||||||
|
#set_output_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {Z80_HI_ADDR[*]}]
|
||||||
|
#set_output_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {Z80_RA_ADDR[*]}]
|
||||||
|
#set_output_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {Z80_WAITn}]
|
||||||
|
#set_output_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {Z80_MREQn}]
|
||||||
|
#set_output_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {Z80_CLK}]
|
||||||
|
#set_output_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {VZ80_ADDR[*]}]
|
||||||
|
#set_output_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {VZ80_DATA[*]}]
|
||||||
|
#set_output_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {VZ80_CLK}]
|
||||||
|
#set_output_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {VZ80_MREQn}]
|
||||||
|
#set_output_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {VZ80_IORQn}]
|
||||||
|
#set_output_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {VZ80_RDn}]
|
||||||
|
#set_output_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {VZ80_WRn}]
|
||||||
|
#set_output_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {VZ80_M1n}]
|
||||||
|
#set_output_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {VIDEO_RDn}]
|
||||||
|
#set_output_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {VIDEO_WRn}]
|
||||||
|
#set_output_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {VZ80_A18_INTn_V_R}]
|
||||||
|
#set_output_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {VZ80_BUSRQn_V_G}]
|
||||||
|
#set_output_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {VZ80_A16_WAITn_V_B}]
|
||||||
|
#set_output_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {VZ80_A17_NMIn_V_COLR}]
|
||||||
|
#set_output_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {VWAITn_A21_V_CSYNC}]
|
||||||
|
#set_output_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {VZ80_A20_RFSHn_V_HSYNC}]
|
||||||
|
#set_output_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {VZ80_A19_HALTn_V_VSYNC}]
|
||||||
|
#set_output_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {Z80_HALTn}]
|
||||||
|
#set_output_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {Z80_RFSHn}]
|
||||||
|
|
||||||
|
# For K64F
|
||||||
|
#set_output_delay -add_delay -clock [get_clocks {CTLCLK}] 5.000 [get_ports {Z80_CLK}]
|
||||||
|
|
||||||
|
# For basic board with oscillator.
|
||||||
|
#set_output_delay -add_delay -clock [get_clocks {cpld512:cpldl512Toplevel|CTLCLKi}] 5.000 [get_ports {Z80_CLK}]
|
||||||
|
|
||||||
|
#**************************************************************
|
||||||
|
# Set Max Delay
|
||||||
|
#**************************************************************
|
||||||
|
#set_max_delay -from [get_ports {CTL_BUSRQn}] -to {Z80_HALTn} 30.000
|
||||||
|
#set_max_delay -from [get_ports {CTL_BUSRQn}] -to {Z80_IORQn} 30.000
|
||||||
|
#set_max_delay -from [get_ports {CTL_BUSRQn}] -to {Z80_M1n} 30.000
|
||||||
|
#set_max_delay -from [get_ports {CTL_BUSRQn}] -to {Z80_RDn} 30.000
|
||||||
|
#set_max_delay -from [get_ports {CTL_BUSRQn}] -to {Z80_WRn} 30.000
|
||||||
|
#set_max_delay -from [get_ports {CTL_BUSRQn}] -to {Z80_RFSHn} 30.000
|
||||||
|
#set_max_delay -from [get_ports {VZ80_A19_HALTn_V_VSYNC}] -to {Z80_HALTn} 30.000
|
||||||
|
#set_max_delay -from [get_ports {VZ80_IORQn}] -to {Z80_IORQn} 30.000
|
||||||
|
#set_max_delay -from [get_ports {VZ80_MREQn}] -to {Z80_IORQn} 30.000
|
||||||
|
#set_max_delay -from [get_ports {VZ80_M1n}] -to {Z80_M1n} 30.000
|
||||||
|
#set_max_delay -from [get_ports {VZ80_RDn}] -to {Z80_RDn} 30.000
|
||||||
|
#set_max_delay -from [get_ports {VZ80_WRn}] -to {Z80_WRn} 30.000
|
||||||
|
#set_max_delay -from [get_ports {VZ80_BUSACKn}] -to {Z80_HALTn} 40.000
|
||||||
|
#set_max_delay -from [get_ports {VZ80_BUSACKn}] -to {Z80_RFSHn} 40.000
|
||||||
|
#set_max_delay -from [get_ports {VZ80_BUSACKn}] -to {Z80_IORQn} 40.000
|
||||||
|
#set_max_delay -from [get_ports {VZ80_BUSACKn}] -to {Z80_M1n} 30.000
|
||||||
|
#set_max_delay -from [get_ports {VZ80_BUSACKn}] -to {Z80_RDn} 30.000
|
||||||
|
#set_max_delay -from [get_ports {VZ80_BUSACKn}] -to {Z80_WRn} 30.000
|
||||||
|
#set_max_delay -from [get_ports {VZ80_A20_RFSHn_V_HSYNC}] -to {Z80_RFSHn} 30.000
|
||||||
|
#set_max_delay -from [get_ports {Z80_BUSACKn}] -to {Z80_HALTn} 30.000
|
||||||
|
#set_max_delay -from [get_ports {Z80_BUSACKn}] -to {Z80_IORQn} 30.000
|
||||||
|
#set_max_delay -from [get_ports {Z80_BUSACKn}] -to {Z80_M1n} 30.000
|
||||||
|
#set_max_delay -from [get_ports {Z80_BUSACKn}] -to {Z80_RDn} 30.000
|
||||||
|
#set_max_delay -from [get_ports {Z80_BUSACKn}] -to {Z80_WRn} 30.000
|
||||||
|
#set_max_delay -from [get_ports {Z80_BUSACKn}] -to {Z80_RFSHn} 30.000
|
||||||
|
#set_max_delay -from {Z80_BUSACKn} -to [get_ports {Z80_HALTn}] 45.000
|
||||||
|
#set_max_delay -from {Z80_BUSACKn} -to [get_ports {Z80_IORQn}] 30.000
|
||||||
|
#set_max_delay -from {Z80_BUSACKn} -to [get_ports {Z80_M1n}] 30.000
|
||||||
|
#set_max_delay -from {Z80_BUSACKn} -to [get_ports {Z80_RDn}] 30.000
|
||||||
|
#set_max_delay -from {Z80_BUSACKn} -to [get_ports {Z80_RFSHn}] 45.000
|
||||||
|
#set_max_delay -from {Z80_BUSACKn} -to [get_ports {Z80_WRn}] 30.000
|
||||||
|
#set_max_delay -from {cpld512:cpldl512Toplevel|CPLD_CFG_DATA[*]} -to [get_ports {Z80_HALTn}] 45.000
|
||||||
|
#set_max_delay -from {cpld512:cpldl512Toplevel|CPLD_CFG_DATA[*]} -to [get_ports {Z80_IORQn}] 50.000
|
||||||
|
#set_max_delay -from {cpld512:cpldl512Toplevel|CPLD_CFG_DATA[*]} -to [get_ports {Z80_M1n}] 40.000
|
||||||
|
#set_max_delay -from {cpld512:cpldl512Toplevel|CPLD_CFG_DATA[*]} -to [get_ports {Z80_RDn}] 40.000
|
||||||
|
#set_max_delay -from {cpld512:cpldl512Toplevel|CPLD_CFG_DATA[*]} -to [get_ports {Z80_WRn}] 40.000
|
||||||
|
#set_max_delay -from {cpld512:cpldl512Toplevel|CPLD_CFG_DATA[*]} -to [get_ports {Z80_RFSHn}] 45.000
|
||||||
|
#set_max_delay -from {cpld512:cpldl512Toplevel|CPU_CFG_DATA[*]} -to [get_ports {Z80_HALTn}] 60.000
|
||||||
|
#set_max_delay -from {cpld512:cpldl512Toplevel|CPU_CFG_DATA[*]} -to [get_ports {Z80_IORQn}] 45.000
|
||||||
|
#set_max_delay -from {cpld512:cpldl512Toplevel|CPU_CFG_DATA[*]} -to [get_ports {Z80_M1n}] 40.000
|
||||||
|
#set_max_delay -from {cpld512:cpldl512Toplevel|CPU_CFG_DATA[*]} -to [get_ports {Z80_RDn}] 40.000
|
||||||
|
#set_max_delay -from {cpld512:cpldl512Toplevel|CPU_CFG_DATA[*]} -to [get_ports {Z80_WRn}] 40.000
|
||||||
|
#set_max_delay -from {cpld512:cpldl512Toplevel|CPU_CFG_DATA[*]} -to [get_ports {Z80_RFSHn}] 60.000
|
||||||
|
|
||||||
|
#**************************************************************
|
||||||
|
# Set Min Delay
|
||||||
|
#**************************************************************
|
||||||
|
#set_min_delay -from [get_ports {CTL_BUSRQn}] -to {Z80_HALTn} 1.000
|
||||||
|
#set_min_delay -from [get_ports {CTL_BUSRQn}] -to {Z80_IORQn} 1.000
|
||||||
|
#set_min_delay -from [get_ports {CTL_BUSRQn}] -to {Z80_M1n} 1.000
|
||||||
|
#set_min_delay -from [get_ports {CTL_BUSRQn}] -to {Z80_RDn} 1.000
|
||||||
|
#set_min_delay -from [get_ports {CTL_BUSRQn}] -to {Z80_WRn} 1.000
|
||||||
|
#set_min_delay -from [get_ports {CTL_BUSRQn}] -to {Z80_RFSHn} 1.000
|
||||||
|
#set_min_delay -from [get_ports {VZ80_A19_HALTn_V_VSYNC}] -to {Z80_HALTn} 1.000
|
||||||
|
#set_min_delay -from [get_ports {VZ80_IORQn}] -to {Z80_IORQn} 1.000
|
||||||
|
#set_min_delay -from [get_ports {VZ80_MREQn}] -to {Z80_IORQn} 1.000
|
||||||
|
#set_min_delay -from [get_ports {VZ80_M1n}] -to {Z80_M1n} 1.000
|
||||||
|
#set_min_delay -from [get_ports {VZ80_RDn}] -to {Z80_RDn} 1.000
|
||||||
|
#set_min_delay -from [get_ports {VZ80_WRn}] -to {Z80_WRn} 1.000
|
||||||
|
#set_min_delay -from [get_ports {VZ80_BUSACKn}] -to {Z80_HALTn} 1.000
|
||||||
|
#set_min_delay -from [get_ports {VZ80_BUSACKn}] -to {Z80_RFSHn} 1.000
|
||||||
|
#set_min_delay -from [get_ports {VZ80_BUSACKn}] -to {Z80_IORQn} 1.000
|
||||||
|
#set_min_delay -from [get_ports {VZ80_BUSACKn}] -to {Z80_M1n} 1.000
|
||||||
|
#set_min_delay -from [get_ports {VZ80_BUSACKn}] -to {Z80_RDn} 1.000
|
||||||
|
#set_min_delay -from [get_ports {VZ80_BUSACKn}] -to {Z80_WRn} 1.000
|
||||||
|
#set_min_delay -from [get_ports {VZ80_A20_RFSHn_V_HSYNC}] -to {Z80_RFSHn} 1.000
|
||||||
|
#set_min_delay -from [get_ports {Z80_BUSACKn}] -to {Z80_HALTn} 1.000
|
||||||
|
#set_min_delay -from [get_ports {Z80_BUSACKn}] -to {Z80_IORQn} 1.000
|
||||||
|
#set_min_delay -from [get_ports {Z80_BUSACKn}] -to {Z80_M1n} 1.000
|
||||||
|
#set_min_delay -from [get_ports {Z80_BUSACKn}] -to {Z80_RDn} 1.000
|
||||||
|
#set_min_delay -from [get_ports {Z80_BUSACKn}] -to {Z80_WRn} 1.000
|
||||||
|
#set_min_delay -from [get_ports {Z80_BUSACKn}] -to {Z80_RFSHn} 1.000
|
||||||
|
#set_min_delay -from {Z80_BUSACKn} -to [get_ports {Z80_HALTn}] 1.000
|
||||||
|
#set_min_delay -from {Z80_BUSACKn} -to [get_ports {Z80_IORQn}] 1.000
|
||||||
|
#set_min_delay -from {Z80_BUSACKn} -to [get_ports {Z80_M1n}] 1.000
|
||||||
|
#set_min_delay -from {Z80_BUSACKn} -to [get_ports {Z80_RDn}] 1.000
|
||||||
|
#set_min_delay -from {Z80_BUSACKn} -to [get_ports {Z80_RFSHn}] 1.000
|
||||||
|
#set_min_delay -from {Z80_BUSACKn} -to [get_ports {Z80_WRn}] 1.000
|
||||||
|
#set_min_delay -from {cpld512:cpldl512Toplevel|CPLD_CFG_DATA[*]} -to [get_ports {Z80_HALTn}] 1.000
|
||||||
|
#set_min_delay -from {cpld512:cpldl512Toplevel|CPLD_CFG_DATA[*]} -to [get_ports {Z80_IORQn}] 1.000
|
||||||
|
#set_min_delay -from {cpld512:cpldl512Toplevel|CPLD_CFG_DATA[*]} -to [get_ports {Z80_M1n}] 1.000
|
||||||
|
#set_min_delay -from {cpld512:cpldl512Toplevel|CPLD_CFG_DATA[*]} -to [get_ports {Z80_RDn}] 1.000
|
||||||
|
#set_min_delay -from {cpld512:cpldl512Toplevel|CPLD_CFG_DATA[*]} -to [get_ports {Z80_WRn}] 1.000
|
||||||
|
#set_min_delay -from {cpld512:cpldl512Toplevel|CPLD_CFG_DATA[*]} -to [get_ports {Z80_RFSHn}] 1.000
|
||||||
|
#set_min_delay -from {cpld512:cpldl512Toplevel|CPU_CFG_DATA[*]} -to [get_ports {Z80_HALTn}] 1.000
|
||||||
|
#set_min_delay -from {cpld512:cpldl512Toplevel|CPU_CFG_DATA[*]} -to [get_ports {Z80_IORQn}] 1.000
|
||||||
|
#set_min_delay -from {cpld512:cpldl512Toplevel|CPU_CFG_DATA[*]} -to [get_ports {Z80_M1n}] 1.000
|
||||||
|
#set_min_delay -from {cpld512:cpldl512Toplevel|CPU_CFG_DATA[*]} -to [get_ports {Z80_RDn}] 1.000
|
||||||
|
#set_min_delay -from {cpld512:cpldl512Toplevel|CPU_CFG_DATA[*]} -to [get_ports {Z80_WRn}] 1.000
|
||||||
|
#set_min_delay -from {cpld512:cpldl512Toplevel|CPU_CFG_DATA[*]} -to [get_ports {Z80_RFSHn}] 1.000
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#**************************************************************
|
||||||
|
# Set Clock Groups
|
||||||
|
#**************************************************************
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#**************************************************************
|
||||||
|
# Set False Path
|
||||||
|
#**************************************************************
|
||||||
|
|
||||||
|
# For K64F
|
||||||
|
#set_false_path -from [get_clocks {CTLCLK}] -to [get_clocks {SYSCLK}]
|
||||||
|
#set_false_path -from [get_clocks {SYSCLK}] -to [get_clocks {CTLCLK}]
|
||||||
|
|
||||||
|
# For basic board with oscillator.
|
||||||
|
#set_false_path -from [get_clocks {cpld512:cpldl512Toplevel|CTLCLKi}] -to [get_clocks {SYSCLK}]
|
||||||
|
#set_false_path -from [get_clocks {cpld512:cpldl512Toplevel|CTLCLKi}] -to [get_clocks {CTLCLK}]
|
||||||
|
#set_false_path -from [get_clocks {SYSCLK}] -to [get_clocks {cpld512:cpldl512Toplevel|CTLCLKi}]
|
||||||
|
#set_false_path -from [get_clocks {SYSCLK}] -to [get_clocks {CTLCLK}]
|
||||||
|
|
||||||
|
# For both configurations.
|
||||||
|
#set_false_path -from {cpld512:cpldl512Toplevel|KEY_SUBSTITUTE} -to {cpld512:cpldl512Toplevel|CTLCLK_Q}
|
||||||
|
#set_false_path -from {cpld512:cpldl512Toplevel|MEM_MODE_LATCH[*]} -to {cpld512:cpldl512Toplevel|CTLCLK_Q}
|
||||||
|
#set_false_path -from {cpld512:cpldl512Toplevel|CPU_CFG_DATA[*]} -to {cpld512:cpldl512Toplevel|CTLCLK_Q}
|
||||||
|
#set_false_path -from {cpld512:cpldl512Toplevel|CPLD_CFG_DATA[*]} -to {cpld512:cpldl512Toplevel|CTLCLK_Q}
|
||||||
|
#set_false_path -from {cpld512:cpldl512Toplevel|MZ80B_VRAM_HI_ADDR} -to {cpld512:cpldl512Toplevel|CTLCLK_Q}
|
||||||
|
#set_false_path -from {cpld512:cpldl512Toplevel|MZ80B_VRAM_LO_ADDR} -to {cpld512:cpldl512Toplevel|CTLCLK_Q}
|
||||||
|
#set_false_path -from {cpld512:cpldl512Toplevel|MODE_VIDEO_MZ80B} -to {cpld512:cpldl512Toplevel|CTLCLK_Q}
|
||||||
|
#set_false_path -from {cpld512:cpldl512Toplevel|GRAM_PAGE_ENABLE} -to {cpld512:cpldl512Toplevel|CTLCLK_Q}
|
||||||
|
|
||||||
|
#**************************************************************
|
||||||
|
# Set Multicycle Path
|
||||||
|
#**************************************************************
|
||||||
|
#set_multicycle_path -from {cpld512:cpldl512Toplevel|CTL_BUSRQni} -to {cpld512:cpldl512Toplevel|CTLCLK_Q} -setup -end 2
|
||||||
|
#set_multicycle_path -from {cpld512:cpldl512Toplevel|CTL_BUSRQni} -to {cpld512:cpldl512Toplevel|CTLCLK_Q} -hold -end 1
|
||||||
|
|
||||||
|
#set_multicycle_path -from {cpld512:cpldl512Toplevel|CTL_BUSRQni} -to {cpld512:cpldl512Toplevel|MEM_MODE_LATCH[*]} -setup -end 2
|
||||||
|
#set_multicycle_path -from {cpld512:cpldl512Toplevel|CTL_BUSRQni} -to {cpld512:cpldl512Toplevel|MEM_MODE_LATCH[*]} -hold -end 1
|
||||||
|
|
||||||
|
#set_multicycle_path -from {cpld512:cpldl512Toplevel|CPU_CFG_DATA[*]} -to {cpld512:cpldl512Toplevel|MEM_MODE_LATCH[*]} -setup -end 2
|
||||||
|
#set_multicycle_path -from {cpld512:cpldl512Toplevel|CPU_CFG_DATA[*]} -to {cpld512:cpldl512Toplevel|MEM_MODE_LATCH[*]} -hold -end 1
|
||||||
|
|
||||||
|
#**************************************************************
|
||||||
|
# Set Maximum Delay
|
||||||
|
#**************************************************************
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#**************************************************************
|
||||||
|
# Set Minimum Delay
|
||||||
|
#**************************************************************
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#**************************************************************
|
||||||
|
# Set Input Transition
|
||||||
|
#**************************************************************
|
||||||
|
|
||||||
985
CPLD/v1.0/MZ2000/tzpuFusionX.vhd
Normal file
@@ -0,0 +1,985 @@
|
|||||||
|
-------------------------------------------------------------------------------------------------------
|
||||||
|
--
|
||||||
|
-- Name: tzpuFusionX.vhd
|
||||||
|
-- Version: MZ-2000
|
||||||
|
-- Created: June 2020
|
||||||
|
-- Author(s): Philip Smart
|
||||||
|
-- Description: tzpuFusionX CPLD logic definition file.
|
||||||
|
-- This module contains the definition of the tzpuFusionX project plus enhancements
|
||||||
|
-- for the MZ-2000.
|
||||||
|
--
|
||||||
|
-- Credits:
|
||||||
|
-- Copyright: (c) 2018-22 Philip Smart <philip.smart@net2net.org>
|
||||||
|
--
|
||||||
|
-- History: Oct 2022 - Initial write for the MZ-2000.
|
||||||
|
--
|
||||||
|
---------------------------------------------------------------------------------------------------------
|
||||||
|
-- This source file is free software: you can redistribute it and-or modify
|
||||||
|
-- it under the terms of the GNU General Public License as published
|
||||||
|
-- by the Free Software Foundation, either version 3 of the License, or
|
||||||
|
-- (at your option) any later version.
|
||||||
|
--
|
||||||
|
-- This source file is distributed in the hope that it will be useful,
|
||||||
|
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
-- GNU General Public License for more details.
|
||||||
|
--
|
||||||
|
-- You should have received a copy of the GNU General Public License
|
||||||
|
-- along with this program. If not, see <http:--www.gnu.org-licenses->.
|
||||||
|
---------------------------------------------------------------------------------------------------------
|
||||||
|
library ieee;
|
||||||
|
library pkgs;
|
||||||
|
use ieee.std_logic_1164.all;
|
||||||
|
use ieee.std_logic_unsigned.all;
|
||||||
|
use ieee.numeric_std.all;
|
||||||
|
use work.tzpuFusionX_pkg.all;
|
||||||
|
|
||||||
|
entity cpld512 is
|
||||||
|
generic (
|
||||||
|
SPI_CLK_POLARITY : std_logic := '0'
|
||||||
|
);
|
||||||
|
port (
|
||||||
|
-- Z80 Address Bus
|
||||||
|
Z80_ADDR : inout std_logic_vector(15 downto 0);
|
||||||
|
|
||||||
|
-- Z80 Data Bus
|
||||||
|
Z80_DATA : inout std_logic_vector(7 downto 0);
|
||||||
|
|
||||||
|
-- Z80 Control signals.
|
||||||
|
Z80_BUSRQn : in std_logic;
|
||||||
|
Z80_BUSAKn : out std_logic;
|
||||||
|
Z80_INTn : in std_logic;
|
||||||
|
Z80_IORQn : inout std_logic;
|
||||||
|
Z80_MREQn : inout std_logic;
|
||||||
|
Z80_NMIn : in std_logic;
|
||||||
|
Z80_RDn : inout std_logic;
|
||||||
|
Z80_WRn : inout std_logic;
|
||||||
|
Z80_RESETn : in std_logic; -- Host CPU Reset signal, also CPLD reset.
|
||||||
|
Z80_HALTn : out std_logic;
|
||||||
|
Z80_WAITn : in std_logic;
|
||||||
|
Z80_M1n : inout std_logic;
|
||||||
|
Z80_RFSHn : inout std_logic;
|
||||||
|
|
||||||
|
-- SOM Control Signals
|
||||||
|
VSOM_SPI_CLK : in std_logic; -- SOM SPI Channel 0 Clock.
|
||||||
|
VSOM_SPI_MOSI : in std_logic; -- MOSI Input.
|
||||||
|
VSOM_SPI_MISO : out std_logic; -- MISO Output.
|
||||||
|
VSOM_SPI_CSn : in std_logic; -- Enable.
|
||||||
|
|
||||||
|
-- SOM Parallel Bus.
|
||||||
|
VSOM_DATA_OUT : out std_logic_vector(7 downto 0); -- Address/Data bus for CPLD control registers.
|
||||||
|
VSOM_HBYTE : in std_logic; -- Parallel Bus High (1)/Low (0) byte.
|
||||||
|
VSOM_READY : out std_logic; -- FSM Ready (1), Busy (0)
|
||||||
|
VSOM_LTSTATE : out std_logic; -- Last T-State in current cycle, 1 = active.
|
||||||
|
VSOM_BUSRQ : out std_logic; -- Host device requesting Z80 Bus.
|
||||||
|
VSOM_BUSACK : out std_logic; -- Host device granted Z80 Bus
|
||||||
|
VSOM_INT : out std_logic; -- Z80 INT signal
|
||||||
|
VSOM_NMI : out std_logic; -- Z80 NMI signal
|
||||||
|
VSOM_WAIT : out std_logic; -- Z80 WAIT signal
|
||||||
|
VSOM_RESET : out std_logic; -- Z80 RESET signal
|
||||||
|
VSOM_RSV : out std_logic_vector(1 downto 1); -- Reserved pins.
|
||||||
|
|
||||||
|
-- SOM Control Signals
|
||||||
|
PM_RESET : out std_logic; -- Reset SOM
|
||||||
|
|
||||||
|
-- VGA_Palette Control
|
||||||
|
VGA_R : in std_logic_vector(9 downto 7); -- Signals used for detecting blank or no video output.
|
||||||
|
VGA_G : in std_logic_vector(9 downto 7);
|
||||||
|
VGA_B : in std_logic_vector(9 downto 8);
|
||||||
|
|
||||||
|
-- VGA Control Signals
|
||||||
|
VGA_PXL_CLK : in std_logic; -- VGA Pixel clock for DAC conversion.
|
||||||
|
VGA_DISPEN : in std_logic; -- Displayed Enabled (SOM video output).
|
||||||
|
VGA_VSYNCn : in std_logic; -- SOM VSync.
|
||||||
|
VGA_HSYNCn : in std_logic; -- SOM HSync.
|
||||||
|
VGA_COLR : out std_logic; -- COLR colour carrier frequency.
|
||||||
|
VGA_CSYNCn : out std_logic; -- VGA Composite Sync.
|
||||||
|
VGA_BLANKn : out std_logic; -- VGA Blank detected.
|
||||||
|
|
||||||
|
-- CRT Control Signals
|
||||||
|
MONO_PXL_CLK : out std_logic; -- Mono CRT pixel clock for DAC conversion.
|
||||||
|
MONO_BLANKn : out std_logic; -- Mono CRT Blank (no active pixel) detection.
|
||||||
|
MONO_CSYNCn : out std_logic; -- Mono CRT composite sync.
|
||||||
|
MONO_RSV : out std_logic;
|
||||||
|
|
||||||
|
-- CRT Lower Chrominance Control
|
||||||
|
MONO_R : out std_logic_vector(2 downto 0); -- Signals to fine tune Red level of monochrome chrominance.
|
||||||
|
MONO_G : out std_logic_vector(2 downto 0); -- Signals to fine tune Green level of monochrome chrominance.
|
||||||
|
MONO_B : out std_logic_vector(2 downto 1); -- Signals to fine tune Blue level of monochrome chrominance.
|
||||||
|
|
||||||
|
-- MUX Control Signals
|
||||||
|
VIDEO_SRC : out std_logic; -- Select video source, Mainboard or SOM.
|
||||||
|
MONO_VIDEO_SRC : out std_logic; -- Select crt video source, Mainboard or SOM.
|
||||||
|
AUDIO_SRC_L : out std_logic; -- Select Audio Source Left Channel, Mainboard or SOM.
|
||||||
|
AUDIO_SRC_R : out std_logic; -- Select Audio Source Right Channel, Mainboard or SOM.
|
||||||
|
|
||||||
|
-- Mainboard Reset Signals
|
||||||
|
MB_RESETn : in std_logic; -- Motherboard Reset pressed.
|
||||||
|
MB_IPLn : in std_logic; -- Motherboard IPL pressed.
|
||||||
|
|
||||||
|
-- USB Power Control
|
||||||
|
VBUS_EN : out std_logic; -- USB Enable Power Output
|
||||||
|
|
||||||
|
-- Clocks.
|
||||||
|
Z80_CLK : in std_logic; -- Host CPU Clock
|
||||||
|
CLK_50M : in std_logic -- 50MHz oscillator.
|
||||||
|
);
|
||||||
|
end entity;
|
||||||
|
|
||||||
|
architecture rtl of cpld512 is
|
||||||
|
|
||||||
|
-- Finite State Machine states.
|
||||||
|
type SOMFSMState is
|
||||||
|
(
|
||||||
|
IdleCycle,
|
||||||
|
FetchCycle,
|
||||||
|
FetchCycle_11,
|
||||||
|
FetchCycle_20,
|
||||||
|
FetchCycle_21,
|
||||||
|
FetchCycle_30,
|
||||||
|
RefreshCycle,
|
||||||
|
RefreshCycle_11,
|
||||||
|
RefreshCycle_20,
|
||||||
|
RefreshCycle_21,
|
||||||
|
RefreshCycle_3,
|
||||||
|
WriteCycle,
|
||||||
|
WriteCycle_11,
|
||||||
|
WriteCycle_20,
|
||||||
|
WriteCycle_21,
|
||||||
|
WriteCycle_30,
|
||||||
|
WriteCycle_31,
|
||||||
|
ReadCycle,
|
||||||
|
ReadCycle_11,
|
||||||
|
ReadCycle_20,
|
||||||
|
ReadCycle_21,
|
||||||
|
ReadCycle_30,
|
||||||
|
ReadCycle_31,
|
||||||
|
WriteIOCycle,
|
||||||
|
WriteIOCycle_11,
|
||||||
|
WriteIOCycle_20,
|
||||||
|
WriteIOCycle_21,
|
||||||
|
WriteIOCycle_30,
|
||||||
|
WriteIOCycle_31,
|
||||||
|
WriteIOCycle_40,
|
||||||
|
WriteIOCycle_41,
|
||||||
|
ReadIOCycle,
|
||||||
|
ReadIOCycle_11,
|
||||||
|
ReadIOCycle_20,
|
||||||
|
ReadIOCycle_21,
|
||||||
|
ReadIOCycle_30,
|
||||||
|
ReadIOCycle_31,
|
||||||
|
ReadIOCycle_40,
|
||||||
|
ReadIOCycle_41,
|
||||||
|
HaltCycle,
|
||||||
|
BusReqCycle
|
||||||
|
);
|
||||||
|
|
||||||
|
-- CPU Interface internal signals.
|
||||||
|
signal Z80_BUSRQni : std_logic;
|
||||||
|
signal Z80_INTni : std_logic;
|
||||||
|
signal Z80_IORQni : std_logic;
|
||||||
|
signal Z80_MREQni : std_logic;
|
||||||
|
signal Z80_NMIni : std_logic;
|
||||||
|
signal Z80_RDni : std_logic;
|
||||||
|
signal Z80_WRni : std_logic;
|
||||||
|
signal Z80_HALTni : std_logic;
|
||||||
|
signal Z80_M1ni : std_logic;
|
||||||
|
signal Z80_RFSHni : std_logic;
|
||||||
|
signal Z80_DATAi : std_logic_vector(7 downto 0);
|
||||||
|
signal Z80_BUSRQ_ACKni : std_logic;
|
||||||
|
|
||||||
|
-- Internal CPU state control.
|
||||||
|
signal CPU_ADDR : std_logic_vector(15 downto 0) := (others => '0');
|
||||||
|
signal CPU_DATA_IN : std_logic_vector(7 downto 0) := (others => '0');
|
||||||
|
signal CPU_DATA_OUT : std_logic_vector(7 downto 0) := (others => '0');
|
||||||
|
signal CPU_DATA_EN : std_logic;
|
||||||
|
|
||||||
|
-- Clocks.
|
||||||
|
signal CLK_25Mi : std_logic := '0';
|
||||||
|
|
||||||
|
-- Reset control
|
||||||
|
signal PM_RESETi : std_logic := '1';
|
||||||
|
signal VSOM_RESETni : std_logic := '1';
|
||||||
|
|
||||||
|
-- Refresh control.
|
||||||
|
signal FSM_STATE : SOMFSMState := IdleCycle;
|
||||||
|
signal NEW_SPI_CMD : std_logic := '0';
|
||||||
|
signal VCPU_CS_EDGE : std_logic_vector(1 downto 0) := "11";
|
||||||
|
signal AUTOREFRESH_CNT : integer range 0 to 7;
|
||||||
|
signal FSM_STATUS : std_logic := '0';
|
||||||
|
signal FSM_CHECK_WAIT : std_logic := '0';
|
||||||
|
signal FSM_WAIT_ACTIVE : std_logic := '0';
|
||||||
|
signal RFSH_STATUS : std_logic := '0';
|
||||||
|
signal REFRESH_ADDR : std_logic_vector(7 downto 0);
|
||||||
|
signal IPAR : std_logic_vector(7 downto 0);
|
||||||
|
signal AUTOREFRESH : std_logic;
|
||||||
|
|
||||||
|
-- Clock edge detection and flagging.
|
||||||
|
signal Z80_CLKi : std_logic;
|
||||||
|
signal Z80_CLK_LAST : std_logic_vector(1 downto 0);
|
||||||
|
signal Z80_CLK_RE : std_logic;
|
||||||
|
signal Z80_CLK_FE : std_logic;
|
||||||
|
signal Z80_CLK_TGL : std_logic;
|
||||||
|
signal CPU_T_STATE_SET : integer range 0 to 5;
|
||||||
|
signal CPU_LAST_T_STATE : std_logic := '0';
|
||||||
|
|
||||||
|
-- SPI Slave interface.
|
||||||
|
signal SPI_SHIFT_EN : std_logic;
|
||||||
|
signal SPI_TX_SREG : std_logic_vector(6 downto 0); -- TX Shift Register
|
||||||
|
signal SPI_RX_SREG : std_logic_vector(7 downto 0); -- RX Shift Register
|
||||||
|
signal SPI_TX_DATA : std_logic_vector(31 downto 0); -- Data to transmit.
|
||||||
|
signal SPI_RX_DATA : std_logic_vector(31 downto 0); -- Data received.
|
||||||
|
signal SPI_BIT_CNT : integer range 0 to 16; -- Count of bits tx/rx'd.
|
||||||
|
signal SPI_FRAME_CNT : integer range 0 to 4; -- Number of frames received (8bit chunks).
|
||||||
|
|
||||||
|
-- SPI Command interface.
|
||||||
|
signal SOM_CMD : std_logic_vector(7 downto 0) := (others => '0');
|
||||||
|
signal SPI_NEW_DATA : std_logic;
|
||||||
|
signal SPI_PROCESSING : std_logic;
|
||||||
|
signal SPI_CPU_ADDR : std_logic_vector(15 downto 0) := (others => '0');
|
||||||
|
signal SPI_CPU_DATA : std_logic_vector(7 downto 0) := (others => '0');
|
||||||
|
|
||||||
|
-- Test modes.
|
||||||
|
signal SPI_LOOPBACK_TEST : std_logic := '0';
|
||||||
|
|
||||||
|
-- Video/Audio control
|
||||||
|
signal VIDEO_SRCi : std_logic := '0';
|
||||||
|
signal MONO_VIDEO_SRCi : std_logic := '0';
|
||||||
|
signal AUDIO_SRC_Li : std_logic := '0';
|
||||||
|
signal AUDIO_SRC_Ri : std_logic := '0';
|
||||||
|
signal VBUS_ENi : std_logic := '1';
|
||||||
|
|
||||||
|
|
||||||
|
function to_std_logic(L: boolean) return std_logic is
|
||||||
|
begin
|
||||||
|
if L then
|
||||||
|
return('1');
|
||||||
|
else
|
||||||
|
return('0');
|
||||||
|
end if;
|
||||||
|
end function to_std_logic;
|
||||||
|
begin
|
||||||
|
|
||||||
|
|
||||||
|
-- System RESET.
|
||||||
|
--
|
||||||
|
-- Multiple reset sources, Z80_RESETn, MB_IPLn, MB_RESETn. On the MZ-2000, MB_IPLn is a full reset where all the gate array
|
||||||
|
-- registers are reset and the memory map resets to the power on state for initial program loading. MB_RESETn is a warm
|
||||||
|
-- restart for loaded programs, ie. keeps the programmed memory state but resets the Z80 which automatically executes the
|
||||||
|
-- loaded program. Like the MZ-700, we trigger on Z80_RESETn after having sampled the MB_IPLn and MB_RESETn states to decide
|
||||||
|
-- on any extra actions needed within the CPLD and the signals are forwarded onto the SOM so it too can take the correct
|
||||||
|
-- reset path.
|
||||||
|
--
|
||||||
|
-- If the external reset switch is pressed, a Z80_RESETn is invoked sending the signal low for approx 30ms.
|
||||||
|
-- On the first edge the VSOM_RESETn signal is set which allows the SOM to see it and the Z80 application to enter a reset state.
|
||||||
|
-- On the second edge, if occurring within 1 second of the first, the PM_RESET signal to the SOM is triggered, held low for 1 second,
|
||||||
|
-- forcing the SOM to reboot.
|
||||||
|
SYSRESET: process( Z80_CLKi, Z80_RESETn )
|
||||||
|
variable timer1 : integer range 0 to 354000 := 0;
|
||||||
|
variable timer100 : integer range 0 to 10 := 0;
|
||||||
|
variable timerPMReset : integer range 0 to 10 := 0;
|
||||||
|
variable resetCount : integer range 0 to 3 := 0;
|
||||||
|
variable cpuResetEdge : std_logic := '1';
|
||||||
|
begin
|
||||||
|
-- Synchronous on the HOST Clock.
|
||||||
|
if(rising_edge(Z80_CLKi)) then
|
||||||
|
|
||||||
|
-- If the PM Reset timer is active, count down and on expiry release the SOM PM_RESET line.
|
||||||
|
if(timerPMReset = 0 and PM_RESETi = '1') then
|
||||||
|
PM_RESETi <= '0';
|
||||||
|
end if;
|
||||||
|
|
||||||
|
-- If the VSOM_RESETni is active after reset timer expiry, cancel the RESET state.
|
||||||
|
if(timerPMReset = 0 and VSOM_RESETni = '0') then
|
||||||
|
VSOM_RESETni <= '1';
|
||||||
|
end if;
|
||||||
|
|
||||||
|
-- Each time the reset button is pressed, count the edges.
|
||||||
|
if(Z80_RESETn = '0' and cpuResetEdge = '1' and (resetCount = 0 or timer100 > 5)) then
|
||||||
|
resetCount := resetCount + 1;
|
||||||
|
VSOM_RESETni <= '0';
|
||||||
|
timerPMReset := 5;
|
||||||
|
timer100 := 0;
|
||||||
|
|
||||||
|
-- If there are 2 or more reset signals in a given period it means a SOM reset is required.
|
||||||
|
if(resetCount >= 2) then
|
||||||
|
PM_RESETi <= '1';
|
||||||
|
timerPMReset := 10;
|
||||||
|
resetCount := 0;
|
||||||
|
end if;
|
||||||
|
|
||||||
|
end if;
|
||||||
|
|
||||||
|
-- 100ms interval.
|
||||||
|
if(timer1 = 354000) then
|
||||||
|
timer100 := timer100 + 1;
|
||||||
|
|
||||||
|
if(timer100 >= 10) then
|
||||||
|
timer100 := 0;
|
||||||
|
resetCount := 0;
|
||||||
|
end if;
|
||||||
|
|
||||||
|
if(timerPMReset > 0) then
|
||||||
|
timerPMReset := timerPMReset - 1;
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
|
||||||
|
timer1 := timer1 - 1;
|
||||||
|
cpuResetEdge := Z80_RESETn;
|
||||||
|
end if;
|
||||||
|
end process;
|
||||||
|
|
||||||
|
-- Create Mono DAC Clock based on primary clock.
|
||||||
|
MONOCLK: process( CLK_50M )
|
||||||
|
begin
|
||||||
|
if(rising_edge(CLK_50M)) then
|
||||||
|
CLK_25Mi <= not CLK_25Mi;
|
||||||
|
end if;
|
||||||
|
end process;
|
||||||
|
|
||||||
|
-- SPI Slave input. Receive command and data from the SOM.
|
||||||
|
SPI_INPUT : process(VSOM_SPI_CLK)
|
||||||
|
begin
|
||||||
|
-- SPI_CLK_POLARITY='0' => falling edge; SPI_CLK_POLARITY='1' => rising edge
|
||||||
|
if(VSOM_SPI_CLK'event and VSOM_SPI_CLK = SPI_CLK_POLARITY) then
|
||||||
|
if(VSOM_SPI_CSn = '0') then
|
||||||
|
SPI_RX_SREG <= SPI_RX_SREG(6 downto 0) & VSOM_SPI_MOSI;
|
||||||
|
|
||||||
|
-- End of frame then store the data prior to next bit arrival.
|
||||||
|
-- Convert to Little Endian, same as SOM.
|
||||||
|
if(SPI_SHIFT_EN = '1' and SPI_FRAME_CNT = 1 and SPI_BIT_CNT = 0) then
|
||||||
|
SPI_RX_DATA(7 downto 0) <= SPI_RX_SREG(6 downto 0) & VSOM_SPI_MOSI;
|
||||||
|
|
||||||
|
elsif(SPI_SHIFT_EN = '1' and SPI_FRAME_CNT = 2 and SPI_BIT_CNT = 0) then
|
||||||
|
SPI_RX_DATA(15 downto 8) <= SPI_RX_SREG(6 downto 0) & VSOM_SPI_MOSI;
|
||||||
|
|
||||||
|
elsif(SPI_SHIFT_EN = '1' and SPI_FRAME_CNT = 3 and SPI_BIT_CNT = 0) then
|
||||||
|
SPI_RX_DATA(23 downto 16) <= SPI_RX_SREG(6 downto 0) & VSOM_SPI_MOSI;
|
||||||
|
|
||||||
|
elsif(SPI_SHIFT_EN = '1' and SPI_FRAME_CNT = 4 and SPI_BIT_CNT = 0) then
|
||||||
|
SPI_RX_DATA(31 downto 24) <= SPI_RX_SREG(6 downto 0) & VSOM_SPI_MOSI;
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
end process;
|
||||||
|
|
||||||
|
-- SPI Slave output. Return the current data set as selected by the input signals XACT.
|
||||||
|
SPI_OUTPUT : process(VSOM_SPI_CLK,VSOM_SPI_CSn,SPI_TX_DATA)
|
||||||
|
begin
|
||||||
|
if(VSOM_SPI_CSn = '1') then
|
||||||
|
SPI_SHIFT_EN <= '0';
|
||||||
|
SPI_BIT_CNT <= 15;
|
||||||
|
|
||||||
|
-- SPI_CLK_POLARITY='0' => falling edge; SPI_CLK_POLARITY='1' => risinge edge
|
||||||
|
elsif(VSOM_SPI_CLK'event and VSOM_SPI_CLK = not SPI_CLK_POLARITY) then
|
||||||
|
SPI_SHIFT_EN <= '1';
|
||||||
|
|
||||||
|
if(SPI_BIT_CNT > 0) then
|
||||||
|
SPI_BIT_CNT <= SPI_BIT_CNT - 1;
|
||||||
|
end if;
|
||||||
|
|
||||||
|
VSOM_SPI_MISO <= SPI_TX_SREG(6);
|
||||||
|
SPI_TX_SREG <= SPI_TX_SREG(5 downto 0) & '0';
|
||||||
|
|
||||||
|
-- First clock after CS goes active, load up the data to be sent to the SOM.
|
||||||
|
if(SPI_SHIFT_EN = '0' or SPI_BIT_CNT = 0) then
|
||||||
|
|
||||||
|
if(SPI_LOOPBACK_TEST = '1') then
|
||||||
|
VSOM_SPI_MISO<= SPI_RX_SREG(7);
|
||||||
|
SPI_TX_SREG <= SPI_RX_SREG(6 downto 0);
|
||||||
|
|
||||||
|
elsif(SPI_SHIFT_EN = '0') then
|
||||||
|
SPI_FRAME_CNT<= 1;
|
||||||
|
VSOM_SPI_MISO<= SPI_TX_DATA(7);
|
||||||
|
SPI_TX_SREG <= SPI_TX_DATA(6 downto 0);
|
||||||
|
elsif(SPI_FRAME_CNT = 1) then
|
||||||
|
SPI_FRAME_CNT<= 2;
|
||||||
|
VSOM_SPI_MISO<= SPI_TX_DATA(15);
|
||||||
|
SPI_TX_SREG <= SPI_TX_DATA(14 downto 8);
|
||||||
|
elsif(SPI_FRAME_CNT = 2) then
|
||||||
|
SPI_FRAME_CNT<= 3;
|
||||||
|
VSOM_SPI_MISO<= SPI_TX_DATA(23);
|
||||||
|
SPI_TX_SREG <= SPI_TX_DATA(22 downto 16);
|
||||||
|
else
|
||||||
|
-- Increment frame count for each word received. We handle 8bit (1 frame), 16bit (2 frames) or 32bit (4 frames) reception.
|
||||||
|
SPI_FRAME_CNT<= 4;
|
||||||
|
VSOM_SPI_MISO<= SPI_TX_DATA(31);
|
||||||
|
SPI_TX_SREG <= SPI_TX_DATA(30 downto 24);
|
||||||
|
end if;
|
||||||
|
|
||||||
|
SPI_BIT_CNT <= 7;
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
end process;
|
||||||
|
|
||||||
|
SPI_REGISTER : process(Z80_RESETn, VSOM_SPI_CSn, SPI_FRAME_CNT)
|
||||||
|
begin
|
||||||
|
if(Z80_RESETn = '0') then
|
||||||
|
VIDEO_SRCi <= '0';
|
||||||
|
VGA_BLANKn <= '1';
|
||||||
|
VBUS_ENi <= '1';
|
||||||
|
MONO_VIDEO_SRCi <= '1';
|
||||||
|
AUDIO_SRC_Li <= '0';
|
||||||
|
AUDIO_SRC_Ri <= '0';
|
||||||
|
AUTOREFRESH <= '0';
|
||||||
|
SPI_LOOPBACK_TEST <= '0';
|
||||||
|
SOM_CMD <= (others => '0');
|
||||||
|
SPI_CPU_ADDR <= (others => '0');
|
||||||
|
SPI_NEW_DATA <= '0';
|
||||||
|
|
||||||
|
-- On rising edge of SPI CSn a new data packet from the SOM has arrived and in the shift register SPI_RX_SREG.
|
||||||
|
-- The variable SPI_FRAME_CNT indicates which byte (frame) in a 32bit word has been transmitted. This allows
|
||||||
|
-- for 8bit, 16bit and 32bit transmissions.
|
||||||
|
-- The packet is formatted as follows:
|
||||||
|
--
|
||||||
|
-- < SPI_FRAME_CNT=4 >< SPI_FRAME=3 > < SPI_FRAME_CNT=2 >< SPI_FRAME_CNT=1>
|
||||||
|
-- < 16bit Z80 Address > < Z80 Data ><Command=00..80>
|
||||||
|
-- 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
|
||||||
|
--
|
||||||
|
-- < > < Data ><Command=F0..FF>
|
||||||
|
-- 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
|
||||||
|
--
|
||||||
|
elsif(VSOM_SPI_CSn'event and VSOM_SPI_CSn = '1') then
|
||||||
|
|
||||||
|
-- Command is always located in the upper byte of frame 1.
|
||||||
|
SOM_CMD <= SPI_RX_DATA(7 downto 0);
|
||||||
|
|
||||||
|
-- Toggle flag to indicate new data arrived.
|
||||||
|
SPI_NEW_DATA <= not SPI_NEW_DATA;
|
||||||
|
|
||||||
|
-- Process the command. Some commands require the FSM, others can be serviced immediately.
|
||||||
|
case SPI_RX_DATA(7 downto 0) is
|
||||||
|
|
||||||
|
-- Z80XACT(0..15): Setup data and address as provided then execute FSM.
|
||||||
|
when X"10" | X"11" | X"12" | X"13" | X"14" | X"15" | X"16" | X"17" | -- Fetch
|
||||||
|
X"18" | X"19" | X"1A" | X"1B" | X"1C" | X"1D" | X"1E" | X"1F" | -- Write
|
||||||
|
X"20" | X"21" | X"22" | X"23" | X"24" | X"25" | X"26" | X"27" | -- Read
|
||||||
|
X"28" | X"29" | X"2A" | X"2B" | X"2C" | X"2D" | X"2E" | X"2F" | -- WriteIO
|
||||||
|
X"30" | X"31" | X"32" | X"33" | X"34" | X"35" | X"36" | X"37" | -- ReadIO
|
||||||
|
X"38" | X"39" | X"3A" | X"3B" | X"3C" | X"3D" | X"3E" | X"3F" | --
|
||||||
|
X"40" | X"41" | X"42" | X"43" | X"44" | X"45" | X"46" | X"47" | --
|
||||||
|
X"48" | X"49" | X"4A" | X"4B" | X"4C" | X"4D" | X"4E" | X"4F" =>
|
||||||
|
|
||||||
|
-- Direct address set.
|
||||||
|
if(SPI_FRAME_CNT = 4) then
|
||||||
|
SPI_CPU_ADDR <= SPI_RX_DATA(31 downto 16);
|
||||||
|
else
|
||||||
|
-- if(SPI_CPU_ADDR >= X"D010" and SPI_CPU_ADDR < X"D020") then
|
||||||
|
-- SPI_CPU_ADDR <= std_logic_vector(X"D020" + unsigned(SPI_RX_DATA(2 downto 0)));
|
||||||
|
-- else
|
||||||
|
SPI_CPU_ADDR <= std_logic_vector(unsigned(SPI_CPU_ADDR) + unsigned(SPI_RX_DATA(2 downto 0)));
|
||||||
|
-- end if;
|
||||||
|
end if;
|
||||||
|
|
||||||
|
if(SPI_FRAME_CNT > 1) then
|
||||||
|
SPI_CPU_DATA <= SPI_RX_DATA(15 downto 8);
|
||||||
|
end if;
|
||||||
|
|
||||||
|
-- SETSIGSET1: Set control lines directly.
|
||||||
|
when X"F0" =>
|
||||||
|
VIDEO_SRCi <= SPI_RX_DATA(8);
|
||||||
|
MONO_VIDEO_SRCi <= SPI_RX_DATA(9);
|
||||||
|
AUDIO_SRC_Li <= SPI_RX_DATA(10);
|
||||||
|
AUDIO_SRC_Ri <= SPI_RX_DATA(11);
|
||||||
|
VBUS_ENi <= SPI_RX_DATA(12);
|
||||||
|
VGA_BLANKn <= not SPI_RX_DATA(13);
|
||||||
|
|
||||||
|
-- Enable auto refresh DRAM cycle.
|
||||||
|
when X"F1" =>
|
||||||
|
AUTOREFRESH <= '1';
|
||||||
|
|
||||||
|
-- Disable auto refresh DRAM cycle.
|
||||||
|
when X"F2" =>
|
||||||
|
AUTOREFRESH <= '0';
|
||||||
|
|
||||||
|
-- SETLOOPBACK: Enable loopback test mode.
|
||||||
|
when X"FE" =>
|
||||||
|
SPI_LOOPBACK_TEST<= '1';
|
||||||
|
|
||||||
|
-- No action, called to retrieve status.
|
||||||
|
when X"00" | X"FF" =>
|
||||||
|
|
||||||
|
when others =>
|
||||||
|
end case;
|
||||||
|
end if;
|
||||||
|
end process;
|
||||||
|
|
||||||
|
-- Process to detect the Z80 Clock edges. Each edge is used to recreate the Z80 external signals.
|
||||||
|
--
|
||||||
|
Z80CLK: process( CLK_50M, Z80_CLKi, Z80_RESETn )
|
||||||
|
begin
|
||||||
|
if(Z80_RESETn = '0') then
|
||||||
|
Z80_CLK_RE <= '1';
|
||||||
|
Z80_CLK_FE <= '1';
|
||||||
|
Z80_CLK_TGL <= '1';
|
||||||
|
|
||||||
|
elsif(rising_edge(CLK_50M)) then
|
||||||
|
|
||||||
|
-- Default is to clear the signals, only active for 1 clock period.
|
||||||
|
Z80_CLK_RE <= '0';
|
||||||
|
Z80_CLK_FE <= '0';
|
||||||
|
Z80_CLK_TGL <= '0';
|
||||||
|
|
||||||
|
-- Rising Edge.
|
||||||
|
if(Z80_CLKi = '1' and Z80_CLK_LAST = "00") then
|
||||||
|
Z80_CLK_RE <= '1';
|
||||||
|
|
||||||
|
-- Toggle on rising edge is delayed by one clock to allow time for command to be decoded.
|
||||||
|
elsif(Z80_CLKi = '1' and Z80_CLK_LAST = "01") then
|
||||||
|
Z80_CLK_TGL <= '1';
|
||||||
|
|
||||||
|
-- Falling Edge.
|
||||||
|
elsif(Z80_CLKi = '0' and Z80_CLK_LAST = "11") then
|
||||||
|
Z80_CLK_FE <= '1';
|
||||||
|
Z80_CLK_TGL <= '1';
|
||||||
|
end if;
|
||||||
|
Z80_CLK_LAST <= Z80_CLK_LAST(0) & Z80_CLKi;
|
||||||
|
end if;
|
||||||
|
end process;
|
||||||
|
|
||||||
|
-- SOM Finite State Machine.
|
||||||
|
--
|
||||||
|
-- A command processor, based on an FSM concept, to process requested commands, ie. Z80 Write, Z80 Read etc.
|
||||||
|
-- The external signal SOM_CMD_EN, when set, indicates a new command available in SOM_CMD.
|
||||||
|
--
|
||||||
|
SOMFSM: process( CLK_50M, Z80_CLKi, Z80_RESETn )
|
||||||
|
begin
|
||||||
|
if(Z80_RESETn = '0') then
|
||||||
|
Z80_IORQni <= '1';
|
||||||
|
Z80_MREQni <= '1';
|
||||||
|
Z80_RDni <= '1';
|
||||||
|
Z80_WRni <= '1';
|
||||||
|
Z80_HALTni <= '1';
|
||||||
|
Z80_M1ni <= '1';
|
||||||
|
Z80_RFSHni <= '1';
|
||||||
|
Z80_BUSRQ_ACKni <= '1';
|
||||||
|
FSM_CHECK_WAIT <= '0';
|
||||||
|
FSM_WAIT_ACTIVE <= '0';
|
||||||
|
FSM_STATUS <= '0';
|
||||||
|
FSM_STATE <= IdleCycle;
|
||||||
|
RFSH_STATUS <= '0';
|
||||||
|
CPU_DATA_EN <= '0';
|
||||||
|
CPU_DATA_IN <= (others => '0');
|
||||||
|
REFRESH_ADDR <= (others => '0');
|
||||||
|
AUTOREFRESH_CNT <= 7;
|
||||||
|
IPAR <= (others => '0');
|
||||||
|
NEW_SPI_CMD <= '0';
|
||||||
|
VCPU_CS_EDGE <= "11";
|
||||||
|
SPI_PROCESSING <= '0';
|
||||||
|
|
||||||
|
elsif(rising_edge(CLK_50M)) then
|
||||||
|
|
||||||
|
-- Bus request mechanism. If an externel Bus Request comes in and the FSM is idle, run the Bus Request command which
|
||||||
|
-- suspends processing and tri-states the bus.
|
||||||
|
if(Z80_BUSRQn = '0' and Z80_BUSRQ_ACKni = '1' and FSM_STATE = IdleCycle) then
|
||||||
|
FSM_STATE <= BusReqCycle;
|
||||||
|
end if;
|
||||||
|
if(Z80_BUSRQn = '1' and Z80_BUSRQ_ACKni = '0' and FSM_STATE = IdleCycle) then
|
||||||
|
Z80_BUSRQ_ACKni <= '1';
|
||||||
|
end if;
|
||||||
|
|
||||||
|
-- New command, set flag as the signal is only 1 clock wide.
|
||||||
|
if(SPI_LOOPBACK_TEST = '0' and VSOM_SPI_CSn = '1' and VCPU_CS_EDGE = "01") then
|
||||||
|
NEW_SPI_CMD <= '1';
|
||||||
|
end if;
|
||||||
|
|
||||||
|
-- Whenever we return to Idle or just prior to Refresh from a Fetch cycle set all control signals to default.
|
||||||
|
if(FSM_STATE = IdleCycle or FSM_STATE = RefreshCycle) then
|
||||||
|
CPU_DATA_EN <= '0';
|
||||||
|
Z80_MREQni <= '1';
|
||||||
|
Z80_IORQni <= '1';
|
||||||
|
Z80_RDni <= '1';
|
||||||
|
Z80_WRni <= '1';
|
||||||
|
Z80_M1ni <= '1';
|
||||||
|
FSM_STATUS <= '0';
|
||||||
|
Z80_RFSHni <= '1';
|
||||||
|
|
||||||
|
-- Auto DRAM refresh cycles. When enabled, every 7 host clock cycles, a 2 cycle refresh period commences.
|
||||||
|
-- This will be overriden if the SPI receives a new command.
|
||||||
|
--
|
||||||
|
if AUTOREFRESH = '1' and FSM_STATE = IdleCycle then
|
||||||
|
AUTOREFRESH_CNT <= AUTOREFRESH_CNT - 1;
|
||||||
|
if(AUTOREFRESH_CNT = 0) then
|
||||||
|
FSM_STATE <= RefreshCycle_3;
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
|
||||||
|
-- If new command has been given and the FSM enters idle state, load up new command for processing.
|
||||||
|
if(NEW_SPI_CMD = '1' and FSM_STATE = IdleCycle and Z80_CLK_RE = '1') then
|
||||||
|
NEW_SPI_CMD <= '0';
|
||||||
|
|
||||||
|
-- Store new address and data for this command.
|
||||||
|
CPU_ADDR <= SPI_CPU_ADDR;
|
||||||
|
if(SPI_CPU_DATA /= CPU_DATA_OUT) then
|
||||||
|
CPU_DATA_OUT <= SPI_CPU_DATA;
|
||||||
|
end if;
|
||||||
|
|
||||||
|
-- Process the SOM command. The SPI_REGISTER executes non FSM commands and stores FSM
|
||||||
|
-- data prior to this execution block, which fires 1 cycle later on the same control clock.
|
||||||
|
-- If the command is not for the FSM then the READY mechanism is held for one
|
||||||
|
-- further cycle before going inactive.
|
||||||
|
case SOM_CMD is
|
||||||
|
when X"10" | X"11" | X"12" | X"13" | X"14" | X"15" | X"16" | X"17" =>
|
||||||
|
-- Initiate a Fetch Cycle.
|
||||||
|
FSM_STATE <= FetchCycle;
|
||||||
|
|
||||||
|
when X"18" | X"19" | X"1A" | X"1B" | X"1C" | X"1D" | X"1E" | X"1F" =>
|
||||||
|
|
||||||
|
-- Set the Z80 data bus value and initiate a Write Cycle.
|
||||||
|
FSM_STATE <= WriteCycle;
|
||||||
|
|
||||||
|
when X"20" | X"21" | X"22" | X"23" | X"24" | X"25" | X"26" | X"27" =>
|
||||||
|
-- Initiate a Read Cycle.
|
||||||
|
FSM_STATE <= ReadCycle;
|
||||||
|
|
||||||
|
when X"28" | X"29" | X"2A" | X"2B" | X"2C" | X"2D" | X"2E" | X"2F" =>
|
||||||
|
-- Set the Z80 data bus value and initiate an IO Write Cycle.
|
||||||
|
-- The SOM should set 15:8 to the B register value.
|
||||||
|
FSM_STATE <= WriteIOCycle;
|
||||||
|
|
||||||
|
when X"30" | X"31" | X"32" | X"33" | X"34" | X"35" | X"36" | X"37" =>
|
||||||
|
-- Initiate a Read IO Cycle.
|
||||||
|
FSM_STATE <= ReadIOCycle;
|
||||||
|
|
||||||
|
when X"50" =>
|
||||||
|
-- Register a Halt state.
|
||||||
|
FSM_STATE <= HaltCycle;
|
||||||
|
|
||||||
|
when X"51" =>
|
||||||
|
-- Initiate a refresh cycle.
|
||||||
|
FSM_STATE <= RefreshCycle_3;
|
||||||
|
|
||||||
|
when X"E0" =>
|
||||||
|
-- Initiate a Halt Cycle.
|
||||||
|
FSM_STATE <= HaltCycle;
|
||||||
|
|
||||||
|
-- Set the Refresh Address register.
|
||||||
|
when X"E1" =>
|
||||||
|
REFRESH_ADDR <= CPU_DATA_OUT;
|
||||||
|
|
||||||
|
-- Set the Interrupt Page Address Register.
|
||||||
|
when X"E2" =>
|
||||||
|
IPAR <= CPU_DATA_OUT;
|
||||||
|
|
||||||
|
when others =>
|
||||||
|
end case;
|
||||||
|
|
||||||
|
-- Toggle the processing flag to negate the new data flag. Used to indicate device is busy.
|
||||||
|
if(SPI_NEW_DATA /= SPI_PROCESSING) then
|
||||||
|
SPI_PROCESSING <= not SPI_PROCESSING;
|
||||||
|
end if;
|
||||||
|
|
||||||
|
-- FSM Status bit. When processing a command it is set, cleared when idle. Used by SOM to determine command completion.
|
||||||
|
FSM_STATUS <= '1';
|
||||||
|
end if;
|
||||||
|
|
||||||
|
-- Refresh status bit. Indicates a Refresh cycle is under way.
|
||||||
|
if FSM_STATE = RefreshCycle or FSM_STATE = RefreshCycle_11 or FSM_STATE = RefreshCycle_20 or FSM_STATE = RefreshCycle_21 or FSM_STATE = RefreshCycle_3 then
|
||||||
|
RFSH_STATUS <= '1';
|
||||||
|
else
|
||||||
|
RFSH_STATUS <= '0';
|
||||||
|
end if;
|
||||||
|
|
||||||
|
-- If we are in a WAIT sampling 1/2 cycle and wait goes active, set the state so we repeat the full clock cycle by winding back 2 places.
|
||||||
|
if(FSM_CHECK_WAIT = '1' and Z80_WAITn = '0' and Z80_CLK_TGL = '0') then
|
||||||
|
FSM_WAIT_ACTIVE <= '1';
|
||||||
|
end if;
|
||||||
|
|
||||||
|
-- On each Z80 edge we advance the FSM to recreate the Z80 external signal transactions.
|
||||||
|
if(Z80_CLK_TGL = '1') then
|
||||||
|
|
||||||
|
-- The FSM advances to the next stage on each Z80 edge unless in Idle state.
|
||||||
|
if(FSM_STATE /= IdleCycle) then
|
||||||
|
FSM_STATE <= SOMFSMState'val(SOMFSMState'POS(FSM_STATE)+1);
|
||||||
|
end if;
|
||||||
|
|
||||||
|
-- Half cycle expired so we dont check the Z80 wait again.
|
||||||
|
FSM_CHECK_WAIT <= '0';
|
||||||
|
FSM_WAIT_ACTIVE <= '0';
|
||||||
|
|
||||||
|
-- FSM to implement all the required Z80 cycles.
|
||||||
|
--
|
||||||
|
case FSM_STATE is
|
||||||
|
|
||||||
|
when IdleCycle =>
|
||||||
|
CPU_LAST_T_STATE <= '1';
|
||||||
|
-- FSM_STATE <= IdleCycle;
|
||||||
|
|
||||||
|
-----------------------------
|
||||||
|
-- Z80 Fetch Cycle.
|
||||||
|
-----------------------------
|
||||||
|
when FetchCycle =>
|
||||||
|
Z80_M1ni <= '0';
|
||||||
|
|
||||||
|
when FetchCycle_11 =>
|
||||||
|
Z80_M1ni <= '0';
|
||||||
|
Z80_MREQni <= '0';
|
||||||
|
Z80_RDni <= '0';
|
||||||
|
|
||||||
|
when FetchCycle_20 =>
|
||||||
|
FSM_CHECK_WAIT <= '1';
|
||||||
|
|
||||||
|
when FetchCycle_21 =>
|
||||||
|
if(Z80_WAITn = '0' or FSM_WAIT_ACTIVE = '1') then
|
||||||
|
FSM_STATE <= FetchCycle_20;
|
||||||
|
end if;
|
||||||
|
|
||||||
|
when FetchCycle_30 =>
|
||||||
|
-- To meet the timing diagrams, just after Rising edge on T3 clear signals. Data wont be available until
|
||||||
|
-- a short period before the falling edge of T3 (could be an MZ-2000 design restriction or the Z80 timing diagrams are a bit out).
|
||||||
|
FSM_STATE <= RefreshCycle;
|
||||||
|
|
||||||
|
-----------------------------
|
||||||
|
-- Z80 Refresh Cycle.
|
||||||
|
-----------------------------
|
||||||
|
when RefreshCycle =>
|
||||||
|
-- Latch data from mainboard.
|
||||||
|
CPU_DATA_IN <= Z80_DATA;
|
||||||
|
FSM_STATUS <= '0';
|
||||||
|
Z80_RFSHni <= '0';
|
||||||
|
|
||||||
|
when RefreshCycle_11 =>
|
||||||
|
-- Falling edge of T3 activates the MREQ line.
|
||||||
|
Z80_MREQni <= '0';
|
||||||
|
|
||||||
|
when RefreshCycle_20 =>
|
||||||
|
|
||||||
|
when RefreshCycle_21 =>
|
||||||
|
Z80_MREQni <= '1';
|
||||||
|
REFRESH_ADDR(6 downto 0) <= REFRESH_ADDR(6 downto 0) + 1;
|
||||||
|
FSM_STATE <= IdleCycle;
|
||||||
|
|
||||||
|
when RefreshCycle_3 =>
|
||||||
|
Z80_RFSHni <= '0';
|
||||||
|
FSM_STATE <= RefreshCycle_11;
|
||||||
|
|
||||||
|
-----------------------------
|
||||||
|
-- Z80 Write Cycle.
|
||||||
|
-----------------------------
|
||||||
|
when WriteCycle =>
|
||||||
|
|
||||||
|
when WriteCycle_11 =>
|
||||||
|
Z80_MREQni <= '0';
|
||||||
|
CPU_DATA_EN <= '1';
|
||||||
|
|
||||||
|
when WriteCycle_20 =>
|
||||||
|
FSM_CHECK_WAIT <= '1';
|
||||||
|
|
||||||
|
when WriteCycle_21 =>
|
||||||
|
Z80_WRni <= '0';
|
||||||
|
if(Z80_WAITn = '0' or FSM_WAIT_ACTIVE = '1') then
|
||||||
|
FSM_STATE <= WriteCycle_20;
|
||||||
|
end if;
|
||||||
|
|
||||||
|
when WriteCycle_30 =>
|
||||||
|
|
||||||
|
when WriteCycle_31 =>
|
||||||
|
FSM_STATUS <= '0';
|
||||||
|
Z80_MREQni <= '1';
|
||||||
|
Z80_WRni <= '1';
|
||||||
|
FSM_STATE <= IdleCycle;
|
||||||
|
|
||||||
|
-----------------------------
|
||||||
|
-- Z80 Read Cycle.
|
||||||
|
-----------------------------
|
||||||
|
when ReadCycle =>
|
||||||
|
|
||||||
|
when ReadCycle_11 =>
|
||||||
|
Z80_MREQni <= '0';
|
||||||
|
Z80_RDni <= '0';
|
||||||
|
|
||||||
|
when ReadCycle_20 =>
|
||||||
|
FSM_CHECK_WAIT <= '1';
|
||||||
|
|
||||||
|
when ReadCycle_21 =>
|
||||||
|
if(Z80_WAITn = '0' or FSM_WAIT_ACTIVE = '1') then
|
||||||
|
FSM_STATE <= ReadCycle_20;
|
||||||
|
end if;
|
||||||
|
|
||||||
|
when ReadCycle_30 =>
|
||||||
|
|
||||||
|
when ReadCycle_31 =>
|
||||||
|
-- Latch data from mainboard.
|
||||||
|
CPU_DATA_IN <= Z80_DATA;
|
||||||
|
FSM_STATUS <= '0';
|
||||||
|
FSM_STATE <= IdleCycle;
|
||||||
|
|
||||||
|
|
||||||
|
-----------------------------
|
||||||
|
-- Z80 IO Write Cycle.
|
||||||
|
-----------------------------
|
||||||
|
when WriteIOCycle =>
|
||||||
|
|
||||||
|
when WriteIOCycle_11 =>
|
||||||
|
CPU_DATA_EN <= '1';
|
||||||
|
|
||||||
|
when WriteIOCycle_20 =>
|
||||||
|
Z80_IORQni <= '0';
|
||||||
|
Z80_WRni <= '0';
|
||||||
|
|
||||||
|
when WriteIOCycle_21 =>
|
||||||
|
|
||||||
|
when WriteIOCycle_30 =>
|
||||||
|
FSM_CHECK_WAIT <= '1';
|
||||||
|
|
||||||
|
when WriteIOCycle_31 =>
|
||||||
|
if(Z80_WAITn = '0' or FSM_WAIT_ACTIVE = '1') then
|
||||||
|
FSM_STATE <= WriteIOCycle_20;
|
||||||
|
end if;
|
||||||
|
|
||||||
|
when WriteIOCycle_40 =>
|
||||||
|
|
||||||
|
when WriteIOCycle_41 =>
|
||||||
|
FSM_STATUS <= '0';
|
||||||
|
Z80_IORQni <= '1';
|
||||||
|
Z80_WRni <= '1';
|
||||||
|
FSM_STATE <= IdleCycle;
|
||||||
|
|
||||||
|
-----------------------------
|
||||||
|
-- Z80 IO Read Cycle.
|
||||||
|
-----------------------------
|
||||||
|
when ReadIOCycle =>
|
||||||
|
|
||||||
|
when ReadIOCycle_11 =>
|
||||||
|
|
||||||
|
when ReadIOCycle_20 =>
|
||||||
|
Z80_IORQni <= '0';
|
||||||
|
Z80_RDni <= '0';
|
||||||
|
|
||||||
|
when ReadIOCycle_21 =>
|
||||||
|
|
||||||
|
when ReadIOCycle_30 =>
|
||||||
|
FSM_CHECK_WAIT <= '1';
|
||||||
|
|
||||||
|
when ReadIOCycle_31 =>
|
||||||
|
if(Z80_WAITn = '0' or FSM_WAIT_ACTIVE = '1') then
|
||||||
|
FSM_STATE <= ReadIOCycle_20;
|
||||||
|
end if;
|
||||||
|
|
||||||
|
when ReadIOCycle_40 =>
|
||||||
|
|
||||||
|
when ReadIOCycle_41 =>
|
||||||
|
-- Latch data from mainboard.
|
||||||
|
CPU_DATA_IN <= Z80_DATA;
|
||||||
|
FSM_STATUS <= '0';
|
||||||
|
|
||||||
|
-- IORQ/RD are deactivated at idle giving 1 clock to latch the data in.
|
||||||
|
FSM_STATE <= IdleCycle;
|
||||||
|
|
||||||
|
-----------------------------
|
||||||
|
-- Halt Request.
|
||||||
|
-----------------------------
|
||||||
|
when HaltCycle =>
|
||||||
|
Z80_HALTni <= '0';
|
||||||
|
FSM_STATUS <= '0';
|
||||||
|
FSM_STATE <= IdleCycle;
|
||||||
|
|
||||||
|
-----------------------------
|
||||||
|
-- Z80 Bus Request.
|
||||||
|
-----------------------------
|
||||||
|
when BusReqCycle =>
|
||||||
|
Z80_BUSRQ_ACKni <= '0';
|
||||||
|
FSM_STATE <= IdleCycle;
|
||||||
|
|
||||||
|
when others =>
|
||||||
|
FSM_STATE <= IdleCycle;
|
||||||
|
end case;
|
||||||
|
end if;
|
||||||
|
|
||||||
|
VCPU_CS_EDGE <= VCPU_CS_EDGE(0) & VSOM_SPI_CSn;
|
||||||
|
end if;
|
||||||
|
end process;
|
||||||
|
|
||||||
|
Z80_CLKi <= not Z80_CLK;
|
||||||
|
|
||||||
|
-- CPU Interface tri-state control based on acknowledged bus request.
|
||||||
|
Z80_ADDR <= IPAR & REFRESH_ADDR when Z80_RFSHni = '0'
|
||||||
|
else
|
||||||
|
CPU_ADDR when Z80_BUSRQ_ACKni = '1'
|
||||||
|
else
|
||||||
|
(others => 'Z');
|
||||||
|
Z80_DATA <= CPU_DATA_OUT when Z80_BUSRQ_ACKni = '1' and CPU_DATA_EN = '1'
|
||||||
|
else
|
||||||
|
(others => 'Z');
|
||||||
|
-- Z80_DATAi <= Z80_DATA when Z80_RDn = '0'
|
||||||
|
-- else (others => '1');
|
||||||
|
Z80_RDn <= Z80_RDni when Z80_BUSRQ_ACKni = '1'
|
||||||
|
else 'Z';
|
||||||
|
Z80_WRn <= Z80_WRni when Z80_BUSRQ_ACKni = '1'
|
||||||
|
else 'Z';
|
||||||
|
Z80_M1n <= Z80_M1ni when Z80_BUSRQ_ACKni = '1'
|
||||||
|
else 'Z';
|
||||||
|
Z80_RFSHn <= Z80_RFSHni when Z80_BUSRQ_ACKni = '1'
|
||||||
|
else 'Z';
|
||||||
|
Z80_MREQn <= Z80_MREQni when Z80_BUSRQ_ACKni = '1'
|
||||||
|
else 'Z';
|
||||||
|
Z80_IORQn <= Z80_IORQni when Z80_BUSRQ_ACKni = '1'
|
||||||
|
else 'Z';
|
||||||
|
Z80_BUSAKn <= Z80_BUSRQ_ACKni;
|
||||||
|
|
||||||
|
-- CPU Interface single state output.
|
||||||
|
Z80_HALTn <= Z80_HALTni;
|
||||||
|
|
||||||
|
-- CPU Interface single state input.
|
||||||
|
Z80_NMIni <= Z80_NMIn;
|
||||||
|
Z80_INTni <= Z80_INTn;
|
||||||
|
Z80_BUSRQni <= Z80_BUSRQn;
|
||||||
|
|
||||||
|
-- SOM Reset.
|
||||||
|
PM_RESET <= PM_RESETi;
|
||||||
|
|
||||||
|
-- SOM to CPLD Interface.
|
||||||
|
VSOM_DATA_OUT <= CPU_DATA_IN when VSOM_HBYTE = '1'
|
||||||
|
else
|
||||||
|
FSM_STATUS & RFSH_STATUS & Z80_BUSRQ_ACKni & Z80_BUSRQni & Z80_INTni & Z80_NMIni & Z80_WAITn & Z80_RESETn when VSOM_HBYTE = '0'
|
||||||
|
else
|
||||||
|
(others => '0');
|
||||||
|
|
||||||
|
-- Loopback test, echo what was received.
|
||||||
|
SPI_TX_DATA <= SPI_RX_DATA when SPI_LOOPBACK_TEST = '1'
|
||||||
|
else
|
||||||
|
--CPU_ADDR & SOM_CMD & FSM_STATUS & RFSH_STATUS & std_logic_vector(to_unsigned(SOMFSMState'POS(FSM_STATE), 6));
|
||||||
|
CPU_ADDR & CPU_DATA_IN & FSM_STATUS & RFSH_STATUS & Z80_BUSRQ_ACKni & Z80_BUSRQni & Z80_INTni & Z80_NMIni & Z80_WAITn & Z80_RESETn;
|
||||||
|
|
||||||
|
-- Signal mirrors.
|
||||||
|
VSOM_READY <= '0' when FSM_STATUS='1' or SPI_NEW_DATA /= SPI_PROCESSING
|
||||||
|
else '1'; -- FSM Ready (1), Busy (0)
|
||||||
|
VSOM_LTSTATE <= '1' when CPU_LAST_T_STATE = '1' -- Last T-State in current cycle.
|
||||||
|
else '0';
|
||||||
|
VSOM_BUSRQ <= not Z80_BUSRQn; -- Host device requesting Z80 Bus.
|
||||||
|
VSOM_BUSACK <= not Z80_BUSRQ_ACKni; -- Host device granted Z80 Bus
|
||||||
|
VSOM_INT <= not Z80_INTn; -- Z80 INT signal
|
||||||
|
VSOM_NMI <= not Z80_NMIn; -- Z80 NMI signal
|
||||||
|
VSOM_WAIT <= not Z80_WAITn; -- Z80 WAIT signal
|
||||||
|
VSOM_RESET <= not VSOM_RESETni; -- Z80 RESET signal
|
||||||
|
VSOM_RSV <= (others => '0'); -- Reserved pins.
|
||||||
|
|
||||||
|
-- Video/Audio control signals.
|
||||||
|
VIDEO_SRC <= VIDEO_SRCi;
|
||||||
|
MONO_VIDEO_SRC <= MONO_VIDEO_SRCi;
|
||||||
|
AUDIO_SRC_L <= AUDIO_SRC_Li;
|
||||||
|
AUDIO_SRC_R <= AUDIO_SRC_Ri;
|
||||||
|
|
||||||
|
-- USB Power Supply enable.
|
||||||
|
VBUS_EN <= VBUS_ENi;
|
||||||
|
|
||||||
|
-- Monochrome output is based on the incoming VGA to give the best chrominance levels.
|
||||||
|
MONO_R <= VGA_R;
|
||||||
|
MONO_G <= VGA_G;
|
||||||
|
MONO_B <= VGA_B;
|
||||||
|
|
||||||
|
-- Blanking is active when all colour signals are at 0. The DAC converts values in range 4v .. 5v to adjust chrominance
|
||||||
|
-- but true off can obly be achieved by bringing the signal value to 0v which is achieved by a Mux activated with this blanking signal.
|
||||||
|
MONO_BLANKn <= '0' when VGA_R = "000" and VGA_G = "000" and VGA_B = "000"
|
||||||
|
else '1';
|
||||||
|
|
||||||
|
-- Generate composite sync.
|
||||||
|
VGA_CSYNCn <= VGA_HSYNCn xor not VGA_VSYNCn;
|
||||||
|
MONO_CSYNCn <= not VGA_HSYNCn xor not VGA_VSYNCn;
|
||||||
|
|
||||||
|
-- DAC clocks.
|
||||||
|
--VGA_PXL_CLK <= CLK_50M;
|
||||||
|
MONO_PXL_CLK <= VGA_PXL_CLK;
|
||||||
|
|
||||||
|
end architecture;
|
||||||
222
CPLD/v1.0/MZ2000/tzpuFusionX_Toplevel.vhd
Normal file
@@ -0,0 +1,222 @@
|
|||||||
|
---------------------------------------------------------------------------------------------------------
|
||||||
|
--
|
||||||
|
-- Name: tzpuFusionX_Toplevel.vhd
|
||||||
|
-- Version: MZ-2000
|
||||||
|
-- Created: June 2020
|
||||||
|
-- Author(s): Philip Smart
|
||||||
|
-- Description: tzpuFusionX CPLD Top Level module.
|
||||||
|
--
|
||||||
|
-- This module contains the basic pin definition of the CPLD<->logic needed in the
|
||||||
|
-- project which targets the MZ-2000 host.
|
||||||
|
--
|
||||||
|
-- Credits:
|
||||||
|
-- Copyright: (c) 2018-22 Philip Smart <philip.smart@net2net.org>
|
||||||
|
--
|
||||||
|
-- History: June 2020 - Snapshot taken from the MZ80A version of the tranZPUter SW-700 source.
|
||||||
|
--
|
||||||
|
---------------------------------------------------------------------------------------------------------
|
||||||
|
-- This source file is free software: you can redistribute it and-or modify
|
||||||
|
-- it under the terms of the GNU General Public License as published
|
||||||
|
-- by the Free Software Foundation, either version 3 of the License, or
|
||||||
|
-- (at your option) any later version.
|
||||||
|
--
|
||||||
|
-- This source file is distributed in the hope that it will be useful,
|
||||||
|
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
-- GNU General Public License for more details.
|
||||||
|
--
|
||||||
|
-- along with this program. If not, see <http:--www.gnu.org-licenses->.
|
||||||
|
---------------------------------------------------------------------------------------------------------
|
||||||
|
library IEEE;
|
||||||
|
use IEEE.std_logic_1164.all;
|
||||||
|
use IEEE.numeric_std.all;
|
||||||
|
use work.tzpuFusionX_pkg.all;
|
||||||
|
library altera;
|
||||||
|
use altera.altera_syn_attributes.all;
|
||||||
|
|
||||||
|
entity tzpuFusionX_MZ2000 is
|
||||||
|
port (
|
||||||
|
-- Z80 Address Bus
|
||||||
|
Z80_ADDR : inout std_logic_vector(15 downto 0);
|
||||||
|
|
||||||
|
-- Z80 Data Bus
|
||||||
|
Z80_DATA : inout std_logic_vector(7 downto 0);
|
||||||
|
|
||||||
|
-- Z80 Control signals.
|
||||||
|
Z80_BUSRQn : in std_logic;
|
||||||
|
Z80_BUSAKn : out std_logic;
|
||||||
|
Z80_INTn : in std_logic;
|
||||||
|
Z80_IORQn : inout std_logic;
|
||||||
|
Z80_MREQn : inout std_logic;
|
||||||
|
Z80_NMIn : in std_logic;
|
||||||
|
Z80_RDn : inout std_logic;
|
||||||
|
Z80_WRn : inout std_logic;
|
||||||
|
Z80_RESETn : in std_logic; -- Host CPU Reset signal, also CPLD reset.
|
||||||
|
Z80_HALTn : out std_logic;
|
||||||
|
Z80_WAITn : in std_logic;
|
||||||
|
Z80_M1n : inout std_logic;
|
||||||
|
Z80_RFSHn : inout std_logic;
|
||||||
|
|
||||||
|
-- SOM SPI
|
||||||
|
VSOM_SPI_CSn : in std_logic; -- SPI Slave Select
|
||||||
|
VSOM_SPI_CLK : in std_logic; -- SPI Clock
|
||||||
|
VSOM_SPI_MOSI : in std_logic; -- SPI Master Output Slave Input
|
||||||
|
VSOM_SPI_MISO : out std_logic; -- SPI Master Input Slave Output
|
||||||
|
|
||||||
|
-- SOM Parallel Bus.
|
||||||
|
VSOM_DATA_OUT : out std_logic_vector(7 downto 0); -- Address/Data bus for CPLD control registers.
|
||||||
|
VSOM_HBYTE : in std_logic; -- Parallel Bus High (1)/Low (0) byte.
|
||||||
|
VSOM_READY : out std_logic; -- FSM Ready (1), Busy (0)
|
||||||
|
VSOM_LTSTATE : out std_logic; -- Last T-State in current cycle, 1 = active.
|
||||||
|
VSOM_BUSRQ : out std_logic; -- Host device requesting Z80 Bus.
|
||||||
|
VSOM_BUSACK : out std_logic; -- Host device granted Z80 Bus
|
||||||
|
VSOM_INT : out std_logic; -- Z80 INT signal
|
||||||
|
VSOM_NMI : out std_logic; -- Z80 NMI signal
|
||||||
|
VSOM_WAIT : out std_logic; -- Z80 WAIT signal
|
||||||
|
VSOM_RESET : out std_logic; -- Z80 RESET signal
|
||||||
|
VSOM_RSV : out std_logic_vector(1 downto 1); -- Reserved pins.
|
||||||
|
|
||||||
|
-- SOM Control Signals
|
||||||
|
PM_RESET : out std_logic; -- Reset SOM
|
||||||
|
|
||||||
|
-- VGA_Palette Control
|
||||||
|
VGA_R : in std_logic_vector(9 downto 7); -- Signals used for detecting blank or no video output.
|
||||||
|
VGA_G : in std_logic_vector(9 downto 7);
|
||||||
|
VGA_B : in std_logic_vector(9 downto 8);
|
||||||
|
|
||||||
|
-- VGA Control Signals
|
||||||
|
VGA_PXL_CLK : in std_logic; -- VGA Pixel clock for DAC conversion.
|
||||||
|
VGA_DISPEN : in std_logic; -- Displayed Enabled (SOM video output).
|
||||||
|
VGA_VSYNCn : in std_logic; -- SOM VSync.
|
||||||
|
VGA_HSYNCn : in std_logic; -- SOM HSync.
|
||||||
|
VGA_COLR : out std_logic; -- COLR colour carrier frequency.
|
||||||
|
VGA_CSYNCn : out std_logic; -- VGA Composite Sync.
|
||||||
|
VGA_BLANKn : out std_logic; -- VGA Blank detected.
|
||||||
|
|
||||||
|
-- CRT Control Signals
|
||||||
|
MONO_PXL_CLK : out std_logic; -- Mono CRT pixel clock for DAC conversion.
|
||||||
|
MONO_BLANKn : out std_logic; -- Mono CRT Blank (no active pixel) detection.
|
||||||
|
MONO_CSYNCn : out std_logic; -- Mono CRT composite sync.
|
||||||
|
MONO_RSV : out std_logic;
|
||||||
|
|
||||||
|
-- CRT Lower Chrominance Control
|
||||||
|
MONO_R : out std_logic_vector(2 downto 0); -- Signals to fine tune Red level of monochrome chrominance.
|
||||||
|
MONO_G : out std_logic_vector(2 downto 0); -- Signals to fine tune Green level of monochrome chrominance.
|
||||||
|
MONO_B : out std_logic_vector(2 downto 1); -- Signals to fine tune Blue level of monochrome chrominance.
|
||||||
|
|
||||||
|
-- MUX Control Signals
|
||||||
|
VIDEO_SRC : out std_logic; -- Select video source, Mainboard or SOM.
|
||||||
|
MONO_VIDEO_SRC : out std_logic; -- Select crt video source, Mainboard or SOM.
|
||||||
|
AUDIO_SRC_L : out std_logic; -- Select Audio Source Left Channel, Mainboard or SOM.
|
||||||
|
AUDIO_SRC_R : out std_logic; -- Select Audio Source Right Channel, Mainboard or SOM.
|
||||||
|
|
||||||
|
-- Mainboard Reset Signals
|
||||||
|
MB_RESETn : in std_logic; -- Motherboard Reset pressed.
|
||||||
|
MB_IPLn : in std_logic; -- Motherboard IPL pressed.
|
||||||
|
|
||||||
|
-- USB Power Control
|
||||||
|
VBUS_EN : out std_logic; -- USB Enable Power Output
|
||||||
|
|
||||||
|
-- Clocks.
|
||||||
|
Z80_CLK : in std_logic; -- Host CPU Clock
|
||||||
|
CLK_50M : in std_logic -- 50MHz oscillator.
|
||||||
|
);
|
||||||
|
END entity;
|
||||||
|
|
||||||
|
architecture rtl of tzpuFusionX_MZ2000 is
|
||||||
|
|
||||||
|
begin
|
||||||
|
|
||||||
|
cpldl512Toplevel : entity work.cpld512
|
||||||
|
generic map (
|
||||||
|
SPI_CLK_POLARITY => '0'
|
||||||
|
)
|
||||||
|
port map
|
||||||
|
(
|
||||||
|
-- Z80 Address Bus
|
||||||
|
Z80_ADDR => Z80_ADDR,
|
||||||
|
|
||||||
|
-- Z80 Data Bus
|
||||||
|
Z80_DATA => Z80_DATA,
|
||||||
|
|
||||||
|
-- Z80 Control signals.
|
||||||
|
Z80_BUSRQn => Z80_BUSRQn,
|
||||||
|
Z80_BUSAKn => Z80_BUSAKn,
|
||||||
|
Z80_INTn => Z80_INTn,
|
||||||
|
Z80_IORQn => Z80_IORQn,
|
||||||
|
Z80_MREQn => Z80_MREQn,
|
||||||
|
Z80_NMIn => Z80_NMIn,
|
||||||
|
Z80_RDn => Z80_RDn,
|
||||||
|
Z80_WRn => Z80_WRn,
|
||||||
|
Z80_RESETn => Z80_RESETn,
|
||||||
|
Z80_HALTn => Z80_HALTn,
|
||||||
|
Z80_WAITn => Z80_WAITn,
|
||||||
|
Z80_M1n => Z80_M1n,
|
||||||
|
Z80_RFSHn => Z80_RFSHn,
|
||||||
|
|
||||||
|
-- SOM SPI
|
||||||
|
VSOM_SPI_CSn => VSOM_SPI_CSn, -- SPI Slave Select
|
||||||
|
VSOM_SPI_CLK => VSOM_SPI_CLK, -- SPI Clock
|
||||||
|
VSOM_SPI_MOSI => VSOM_SPI_MOSI, -- SPI Master Output Slave Input
|
||||||
|
VSOM_SPI_MISO => VSOM_SPI_MISO, -- SPI Master Input Slave Output
|
||||||
|
|
||||||
|
-- SOM Parallel Bus.
|
||||||
|
VSOM_DATA_OUT => VSOM_DATA_OUT, -- Address/Data bus for CPLD control registers.
|
||||||
|
VSOM_HBYTE => VSOM_HBYTE, -- Parallel Bus High (1)/Low (0) byte.
|
||||||
|
VSOM_READY => VSOM_READY, -- FSM Ready (1), Busy (0)
|
||||||
|
VSOM_LTSTATE => VSOM_LTSTATE, -- Last T-State in current cycle.
|
||||||
|
VSOM_BUSRQ => VSOM_BUSRQ, -- Host device requesting Z80 Bus.
|
||||||
|
VSOM_BUSACK => VSOM_BUSACK, -- Host device granted Z80 Bus
|
||||||
|
VSOM_INT => VSOM_INT, -- Z80 INT signal
|
||||||
|
VSOM_NMI => VSOM_NMI, -- Z80 NMI signal
|
||||||
|
VSOM_WAIT => VSOM_WAIT, -- Z80 WAIT signal
|
||||||
|
VSOM_RESET => VSOM_RESET, -- Z80 RESET signal
|
||||||
|
VSOM_RSV => VSOM_RSV, -- Reserved pins.
|
||||||
|
|
||||||
|
-- SOM Control Signals
|
||||||
|
PM_RESET => PM_RESET, -- Reset SOM
|
||||||
|
|
||||||
|
-- VGA_Palette Control
|
||||||
|
VGA_R => VGA_R, -- Signals used for detecting blank or no video output.
|
||||||
|
VGA_G => VGA_G,
|
||||||
|
VGA_B => VGA_B,
|
||||||
|
|
||||||
|
-- VGA Control Signals
|
||||||
|
VGA_PXL_CLK => VGA_PXL_CLK, -- VGA Pixel clock for DAC conversion.
|
||||||
|
VGA_DISPEN => VGA_DISPEN, -- Displayed Enabled (SOM video output).
|
||||||
|
VGA_VSYNCn => VGA_VSYNCn, -- SOM VSync.
|
||||||
|
VGA_HSYNCn => VGA_HSYNCn, -- SOM HSync.
|
||||||
|
VGA_COLR => VGA_COLR, -- COLR colour carrier frequency.
|
||||||
|
VGA_CSYNCn => VGA_CSYNCn, -- VGA Composite Sync.
|
||||||
|
VGA_BLANKn => VGA_BLANKn, -- VGA Blank detected.
|
||||||
|
|
||||||
|
-- CRT Control Signals
|
||||||
|
MONO_PXL_CLK => MONO_PXL_CLK, -- Mono CRT pixel clock for DAC conversion.
|
||||||
|
MONO_BLANKn => MONO_BLANKn, -- Mono CRT Blank (no active pixel) detection.
|
||||||
|
MONO_CSYNCn => MONO_CSYNCn, -- Mono CRT composite sync.
|
||||||
|
MONO_RSV => MONO_RSV,
|
||||||
|
|
||||||
|
-- CRT Lower Chrominance Control
|
||||||
|
MONO_R => MONO_R, -- Signals to fine tune Red level of monochrome chrominance.
|
||||||
|
MONO_G => MONO_G, -- Signals to fine tune Green level of monochrome chrominance.
|
||||||
|
MONO_B => MONO_B, -- Signals to fine tune Blue level of monochrome chrominance.
|
||||||
|
|
||||||
|
-- MUX Control Signals
|
||||||
|
VIDEO_SRC => VIDEO_SRC, -- Select video source, Mainboard or SOM.
|
||||||
|
MONO_VIDEO_SRC => MONO_VIDEO_SRC, -- Select crt video source, Mainboard or SOM.
|
||||||
|
AUDIO_SRC_L => AUDIO_SRC_L, -- Select Audio Source Left Channel, Mainboard or SOM.
|
||||||
|
AUDIO_SRC_R => AUDIO_SRC_R, -- Select Audio Source Right Channel, Mainboard or SOM.
|
||||||
|
|
||||||
|
-- Mainboard Reset Signals=> MONO_R,
|
||||||
|
MB_RESETn => MB_RESETn, -- Motherboard Reset pressed.
|
||||||
|
MB_IPLn => MB_IPLn, -- Motherboard IPL pressed.
|
||||||
|
|
||||||
|
-- USB Power Control
|
||||||
|
VBUS_EN => VBUS_EN, -- USB Enable Power Output
|
||||||
|
|
||||||
|
-- Clocks.
|
||||||
|
Z80_CLK => Z80_CLK, -- Host CPU Clock
|
||||||
|
CLK_50M => CLK_50M -- 50MHz oscillator.
|
||||||
|
);
|
||||||
|
|
||||||
|
end architecture;
|
||||||
221
CPLD/v1.0/MZ2000/tzpuFusionX_pkg.vhd
Normal file
@@ -0,0 +1,221 @@
|
|||||||
|
---------------------------------------------------------------------------------------------------------
|
||||||
|
--
|
||||||
|
-- Name: tzpuFusionX_pkg.vhd
|
||||||
|
-- Created: June 2020
|
||||||
|
-- Author(s): Philip Smart
|
||||||
|
-- Description: tzpuFusionX CPLD configuration file.
|
||||||
|
--
|
||||||
|
-- This module contains parameters for the CPLD in the tzpuFusionX project
|
||||||
|
-- which targets the MZ-2000 host.
|
||||||
|
--
|
||||||
|
-- Credits:
|
||||||
|
-- Copyright: (c) 2018-22 Philip Smart <philip.smart@net2net.org>
|
||||||
|
--
|
||||||
|
-- History: June 2020 - Snapshot taken from the MZ2000 version of the tranZPUter SW-700 source.
|
||||||
|
--
|
||||||
|
---------------------------------------------------------------------------------------------------------
|
||||||
|
-- This source file is free software: you can redistribute it and-or modify
|
||||||
|
-- it under the terms of the GNU General Public License as published
|
||||||
|
-- by the Free Software Foundation, either version 3 of the License, or
|
||||||
|
-- (at your option) any later version.
|
||||||
|
--
|
||||||
|
-- This source file is distributed in the hope that it will be useful,
|
||||||
|
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
-- GNU General Public License for more details.
|
||||||
|
--
|
||||||
|
-- You should have received a copy of the GNU General Public License
|
||||||
|
-- along with this program. If not, see <http:--www.gnu.org-licenses->.
|
||||||
|
---------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
library ieee;
|
||||||
|
library pkgs;
|
||||||
|
use ieee.std_logic_1164.all;
|
||||||
|
use ieee.numeric_std.all;
|
||||||
|
use ieee.math_real.all;
|
||||||
|
|
||||||
|
package tzpuFusionX_pkg is
|
||||||
|
|
||||||
|
------------------------------------------------------------
|
||||||
|
-- Constants
|
||||||
|
------------------------------------------------------------
|
||||||
|
|
||||||
|
-- Potential logic state constants.
|
||||||
|
constant YES : std_logic := '1';
|
||||||
|
constant NO : std_logic := '0';
|
||||||
|
constant HI : std_logic := '1';
|
||||||
|
constant LO : std_logic := '0';
|
||||||
|
constant ONE : std_logic := '1';
|
||||||
|
constant ZERO : std_logic := '0';
|
||||||
|
constant HIZ : std_logic := 'Z';
|
||||||
|
|
||||||
|
-- CPLD Command instructions.
|
||||||
|
constant CPLD_CMD_RESET_HOST : integer := 1;
|
||||||
|
constant CPLD_CMD_HOLD_HOST_BUS : integer := 2;
|
||||||
|
constant CPLD_CMD_RELEASE_HOST_BUS: integer := 3;
|
||||||
|
|
||||||
|
-- Target hardware modes.
|
||||||
|
constant MODE_MZ80K : integer := 0;
|
||||||
|
constant MODE_MZ80C : integer := 1;
|
||||||
|
constant MODE_MZ1200 : integer := 2;
|
||||||
|
constant MODE_MZ80A : integer := 3;
|
||||||
|
constant MODE_MZ700 : integer := 4;
|
||||||
|
constant MODE_MZ800 : integer := 5;
|
||||||
|
constant MODE_MZ80B : integer := 6;
|
||||||
|
constant MODE_MZ2000 : integer := 7;
|
||||||
|
|
||||||
|
-- Memory management modes.
|
||||||
|
constant TZMM_ORIG : integer := 00; -- Original Sharp mode, no tranZPUter features are selected except the I/O control registers (default: 0x60-063).
|
||||||
|
constant TZMM_BOOT : integer := 01; -- Original mode but E800-EFFF is mapped to tranZPUter RAM so TZFS can be booted.
|
||||||
|
constant TZMM_TZFS : integer := 02; -- TZFS main memory configuration. all memory is in tranZPUter RAM, E800-FFFF is used by TZFS, SA1510 is at 0000-1000 and RAM is 1000-CFFF, 64K Block 0 selected.
|
||||||
|
constant TZMM_TZFS2 : integer := 03; -- TZFS main memory configuration. all memory is in tranZPUter RAM, E800-EFFF is used by TZFS, SA1510 is at 0000-1000 and RAM is 1000-CFFF, 64K Block 0 selected, F000-FFFF is in 64K Block 1.
|
||||||
|
constant TZMM_TZFS3 : integer := 04; -- TZFS main memory configuration. all memory is in tranZPUter RAM, E800-EFFF is used by TZFS, SA1510 is at 0000-1000 and RAM is 1000-CFFF, 64K Block 0 selected, F000-FFFF is in 64K Block 2.
|
||||||
|
constant TZMM_TZFS4 : integer := 05; -- TZFS main memory configuration. all memory is in tranZPUter RAM, E800-EFFF is used by TZFS, SA1510 is at 0000-1000 and RAM is 1000-CFFF, 64K Block 0 selected, F000-FFFF is in 64K Block 3.
|
||||||
|
constant TZMM_CPM : integer := 06; -- CPM main memory configuration, all memory on the tranZPUter board, 64K block 4 selected. Special case for F3C0:F3FF & F7C0:F7FF (floppy disk paging vectors) which resides on the mainboard.
|
||||||
|
constant TZMM_CPM2 : integer := 07; -- CPM main memory configuration, F000-FFFF are on the tranZPUter board in block 4, 0040-CFFF and E800-EFFF are in block 5, mainboard for D000-DFFF (video), E000-E800 (Memory control) selected.
|
||||||
|
-- Special case for 0000:003F (interrupt vectors) which resides in block 4, F3FE:F3FF & F7FE:F7FF (floppy disk paging vectors) which resides on the mainboard.
|
||||||
|
constant TZMM_COMPAT : integer := 08; -- Compatibility monitor mode, monitor ROM on mainboard, RAM on tranZPUter in Block 0 1000-CFFF.
|
||||||
|
constant TZMM_HOSTACCESS : integer := 09; -- Monitor ROM 0000-0FFF and Main DRAM 0x1000-0xD000, video and memory mapped I/O are on the host machine, User/Floppy ROM E800-FFFF are in tranZPUter memory.
|
||||||
|
constant TZMM_MZ700_0 : integer := 10; -- MZ700 Mode - 0000:0FFF is on the tranZPUter board in block 6, 1000:CFFF is on the tranZPUter board in block 0, D000:FFFF is on the mainboard.
|
||||||
|
constant TZMM_MZ700_1 : integer := 11; -- MZ700 Mode - 0000:0FFF is on the tranZPUter board in block 0, 1000:CFFF is on the tranZPUter board in block 0, D000:FFFF is on the tranZPUter in block 6.
|
||||||
|
constant TZMM_MZ700_2 : integer := 12; -- MZ700 Mode - 0000:0FFF is on the tranZPUter board in block 6, 1000:CFFF is on the tranZPUter board in block 0, D000:FFFF is on the tranZPUter in block 6.
|
||||||
|
constant TZMM_MZ700_3 : integer := 13; -- MZ700 Mode - 0000:0FFF is on the tranZPUter board in block 0, 1000:CFFF is on the tranZPUter board in block 0, D000:FFFF is inaccessible.
|
||||||
|
constant TZMM_MZ700_4 : integer := 14; -- MZ700 Mode - 0000:0FFF is on the tranZPUter board in block 6, 1000:CFFF is on the tranZPUter board in block 0, D000:FFFF is inaccessible.
|
||||||
|
constant TZMM_MZ800 : integer := 15; -- MZ800 Mode - Running on MZ800 hardware, configuration set according to MZ700/MZ800 mode.
|
||||||
|
constant TZMM_MZ2000 : integer := 16; -- MZ2000 Mode - Running on MZ2000 hardware, configuration set according to runtime configuration registers.
|
||||||
|
constant TZMM_FPGA : integer := 21; -- Open up access for the K64F to the FPGA resources such as memory. All other access to RAM or mainboard is blocked.
|
||||||
|
constant TZMM_TZPUM : integer := 22; -- Everything in on mainboard, no access to tranZPUter memory.
|
||||||
|
constant TZMM_TZPU : integer := 23; -- Everything is in tranZPUter domain, no access to underlying Sharp mainboard unless memory management mode is switched. tranZPUter RAM 64K block 0 is selected.
|
||||||
|
constant TZMM_TZPU0 : integer := 24; -- Everything is in tranZPUter domain, no access to underlying Sharp mainboard unless memory management mode is switched. tranZPUter RAM 64K block 0 is selected.
|
||||||
|
constant TZMM_TZPU1 : integer := 25; -- Everything is in tranZPUter domain, no access to underlying Sharp mainboard unless memory management mode is switched. tranZPUter RAM 64K block 1 is selected.
|
||||||
|
constant TZMM_TZPU2 : integer := 26; -- Everything is in tranZPUter domain, no access to underlying Sharp mainboard unless memory management mode is switched. tranZPUter RAM 64K block 2 is selected.
|
||||||
|
constant TZMM_TZPU3 : integer := 27; -- Everything is in tranZPUter domain, no access to underlying Sharp mainboard unless memory management mode is switched. tranZPUter RAM 64K block 3 is selected.
|
||||||
|
constant TZMM_TZPU4 : integer := 28; -- Everything is in tranZPUter domain, no access to underlying Sharp mainboard unless memory management mode is switched. tranZPUter RAM 64K block 4 is selected.
|
||||||
|
constant TZMM_TZPU5 : integer := 29; -- Everything is in tranZPUter domain, no access to underlying Sharp mainboard unless memory management mode is switched. tranZPUter RAM 64K block 5 is selected.
|
||||||
|
constant TZMM_TZPU6 : integer := 30; -- Everything is in tranZPUter domain, no access to underlying Sharp mainboard unless memory management mode is switched. tranZPUter RAM 64K block 6 is selected.
|
||||||
|
constant TZMM_TZPU7 : integer := 31; -- Everything is in tranZPUter domain, no access to underlying Sharp mainboard unless memory management mode is switched. tranZPUter RAM 64K block 7 is selected.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
------------------------------------------------------------
|
||||||
|
-- Configurable parameters.
|
||||||
|
------------------------------------------------------------
|
||||||
|
-- Target hardware.
|
||||||
|
constant CPLD_HOST_HW : integer := MODE_MZ700;
|
||||||
|
|
||||||
|
-- Target video hardware.
|
||||||
|
constant CPLD_HAS_FPGA_VIDEO : std_logic := '1';
|
||||||
|
|
||||||
|
-- Version of hdl.
|
||||||
|
constant CPLD_VERSION : integer := 2;
|
||||||
|
|
||||||
|
-- Clock source for the secondary clock. If a K64F is installed then enable it otherwise use the onboard oscillator.
|
||||||
|
--
|
||||||
|
constant USE_K64F_CTL_CLOCK : integer := 1;
|
||||||
|
|
||||||
|
------------------------------------------------------------
|
||||||
|
-- Function prototypes
|
||||||
|
------------------------------------------------------------
|
||||||
|
-- Find the maximum of two integers.
|
||||||
|
function IntMax(a : in integer; b : in integer) return integer;
|
||||||
|
|
||||||
|
-- Find the number of bits required to represent an integer.
|
||||||
|
function log2ceil(arg : positive) return natural;
|
||||||
|
|
||||||
|
-- Function to calculate the number of whole 'clock' cycles in a given time period, the period being in ns.
|
||||||
|
function clockTicks(period : in integer; clock : in integer) return integer;
|
||||||
|
|
||||||
|
-- Function to reverse the order of the bits in a standard logic vector.
|
||||||
|
-- ie. 1010 becomes 0101
|
||||||
|
function reverse_vector(slv:std_logic_vector) return std_logic_vector;
|
||||||
|
|
||||||
|
-- Function to convert an integer (0 or 1) into std_logic.
|
||||||
|
--
|
||||||
|
function to_std_logic(i : in integer) return std_logic;
|
||||||
|
|
||||||
|
-- Function to return the value of a bit as an integer for array indexing etc.
|
||||||
|
function bit_to_integer( s : std_logic ) return natural;
|
||||||
|
|
||||||
|
------------------------------------------------------------
|
||||||
|
-- Records
|
||||||
|
------------------------------------------------------------
|
||||||
|
|
||||||
|
------------------------------------------------------------
|
||||||
|
-- Components
|
||||||
|
------------------------------------------------------------
|
||||||
|
|
||||||
|
end tzpuFusionX_pkg;
|
||||||
|
|
||||||
|
------------------------------------------------------------
|
||||||
|
-- Function definitions.
|
||||||
|
------------------------------------------------------------
|
||||||
|
package body tzpuFusionX_pkg is
|
||||||
|
|
||||||
|
-- Find the maximum of two integers.
|
||||||
|
function IntMax(a : in integer; b : in integer) return integer is
|
||||||
|
begin
|
||||||
|
if a > b then
|
||||||
|
return a;
|
||||||
|
else
|
||||||
|
return b;
|
||||||
|
end if;
|
||||||
|
return a;
|
||||||
|
end function IntMax;
|
||||||
|
|
||||||
|
-- Find the number of bits required to represent an integer.
|
||||||
|
function log2ceil(arg : positive) return natural is
|
||||||
|
variable tmp : positive := 1;
|
||||||
|
variable log : natural := 0;
|
||||||
|
begin
|
||||||
|
if arg = 1 then
|
||||||
|
return 0;
|
||||||
|
end if;
|
||||||
|
|
||||||
|
while arg > tmp loop
|
||||||
|
tmp := tmp * 2;
|
||||||
|
log := log + 1;
|
||||||
|
end loop;
|
||||||
|
return log;
|
||||||
|
end function;
|
||||||
|
|
||||||
|
-- Function to calculate the number of whole 'clock' cycles in a given time period, the period being in ns.
|
||||||
|
function clockTicks(period : in integer; clock : in integer) return integer is
|
||||||
|
variable ticks : real;
|
||||||
|
variable fracTicks : real;
|
||||||
|
begin
|
||||||
|
ticks := (Real(period) * Real(clock)) / 1000000000.0;
|
||||||
|
fracTicks := ticks - CEIL(ticks);
|
||||||
|
if fracTicks > 0.0001 then
|
||||||
|
return Integer(CEIL(ticks + 1.0));
|
||||||
|
else
|
||||||
|
return Integer(CEIL(ticks));
|
||||||
|
end if;
|
||||||
|
end function;
|
||||||
|
|
||||||
|
function reverse_vector(slv:std_logic_vector) return std_logic_vector is
|
||||||
|
variable target : std_logic_vector(slv'high downto slv'low);
|
||||||
|
begin
|
||||||
|
for idx in slv'high downto slv'low loop
|
||||||
|
target(idx) := slv(slv'low + (slv'high-idx));
|
||||||
|
end loop;
|
||||||
|
return target;
|
||||||
|
end reverse_vector;
|
||||||
|
|
||||||
|
function to_std_logic(i : in integer) return std_logic is
|
||||||
|
begin
|
||||||
|
if i = 0 then
|
||||||
|
return '0';
|
||||||
|
end if;
|
||||||
|
return '1';
|
||||||
|
end function;
|
||||||
|
|
||||||
|
-- Function to return the value of a bit as an integer for array indexing etc.
|
||||||
|
function bit_to_integer( s : std_logic ) return natural is
|
||||||
|
begin
|
||||||
|
if s = '1' then
|
||||||
|
return 1;
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
end if;
|
||||||
|
end function;
|
||||||
|
end package body;
|
||||||
30
CPLD/v1.0/MZ700/build/tzpuFusionX_MZ700.qpf
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
# -------------------------------------------------------------------------- #
|
||||||
|
#
|
||||||
|
# Copyright (C) 1991-2013 Altera Corporation
|
||||||
|
# Your use of Altera Corporation's design tools, logic functions
|
||||||
|
# and other software and tools, and its AMPP partner logic
|
||||||
|
# functions, and any output files from any of the foregoing
|
||||||
|
# (including device programming or simulation files), and any
|
||||||
|
# associated documentation or information are expressly subject
|
||||||
|
# to the terms and conditions of the Altera Program License
|
||||||
|
# Subscription Agreement, Altera MegaCore Function License
|
||||||
|
# Agreement, or other applicable license agreement, including,
|
||||||
|
# without limitation, that your use is for the sole purpose of
|
||||||
|
# programming logic devices manufactured by Altera and sold by
|
||||||
|
# Altera or its authorized distributors. Please refer to the
|
||||||
|
# applicable agreement for further details.
|
||||||
|
#
|
||||||
|
# -------------------------------------------------------------------------- #
|
||||||
|
#
|
||||||
|
# Quartus II 64-Bit
|
||||||
|
# Version 13.0.1 Build 232 06/12/2013 Service Pack 1 SJ Web Edition
|
||||||
|
# Date created = 14:14:16 November 28, 2022
|
||||||
|
#
|
||||||
|
# -------------------------------------------------------------------------- #
|
||||||
|
|
||||||
|
QUARTUS_VERSION = "13.0"
|
||||||
|
DATE = "14:14:16 November 28, 2022"
|
||||||
|
|
||||||
|
# Revisions
|
||||||
|
|
||||||
|
PROJECT_REVISION = "tzpuFusionX_MZ700"
|
||||||
243
CPLD/v1.0/MZ700/build/tzpuFusionX_MZ700.qsf
Normal file
@@ -0,0 +1,243 @@
|
|||||||
|
# -------------------------------------------------------------------------- #
|
||||||
|
#
|
||||||
|
# Copyright (C) 1991-2013 Altera Corporation
|
||||||
|
# Your use of Altera Corporation's design tools, logic functions
|
||||||
|
# and other software and tools, and its AMPP partner logic
|
||||||
|
# functions, and any output files from any of the foregoing
|
||||||
|
# (including device programming or simulation files), and any
|
||||||
|
# associated documentation or information are expressly subject
|
||||||
|
# to the terms and conditions of the Altera Program License
|
||||||
|
# Subscription Agreement, Altera MegaCore Function License
|
||||||
|
# Agreement, or other applicable license agreement, including,
|
||||||
|
# without limitation, that your use is for the sole purpose of
|
||||||
|
# programming logic devices manufactured by Altera and sold by
|
||||||
|
# Altera or its authorized distributors. Please refer to the
|
||||||
|
# applicable agreement for further details.
|
||||||
|
#
|
||||||
|
# -------------------------------------------------------------------------- #
|
||||||
|
#
|
||||||
|
# Quartus II 64-Bit
|
||||||
|
# Version 13.0.1 Build 232 06/12/2013 Service Pack 1 SJ Web Edition
|
||||||
|
# Date created = 16:29:32 June 24, 2020
|
||||||
|
#
|
||||||
|
# -------------------------------------------------------------------------- #
|
||||||
|
#
|
||||||
|
# Notes:
|
||||||
|
#
|
||||||
|
# 1) The default values for assignments are stored in the file:
|
||||||
|
# tzpuFusionX_MZ700.qdf
|
||||||
|
# If this file doesn't exist, see file:
|
||||||
|
# assignment_defaults.qdf
|
||||||
|
#
|
||||||
|
# 2) Altera recommends that you do not modify this file. This
|
||||||
|
# file is updated automatically by the Quartus II software
|
||||||
|
# and any changes you make may be lost or overwritten.
|
||||||
|
#
|
||||||
|
# -------------------------------------------------------------------------- #
|
||||||
|
|
||||||
|
|
||||||
|
set_global_assignment -name FAMILY MAX7000AE
|
||||||
|
set_global_assignment -name DEVICE "EPM7512AETC144-10"
|
||||||
|
set_global_assignment -name TOP_LEVEL_ENTITY tzpuFusionX_MZ700
|
||||||
|
set_global_assignment -name ORIGINAL_QUARTUS_VERSION "13.0 SP1"
|
||||||
|
set_global_assignment -name PROJECT_CREATION_TIME_DATE "16:29:32 JUNE 24, 2020"
|
||||||
|
set_global_assignment -name LAST_QUARTUS_VERSION "13.0 SP1"
|
||||||
|
set_global_assignment -name PROJECT_OUTPUT_DIRECTORY output_files
|
||||||
|
set_global_assignment -name ERROR_CHECK_FREQUENCY_DIVISOR "-1"
|
||||||
|
set_global_assignment -name EDA_DESIGN_ENTRY_SYNTHESIS_TOOL "<None>"
|
||||||
|
set_global_assignment -name EDA_INPUT_VCC_NAME VCC -section_id eda_design_synthesis
|
||||||
|
set_global_assignment -name EDA_INPUT_DATA_FORMAT EDIF -section_id eda_design_synthesis
|
||||||
|
set_global_assignment -name EDA_SIMULATION_TOOL "ModelSim-Altera (VHDL)"
|
||||||
|
set_global_assignment -name EDA_OUTPUT_DATA_FORMAT VHDL -section_id eda_simulation
|
||||||
|
set_global_assignment -name OPTIMIZE_HOLD_TIMING OFF
|
||||||
|
set_global_assignment -name OPTIMIZE_MULTI_CORNER_TIMING OFF
|
||||||
|
set_global_assignment -name FITTER_EFFORT "STANDARD FIT"
|
||||||
|
set_global_assignment -name MAX7000_DEVICE_IO_STANDARD LVTTL
|
||||||
|
|
||||||
|
# Z80 Data Bus
|
||||||
|
# ============
|
||||||
|
set_location_assignment PIN_88 -to Z80_DATA[0]
|
||||||
|
set_location_assignment PIN_91 -to Z80_DATA[1]
|
||||||
|
set_location_assignment PIN_83 -to Z80_DATA[2]
|
||||||
|
set_location_assignment PIN_79 -to Z80_DATA[3]
|
||||||
|
set_location_assignment PIN_60 -to Z80_DATA[4]
|
||||||
|
set_location_assignment PIN_93 -to Z80_DATA[5]
|
||||||
|
set_location_assignment PIN_80 -to Z80_DATA[6]
|
||||||
|
set_location_assignment PIN_86 -to Z80_DATA[7]
|
||||||
|
|
||||||
|
# Z80 Control signals.
|
||||||
|
# ====================
|
||||||
|
set_location_assignment PIN_92 -to Z80_INTn
|
||||||
|
set_location_assignment PIN_96 -to Z80_NMIn
|
||||||
|
set_location_assignment PIN_97 -to Z80_HALTn
|
||||||
|
set_location_assignment PIN_98 -to Z80_MREQn
|
||||||
|
set_location_assignment PIN_99 -to Z80_IORQn
|
||||||
|
set_location_assignment PIN_110 -to Z80_RDn
|
||||||
|
set_location_assignment PIN_108 -to Z80_WRn
|
||||||
|
set_location_assignment PIN_107 -to Z80_BUSAKn
|
||||||
|
set_location_assignment PIN_106 -to Z80_WAITn
|
||||||
|
set_location_assignment PIN_103 -to Z80_BUSRQn
|
||||||
|
set_location_assignment PIN_100 -to Z80_RFSHn
|
||||||
|
set_location_assignment PIN_102 -to Z80_M1n
|
||||||
|
set_location_assignment PIN_56 -to Z80_RESETn
|
||||||
|
set_location_assignment PIN_101 -to Z80_CLK
|
||||||
|
|
||||||
|
# Z80 Address Bus
|
||||||
|
# ===============
|
||||||
|
set_location_assignment PIN_94 -to Z80_ADDR[0]
|
||||||
|
set_location_assignment PIN_90 -to Z80_ADDR[1]
|
||||||
|
set_location_assignment PIN_87 -to Z80_ADDR[2]
|
||||||
|
set_location_assignment PIN_84 -to Z80_ADDR[3]
|
||||||
|
set_location_assignment PIN_81 -to Z80_ADDR[4]
|
||||||
|
set_location_assignment PIN_78 -to Z80_ADDR[5]
|
||||||
|
set_location_assignment PIN_69 -to Z80_ADDR[6]
|
||||||
|
set_location_assignment PIN_70 -to Z80_ADDR[7]
|
||||||
|
set_location_assignment PIN_71 -to Z80_ADDR[8]
|
||||||
|
set_location_assignment PIN_68 -to Z80_ADDR[9]
|
||||||
|
set_location_assignment PIN_65 -to Z80_ADDR[10]
|
||||||
|
set_location_assignment PIN_67 -to Z80_ADDR[11]
|
||||||
|
set_location_assignment PIN_66 -to Z80_ADDR[12]
|
||||||
|
set_location_assignment PIN_63 -to Z80_ADDR[13]
|
||||||
|
set_location_assignment PIN_62 -to Z80_ADDR[14]
|
||||||
|
set_location_assignment PIN_61 -to Z80_ADDR[15]
|
||||||
|
|
||||||
|
# SOM SPI
|
||||||
|
# =======
|
||||||
|
set_location_assignment PIN_32 -to VSOM_SPI_CSn
|
||||||
|
set_location_assignment PIN_31 -to VSOM_SPI_CLK
|
||||||
|
set_location_assignment PIN_30 -to VSOM_SPI_MOSI
|
||||||
|
set_location_assignment PIN_29 -to VSOM_SPI_MISO
|
||||||
|
|
||||||
|
# SOM Parallel Bus
|
||||||
|
# ================
|
||||||
|
set_location_assignment PIN_41 -to VSOM_DATA_OUT[0]
|
||||||
|
set_location_assignment PIN_40 -to VSOM_DATA_OUT[1]
|
||||||
|
set_location_assignment PIN_39 -to VSOM_DATA_OUT[2]
|
||||||
|
set_location_assignment PIN_38 -to VSOM_DATA_OUT[3]
|
||||||
|
set_location_assignment PIN_37 -to VSOM_DATA_OUT[4]
|
||||||
|
set_location_assignment PIN_36 -to VSOM_DATA_OUT[5]
|
||||||
|
set_location_assignment PIN_35 -to VSOM_DATA_OUT[6]
|
||||||
|
set_location_assignment PIN_34 -to VSOM_DATA_OUT[7]
|
||||||
|
set_location_assignment PIN_132 -to VSOM_HBYTE
|
||||||
|
|
||||||
|
# SOM Reserved signals.
|
||||||
|
# =====================
|
||||||
|
set_location_assignment PIN_21 -to VSOM_RSV[1]
|
||||||
|
|
||||||
|
# SOM Control Signals
|
||||||
|
# ===================
|
||||||
|
set_location_assignment PIN_28 -to VSOM_READY
|
||||||
|
set_location_assignment PIN_18 -to VSOM_LTSTATE
|
||||||
|
set_location_assignment PIN_27 -to VSOM_BUSRQ
|
||||||
|
set_location_assignment PIN_26 -to VSOM_BUSACK
|
||||||
|
set_location_assignment PIN_19 -to VSOM_INT
|
||||||
|
set_location_assignment PIN_22 -to VSOM_NMI
|
||||||
|
set_location_assignment PIN_25 -to VSOM_WAIT
|
||||||
|
set_location_assignment PIN_23 -to VSOM_RESET
|
||||||
|
set_location_assignment PIN_16 -to PM_RESET
|
||||||
|
|
||||||
|
# VGA_Palette Control
|
||||||
|
# ===================
|
||||||
|
set_location_assignment PIN_133 -to VGA_R[7]
|
||||||
|
set_location_assignment PIN_137 -to VGA_R[8]
|
||||||
|
set_location_assignment PIN_140 -to VGA_R[9]
|
||||||
|
set_location_assignment PIN_134 -to VGA_G[7]
|
||||||
|
set_location_assignment PIN_138 -to VGA_G[8]
|
||||||
|
set_location_assignment PIN_141 -to VGA_G[9]
|
||||||
|
set_location_assignment PIN_136 -to VGA_B[8]
|
||||||
|
set_location_assignment PIN_139 -to VGA_B[9]
|
||||||
|
|
||||||
|
|
||||||
|
# VGA Control Signals
|
||||||
|
# ===================
|
||||||
|
set_location_assignment PIN_142 -to VGA_PXL_CLK
|
||||||
|
set_location_assignment PIN_14 -to VGA_DISPEN
|
||||||
|
set_location_assignment PIN_12 -to VGA_VSYNCn
|
||||||
|
set_location_assignment PIN_11 -to VGA_HSYNCn
|
||||||
|
set_location_assignment PIN_82 -to VGA_COLR
|
||||||
|
set_location_assignment PIN_109 -to VGA_CSYNCn
|
||||||
|
set_location_assignment PIN_143 -to VGA_BLANKn
|
||||||
|
|
||||||
|
# CRT Control Signals
|
||||||
|
# ===================
|
||||||
|
set_location_assignment PIN_15 -to MONO_PXL_CLK
|
||||||
|
set_location_assignment PIN_114 -to MONO_BLANKn
|
||||||
|
set_location_assignment PIN_113 -to MONO_CSYNCn
|
||||||
|
set_location_assignment PIN_116 -to MONO_RSV
|
||||||
|
|
||||||
|
# CRT Lower Chrominance Control
|
||||||
|
# =============================
|
||||||
|
set_location_assignment PIN_1 -to MONO_R[0]
|
||||||
|
set_location_assignment PIN_6 -to MONO_R[1]
|
||||||
|
set_location_assignment PIN_10 -to MONO_R[2]
|
||||||
|
set_location_assignment PIN_2 -to MONO_G[0]
|
||||||
|
set_location_assignment PIN_7 -to MONO_G[1]
|
||||||
|
set_location_assignment PIN_9 -to MONO_G[2]
|
||||||
|
set_location_assignment PIN_5 -to MONO_B[1]
|
||||||
|
set_location_assignment PIN_8 -to MONO_B[2]
|
||||||
|
|
||||||
|
# MUX Control Signals
|
||||||
|
# ===================
|
||||||
|
set_location_assignment PIN_72 -to VIDEO_SRC
|
||||||
|
set_location_assignment PIN_74 -to MONO_VIDEO_SRC
|
||||||
|
set_location_assignment PIN_77 -to AUDIO_SRC_L
|
||||||
|
set_location_assignment PIN_75 -to AUDIO_SRC_R
|
||||||
|
|
||||||
|
# Mainboard Reset Signals
|
||||||
|
# =======================
|
||||||
|
#set_location_assignment PIN_127 -to CPU_RESETn
|
||||||
|
set_location_assignment PIN_122 -to MB_RESETn
|
||||||
|
set_location_assignment PIN_111 -to MB_IPLn
|
||||||
|
|
||||||
|
# USB Power Control
|
||||||
|
# =================
|
||||||
|
set_location_assignment PIN_55 -to VBUS_EN
|
||||||
|
|
||||||
|
# Clocks
|
||||||
|
# ======
|
||||||
|
#set_location_assignment PIN_125 -to CPU_CLK
|
||||||
|
set_location_assignment PIN_128 -to CLK_50M
|
||||||
|
|
||||||
|
# Unused ports
|
||||||
|
# ============
|
||||||
|
#set_location_assignment PIN_42 -to
|
||||||
|
#set_location_assignment PIN_43 -to
|
||||||
|
#set_location_assignment PIN_44 -to
|
||||||
|
#set_location_assignment PIN_45 -to
|
||||||
|
#set_location_assignment PIN_112 -to
|
||||||
|
#set_location_assignment PIN_131 -to
|
||||||
|
#set_location_assignment PIN_117 -to
|
||||||
|
#set_location_assignment PIN_118 -to
|
||||||
|
#set_location_assignment PIN_119 -to
|
||||||
|
#set_location_assignment PIN_120 -to
|
||||||
|
#set_location_assignment PIN_121 -to
|
||||||
|
#set_location_assignment PIN_25 -to
|
||||||
|
#set_location_assignment PIN_53 -to
|
||||||
|
#set_location_assignment PIN_128 -to
|
||||||
|
#set_location_assignment PIN_47 -to
|
||||||
|
#set_location_assignment PIN_54 -to
|
||||||
|
#set_location_assignment PIN_127 -to
|
||||||
|
#set_location_assignment PIN_125 -to
|
||||||
|
#set_location_assignment PIN_48 -to
|
||||||
|
#set_location_assignment PIN_46 -to
|
||||||
|
#set_location_assignment PIN_49 -to
|
||||||
|
|
||||||
|
|
||||||
|
set_global_assignment -name VHDL_FILE ../tzpuFusionX_Toplevel.vhd
|
||||||
|
set_global_assignment -name VHDL_FILE ../tzpuFusionX_pkg.vhd
|
||||||
|
set_global_assignment -name VHDL_FILE ../tzpuFusionX.vhd
|
||||||
|
set_global_assignment -name SDC_FILE tzpuFusionX_MZ700_constraints.sdc
|
||||||
|
|
||||||
|
set_global_assignment -name VHDL_INPUT_VERSION VHDL_2008
|
||||||
|
set_global_assignment -name VHDL_SHOW_LMF_MAPPING_MESSAGES OFF
|
||||||
|
|
||||||
|
set_global_assignment -name SYNTH_TIMING_DRIVEN_SYNTHESIS OFF
|
||||||
|
set_global_assignment -name MAX7000_OPTIMIZATION_TECHNIQUE AREA
|
||||||
|
set_global_assignment -name AUTO_RESOURCE_SHARING OFF
|
||||||
|
set_global_assignment -name PRE_MAPPING_RESYNTHESIS OFF
|
||||||
|
set_global_assignment -name USE_LOGICLOCK_CONSTRAINTS_IN_BALANCING OFF
|
||||||
|
|
||||||
|
set_global_assignment -name INFER_RAMS_FROM_RAW_LOGIC OFF
|
||||||
|
set_global_assignment -name AUTO_LCELL_INSERTION ON
|
||||||
|
|
||||||
|
set_global_assignment -name CDF_FILE output_files/tzpuFusionX_MZ700.cdf
|
||||||
324
CPLD/v1.0/MZ700/build/tzpuFusionX_MZ700_constraints.sdc
Normal file
@@ -0,0 +1,324 @@
|
|||||||
|
## Generated SDC file "tzpuFusionX.out.sdc"
|
||||||
|
|
||||||
|
## Copyright (C) 1991-2013 Altera Corporation
|
||||||
|
## Your use of Altera Corporation's design tools, logic functions
|
||||||
|
## and other software and tools, and its AMPP partner logic
|
||||||
|
## functions, and any output files from any of the foregoing
|
||||||
|
## (including device programming or simulation files), and any
|
||||||
|
## associated documentation or information are expressly subject
|
||||||
|
## to the terms and conditions of the Altera Program License
|
||||||
|
## Subscription Agreement, Altera MegaCore Function License
|
||||||
|
## Agreement, or other applicable license agreement, including,
|
||||||
|
## without limitation, that your use is for the sole purpose of
|
||||||
|
## programming logic devices manufactured by Altera and sold by
|
||||||
|
## Altera or its authorized distributors. Please refer to the
|
||||||
|
## applicable agreement for further details.
|
||||||
|
|
||||||
|
|
||||||
|
## VENDOR "Altera"
|
||||||
|
## PROGRAM "Quartus II"
|
||||||
|
## VERSION "Version 13.0.1 Build 232 06/12/2013 Service Pack 1 SJ Web Edition"
|
||||||
|
|
||||||
|
## DATE "Fri Jun 26 22:10:05 2020"
|
||||||
|
|
||||||
|
##
|
||||||
|
## DEVICE "EPM7160STC100-10"
|
||||||
|
##
|
||||||
|
|
||||||
|
|
||||||
|
#**************************************************************
|
||||||
|
# Time Information
|
||||||
|
#**************************************************************
|
||||||
|
|
||||||
|
set_time_format -unit ns -decimal_places 3
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#**************************************************************
|
||||||
|
# Create Clock
|
||||||
|
#**************************************************************
|
||||||
|
|
||||||
|
# Standard mainboard clock. If using tzpuFusionX on a different host then set to the host frequency.
|
||||||
|
create_clock -name {Z80_CLK} -period 282.486 -waveform { 0.000 141.243 } [get_ports { Z80_CLK }]
|
||||||
|
|
||||||
|
# For 50MHz crystal.
|
||||||
|
create_clock -name {CLK_50M} -period 20.000 -waveform { 0.000 10.000 } [ get_ports { CLK_50M }]
|
||||||
|
|
||||||
|
# For SPI CSn
|
||||||
|
#create_clock -name {VSOM_SPI_CSn} -period 200.000 -waveform { 160.000 40.000 } [ get_ports { VSOM_SPI_CSn }]
|
||||||
|
|
||||||
|
# For SPI CLK
|
||||||
|
create_clock -name {VSOM_SPI_CLK} -period 14.000 -waveform { 0.000 7.000 } [ get_ports { VSOM_SPI_CLK }]
|
||||||
|
|
||||||
|
# For basic board with oscillator.
|
||||||
|
#create_clock -name {CTLCLK} -period 20.000 -waveform { 0.000 10.000 } [ get_ports { CTLCLK }]
|
||||||
|
#create_clock -name {cpld512:cpldl512Toplevel|CTLCLKi} -period 280.000 -waveform { 0.000 140.000 } [ get_keepers {cpld512:cpldl512Toplevel|CTLCLKi} ]
|
||||||
|
##create_clock -name {Z80_CLK} -period 50.000 -waveform { 0.000 25.000 } [get_ports { CTLCLK }]
|
||||||
|
|
||||||
|
|
||||||
|
#**************************************************************
|
||||||
|
# Create Generated Clock
|
||||||
|
#**************************************************************
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#**************************************************************
|
||||||
|
# Set Clock Latency
|
||||||
|
#**************************************************************
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#**************************************************************
|
||||||
|
# Set Clock Uncertainty
|
||||||
|
#**************************************************************
|
||||||
|
|
||||||
|
derive_clock_uncertainty
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#**************************************************************
|
||||||
|
# Set Input Delay
|
||||||
|
#**************************************************************
|
||||||
|
|
||||||
|
#set_input_delay -add_delay -clock [get_clocks {SYSCLK}] 1.000 [get_ports {CTL_MBSEL}]
|
||||||
|
#set_input_delay -add_delay -clock [get_clocks {SYSCLK}] 1.000 [get_ports {CTL_BUSRQn}]
|
||||||
|
#set_input_delay -add_delay -clock [get_clocks {SYSCLK}] 1.000 [get_ports {CTL_WAITn}]
|
||||||
|
#set_input_delay -add_delay -clock [get_clocks {SYSCLK}] 1.000 [get_ports {SYS_BUSRQn}]
|
||||||
|
#set_input_delay -add_delay -clock [get_clocks {SYSCLK}] 1.000 [get_ports {SYS_WAITn}]
|
||||||
|
#set_input_delay -add_delay -clock [get_clocks {SYSCLK}] 1.000 [get_ports {Z80_ADDR[*]}]
|
||||||
|
#set_input_delay -add_delay -clock [get_clocks {SYSCLK}] 1.000 [get_ports {Z80_HI_ADDR[*]}]
|
||||||
|
#set_input_delay -add_delay -clock [get_clocks {SYSCLK}] 1.000 [get_ports {VZ80_ADDR[*]}]
|
||||||
|
#set_input_delay -add_delay -clock [get_clocks {SYSCLK}] 1.000 [get_ports {Z80_BUSACKn}]
|
||||||
|
#set_input_delay -add_delay -clock [get_clocks {SYSCLK}] 1.000 [get_ports {Z80_DATA[*]}]
|
||||||
|
#set_input_delay -add_delay -clock [get_clocks {SYSCLK}] 1.000 [get_ports {Z80_HALTn}]
|
||||||
|
#set_input_delay -add_delay -clock [get_clocks {SYSCLK}] 1.000 [get_ports {Z80_IORQn}]
|
||||||
|
#set_input_delay -add_delay -clock [get_clocks {SYSCLK}] 1.000 [get_ports {Z80_M1n}]
|
||||||
|
#set_input_delay -add_delay -clock [get_clocks {SYSCLK}] 1.000 [get_ports {Z80_MREQn}]
|
||||||
|
#set_input_delay -add_delay -clock [get_clocks {SYSCLK}] 1.000 [get_ports {Z80_RESETn}]
|
||||||
|
#set_input_delay -add_delay -clock [get_clocks {SYSCLK}] 1.000 [get_ports {Z80_RFSHn}]
|
||||||
|
#set_input_delay -add_delay -clock [get_clocks {SYSCLK}] 1.000 [get_ports {Z80_WRn}]
|
||||||
|
#set_input_delay -add_delay -clock [get_clocks {SYSCLK}] 1.000 [get_ports {Z80_RDn}]
|
||||||
|
#set_input_delay -add_delay -clock [get_clocks {SYSCLK}] 1.000 [get_ports {R_IN}]
|
||||||
|
#set_input_delay -add_delay -clock [get_clocks {SYSCLK}] 1.000 [get_ports {G_IN}]
|
||||||
|
#set_input_delay -add_delay -clock [get_clocks {SYSCLK}] 1.000 [get_ports {B_IN}]
|
||||||
|
#set_input_delay -add_delay -clock [get_clocks {SYSCLK}] 1.000 [get_ports {COLR_IN}]
|
||||||
|
#set_input_delay -add_delay -clock [get_clocks {SYSCLK}] 1.000 [get_ports {CSYNC_IN}]
|
||||||
|
##set_input_delay -add_delay -clock [get_clocks {SYSCLK}] 1.000 [get_ports {CVIDEO_IN}]
|
||||||
|
#set_input_delay -add_delay -clock [get_clocks {SYSCLK}] 1.000 [get_ports {HSYNC_IN}]
|
||||||
|
#set_input_delay -add_delay -clock [get_clocks {SYSCLK}] 1.000 [get_ports {VSYNC_IN}]
|
||||||
|
#set_input_delay -add_delay -clock [get_clocks {SYSCLK}] 1.000 [get_ports {VZ80_DATA[*]}]
|
||||||
|
#set_input_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {VZ80_MREQn}]
|
||||||
|
#set_input_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {VZ80_IORQn}]
|
||||||
|
#set_input_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {VZ80_WRn}]
|
||||||
|
#set_input_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {VZ80_RDn}]
|
||||||
|
#set_input_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {VZ80_M1n}]
|
||||||
|
#set_input_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {VZ80_BUSACKn}]
|
||||||
|
#set_input_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {Z80_INTn}]
|
||||||
|
#set_input_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {Z80_NMIn}]
|
||||||
|
#set_input_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {Z80_WAITn}]
|
||||||
|
#set_input_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {VWAITn_A21_V_CSYNC}]
|
||||||
|
#set_input_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {VZ80_A20_RFSHn_V_HSYNC}]
|
||||||
|
#set_input_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {VZ80_A19_HALTn_V_VSYNC}]
|
||||||
|
|
||||||
|
#**************************************************************
|
||||||
|
# Set Output Delay
|
||||||
|
#**************************************************************
|
||||||
|
|
||||||
|
#set_output_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {CTL_BUSACKn}]
|
||||||
|
#set_output_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {CTL_HALTn}]
|
||||||
|
#set_output_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {CTL_M1n}]
|
||||||
|
#set_output_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {CTL_RFSHn}]
|
||||||
|
#set_output_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {RAM_CSn}]
|
||||||
|
#set_output_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {RAM_CS2n}]
|
||||||
|
#set_output_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {RAM_OEn}]
|
||||||
|
#set_output_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {RAM_WEn}]
|
||||||
|
#set_output_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {SVCREQn}]
|
||||||
|
#set_output_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {SYS_BUSACKn}]
|
||||||
|
#set_output_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {Z80_BUSRQn}]
|
||||||
|
#set_output_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {Z80_DATA[*]}]
|
||||||
|
#set_output_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {Z80_ADDR[*]}]
|
||||||
|
#set_output_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {Z80_HI_ADDR[*]}]
|
||||||
|
#set_output_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {Z80_RA_ADDR[*]}]
|
||||||
|
#set_output_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {Z80_WAITn}]
|
||||||
|
#set_output_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {Z80_MREQn}]
|
||||||
|
#set_output_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {Z80_CLK}]
|
||||||
|
#set_output_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {VZ80_ADDR[*]}]
|
||||||
|
#set_output_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {VZ80_DATA[*]}]
|
||||||
|
#set_output_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {VZ80_CLK}]
|
||||||
|
#set_output_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {VZ80_MREQn}]
|
||||||
|
#set_output_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {VZ80_IORQn}]
|
||||||
|
#set_output_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {VZ80_RDn}]
|
||||||
|
#set_output_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {VZ80_WRn}]
|
||||||
|
#set_output_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {VZ80_M1n}]
|
||||||
|
#set_output_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {VIDEO_RDn}]
|
||||||
|
#set_output_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {VIDEO_WRn}]
|
||||||
|
#set_output_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {VZ80_A18_INTn_V_R}]
|
||||||
|
#set_output_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {VZ80_BUSRQn_V_G}]
|
||||||
|
#set_output_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {VZ80_A16_WAITn_V_B}]
|
||||||
|
#set_output_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {VZ80_A17_NMIn_V_COLR}]
|
||||||
|
#set_output_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {VWAITn_A21_V_CSYNC}]
|
||||||
|
#set_output_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {VZ80_A20_RFSHn_V_HSYNC}]
|
||||||
|
#set_output_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {VZ80_A19_HALTn_V_VSYNC}]
|
||||||
|
#set_output_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {Z80_HALTn}]
|
||||||
|
#set_output_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {Z80_RFSHn}]
|
||||||
|
|
||||||
|
# For K64F
|
||||||
|
#set_output_delay -add_delay -clock [get_clocks {CTLCLK}] 5.000 [get_ports {Z80_CLK}]
|
||||||
|
|
||||||
|
# For basic board with oscillator.
|
||||||
|
#set_output_delay -add_delay -clock [get_clocks {cpld512:cpldl512Toplevel|CTLCLKi}] 5.000 [get_ports {Z80_CLK}]
|
||||||
|
|
||||||
|
#**************************************************************
|
||||||
|
# Set Max Delay
|
||||||
|
#**************************************************************
|
||||||
|
#set_max_delay -from [get_ports {CTL_BUSRQn}] -to {Z80_HALTn} 30.000
|
||||||
|
#set_max_delay -from [get_ports {CTL_BUSRQn}] -to {Z80_IORQn} 30.000
|
||||||
|
#set_max_delay -from [get_ports {CTL_BUSRQn}] -to {Z80_M1n} 30.000
|
||||||
|
#set_max_delay -from [get_ports {CTL_BUSRQn}] -to {Z80_RDn} 30.000
|
||||||
|
#set_max_delay -from [get_ports {CTL_BUSRQn}] -to {Z80_WRn} 30.000
|
||||||
|
#set_max_delay -from [get_ports {CTL_BUSRQn}] -to {Z80_RFSHn} 30.000
|
||||||
|
#set_max_delay -from [get_ports {VZ80_A19_HALTn_V_VSYNC}] -to {Z80_HALTn} 30.000
|
||||||
|
#set_max_delay -from [get_ports {VZ80_IORQn}] -to {Z80_IORQn} 30.000
|
||||||
|
#set_max_delay -from [get_ports {VZ80_MREQn}] -to {Z80_IORQn} 30.000
|
||||||
|
#set_max_delay -from [get_ports {VZ80_M1n}] -to {Z80_M1n} 30.000
|
||||||
|
#set_max_delay -from [get_ports {VZ80_RDn}] -to {Z80_RDn} 30.000
|
||||||
|
#set_max_delay -from [get_ports {VZ80_WRn}] -to {Z80_WRn} 30.000
|
||||||
|
#set_max_delay -from [get_ports {VZ80_BUSACKn}] -to {Z80_HALTn} 40.000
|
||||||
|
#set_max_delay -from [get_ports {VZ80_BUSACKn}] -to {Z80_RFSHn} 40.000
|
||||||
|
#set_max_delay -from [get_ports {VZ80_BUSACKn}] -to {Z80_IORQn} 40.000
|
||||||
|
#set_max_delay -from [get_ports {VZ80_BUSACKn}] -to {Z80_M1n} 30.000
|
||||||
|
#set_max_delay -from [get_ports {VZ80_BUSACKn}] -to {Z80_RDn} 30.000
|
||||||
|
#set_max_delay -from [get_ports {VZ80_BUSACKn}] -to {Z80_WRn} 30.000
|
||||||
|
#set_max_delay -from [get_ports {VZ80_A20_RFSHn_V_HSYNC}] -to {Z80_RFSHn} 30.000
|
||||||
|
#set_max_delay -from [get_ports {Z80_BUSACKn}] -to {Z80_HALTn} 30.000
|
||||||
|
#set_max_delay -from [get_ports {Z80_BUSACKn}] -to {Z80_IORQn} 30.000
|
||||||
|
#set_max_delay -from [get_ports {Z80_BUSACKn}] -to {Z80_M1n} 30.000
|
||||||
|
#set_max_delay -from [get_ports {Z80_BUSACKn}] -to {Z80_RDn} 30.000
|
||||||
|
#set_max_delay -from [get_ports {Z80_BUSACKn}] -to {Z80_WRn} 30.000
|
||||||
|
#set_max_delay -from [get_ports {Z80_BUSACKn}] -to {Z80_RFSHn} 30.000
|
||||||
|
#set_max_delay -from {Z80_BUSACKn} -to [get_ports {Z80_HALTn}] 45.000
|
||||||
|
#set_max_delay -from {Z80_BUSACKn} -to [get_ports {Z80_IORQn}] 30.000
|
||||||
|
#set_max_delay -from {Z80_BUSACKn} -to [get_ports {Z80_M1n}] 30.000
|
||||||
|
#set_max_delay -from {Z80_BUSACKn} -to [get_ports {Z80_RDn}] 30.000
|
||||||
|
#set_max_delay -from {Z80_BUSACKn} -to [get_ports {Z80_RFSHn}] 45.000
|
||||||
|
#set_max_delay -from {Z80_BUSACKn} -to [get_ports {Z80_WRn}] 30.000
|
||||||
|
#set_max_delay -from {cpld512:cpldl512Toplevel|CPLD_CFG_DATA[*]} -to [get_ports {Z80_HALTn}] 45.000
|
||||||
|
#set_max_delay -from {cpld512:cpldl512Toplevel|CPLD_CFG_DATA[*]} -to [get_ports {Z80_IORQn}] 50.000
|
||||||
|
#set_max_delay -from {cpld512:cpldl512Toplevel|CPLD_CFG_DATA[*]} -to [get_ports {Z80_M1n}] 40.000
|
||||||
|
#set_max_delay -from {cpld512:cpldl512Toplevel|CPLD_CFG_DATA[*]} -to [get_ports {Z80_RDn}] 40.000
|
||||||
|
#set_max_delay -from {cpld512:cpldl512Toplevel|CPLD_CFG_DATA[*]} -to [get_ports {Z80_WRn}] 40.000
|
||||||
|
#set_max_delay -from {cpld512:cpldl512Toplevel|CPLD_CFG_DATA[*]} -to [get_ports {Z80_RFSHn}] 45.000
|
||||||
|
#set_max_delay -from {cpld512:cpldl512Toplevel|CPU_CFG_DATA[*]} -to [get_ports {Z80_HALTn}] 60.000
|
||||||
|
#set_max_delay -from {cpld512:cpldl512Toplevel|CPU_CFG_DATA[*]} -to [get_ports {Z80_IORQn}] 45.000
|
||||||
|
#set_max_delay -from {cpld512:cpldl512Toplevel|CPU_CFG_DATA[*]} -to [get_ports {Z80_M1n}] 40.000
|
||||||
|
#set_max_delay -from {cpld512:cpldl512Toplevel|CPU_CFG_DATA[*]} -to [get_ports {Z80_RDn}] 40.000
|
||||||
|
#set_max_delay -from {cpld512:cpldl512Toplevel|CPU_CFG_DATA[*]} -to [get_ports {Z80_WRn}] 40.000
|
||||||
|
#set_max_delay -from {cpld512:cpldl512Toplevel|CPU_CFG_DATA[*]} -to [get_ports {Z80_RFSHn}] 60.000
|
||||||
|
|
||||||
|
#**************************************************************
|
||||||
|
# Set Min Delay
|
||||||
|
#**************************************************************
|
||||||
|
#set_min_delay -from [get_ports {CTL_BUSRQn}] -to {Z80_HALTn} 1.000
|
||||||
|
#set_min_delay -from [get_ports {CTL_BUSRQn}] -to {Z80_IORQn} 1.000
|
||||||
|
#set_min_delay -from [get_ports {CTL_BUSRQn}] -to {Z80_M1n} 1.000
|
||||||
|
#set_min_delay -from [get_ports {CTL_BUSRQn}] -to {Z80_RDn} 1.000
|
||||||
|
#set_min_delay -from [get_ports {CTL_BUSRQn}] -to {Z80_WRn} 1.000
|
||||||
|
#set_min_delay -from [get_ports {CTL_BUSRQn}] -to {Z80_RFSHn} 1.000
|
||||||
|
#set_min_delay -from [get_ports {VZ80_A19_HALTn_V_VSYNC}] -to {Z80_HALTn} 1.000
|
||||||
|
#set_min_delay -from [get_ports {VZ80_IORQn}] -to {Z80_IORQn} 1.000
|
||||||
|
#set_min_delay -from [get_ports {VZ80_MREQn}] -to {Z80_IORQn} 1.000
|
||||||
|
#set_min_delay -from [get_ports {VZ80_M1n}] -to {Z80_M1n} 1.000
|
||||||
|
#set_min_delay -from [get_ports {VZ80_RDn}] -to {Z80_RDn} 1.000
|
||||||
|
#set_min_delay -from [get_ports {VZ80_WRn}] -to {Z80_WRn} 1.000
|
||||||
|
#set_min_delay -from [get_ports {VZ80_BUSACKn}] -to {Z80_HALTn} 1.000
|
||||||
|
#set_min_delay -from [get_ports {VZ80_BUSACKn}] -to {Z80_RFSHn} 1.000
|
||||||
|
#set_min_delay -from [get_ports {VZ80_BUSACKn}] -to {Z80_IORQn} 1.000
|
||||||
|
#set_min_delay -from [get_ports {VZ80_BUSACKn}] -to {Z80_M1n} 1.000
|
||||||
|
#set_min_delay -from [get_ports {VZ80_BUSACKn}] -to {Z80_RDn} 1.000
|
||||||
|
#set_min_delay -from [get_ports {VZ80_BUSACKn}] -to {Z80_WRn} 1.000
|
||||||
|
#set_min_delay -from [get_ports {VZ80_A20_RFSHn_V_HSYNC}] -to {Z80_RFSHn} 1.000
|
||||||
|
#set_min_delay -from [get_ports {Z80_BUSACKn}] -to {Z80_HALTn} 1.000
|
||||||
|
#set_min_delay -from [get_ports {Z80_BUSACKn}] -to {Z80_IORQn} 1.000
|
||||||
|
#set_min_delay -from [get_ports {Z80_BUSACKn}] -to {Z80_M1n} 1.000
|
||||||
|
#set_min_delay -from [get_ports {Z80_BUSACKn}] -to {Z80_RDn} 1.000
|
||||||
|
#set_min_delay -from [get_ports {Z80_BUSACKn}] -to {Z80_WRn} 1.000
|
||||||
|
#set_min_delay -from [get_ports {Z80_BUSACKn}] -to {Z80_RFSHn} 1.000
|
||||||
|
#set_min_delay -from {Z80_BUSACKn} -to [get_ports {Z80_HALTn}] 1.000
|
||||||
|
#set_min_delay -from {Z80_BUSACKn} -to [get_ports {Z80_IORQn}] 1.000
|
||||||
|
#set_min_delay -from {Z80_BUSACKn} -to [get_ports {Z80_M1n}] 1.000
|
||||||
|
#set_min_delay -from {Z80_BUSACKn} -to [get_ports {Z80_RDn}] 1.000
|
||||||
|
#set_min_delay -from {Z80_BUSACKn} -to [get_ports {Z80_RFSHn}] 1.000
|
||||||
|
#set_min_delay -from {Z80_BUSACKn} -to [get_ports {Z80_WRn}] 1.000
|
||||||
|
#set_min_delay -from {cpld512:cpldl512Toplevel|CPLD_CFG_DATA[*]} -to [get_ports {Z80_HALTn}] 1.000
|
||||||
|
#set_min_delay -from {cpld512:cpldl512Toplevel|CPLD_CFG_DATA[*]} -to [get_ports {Z80_IORQn}] 1.000
|
||||||
|
#set_min_delay -from {cpld512:cpldl512Toplevel|CPLD_CFG_DATA[*]} -to [get_ports {Z80_M1n}] 1.000
|
||||||
|
#set_min_delay -from {cpld512:cpldl512Toplevel|CPLD_CFG_DATA[*]} -to [get_ports {Z80_RDn}] 1.000
|
||||||
|
#set_min_delay -from {cpld512:cpldl512Toplevel|CPLD_CFG_DATA[*]} -to [get_ports {Z80_WRn}] 1.000
|
||||||
|
#set_min_delay -from {cpld512:cpldl512Toplevel|CPLD_CFG_DATA[*]} -to [get_ports {Z80_RFSHn}] 1.000
|
||||||
|
#set_min_delay -from {cpld512:cpldl512Toplevel|CPU_CFG_DATA[*]} -to [get_ports {Z80_HALTn}] 1.000
|
||||||
|
#set_min_delay -from {cpld512:cpldl512Toplevel|CPU_CFG_DATA[*]} -to [get_ports {Z80_IORQn}] 1.000
|
||||||
|
#set_min_delay -from {cpld512:cpldl512Toplevel|CPU_CFG_DATA[*]} -to [get_ports {Z80_M1n}] 1.000
|
||||||
|
#set_min_delay -from {cpld512:cpldl512Toplevel|CPU_CFG_DATA[*]} -to [get_ports {Z80_RDn}] 1.000
|
||||||
|
#set_min_delay -from {cpld512:cpldl512Toplevel|CPU_CFG_DATA[*]} -to [get_ports {Z80_WRn}] 1.000
|
||||||
|
#set_min_delay -from {cpld512:cpldl512Toplevel|CPU_CFG_DATA[*]} -to [get_ports {Z80_RFSHn}] 1.000
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#**************************************************************
|
||||||
|
# Set Clock Groups
|
||||||
|
#**************************************************************
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#**************************************************************
|
||||||
|
# Set False Path
|
||||||
|
#**************************************************************
|
||||||
|
|
||||||
|
# For K64F
|
||||||
|
#set_false_path -from [get_clocks {CTLCLK}] -to [get_clocks {SYSCLK}]
|
||||||
|
#set_false_path -from [get_clocks {SYSCLK}] -to [get_clocks {CTLCLK}]
|
||||||
|
|
||||||
|
# For basic board with oscillator.
|
||||||
|
#set_false_path -from [get_clocks {cpld512:cpldl512Toplevel|CTLCLKi}] -to [get_clocks {SYSCLK}]
|
||||||
|
#set_false_path -from [get_clocks {cpld512:cpldl512Toplevel|CTLCLKi}] -to [get_clocks {CTLCLK}]
|
||||||
|
#set_false_path -from [get_clocks {SYSCLK}] -to [get_clocks {cpld512:cpldl512Toplevel|CTLCLKi}]
|
||||||
|
#set_false_path -from [get_clocks {SYSCLK}] -to [get_clocks {CTLCLK}]
|
||||||
|
|
||||||
|
# For both configurations.
|
||||||
|
#set_false_path -from {cpld512:cpldl512Toplevel|KEY_SUBSTITUTE} -to {cpld512:cpldl512Toplevel|CTLCLK_Q}
|
||||||
|
#set_false_path -from {cpld512:cpldl512Toplevel|MEM_MODE_LATCH[*]} -to {cpld512:cpldl512Toplevel|CTLCLK_Q}
|
||||||
|
#set_false_path -from {cpld512:cpldl512Toplevel|CPU_CFG_DATA[*]} -to {cpld512:cpldl512Toplevel|CTLCLK_Q}
|
||||||
|
#set_false_path -from {cpld512:cpldl512Toplevel|CPLD_CFG_DATA[*]} -to {cpld512:cpldl512Toplevel|CTLCLK_Q}
|
||||||
|
#set_false_path -from {cpld512:cpldl512Toplevel|MZ80B_VRAM_HI_ADDR} -to {cpld512:cpldl512Toplevel|CTLCLK_Q}
|
||||||
|
#set_false_path -from {cpld512:cpldl512Toplevel|MZ80B_VRAM_LO_ADDR} -to {cpld512:cpldl512Toplevel|CTLCLK_Q}
|
||||||
|
#set_false_path -from {cpld512:cpldl512Toplevel|MODE_VIDEO_MZ80B} -to {cpld512:cpldl512Toplevel|CTLCLK_Q}
|
||||||
|
#set_false_path -from {cpld512:cpldl512Toplevel|GRAM_PAGE_ENABLE} -to {cpld512:cpldl512Toplevel|CTLCLK_Q}
|
||||||
|
|
||||||
|
#**************************************************************
|
||||||
|
# Set Multicycle Path
|
||||||
|
#**************************************************************
|
||||||
|
#set_multicycle_path -from {cpld512:cpldl512Toplevel|CTL_BUSRQni} -to {cpld512:cpldl512Toplevel|CTLCLK_Q} -setup -end 2
|
||||||
|
#set_multicycle_path -from {cpld512:cpldl512Toplevel|CTL_BUSRQni} -to {cpld512:cpldl512Toplevel|CTLCLK_Q} -hold -end 1
|
||||||
|
|
||||||
|
#set_multicycle_path -from {cpld512:cpldl512Toplevel|CTL_BUSRQni} -to {cpld512:cpldl512Toplevel|MEM_MODE_LATCH[*]} -setup -end 2
|
||||||
|
#set_multicycle_path -from {cpld512:cpldl512Toplevel|CTL_BUSRQni} -to {cpld512:cpldl512Toplevel|MEM_MODE_LATCH[*]} -hold -end 1
|
||||||
|
|
||||||
|
#set_multicycle_path -from {cpld512:cpldl512Toplevel|CPU_CFG_DATA[*]} -to {cpld512:cpldl512Toplevel|MEM_MODE_LATCH[*]} -setup -end 2
|
||||||
|
#set_multicycle_path -from {cpld512:cpldl512Toplevel|CPU_CFG_DATA[*]} -to {cpld512:cpldl512Toplevel|MEM_MODE_LATCH[*]} -hold -end 1
|
||||||
|
|
||||||
|
#**************************************************************
|
||||||
|
# Set Maximum Delay
|
||||||
|
#**************************************************************
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#**************************************************************
|
||||||
|
# Set Minimum Delay
|
||||||
|
#**************************************************************
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#**************************************************************
|
||||||
|
# Set Input Transition
|
||||||
|
#**************************************************************
|
||||||
|
|
||||||
999
CPLD/v1.0/MZ700/tzpuFusionX.vhd
Normal file
@@ -0,0 +1,999 @@
|
|||||||
|
-------------------------------------------------------------------------------------------------------
|
||||||
|
--
|
||||||
|
-- Name: tzpuFusionX.vhd
|
||||||
|
-- Version: MZ-700
|
||||||
|
-- Created: June 2020
|
||||||
|
-- Author(s): Philip Smart
|
||||||
|
-- Description: tzpuFusionX CPLD logic definition file.
|
||||||
|
-- This module contains the definition of the tzpuFusionX project plus enhancements
|
||||||
|
-- for the MZ700.
|
||||||
|
--
|
||||||
|
-- Credits:
|
||||||
|
-- Copyright: (c) 2018-22 Philip Smart <philip.smart@net2net.org>
|
||||||
|
--
|
||||||
|
-- History: Oct 2022 - Initial write for the MZ-700.
|
||||||
|
--
|
||||||
|
---------------------------------------------------------------------------------------------------------
|
||||||
|
-- This source file is free software: you can redistribute it and-or modify
|
||||||
|
-- it under the terms of the GNU General Public License as published
|
||||||
|
-- by the Free Software Foundation, either version 3 of the License, or
|
||||||
|
-- (at your option) any later version.
|
||||||
|
--
|
||||||
|
-- This source file is distributed in the hope that it will be useful,
|
||||||
|
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
-- GNU General Public License for more details.
|
||||||
|
--
|
||||||
|
-- You should have received a copy of the GNU General Public License
|
||||||
|
-- along with this program. If not, see <http:--www.gnu.org-licenses->.
|
||||||
|
---------------------------------------------------------------------------------------------------------
|
||||||
|
library ieee;
|
||||||
|
library pkgs;
|
||||||
|
use ieee.std_logic_1164.all;
|
||||||
|
use ieee.std_logic_unsigned.all;
|
||||||
|
use ieee.numeric_std.all;
|
||||||
|
use work.tzpuFusionX_pkg.all;
|
||||||
|
|
||||||
|
entity cpld512 is
|
||||||
|
generic (
|
||||||
|
SPI_CLK_POLARITY : std_logic := '0'
|
||||||
|
);
|
||||||
|
port (
|
||||||
|
-- Z80 Address Bus
|
||||||
|
Z80_ADDR : inout std_logic_vector(15 downto 0);
|
||||||
|
|
||||||
|
-- Z80 Data Bus
|
||||||
|
Z80_DATA : inout std_logic_vector(7 downto 0);
|
||||||
|
|
||||||
|
-- Z80 Control signals.
|
||||||
|
Z80_BUSRQn : in std_logic;
|
||||||
|
Z80_BUSAKn : out std_logic;
|
||||||
|
Z80_INTn : in std_logic;
|
||||||
|
Z80_IORQn : inout std_logic;
|
||||||
|
Z80_MREQn : inout std_logic;
|
||||||
|
Z80_NMIn : in std_logic;
|
||||||
|
Z80_RDn : inout std_logic;
|
||||||
|
Z80_WRn : inout std_logic;
|
||||||
|
Z80_RESETn : in std_logic; -- Host CPU Reset signal, also CPLD reset.
|
||||||
|
Z80_HALTn : out std_logic;
|
||||||
|
Z80_WAITn : in std_logic;
|
||||||
|
Z80_M1n : inout std_logic;
|
||||||
|
Z80_RFSHn : inout std_logic;
|
||||||
|
|
||||||
|
-- SOM Control Signals
|
||||||
|
VSOM_SPI_CLK : in std_logic; -- SOM SPI Channel 0 Clock.
|
||||||
|
VSOM_SPI_MOSI : in std_logic; -- MOSI Input.
|
||||||
|
VSOM_SPI_MISO : out std_logic; -- MISO Output.
|
||||||
|
VSOM_SPI_CSn : in std_logic; -- Enable.
|
||||||
|
|
||||||
|
-- SOM Parallel Bus.
|
||||||
|
VSOM_DATA_OUT : out std_logic_vector(7 downto 0); -- Address/Data bus for CPLD control registers.
|
||||||
|
VSOM_HBYTE : in std_logic; -- Parallel Bus High (1)/Low (0) byte.
|
||||||
|
VSOM_READY : out std_logic; -- FSM Ready (1), Busy (0)
|
||||||
|
VSOM_LTSTATE : out std_logic; -- Last T-State in current cycle, 1 = active.
|
||||||
|
VSOM_BUSRQ : out std_logic; -- Host device requesting Z80 Bus.
|
||||||
|
VSOM_BUSACK : out std_logic; -- Host device granted Z80 Bus
|
||||||
|
VSOM_INT : out std_logic; -- Z80 INT signal
|
||||||
|
VSOM_NMI : out std_logic; -- Z80 NMI signal
|
||||||
|
VSOM_WAIT : out std_logic; -- Z80 WAIT signal
|
||||||
|
VSOM_RESET : out std_logic; -- Z80 RESET signal
|
||||||
|
VSOM_RSV : out std_logic_vector(1 downto 1); -- Reserved pins.
|
||||||
|
|
||||||
|
-- SOM Control Signals
|
||||||
|
PM_RESET : out std_logic; -- Reset SOM
|
||||||
|
|
||||||
|
-- VGA_Palette Control
|
||||||
|
VGA_R : in std_logic_vector(9 downto 7); -- Signals used for detecting blank or no video output.
|
||||||
|
VGA_G : in std_logic_vector(9 downto 7);
|
||||||
|
VGA_B : in std_logic_vector(9 downto 8);
|
||||||
|
|
||||||
|
-- VGA Control Signals
|
||||||
|
VGA_PXL_CLK : in std_logic; -- VGA Pixel clock for DAC conversion.
|
||||||
|
VGA_DISPEN : in std_logic; -- Displayed Enabled (SOM video output).
|
||||||
|
VGA_VSYNCn : in std_logic; -- SOM VSync.
|
||||||
|
VGA_HSYNCn : in std_logic; -- SOM HSync.
|
||||||
|
VGA_COLR : out std_logic; -- COLR colour carrier frequency.
|
||||||
|
VGA_CSYNCn : out std_logic; -- VGA Composite Sync.
|
||||||
|
VGA_BLANKn : out std_logic; -- VGA Blank detected.
|
||||||
|
|
||||||
|
-- CRT Control Signals
|
||||||
|
MONO_PXL_CLK : out std_logic; -- Mono CRT pixel clock for DAC conversion.
|
||||||
|
MONO_BLANKn : out std_logic; -- Mono CRT Blank (no active pixel) detection.
|
||||||
|
MONO_CSYNCn : out std_logic; -- Mono CRT composite sync.
|
||||||
|
MONO_RSV : out std_logic;
|
||||||
|
|
||||||
|
-- CRT Lower Chrominance Control
|
||||||
|
MONO_R : out std_logic_vector(2 downto 0); -- Signals to fine tune Red level of monochrome chrominance.
|
||||||
|
MONO_G : out std_logic_vector(2 downto 0); -- Signals to fine tune Green level of monochrome chrominance.
|
||||||
|
MONO_B : out std_logic_vector(2 downto 1); -- Signals to fine tune Blue level of monochrome chrominance.
|
||||||
|
|
||||||
|
-- MUX Control Signals
|
||||||
|
VIDEO_SRC : out std_logic; -- Select video source, Mainboard or SOM.
|
||||||
|
MONO_VIDEO_SRC : out std_logic; -- Select crt video source, Mainboard or SOM.
|
||||||
|
AUDIO_SRC_L : out std_logic; -- Select Audio Source Left Channel, Mainboard or SOM.
|
||||||
|
AUDIO_SRC_R : out std_logic; -- Select Audio Source Right Channel, Mainboard or SOM.
|
||||||
|
|
||||||
|
-- Mainboard Reset Signals
|
||||||
|
MB_RESETn : in std_logic; -- Motherboard Reset pressed.
|
||||||
|
MB_IPLn : in std_logic; -- Motherboard IPL pressed.
|
||||||
|
|
||||||
|
-- USB Power Control
|
||||||
|
VBUS_EN : out std_logic; -- USB Enable Power Output
|
||||||
|
|
||||||
|
-- Clocks.
|
||||||
|
Z80_CLK : in std_logic; -- Host CPU Clock
|
||||||
|
CLK_50M : in std_logic -- 50MHz oscillator.
|
||||||
|
);
|
||||||
|
end entity;
|
||||||
|
|
||||||
|
architecture rtl of cpld512 is
|
||||||
|
|
||||||
|
-- Finite State Machine states.
|
||||||
|
type SOMFSMState is
|
||||||
|
(
|
||||||
|
IdleCycle,
|
||||||
|
FetchCycle,
|
||||||
|
FetchCycle_2,
|
||||||
|
FetchCycle_3,
|
||||||
|
FetchCycle_4,
|
||||||
|
RefreshCycle,
|
||||||
|
RefreshCycle_1,
|
||||||
|
RefreshCycle_2,
|
||||||
|
RefreshCycle_3,
|
||||||
|
WriteCycle,
|
||||||
|
WriteCycle_2,
|
||||||
|
WriteCycle_3,
|
||||||
|
WriteCycle_4,
|
||||||
|
ReadCycle,
|
||||||
|
ReadCycle_2,
|
||||||
|
ReadCycle_3,
|
||||||
|
ReadCycle_4,
|
||||||
|
WriteIOCycle,
|
||||||
|
WriteIOCycle_2,
|
||||||
|
WriteIOCycle_3,
|
||||||
|
WriteIOCycle_4,
|
||||||
|
WriteIOCycle_5,
|
||||||
|
ReadIOCycle,
|
||||||
|
ReadIOCycle_2,
|
||||||
|
ReadIOCycle_3,
|
||||||
|
ReadIOCycle_4,
|
||||||
|
HaltCycle,
|
||||||
|
BusReqCycle
|
||||||
|
);
|
||||||
|
|
||||||
|
-- CPU Interface internal signals.
|
||||||
|
signal Z80_BUSRQni : std_logic;
|
||||||
|
signal Z80_BUSAKni : std_logic;
|
||||||
|
signal Z80_INTni : std_logic;
|
||||||
|
signal Z80_IORQni : std_logic;
|
||||||
|
signal Z80_MREQni : std_logic;
|
||||||
|
signal Z80_NMIni : std_logic;
|
||||||
|
signal Z80_RDni : std_logic;
|
||||||
|
signal Z80_WRni : std_logic;
|
||||||
|
signal Z80_HALTni : std_logic;
|
||||||
|
signal Z80_WAITni : std_logic;
|
||||||
|
signal Z80_M1ni : std_logic;
|
||||||
|
signal Z80_RFSHni : std_logic;
|
||||||
|
signal Z80_DATAi : std_logic_vector(7 downto 0);
|
||||||
|
signal Z80_BUSRQ_ACKni : std_logic;
|
||||||
|
|
||||||
|
-- Internal CPU state control.
|
||||||
|
signal CPU_ADDR : std_logic_vector(15 downto 0) := (others => '0');
|
||||||
|
signal CPU_DATA_IN : std_logic_vector(7 downto 0) := (others => '0');
|
||||||
|
signal CPU_DATA_OUT : std_logic_vector(7 downto 0) := (others => '0');
|
||||||
|
signal CPU_DATA_EN : std_logic;
|
||||||
|
|
||||||
|
-- Clocks.
|
||||||
|
signal CLK_25Mi : std_logic := '0';
|
||||||
|
|
||||||
|
-- Reset control
|
||||||
|
signal PM_RESETi : std_logic := '1';
|
||||||
|
signal VSOM_RESETni : std_logic := '1';
|
||||||
|
|
||||||
|
-- Refresh control.
|
||||||
|
signal FSM_STATE : SOMFSMState := IdleCycle;
|
||||||
|
signal NEW_SPI_CMD : std_logic := '0';
|
||||||
|
signal VCPU_CS_EDGE : std_logic_vector(1 downto 0) := "11";
|
||||||
|
signal AUTOREFRESH_CNT : integer range 0 to 7;
|
||||||
|
signal FSM_STATUS : std_logic := '0';
|
||||||
|
signal RFSH_STATUS : std_logic := '0';
|
||||||
|
signal REFRESH_ADDR : std_logic_vector(7 downto 0);
|
||||||
|
signal IPAR : std_logic_vector(7 downto 0);
|
||||||
|
signal AUTOREFRESH : std_logic;
|
||||||
|
|
||||||
|
-- Clock edge detection and flagging.
|
||||||
|
signal Z80_CLK_RE : std_logic := '0';
|
||||||
|
signal Z80_CLK_FE : std_logic := '0';
|
||||||
|
signal Z80_CLK_LEVEL : std_logic := '0';
|
||||||
|
signal Z80_CLK_LAST : std_logic := '0';
|
||||||
|
signal CPU_T_STATE : integer range 0 to 5;
|
||||||
|
signal CPU_T_STATES : integer range 0 to 5;
|
||||||
|
signal CPU_T_STATE_SET : integer range 0 to 5;
|
||||||
|
signal CPU_LAST_T_STATE : std_logic := '0';
|
||||||
|
|
||||||
|
-- SPI Slave interface.
|
||||||
|
signal SPI_SHIFT_EN : std_logic;
|
||||||
|
signal SPI_TX_SREG : std_logic_vector(6 downto 0); -- TX Shift Register
|
||||||
|
signal SPI_RX_SREG : std_logic_vector(7 downto 0); -- RX Shift Register
|
||||||
|
signal SPI_TX_DATA : std_logic_vector(31 downto 0); -- Data to transmit.
|
||||||
|
signal SPI_RX_DATA : std_logic_vector(31 downto 0); -- Data received.
|
||||||
|
signal SPI_BIT_CNT : integer range 0 to 16; -- Count of bits tx/rx'd.
|
||||||
|
signal SPI_FRAME_CNT : integer range 0 to 4; -- Number of frames received (8bit chunks).
|
||||||
|
|
||||||
|
-- SPI Command interface.
|
||||||
|
signal SOM_CMD : std_logic_vector(7 downto 0) := (others => '0');
|
||||||
|
signal SPI_NEW_DATA : std_logic;
|
||||||
|
signal SPI_PROCESSING : std_logic;
|
||||||
|
signal SPI_CPU_ADDR : std_logic_vector(15 downto 0) := (others => '0');
|
||||||
|
signal SPI_CPU_DATA : std_logic_vector(7 downto 0) := (others => '0');
|
||||||
|
|
||||||
|
-- Test modes.
|
||||||
|
signal SPI_LOOPBACK_TEST : std_logic := '0';
|
||||||
|
|
||||||
|
-- Video/Audio control
|
||||||
|
signal VIDEO_SRCi : std_logic := '0';
|
||||||
|
signal MONO_VIDEO_SRCi : std_logic := '0';
|
||||||
|
signal AUDIO_SRC_Li : std_logic := '0';
|
||||||
|
signal AUDIO_SRC_Ri : std_logic := '0';
|
||||||
|
signal VBUS_ENi : std_logic := '1';
|
||||||
|
|
||||||
|
|
||||||
|
function to_std_logic(L: boolean) return std_logic is
|
||||||
|
begin
|
||||||
|
if L then
|
||||||
|
return('1');
|
||||||
|
else
|
||||||
|
return('0');
|
||||||
|
end if;
|
||||||
|
end function to_std_logic;
|
||||||
|
begin
|
||||||
|
|
||||||
|
|
||||||
|
-- System RESET.
|
||||||
|
--
|
||||||
|
-- Multiple reset sources, Z80_RESETn, MB_IPLn, MB_RESETn. On the MZ-700 we are only concerned with the Z80_RESETn.
|
||||||
|
-- If the external reset switch is pressed, a Z80_RESETn is invoked sending the signal low for approx 30ms.
|
||||||
|
-- On the first edge the VSOM_RESETn signal is set which allows the SOM to see it and the Z80 application to enter a reset state.
|
||||||
|
-- On the second edge, if occurring within 1 second of the first, the PM_RESET signal to the SOM is triggered, held low for 1 second,
|
||||||
|
-- forcing the SOM to reboot.
|
||||||
|
SYSRESET: process( Z80_CLK, Z80_RESETn )
|
||||||
|
variable timer1 : integer range 0 to 354000 := 0;
|
||||||
|
variable timer100 : integer range 0 to 10 := 0;
|
||||||
|
variable timerPMReset : integer range 0 to 10 := 0;
|
||||||
|
variable resetCount : integer range 0 to 3 := 0;
|
||||||
|
variable cpuResetEdge : std_logic := '1';
|
||||||
|
begin
|
||||||
|
-- Synchronous on the HOST Clock.
|
||||||
|
if(rising_edge(Z80_CLK)) then
|
||||||
|
|
||||||
|
-- If the PM Reset timer is active, count down and on expiry release the SOM PM_RESET line.
|
||||||
|
if(timerPMReset = 0 and PM_RESETi = '1') then
|
||||||
|
PM_RESETi <= '0';
|
||||||
|
end if;
|
||||||
|
|
||||||
|
-- If the VSOM_RESETni is active after reset timer expiry, cancel the RESET state.
|
||||||
|
if(timerPMReset = 0 and VSOM_RESETni = '0') then
|
||||||
|
VSOM_RESETni <= '1';
|
||||||
|
end if;
|
||||||
|
|
||||||
|
-- Each time the reset button is pressed, count the edges.
|
||||||
|
if(Z80_RESETn = '0' and cpuResetEdge = '1' and (resetCount = 0 or timer100 > 5)) then
|
||||||
|
resetCount := resetCount + 1;
|
||||||
|
VSOM_RESETni <= '0';
|
||||||
|
timerPMReset := 5;
|
||||||
|
timer100 := 0;
|
||||||
|
|
||||||
|
-- If there are 2 or more reset signals in a given period it means a SOM reset is required.
|
||||||
|
if(resetCount >= 2) then
|
||||||
|
PM_RESETi <= '1';
|
||||||
|
timerPMReset := 10;
|
||||||
|
resetCount := 0;
|
||||||
|
end if;
|
||||||
|
|
||||||
|
end if;
|
||||||
|
|
||||||
|
-- 100ms interval.
|
||||||
|
if(timer1 = 354000) then
|
||||||
|
timer100 := timer100 + 1;
|
||||||
|
|
||||||
|
if(timer100 >= 10) then
|
||||||
|
timer100 := 0;
|
||||||
|
resetCount := 0;
|
||||||
|
end if;
|
||||||
|
|
||||||
|
if(timerPMReset > 0) then
|
||||||
|
timerPMReset := timerPMReset - 1;
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
|
||||||
|
timer1 := timer1 - 1;
|
||||||
|
cpuResetEdge := Z80_RESETn;
|
||||||
|
end if;
|
||||||
|
end process;
|
||||||
|
|
||||||
|
-- Create Mono DAC Clock based on primary clock.
|
||||||
|
MONOCLK: process( CLK_50M )
|
||||||
|
begin
|
||||||
|
if(rising_edge(CLK_50M)) then
|
||||||
|
CLK_25Mi <= not CLK_25Mi;
|
||||||
|
end if;
|
||||||
|
end process;
|
||||||
|
|
||||||
|
-- SPI Slave input. Receive command and data from the SOM.
|
||||||
|
SPI_INPUT : process(VSOM_SPI_CLK)
|
||||||
|
begin
|
||||||
|
-- SPI_CLK_POLARITY='0' => falling edge; SPI_CLK_POLARITY='1' => rising edge
|
||||||
|
if(VSOM_SPI_CLK'event and VSOM_SPI_CLK = SPI_CLK_POLARITY) then
|
||||||
|
if(VSOM_SPI_CSn = '0') then
|
||||||
|
SPI_RX_SREG <= SPI_RX_SREG(6 downto 0) & VSOM_SPI_MOSI;
|
||||||
|
|
||||||
|
-- End of frame then store the data prior to next bit arrival.
|
||||||
|
-- Convert to Little Endian, same as SOM.
|
||||||
|
if(SPI_SHIFT_EN = '1' and SPI_FRAME_CNT = 1 and SPI_BIT_CNT = 0) then
|
||||||
|
SPI_RX_DATA(7 downto 0) <= SPI_RX_SREG(6 downto 0) & VSOM_SPI_MOSI;
|
||||||
|
|
||||||
|
elsif(SPI_SHIFT_EN = '1' and SPI_FRAME_CNT = 2 and SPI_BIT_CNT = 0) then
|
||||||
|
SPI_RX_DATA(15 downto 8) <= SPI_RX_SREG(6 downto 0) & VSOM_SPI_MOSI;
|
||||||
|
|
||||||
|
elsif(SPI_SHIFT_EN = '1' and SPI_FRAME_CNT = 3 and SPI_BIT_CNT = 0) then
|
||||||
|
SPI_RX_DATA(23 downto 16) <= SPI_RX_SREG(6 downto 0) & VSOM_SPI_MOSI;
|
||||||
|
|
||||||
|
elsif(SPI_SHIFT_EN = '1' and SPI_FRAME_CNT = 4 and SPI_BIT_CNT = 0) then
|
||||||
|
SPI_RX_DATA(31 downto 24) <= SPI_RX_SREG(6 downto 0) & VSOM_SPI_MOSI;
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
end process;
|
||||||
|
|
||||||
|
-- SPI Slave output. Return the current data set as selected by the input signals XACT.
|
||||||
|
SPI_OUTPUT : process(VSOM_SPI_CLK,VSOM_SPI_CSn,SPI_TX_DATA)
|
||||||
|
begin
|
||||||
|
if(VSOM_SPI_CSn = '1') then
|
||||||
|
SPI_SHIFT_EN <= '0';
|
||||||
|
SPI_BIT_CNT <= 15;
|
||||||
|
|
||||||
|
-- SPI_CLK_POLARITY='0' => falling edge; SPI_CLK_POLARITY='1' => risinge edge
|
||||||
|
elsif(VSOM_SPI_CLK'event and VSOM_SPI_CLK = not SPI_CLK_POLARITY) then
|
||||||
|
SPI_SHIFT_EN <= '1';
|
||||||
|
|
||||||
|
if(SPI_BIT_CNT > 0) then
|
||||||
|
SPI_BIT_CNT <= SPI_BIT_CNT - 1;
|
||||||
|
end if;
|
||||||
|
|
||||||
|
VSOM_SPI_MISO <= SPI_TX_SREG(6);
|
||||||
|
SPI_TX_SREG <= SPI_TX_SREG(5 downto 0) & '0';
|
||||||
|
|
||||||
|
-- First clock after CS goes active, load up the data to be sent to the SOM.
|
||||||
|
if(SPI_SHIFT_EN = '0' or SPI_BIT_CNT = 0) then
|
||||||
|
|
||||||
|
if(SPI_LOOPBACK_TEST = '1') then
|
||||||
|
VSOM_SPI_MISO<= SPI_RX_SREG(7);
|
||||||
|
SPI_TX_SREG <= SPI_RX_SREG(6 downto 0);
|
||||||
|
|
||||||
|
elsif(SPI_SHIFT_EN = '0') then
|
||||||
|
SPI_FRAME_CNT<= 1;
|
||||||
|
VSOM_SPI_MISO<= SPI_TX_DATA(7);
|
||||||
|
SPI_TX_SREG <= SPI_TX_DATA(6 downto 0);
|
||||||
|
elsif(SPI_FRAME_CNT = 1) then
|
||||||
|
SPI_FRAME_CNT<= 2;
|
||||||
|
VSOM_SPI_MISO<= SPI_TX_DATA(15);
|
||||||
|
SPI_TX_SREG <= SPI_TX_DATA(14 downto 8);
|
||||||
|
elsif(SPI_FRAME_CNT = 2) then
|
||||||
|
SPI_FRAME_CNT<= 3;
|
||||||
|
VSOM_SPI_MISO<= SPI_TX_DATA(23);
|
||||||
|
SPI_TX_SREG <= SPI_TX_DATA(22 downto 16);
|
||||||
|
else
|
||||||
|
-- Increment frame count for each word received. We handle 8bit (1 frame), 16bit (2 frames) or 32bit (4 frames) reception.
|
||||||
|
SPI_FRAME_CNT<= 4;
|
||||||
|
VSOM_SPI_MISO<= SPI_TX_DATA(31);
|
||||||
|
SPI_TX_SREG <= SPI_TX_DATA(30 downto 24);
|
||||||
|
end if;
|
||||||
|
|
||||||
|
SPI_BIT_CNT <= 7;
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
end process;
|
||||||
|
|
||||||
|
SPI_REGISTER : process(Z80_RESETn, VSOM_SPI_CSn, SPI_FRAME_CNT)
|
||||||
|
begin
|
||||||
|
if(Z80_RESETn = '0') then
|
||||||
|
VIDEO_SRCi <= '0';
|
||||||
|
VGA_BLANKn <= '1';
|
||||||
|
VBUS_ENi <= '1';
|
||||||
|
MONO_VIDEO_SRCi <= '1';
|
||||||
|
AUDIO_SRC_Li <= '0';
|
||||||
|
AUDIO_SRC_Ri <= '0';
|
||||||
|
AUTOREFRESH <= '1';
|
||||||
|
SPI_LOOPBACK_TEST <= '0';
|
||||||
|
SOM_CMD <= (others => '0');
|
||||||
|
SPI_CPU_ADDR <= (others => '0');
|
||||||
|
SPI_NEW_DATA <= '0';
|
||||||
|
|
||||||
|
-- On rising edge of SPI CSn a new data packet from the SOM has arrived and in the shift register SPI_RX_SREG.
|
||||||
|
-- The variable SPI_FRAME_CNT indicates which byte (frame) in a 32bit word has been transmitted. This allows
|
||||||
|
-- for 8bit, 16bit and 32bit transmissions.
|
||||||
|
-- The packet is formatted as follows:
|
||||||
|
--
|
||||||
|
-- < SPI_FRAME_CNT=4 >< SPI_FRAME=3 > < SPI_FRAME_CNT=2 >< SPI_FRAME_CNT=1>
|
||||||
|
-- < 16bit Z80 Address > < Z80 Data >< Command = 00.. 80 >
|
||||||
|
-- 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 2 0
|
||||||
|
--
|
||||||
|
-- < > < Data >< Command = F0.. FF >
|
||||||
|
-- 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 2 0
|
||||||
|
--
|
||||||
|
elsif(VSOM_SPI_CSn'event and VSOM_SPI_CSn = '1') then
|
||||||
|
|
||||||
|
-- Command is always located in the upper byte of frame 1.
|
||||||
|
SOM_CMD <= SPI_RX_DATA(7 downto 0);
|
||||||
|
|
||||||
|
-- Toggle flag to indicate new data arrived.
|
||||||
|
SPI_NEW_DATA <= not SPI_NEW_DATA;
|
||||||
|
|
||||||
|
-- Process the command. Some commands require the FSM, others can be serviced immediately.
|
||||||
|
case SPI_RX_DATA(7 downto 0) is
|
||||||
|
|
||||||
|
-- Z80XACT(0..15): Setup data and address as provided then execute FSM.
|
||||||
|
when X"10" | X"11" | X"12" | X"13" | X"14" | X"15" | X"16" | X"17" | -- Fetch
|
||||||
|
X"18" | X"19" | X"1A" | X"1B" | X"1C" | X"1D" | X"1E" | X"1F" | -- Write
|
||||||
|
X"20" | X"21" | X"22" | X"23" | X"24" | X"25" | X"26" | X"27" | -- Read
|
||||||
|
X"28" | X"29" | X"2A" | X"2B" | X"2C" | X"2D" | X"2E" | X"2F" | -- WriteIO
|
||||||
|
X"30" | X"31" | X"32" | X"33" | X"34" | X"35" | X"36" | X"37" | -- ReadIO
|
||||||
|
X"38" | X"39" | X"3A" | X"3B" | X"3C" | X"3D" | X"3E" | X"3F" | --
|
||||||
|
X"40" | X"41" | X"42" | X"43" | X"44" | X"45" | X"46" | X"47" | --
|
||||||
|
X"48" | X"49" | X"4A" | X"4B" | X"4C" | X"4D" | X"4E" | X"4F" =>
|
||||||
|
|
||||||
|
-- Direct address set.
|
||||||
|
if(SPI_FRAME_CNT = 4) then
|
||||||
|
SPI_CPU_ADDR <= SPI_RX_DATA(31 downto 16);
|
||||||
|
else
|
||||||
|
SPI_CPU_ADDR <= std_logic_vector(unsigned(CPU_ADDR) + unsigned(SPI_RX_DATA(2 downto 0)));
|
||||||
|
end if;
|
||||||
|
|
||||||
|
if(SPI_FRAME_CNT > 1) then
|
||||||
|
SPI_CPU_DATA <= SPI_RX_DATA(15 downto 8);
|
||||||
|
end if;
|
||||||
|
|
||||||
|
-- SETSIGSET1: Set control lines directly.
|
||||||
|
when X"F0" =>
|
||||||
|
VIDEO_SRCi <= SPI_RX_DATA(8);
|
||||||
|
MONO_VIDEO_SRCi <= SPI_RX_DATA(9);
|
||||||
|
AUDIO_SRC_Li <= SPI_RX_DATA(10);
|
||||||
|
AUDIO_SRC_Ri <= SPI_RX_DATA(11);
|
||||||
|
VBUS_ENi <= SPI_RX_DATA(12);
|
||||||
|
VGA_BLANKn <= not SPI_RX_DATA(13);
|
||||||
|
|
||||||
|
-- Enable auto refresh DRAM cycle.
|
||||||
|
when X"F1" =>
|
||||||
|
AUTOREFRESH <= '1';
|
||||||
|
|
||||||
|
-- Disable auto refresh DRAM cycle.
|
||||||
|
when X"F2" =>
|
||||||
|
AUTOREFRESH <= '0';
|
||||||
|
|
||||||
|
-- SETLOOPBACK: Enable loopback test mode.
|
||||||
|
when X"FE" =>
|
||||||
|
SPI_LOOPBACK_TEST <= '1';
|
||||||
|
|
||||||
|
-- No action, called to retrieve status.
|
||||||
|
when X"00" | X"FF" =>
|
||||||
|
|
||||||
|
when others =>
|
||||||
|
end case;
|
||||||
|
end if;
|
||||||
|
end process;
|
||||||
|
|
||||||
|
-- Z80 Clock edge detection. Each falling and rising edge sets a flag for 1 cycle along with the current clock level flag.
|
||||||
|
-- On expiry of the defined T-States, a flag is raised to indicate end of cycle.
|
||||||
|
CLKEDGE: process( CLK_50M, Z80_RESETn, Z80_CLK, CPU_T_STATE_SET )
|
||||||
|
begin
|
||||||
|
if(Z80_RESETn = '0') then
|
||||||
|
Z80_CLK_RE <= '0';
|
||||||
|
Z80_CLK_FE <= '0';
|
||||||
|
Z80_CLK_LEVEL <= '0';
|
||||||
|
CPU_T_STATE <= 1;
|
||||||
|
CPU_LAST_T_STATE <= '0';
|
||||||
|
|
||||||
|
elsif(rising_edge(CLK_50M)) then
|
||||||
|
-- Host clock edge detection. For Z80 operations the clock edge is required to meet host and original timings.
|
||||||
|
if(Z80_CLK = '1' and Z80_CLK_LAST = '0') then
|
||||||
|
Z80_CLK_RE <= '1';
|
||||||
|
Z80_CLK_LEVEL <= '1';
|
||||||
|
|
||||||
|
-- T state increments on each rising edge unless WAIT asserted.
|
||||||
|
if(Z80_WAITni = '1') then
|
||||||
|
|
||||||
|
-- Wrap around to next T-State if limit for last transaction type reached.
|
||||||
|
if(CPU_T_STATE = CPU_T_STATES) then
|
||||||
|
CPU_T_STATE <= 1;
|
||||||
|
CPU_LAST_T_STATE <= '0';
|
||||||
|
else
|
||||||
|
CPU_T_STATE <= CPU_T_STATE + 1;
|
||||||
|
end if;
|
||||||
|
|
||||||
|
end if;
|
||||||
|
|
||||||
|
elsif(Z80_CLK = '0' and Z80_CLK_LAST = '1') then
|
||||||
|
Z80_CLK_FE <= '1';
|
||||||
|
Z80_CLK_LEVEL <= '0';
|
||||||
|
|
||||||
|
-- Falling edge of the last T-State sets the Last T-State flag. This gives the SOM sufficient time to detect it
|
||||||
|
-- and execute necessary code before next T-State commences.
|
||||||
|
if(CPU_T_STATE = CPU_T_STATES) then
|
||||||
|
CPU_LAST_T_STATE <= '1';
|
||||||
|
end if;
|
||||||
|
else
|
||||||
|
Z80_CLK_RE <= '0';
|
||||||
|
Z80_CLK_FE <= '0';
|
||||||
|
end if;
|
||||||
|
|
||||||
|
-- Mechanism to set the T-State.
|
||||||
|
if(CPU_T_STATE_SET /= 0) then
|
||||||
|
CPU_T_STATE <= CPU_T_STATE_SET;
|
||||||
|
CPU_LAST_T_STATE <= '0';
|
||||||
|
end if;
|
||||||
|
|
||||||
|
Z80_CLK_LAST <= Z80_CLK;
|
||||||
|
end if;
|
||||||
|
end process;
|
||||||
|
|
||||||
|
-- SOM Finite State Machine.
|
||||||
|
--
|
||||||
|
-- A command processor, based on an FSM concept, to process requested commands, ie. Z80 Write, Z80 Read etc.
|
||||||
|
-- The external signal SOM_CMD_EN, when set, indicates a new command available in SOM_CMD.
|
||||||
|
--
|
||||||
|
SOMFSM: process( CLK_50M, Z80_RESETn )
|
||||||
|
begin
|
||||||
|
if(Z80_RESETn = '0') then
|
||||||
|
Z80_BUSAKni <= '1';
|
||||||
|
Z80_IORQni <= '1';
|
||||||
|
Z80_MREQni <= '1';
|
||||||
|
Z80_RDni <= '1';
|
||||||
|
Z80_WRni <= '1';
|
||||||
|
Z80_HALTni <= '1';
|
||||||
|
Z80_M1ni <= '1';
|
||||||
|
Z80_RFSHni <= '1';
|
||||||
|
Z80_BUSRQ_ACKni <= '1';
|
||||||
|
FSM_STATUS <= '0';
|
||||||
|
RFSH_STATUS <= '0';
|
||||||
|
CPU_DATA_EN <= '0';
|
||||||
|
CPU_DATA_IN <= (others => '0');
|
||||||
|
REFRESH_ADDR <= (others => '0');
|
||||||
|
AUTOREFRESH_CNT <= 7;
|
||||||
|
IPAR <= (others => '0');
|
||||||
|
FSM_STATE <= IdleCycle;
|
||||||
|
NEW_SPI_CMD <= '0';
|
||||||
|
VCPU_CS_EDGE <= "11";
|
||||||
|
CPU_T_STATES <= 3;
|
||||||
|
CPU_T_STATE_SET <= 0;
|
||||||
|
SPI_PROCESSING <= '0';
|
||||||
|
|
||||||
|
elsif(rising_edge(CLK_50M)) then
|
||||||
|
|
||||||
|
-- Setup of T State is one cycle wide.
|
||||||
|
CPU_T_STATE_SET <= 0;
|
||||||
|
|
||||||
|
-- Bus request mechanism. If an externel Bus Request comes in and the FSM is idle, run the Bus Request command which
|
||||||
|
-- suspends processing and tri-states the bus.
|
||||||
|
if(Z80_BUSRQn = '0' and Z80_BUSRQ_ACKni = '1' and FSM_STATE = IdleCycle) then
|
||||||
|
FSM_STATE <= BusReqCycle;
|
||||||
|
end if;
|
||||||
|
if(Z80_BUSRQn = '1' and Z80_BUSRQ_ACKni = '0' and FSM_STATE = IdleCycle) then
|
||||||
|
Z80_BUSRQ_ACKni <= '1';
|
||||||
|
end if;
|
||||||
|
|
||||||
|
-- New command, set flag as the signal is only 1 clock wide.
|
||||||
|
if(SPI_LOOPBACK_TEST = '0' and VSOM_SPI_CSn = '1' and VCPU_CS_EDGE = "01") then
|
||||||
|
NEW_SPI_CMD <= '1';
|
||||||
|
end if;
|
||||||
|
|
||||||
|
-- Whenever we return to Idle or just prior to Refresh from a Fetch cycle set all control signals to default.
|
||||||
|
if(FSM_STATE = IdleCycle or FSM_STATE = RefreshCycle) then
|
||||||
|
CPU_DATA_EN <= '0';
|
||||||
|
Z80_MREQni <= '1';
|
||||||
|
Z80_IORQni <= '1';
|
||||||
|
Z80_RDni <= '1';
|
||||||
|
Z80_WRni <= '1';
|
||||||
|
Z80_M1ni <= '1';
|
||||||
|
FSM_STATUS <= '0';
|
||||||
|
Z80_RFSHni <= '1';
|
||||||
|
|
||||||
|
-- Auto DRAM refresh cycles. When enabled, every 7 host clock cycles, a 2 cycle refresh period commences.
|
||||||
|
-- This will be overriden if the SPI receives a new command.
|
||||||
|
--
|
||||||
|
if AUTOREFRESH = '1' and FSM_STATE = IdleCycle then
|
||||||
|
AUTOREFRESH_CNT <= AUTOREFRESH_CNT - 1;
|
||||||
|
if(AUTOREFRESH_CNT = 0) then
|
||||||
|
FSM_STATE <= RefreshCycle_3;
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
|
||||||
|
-- If new command has been given and the FSM enters idle state, load up new command for processing.
|
||||||
|
if(NEW_SPI_CMD = '1' and FSM_STATE = IdleCycle) then
|
||||||
|
NEW_SPI_CMD <= '0';
|
||||||
|
|
||||||
|
-- Store new address and data for this command.
|
||||||
|
CPU_ADDR <= SPI_CPU_ADDR;
|
||||||
|
if(SPI_CPU_DATA /= CPU_DATA_OUT) then
|
||||||
|
CPU_DATA_OUT <= SPI_CPU_DATA;
|
||||||
|
end if;
|
||||||
|
|
||||||
|
-- Process the SOM command. The SPI_REGISTER executes non FSM commands and stores FSM
|
||||||
|
-- data prior to this execution block, which fires 1 cycle later on the same control clock.
|
||||||
|
-- If the command is not for the FSM then the READY mechanism is held for one
|
||||||
|
-- further cycle before going inactive.
|
||||||
|
case SOM_CMD is
|
||||||
|
when X"10" | X"11" | X"12" | X"13" | X"14" | X"15" | X"16" | X"17" =>
|
||||||
|
-- Initiate a Fetch Cycle.
|
||||||
|
FSM_STATE <= FetchCycle;
|
||||||
|
|
||||||
|
when X"18" | X"19" | X"1A" | X"1B" | X"1C" | X"1D" | X"1E" | X"1F" =>
|
||||||
|
|
||||||
|
-- Set the Z80 data bus value and initiate a Write Cycle.
|
||||||
|
FSM_STATE <= WriteCycle;
|
||||||
|
|
||||||
|
when X"20" | X"21" | X"22" | X"23" | X"24" | X"25" | X"26" | X"27" =>
|
||||||
|
-- Initiate a Read Cycle.
|
||||||
|
FSM_STATE <= ReadCycle;
|
||||||
|
|
||||||
|
when X"28" | X"29" | X"2A" | X"2B" | X"2C" | X"2D" | X"2E" | X"2F" =>
|
||||||
|
-- Set the Z80 data bus value and initiate an IO Write Cycle.
|
||||||
|
-- The SOM should set 15:8 to the B register value.
|
||||||
|
FSM_STATE <= WriteIOCycle;
|
||||||
|
|
||||||
|
when X"30" | X"31" | X"32" | X"33" | X"34" | X"35" | X"36" | X"37" =>
|
||||||
|
-- Initiate a Read IO Cycle.
|
||||||
|
FSM_STATE <= ReadIOCycle;
|
||||||
|
|
||||||
|
when X"50" =>
|
||||||
|
-- Register a Halt state.
|
||||||
|
FSM_STATE <= HaltCycle;
|
||||||
|
|
||||||
|
when X"51" =>
|
||||||
|
-- Initiate a refresh cycle.
|
||||||
|
FSM_STATE <= RefreshCycle_3;
|
||||||
|
|
||||||
|
when X"E0" =>
|
||||||
|
-- Initiate a Halt Cycle.
|
||||||
|
FSM_STATE <= HaltCycle;
|
||||||
|
|
||||||
|
-- Set the Refresh Address register.
|
||||||
|
when X"E1" =>
|
||||||
|
REFRESH_ADDR <= CPU_DATA_OUT;
|
||||||
|
|
||||||
|
-- Set the Interrupt Page Address Register.
|
||||||
|
when X"E2" =>
|
||||||
|
IPAR <= CPU_DATA_OUT;
|
||||||
|
|
||||||
|
when others =>
|
||||||
|
end case;
|
||||||
|
|
||||||
|
-- Toggle the processing flag to negate the new data flag. Used to indicate device is busy.
|
||||||
|
if(SPI_NEW_DATA /= SPI_PROCESSING) then
|
||||||
|
SPI_PROCESSING <= not SPI_PROCESSING;
|
||||||
|
end if;
|
||||||
|
|
||||||
|
-- FSM Status bit. When processing a command it is set, cleared when idle. Used by SOM to determine command completion.
|
||||||
|
FSM_STATUS <= '1';
|
||||||
|
end if;
|
||||||
|
|
||||||
|
-- Refresh status bit. Indicates a Refresh cycle is under way.
|
||||||
|
if FSM_STATE = RefreshCycle or FSM_STATE = RefreshCycle_1 or FSM_STATE = RefreshCycle_2 or FSM_STATE = RefreshCycle_3 then
|
||||||
|
RFSH_STATUS <= '1';
|
||||||
|
else
|
||||||
|
RFSH_STATUS <= '0';
|
||||||
|
end if;
|
||||||
|
|
||||||
|
-- FSM to implement all the required Z80 cycles.
|
||||||
|
--
|
||||||
|
case FSM_STATE is
|
||||||
|
when IdleCycle =>
|
||||||
|
|
||||||
|
-----------------------------
|
||||||
|
-- Z80 Fetch Cycle.
|
||||||
|
-----------------------------
|
||||||
|
when FetchCycle =>
|
||||||
|
if(Z80_CLK_RE = '1' or Z80_CLK_LEVEL = '1') then
|
||||||
|
CPU_T_STATE_SET<= 1;
|
||||||
|
CPU_T_STATES <= 4;
|
||||||
|
Z80_M1ni <= '0';
|
||||||
|
FSM_STATE <= FetchCycle_2;
|
||||||
|
end if;
|
||||||
|
|
||||||
|
when FetchCycle_2 =>
|
||||||
|
if(Z80_CLK_FE = '1' and CPU_T_STATE = 1) then
|
||||||
|
Z80_MREQni <= '0';
|
||||||
|
Z80_RDni <= '0';
|
||||||
|
FSM_STATE <= FetchCycle_3;
|
||||||
|
end if;
|
||||||
|
|
||||||
|
when FetchCycle_3 =>
|
||||||
|
if(CPU_T_STATE = 2 and Z80_CLK_FE = '1' and Z80_WAITni = '1') then
|
||||||
|
FSM_STATE <= FetchCycle_4;
|
||||||
|
end if;
|
||||||
|
|
||||||
|
when FetchCycle_4 =>
|
||||||
|
-- To meet the timing diagrams, just after Rising edge on T3 clear signals. Data wont be available until
|
||||||
|
-- a short period before the falling edge of T3 (could be an MZ-700 design restriction or the Z80 timing diagrams are a bit out).
|
||||||
|
if(CPU_T_STATE = 3 and Z80_CLK_RE = '1' and Z80_WAITni = '1') then
|
||||||
|
FSM_STATE <= RefreshCycle;
|
||||||
|
end if;
|
||||||
|
|
||||||
|
-----------------------------
|
||||||
|
-- Z80 Refresh Cycle.
|
||||||
|
-----------------------------
|
||||||
|
when RefreshCycle =>
|
||||||
|
-- Latch data from mainboard.
|
||||||
|
CPU_DATA_IN <= Z80_DATA;
|
||||||
|
FSM_STATUS <= '0';
|
||||||
|
Z80_RFSHni <= '0';
|
||||||
|
FSM_STATE <= RefreshCycle_1;
|
||||||
|
|
||||||
|
when RefreshCycle_1 =>
|
||||||
|
-- Falling edge of T3 activates the MREQ line.
|
||||||
|
if(Z80_CLK_FE = '1' and CPU_T_STATE = 3) then
|
||||||
|
Z80_MREQni <= '0';
|
||||||
|
FSM_STATE <= RefreshCycle_2;
|
||||||
|
end if;
|
||||||
|
|
||||||
|
when RefreshCycle_2 =>
|
||||||
|
if(Z80_CLK_FE = '1' and CPU_T_STATE = 4) then
|
||||||
|
Z80_MREQni <= '1';
|
||||||
|
end if;
|
||||||
|
if(Z80_MREQni = '1' and CPU_T_STATE = 4) then
|
||||||
|
REFRESH_ADDR(6 downto 0) <= REFRESH_ADDR(6 downto 0) + 1;
|
||||||
|
FSM_STATE <= IdleCycle;
|
||||||
|
end if;
|
||||||
|
|
||||||
|
when RefreshCycle_3 =>
|
||||||
|
CPU_T_STATE_SET <= 3;
|
||||||
|
CPU_T_STATES <= 4;
|
||||||
|
Z80_RFSHni <= '0';
|
||||||
|
FSM_STATE <= RefreshCycle_1;
|
||||||
|
|
||||||
|
-----------------------------
|
||||||
|
-- Z80 Write Cycle.
|
||||||
|
-----------------------------
|
||||||
|
when WriteCycle =>
|
||||||
|
FSM_STATUS <= '0';
|
||||||
|
if(Z80_CLK_RE = '1' or Z80_CLK_LEVEL = '1') then
|
||||||
|
CPU_T_STATE_SET<= 1;
|
||||||
|
CPU_T_STATES <= 3;
|
||||||
|
FSM_STATE <= WriteCycle_2;
|
||||||
|
end if;
|
||||||
|
|
||||||
|
when WriteCycle_2 =>
|
||||||
|
if(Z80_CLK_FE = '1' and CPU_T_STATE = 1) then
|
||||||
|
Z80_MREQni <= '0';
|
||||||
|
CPU_DATA_EN <= '1';
|
||||||
|
FSM_STATE <= WriteCycle_3;
|
||||||
|
end if;
|
||||||
|
|
||||||
|
when WriteCycle_3 =>
|
||||||
|
if(CPU_T_STATE = 2 and Z80_CLK_FE = '1' and Z80_WAITni = '1') then
|
||||||
|
Z80_WRni <= '0';
|
||||||
|
FSM_STATE <= WriteCycle_4;
|
||||||
|
end if;
|
||||||
|
|
||||||
|
when WriteCycle_4 =>
|
||||||
|
if(CPU_T_STATE = 3 and Z80_CLK_FE = '1' and Z80_WAITni = '1') then
|
||||||
|
Z80_MREQni <= '1';
|
||||||
|
Z80_WRni <= '1';
|
||||||
|
FSM_STATE <= IdleCycle;
|
||||||
|
end if;
|
||||||
|
|
||||||
|
|
||||||
|
-----------------------------
|
||||||
|
-- Z80 Read Cycle.
|
||||||
|
-----------------------------
|
||||||
|
when ReadCycle =>
|
||||||
|
if(Z80_CLK_RE = '1' or Z80_CLK_LEVEL = '1') then
|
||||||
|
CPU_T_STATE_SET<= 1;
|
||||||
|
CPU_T_STATES <= 3;
|
||||||
|
FSM_STATE <= ReadCycle_2;
|
||||||
|
end if;
|
||||||
|
|
||||||
|
when ReadCycle_2 =>
|
||||||
|
if(Z80_CLK_FE = '1' and CPU_T_STATE = 1) then
|
||||||
|
Z80_MREQni <= '0';
|
||||||
|
Z80_RDni <= '0';
|
||||||
|
FSM_STATE <= ReadCycle_3;
|
||||||
|
end if;
|
||||||
|
|
||||||
|
when ReadCycle_3 =>
|
||||||
|
if(CPU_T_STATE = 2 and Z80_CLK_FE = '1' and Z80_WAITni = '1') then
|
||||||
|
FSM_STATE <= ReadCycle_4;
|
||||||
|
end if;
|
||||||
|
|
||||||
|
when ReadCycle_4 =>
|
||||||
|
if(CPU_T_STATE = 3 and Z80_CLK_FE = '1' and Z80_WAITni = '1') then
|
||||||
|
-- Latch data from mainboard.
|
||||||
|
CPU_DATA_IN <= Z80_DATA;
|
||||||
|
FSM_STATUS <= '0';
|
||||||
|
|
||||||
|
-- MREQ/RD are deactivated at idle giving 1 clock to latch the data in.
|
||||||
|
FSM_STATE <= IdleCycle;
|
||||||
|
end if;
|
||||||
|
|
||||||
|
|
||||||
|
-----------------------------
|
||||||
|
-- Z80 IO Write Cycle.
|
||||||
|
-----------------------------
|
||||||
|
when WriteIOCycle =>
|
||||||
|
FSM_STATUS <= '0';
|
||||||
|
if(Z80_CLK_RE = '1' or Z80_CLK_LEVEL = '1') then
|
||||||
|
CPU_T_STATE_SET<= 1;
|
||||||
|
CPU_T_STATES <= 4;
|
||||||
|
FSM_STATE <= WriteIOCycle_2;
|
||||||
|
end if;
|
||||||
|
|
||||||
|
when WriteIOCycle_2 =>
|
||||||
|
if(Z80_CLK_FE = '1') then
|
||||||
|
CPU_DATA_EN <= '1';
|
||||||
|
FSM_STATE <= WriteIOCycle_3;
|
||||||
|
end if;
|
||||||
|
|
||||||
|
when WriteIOCycle_3 =>
|
||||||
|
if(Z80_CLK_FE = '1' and CPU_T_STATE = 2) then
|
||||||
|
Z80_IORQni <= '0';
|
||||||
|
Z80_WRni <= '0';
|
||||||
|
FSM_STATE <= WriteIOCycle_4;
|
||||||
|
end if;
|
||||||
|
|
||||||
|
when WriteIOCycle_4 =>
|
||||||
|
-- Add automatic Wait State (called T3 here but actually TW).
|
||||||
|
if(CPU_T_STATE = 3 and Z80_CLK_FE = '1' and Z80_WAITni = '1') then
|
||||||
|
FSM_STATE <= WriteIOCycle_5;
|
||||||
|
end if;
|
||||||
|
|
||||||
|
when WriteIOCycle_5 =>
|
||||||
|
if(CPU_T_STATE = 4 and Z80_CLK_FE = '1' and Z80_WAITni = '1') then
|
||||||
|
Z80_IORQni <= '1';
|
||||||
|
Z80_WRni <= '1';
|
||||||
|
FSM_STATE <= IdleCycle;
|
||||||
|
end if;
|
||||||
|
|
||||||
|
-----------------------------
|
||||||
|
-- Z80 IO Read Cycle.
|
||||||
|
-----------------------------
|
||||||
|
when ReadIOCycle =>
|
||||||
|
if(Z80_CLK_RE = '1' or Z80_CLK_LEVEL = '1') then
|
||||||
|
CPU_T_STATE_SET<= 1;
|
||||||
|
CPU_T_STATES <= 4;
|
||||||
|
FSM_STATE <= ReadIOCycle_2;
|
||||||
|
end if;
|
||||||
|
|
||||||
|
when ReadIOCycle_2 =>
|
||||||
|
if(Z80_CLK_FE = '1' and CPU_T_STATE = 2) then
|
||||||
|
Z80_IORQni <= '0';
|
||||||
|
Z80_RDni <= '0';
|
||||||
|
FSM_STATE <= ReadIOCycle_3;
|
||||||
|
end if;
|
||||||
|
|
||||||
|
when ReadIOCycle_3 =>
|
||||||
|
-- Add automatic Wait State.
|
||||||
|
if(CPU_T_STATE = 3 and Z80_CLK_FE = '1' and Z80_WAITni = '1') then
|
||||||
|
CPU_T_STATE_SET<= 2;
|
||||||
|
FSM_STATE <= ReadIOCycle_4;
|
||||||
|
end if;
|
||||||
|
|
||||||
|
when ReadIOCycle_4 =>
|
||||||
|
if(CPU_T_STATE = 4 and Z80_CLK_FE = '1' and Z80_WAITni = '1') then
|
||||||
|
-- Latch data from mainboard.
|
||||||
|
CPU_DATA_IN <= Z80_DATA;
|
||||||
|
FSM_STATUS <= '0';
|
||||||
|
|
||||||
|
-- IORA/RD are deactivated at idle giving 1 clock to latch the data in.
|
||||||
|
FSM_STATE <= IdleCycle;
|
||||||
|
end if;
|
||||||
|
|
||||||
|
-----------------------------
|
||||||
|
-- Halt Request.
|
||||||
|
-----------------------------
|
||||||
|
when HaltCycle =>
|
||||||
|
Z80_HALTni <= '0';
|
||||||
|
FSM_STATUS <= '0';
|
||||||
|
FSM_STATE <= IdleCycle;
|
||||||
|
|
||||||
|
-----------------------------
|
||||||
|
-- Z80 Bus Request.
|
||||||
|
-----------------------------
|
||||||
|
when BusReqCycle =>
|
||||||
|
Z80_BUSRQ_ACKni <= '0';
|
||||||
|
FSM_STATE <= IdleCycle;
|
||||||
|
end case;
|
||||||
|
|
||||||
|
VCPU_CS_EDGE <= VCPU_CS_EDGE(0) & VSOM_SPI_CSn;
|
||||||
|
end if;
|
||||||
|
end process;
|
||||||
|
|
||||||
|
-- CPU Interface tri-state control based on acknowledged bus request.
|
||||||
|
Z80_ADDR <= IPAR & REFRESH_ADDR when Z80_RFSHni = '0'
|
||||||
|
else
|
||||||
|
CPU_ADDR when Z80_BUSRQ_ACKni = '1'
|
||||||
|
else
|
||||||
|
(others => 'Z');
|
||||||
|
Z80_DATA <= CPU_DATA_OUT when Z80_BUSRQ_ACKni = '1' and CPU_DATA_EN = '1'
|
||||||
|
else
|
||||||
|
(others => 'Z');
|
||||||
|
-- Z80_DATAi <= Z80_DATA when Z80_RDn = '0'
|
||||||
|
-- else (others => '1');
|
||||||
|
Z80_RDn <= Z80_RDni when Z80_BUSRQ_ACKni = '1'
|
||||||
|
else 'Z';
|
||||||
|
Z80_WRn <= Z80_WRni when Z80_BUSRQ_ACKni = '1'
|
||||||
|
else 'Z';
|
||||||
|
Z80_M1n <= Z80_M1ni when Z80_BUSRQ_ACKni = '1'
|
||||||
|
else 'Z';
|
||||||
|
Z80_RFSHn <= Z80_RFSHni when Z80_BUSRQ_ACKni = '1'
|
||||||
|
else 'Z';
|
||||||
|
Z80_MREQn <= Z80_MREQni when Z80_BUSRQ_ACKni = '1'
|
||||||
|
else 'Z';
|
||||||
|
Z80_IORQn <= Z80_IORQni when Z80_BUSRQ_ACKni = '1'
|
||||||
|
else 'Z';
|
||||||
|
Z80_BUSAKn <= Z80_BUSRQ_ACKni;
|
||||||
|
|
||||||
|
-- CPU Interface single state output.
|
||||||
|
Z80_HALTn <= Z80_HALTni;
|
||||||
|
|
||||||
|
-- CPU Interface single state input.
|
||||||
|
Z80_NMIni <= Z80_NMIn;
|
||||||
|
Z80_INTni <= Z80_INTn;
|
||||||
|
Z80_WAITni <= Z80_WAITn;
|
||||||
|
Z80_BUSRQni <= Z80_BUSRQn;
|
||||||
|
|
||||||
|
-- SOM Reset.
|
||||||
|
PM_RESET <= PM_RESETi;
|
||||||
|
|
||||||
|
-- SOM to CPLD Interface.
|
||||||
|
VSOM_DATA_OUT <= CPU_DATA_IN when VSOM_HBYTE = '1'
|
||||||
|
else
|
||||||
|
FSM_STATUS & RFSH_STATUS & Z80_BUSRQ_ACKni & Z80_BUSRQn & Z80_INTn & Z80_NMIn & Z80_WAITn & Z80_RESETn when VSOM_HBYTE = '0'
|
||||||
|
else
|
||||||
|
(others => '0');
|
||||||
|
|
||||||
|
-- Loopback test, echo what was received.
|
||||||
|
SPI_TX_DATA <= SPI_RX_DATA when SPI_LOOPBACK_TEST = '1'
|
||||||
|
else
|
||||||
|
CPU_ADDR & CPU_DATA_IN & FSM_STATUS & RFSH_STATUS & Z80_BUSRQ_ACKni & Z80_BUSRQn & Z80_INTn & Z80_NMIn & Z80_WAITn & Z80_RESETn;
|
||||||
|
|
||||||
|
-- Signal mirrors.
|
||||||
|
VSOM_READY <= '0' when FSM_STATUS='1' or SPI_NEW_DATA /= SPI_PROCESSING
|
||||||
|
else '1'; -- FSM Ready (1), Busy (0)
|
||||||
|
VSOM_LTSTATE <= '1' when CPU_LAST_T_STATE = '1' -- Last T-State in current cycle.
|
||||||
|
else '0';
|
||||||
|
VSOM_BUSRQ <= not Z80_BUSRQn; -- Host device requesting Z80 Bus.
|
||||||
|
VSOM_BUSACK <= not Z80_BUSRQ_ACKni; -- Host device granted Z80 Bus
|
||||||
|
VSOM_INT <= not Z80_INTn; -- Z80 INT signal
|
||||||
|
VSOM_NMI <= not Z80_NMIn; -- Z80 NMI signal
|
||||||
|
VSOM_WAIT <= not Z80_WAITn; -- Z80 WAIT signal
|
||||||
|
VSOM_RESET <= not VSOM_RESETni; -- Z80 RESET signal
|
||||||
|
VSOM_RSV <= (others => '0'); -- Reserved pins.
|
||||||
|
|
||||||
|
-- Video/Audio control signals.
|
||||||
|
VIDEO_SRC <= VIDEO_SRCi;
|
||||||
|
MONO_VIDEO_SRC <= MONO_VIDEO_SRCi;
|
||||||
|
AUDIO_SRC_L <= AUDIO_SRC_Li;
|
||||||
|
AUDIO_SRC_R <= AUDIO_SRC_Ri;
|
||||||
|
|
||||||
|
-- USB Power Supply enable.
|
||||||
|
VBUS_EN <= VBUS_ENi;
|
||||||
|
|
||||||
|
-- Monochrome output is based on the incoming VGA to give the best chrominance levels.
|
||||||
|
MONO_R <= VGA_R;
|
||||||
|
MONO_G <= VGA_G;
|
||||||
|
MONO_B <= VGA_B;
|
||||||
|
|
||||||
|
-- Blanking is active when all colour signals are at 0. The DAC converts values in range 4v .. 5v to adjust chrominance
|
||||||
|
-- but true off can obly be achieved by bringing the signal value to 0v which is achieved by a Mux activated with this blanking signal.
|
||||||
|
MONO_BLANKn <= '0' when VGA_R = "000" and VGA_G = "000" and VGA_B = "000"
|
||||||
|
else '1';
|
||||||
|
|
||||||
|
-- Generate composite sync.
|
||||||
|
VGA_CSYNCn <= VGA_HSYNCn xor not VGA_VSYNCn;
|
||||||
|
MONO_CSYNCn <= VGA_HSYNCn xor not VGA_VSYNCn;
|
||||||
|
|
||||||
|
-- DAC clocks.
|
||||||
|
--VGA_PXL_CLK <= CLK_50M;
|
||||||
|
MONO_PXL_CLK <= VGA_PXL_CLK;
|
||||||
|
|
||||||
|
end architecture;
|
||||||
222
CPLD/v1.0/MZ700/tzpuFusionX_Toplevel.vhd
Normal file
@@ -0,0 +1,222 @@
|
|||||||
|
---------------------------------------------------------------------------------------------------------
|
||||||
|
--
|
||||||
|
-- Name: tzpuFusionX_Toplevel.vhd
|
||||||
|
-- Version: MZ-700
|
||||||
|
-- Created: June 2020
|
||||||
|
-- Author(s): Philip Smart
|
||||||
|
-- Description: tzpuFusionX CPLD Top Level module.
|
||||||
|
--
|
||||||
|
-- This module contains the basic pin definition of the CPLD<->logic needed in the
|
||||||
|
-- project which targets the MZ-700 host.
|
||||||
|
--
|
||||||
|
-- Credits:
|
||||||
|
-- Copyright: (c) 2018-22 Philip Smart <philip.smart@net2net.org>
|
||||||
|
--
|
||||||
|
-- History: June 2020 - Snapshot taken from the MZ80A version of the tranZPUter SW-700 source.
|
||||||
|
--
|
||||||
|
---------------------------------------------------------------------------------------------------------
|
||||||
|
-- This source file is free software: you can redistribute it and-or modify
|
||||||
|
-- it under the terms of the GNU General Public License as published
|
||||||
|
-- by the Free Software Foundation, either version 3 of the License, or
|
||||||
|
-- (at your option) any later version.
|
||||||
|
--
|
||||||
|
-- This source file is distributed in the hope that it will be useful,
|
||||||
|
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
-- GNU General Public License for more details.
|
||||||
|
--
|
||||||
|
-- along with this program. If not, see <http:--www.gnu.org-licenses->.
|
||||||
|
---------------------------------------------------------------------------------------------------------
|
||||||
|
library IEEE;
|
||||||
|
use IEEE.std_logic_1164.all;
|
||||||
|
use IEEE.numeric_std.all;
|
||||||
|
use work.tzpuFusionX_pkg.all;
|
||||||
|
library altera;
|
||||||
|
use altera.altera_syn_attributes.all;
|
||||||
|
|
||||||
|
entity tzpuFusionX_MZ700 is
|
||||||
|
port (
|
||||||
|
-- Z80 Address Bus
|
||||||
|
Z80_ADDR : inout std_logic_vector(15 downto 0);
|
||||||
|
|
||||||
|
-- Z80 Data Bus
|
||||||
|
Z80_DATA : inout std_logic_vector(7 downto 0);
|
||||||
|
|
||||||
|
-- Z80 Control signals.
|
||||||
|
Z80_BUSRQn : in std_logic;
|
||||||
|
Z80_BUSAKn : out std_logic;
|
||||||
|
Z80_INTn : in std_logic;
|
||||||
|
Z80_IORQn : inout std_logic;
|
||||||
|
Z80_MREQn : inout std_logic;
|
||||||
|
Z80_NMIn : in std_logic;
|
||||||
|
Z80_RDn : inout std_logic;
|
||||||
|
Z80_WRn : inout std_logic;
|
||||||
|
Z80_RESETn : in std_logic; -- Host CPU Reset signal, also CPLD reset.
|
||||||
|
Z80_HALTn : out std_logic;
|
||||||
|
Z80_WAITn : in std_logic;
|
||||||
|
Z80_M1n : inout std_logic;
|
||||||
|
Z80_RFSHn : inout std_logic;
|
||||||
|
|
||||||
|
-- SOM SPI
|
||||||
|
VSOM_SPI_CSn : in std_logic; -- SPI Slave Select
|
||||||
|
VSOM_SPI_CLK : in std_logic; -- SPI Clock
|
||||||
|
VSOM_SPI_MOSI : in std_logic; -- SPI Master Output Slave Input
|
||||||
|
VSOM_SPI_MISO : out std_logic; -- SPI Master Input Slave Output
|
||||||
|
|
||||||
|
-- SOM Parallel Bus.
|
||||||
|
VSOM_DATA_OUT : out std_logic_vector(7 downto 0); -- Address/Data bus for CPLD control registers.
|
||||||
|
VSOM_HBYTE : in std_logic; -- Parallel Bus High (1)/Low (0) byte.
|
||||||
|
VSOM_READY : out std_logic; -- FSM Ready (1), Busy (0)
|
||||||
|
VSOM_LTSTATE : out std_logic; -- Last T-State in current cycle, 1 = active.
|
||||||
|
VSOM_BUSRQ : out std_logic; -- Host device requesting Z80 Bus.
|
||||||
|
VSOM_BUSACK : out std_logic; -- Host device granted Z80 Bus
|
||||||
|
VSOM_INT : out std_logic; -- Z80 INT signal
|
||||||
|
VSOM_NMI : out std_logic; -- Z80 NMI signal
|
||||||
|
VSOM_WAIT : out std_logic; -- Z80 WAIT signal
|
||||||
|
VSOM_RESET : out std_logic; -- Z80 RESET signal
|
||||||
|
VSOM_RSV : out std_logic_vector(1 downto 1); -- Reserved pins.
|
||||||
|
|
||||||
|
-- SOM Control Signals
|
||||||
|
PM_RESET : out std_logic; -- Reset SOM
|
||||||
|
|
||||||
|
-- VGA_Palette Control
|
||||||
|
VGA_R : in std_logic_vector(9 downto 7); -- Signals used for detecting blank or no video output.
|
||||||
|
VGA_G : in std_logic_vector(9 downto 7);
|
||||||
|
VGA_B : in std_logic_vector(9 downto 8);
|
||||||
|
|
||||||
|
-- VGA Control Signals
|
||||||
|
VGA_PXL_CLK : in std_logic; -- VGA Pixel clock for DAC conversion.
|
||||||
|
VGA_DISPEN : in std_logic; -- Displayed Enabled (SOM video output).
|
||||||
|
VGA_VSYNCn : in std_logic; -- SOM VSync.
|
||||||
|
VGA_HSYNCn : in std_logic; -- SOM HSync.
|
||||||
|
VGA_COLR : out std_logic; -- COLR colour carrier frequency.
|
||||||
|
VGA_CSYNCn : out std_logic; -- VGA Composite Sync.
|
||||||
|
VGA_BLANKn : out std_logic; -- VGA Blank detected.
|
||||||
|
|
||||||
|
-- CRT Control Signals
|
||||||
|
MONO_PXL_CLK : out std_logic; -- Mono CRT pixel clock for DAC conversion.
|
||||||
|
MONO_BLANKn : out std_logic; -- Mono CRT Blank (no active pixel) detection.
|
||||||
|
MONO_CSYNCn : out std_logic; -- Mono CRT composite sync.
|
||||||
|
MONO_RSV : out std_logic;
|
||||||
|
|
||||||
|
-- CRT Lower Chrominance Control
|
||||||
|
MONO_R : out std_logic_vector(2 downto 0); -- Signals to fine tune Red level of monochrome chrominance.
|
||||||
|
MONO_G : out std_logic_vector(2 downto 0); -- Signals to fine tune Green level of monochrome chrominance.
|
||||||
|
MONO_B : out std_logic_vector(2 downto 1); -- Signals to fine tune Blue level of monochrome chrominance.
|
||||||
|
|
||||||
|
-- MUX Control Signals
|
||||||
|
VIDEO_SRC : out std_logic; -- Select video source, Mainboard or SOM.
|
||||||
|
MONO_VIDEO_SRC : out std_logic; -- Select crt video source, Mainboard or SOM.
|
||||||
|
AUDIO_SRC_L : out std_logic; -- Select Audio Source Left Channel, Mainboard or SOM.
|
||||||
|
AUDIO_SRC_R : out std_logic; -- Select Audio Source Right Channel, Mainboard or SOM.
|
||||||
|
|
||||||
|
-- Mainboard Reset Signals
|
||||||
|
MB_RESETn : in std_logic; -- Motherboard Reset pressed.
|
||||||
|
MB_IPLn : in std_logic; -- Motherboard IPL pressed.
|
||||||
|
|
||||||
|
-- USB Power Control
|
||||||
|
VBUS_EN : out std_logic; -- USB Enable Power Output
|
||||||
|
|
||||||
|
-- Clocks.
|
||||||
|
Z80_CLK : in std_logic; -- Host CPU Clock
|
||||||
|
CLK_50M : in std_logic -- 50MHz oscillator.
|
||||||
|
);
|
||||||
|
END entity;
|
||||||
|
|
||||||
|
architecture rtl of tzpuFusionX_MZ700 is
|
||||||
|
|
||||||
|
begin
|
||||||
|
|
||||||
|
cpldl512Toplevel : entity work.cpld512
|
||||||
|
generic map (
|
||||||
|
SPI_CLK_POLARITY => '0'
|
||||||
|
)
|
||||||
|
port map
|
||||||
|
(
|
||||||
|
-- Z80 Address Bus
|
||||||
|
Z80_ADDR => Z80_ADDR,
|
||||||
|
|
||||||
|
-- Z80 Data Bus
|
||||||
|
Z80_DATA => Z80_DATA,
|
||||||
|
|
||||||
|
-- Z80 Control signals.
|
||||||
|
Z80_BUSRQn => Z80_BUSRQn,
|
||||||
|
Z80_BUSAKn => Z80_BUSAKn,
|
||||||
|
Z80_INTn => Z80_INTn,
|
||||||
|
Z80_IORQn => Z80_IORQn,
|
||||||
|
Z80_MREQn => Z80_MREQn,
|
||||||
|
Z80_NMIn => Z80_NMIn,
|
||||||
|
Z80_RDn => Z80_RDn,
|
||||||
|
Z80_WRn => Z80_WRn,
|
||||||
|
Z80_RESETn => Z80_RESETn,
|
||||||
|
Z80_HALTn => Z80_HALTn,
|
||||||
|
Z80_WAITn => Z80_WAITn,
|
||||||
|
Z80_M1n => Z80_M1n,
|
||||||
|
Z80_RFSHn => Z80_RFSHn,
|
||||||
|
|
||||||
|
-- SOM SPI
|
||||||
|
VSOM_SPI_CSn => VSOM_SPI_CSn, -- SPI Slave Select
|
||||||
|
VSOM_SPI_CLK => VSOM_SPI_CLK, -- SPI Clock
|
||||||
|
VSOM_SPI_MOSI => VSOM_SPI_MOSI, -- SPI Master Output Slave Input
|
||||||
|
VSOM_SPI_MISO => VSOM_SPI_MISO, -- SPI Master Input Slave Output
|
||||||
|
|
||||||
|
-- SOM Parallel Bus.
|
||||||
|
VSOM_DATA_OUT => VSOM_DATA_OUT, -- Address/Data bus for CPLD control registers.
|
||||||
|
VSOM_HBYTE => VSOM_HBYTE, -- Parallel Bus High (1)/Low (0) byte.
|
||||||
|
VSOM_READY => VSOM_READY, -- FSM Ready (1), Busy (0)
|
||||||
|
VSOM_LTSTATE => VSOM_LTSTATE, -- Last T-State in current cycle.
|
||||||
|
VSOM_BUSRQ => VSOM_BUSRQ, -- Host device requesting Z80 Bus.
|
||||||
|
VSOM_BUSACK => VSOM_BUSACK, -- Host device granted Z80 Bus
|
||||||
|
VSOM_INT => VSOM_INT, -- Z80 INT signal
|
||||||
|
VSOM_NMI => VSOM_NMI, -- Z80 NMI signal
|
||||||
|
VSOM_WAIT => VSOM_WAIT, -- Z80 WAIT signal
|
||||||
|
VSOM_RESET => VSOM_RESET, -- Z80 RESET signal
|
||||||
|
VSOM_RSV => VSOM_RSV, -- Reserved pins.
|
||||||
|
|
||||||
|
-- SOM Control Signals
|
||||||
|
PM_RESET => PM_RESET, -- Reset SOM
|
||||||
|
|
||||||
|
-- VGA_Palette Control
|
||||||
|
VGA_R => VGA_R, -- Signals used for detecting blank or no video output.
|
||||||
|
VGA_G => VGA_G,
|
||||||
|
VGA_B => VGA_B,
|
||||||
|
|
||||||
|
-- VGA Control Signals
|
||||||
|
VGA_PXL_CLK => VGA_PXL_CLK, -- VGA Pixel clock for DAC conversion.
|
||||||
|
VGA_DISPEN => VGA_DISPEN, -- Displayed Enabled (SOM video output).
|
||||||
|
VGA_VSYNCn => VGA_VSYNCn, -- SOM VSync.
|
||||||
|
VGA_HSYNCn => VGA_HSYNCn, -- SOM HSync.
|
||||||
|
VGA_COLR => VGA_COLR, -- COLR colour carrier frequency.
|
||||||
|
VGA_CSYNCn => VGA_CSYNCn, -- VGA Composite Sync.
|
||||||
|
VGA_BLANKn => VGA_BLANKn, -- VGA Blank detected.
|
||||||
|
|
||||||
|
-- CRT Control Signals
|
||||||
|
MONO_PXL_CLK => MONO_PXL_CLK, -- Mono CRT pixel clock for DAC conversion.
|
||||||
|
MONO_BLANKn => MONO_BLANKn, -- Mono CRT Blank (no active pixel) detection.
|
||||||
|
MONO_CSYNCn => MONO_CSYNCn, -- Mono CRT composite sync.
|
||||||
|
MONO_RSV => MONO_RSV,
|
||||||
|
|
||||||
|
-- CRT Lower Chrominance Control
|
||||||
|
MONO_R => MONO_R, -- Signals to fine tune Red level of monochrome chrominance.
|
||||||
|
MONO_G => MONO_G, -- Signals to fine tune Green level of monochrome chrominance.
|
||||||
|
MONO_B => MONO_B, -- Signals to fine tune Blue level of monochrome chrominance.
|
||||||
|
|
||||||
|
-- MUX Control Signals
|
||||||
|
VIDEO_SRC => VIDEO_SRC, -- Select video source, Mainboard or SOM.
|
||||||
|
MONO_VIDEO_SRC => MONO_VIDEO_SRC, -- Select crt video source, Mainboard or SOM.
|
||||||
|
AUDIO_SRC_L => AUDIO_SRC_L, -- Select Audio Source Left Channel, Mainboard or SOM.
|
||||||
|
AUDIO_SRC_R => AUDIO_SRC_R, -- Select Audio Source Right Channel, Mainboard or SOM.
|
||||||
|
|
||||||
|
-- Mainboard Reset Signals=> MONO_R,
|
||||||
|
MB_RESETn => MB_RESETn, -- Motherboard Reset pressed.
|
||||||
|
MB_IPLn => MB_IPLn, -- Motherboard IPL pressed.
|
||||||
|
|
||||||
|
-- USB Power Control
|
||||||
|
VBUS_EN => VBUS_EN, -- USB Enable Power Output
|
||||||
|
|
||||||
|
-- Clocks.
|
||||||
|
Z80_CLK => Z80_CLK, -- Host CPU Clock
|
||||||
|
CLK_50M => CLK_50M -- 50MHz oscillator.
|
||||||
|
);
|
||||||
|
|
||||||
|
end architecture;
|
||||||
221
CPLD/v1.0/MZ700/tzpuFusionX_pkg.vhd
Normal file
@@ -0,0 +1,221 @@
|
|||||||
|
---------------------------------------------------------------------------------------------------------
|
||||||
|
--
|
||||||
|
-- Name: tzpuFusionX_pkg.vhd
|
||||||
|
-- Created: June 2020
|
||||||
|
-- Author(s): Philip Smart
|
||||||
|
-- Description: tzpuFusionX CPLD configuration file.
|
||||||
|
--
|
||||||
|
-- This module contains parameters for the CPLD in the tzpuFusionX project
|
||||||
|
-- which targets the MZ-700 host.
|
||||||
|
--
|
||||||
|
-- Credits:
|
||||||
|
-- Copyright: (c) 2018-22 Philip Smart <philip.smart@net2net.org>
|
||||||
|
--
|
||||||
|
-- History: June 2020 - Snapshot taken from the MZ700 version of the tranZPUter SW-700 source.
|
||||||
|
--
|
||||||
|
---------------------------------------------------------------------------------------------------------
|
||||||
|
-- This source file is free software: you can redistribute it and-or modify
|
||||||
|
-- it under the terms of the GNU General Public License as published
|
||||||
|
-- by the Free Software Foundation, either version 3 of the License, or
|
||||||
|
-- (at your option) any later version.
|
||||||
|
--
|
||||||
|
-- This source file is distributed in the hope that it will be useful,
|
||||||
|
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
-- GNU General Public License for more details.
|
||||||
|
--
|
||||||
|
-- You should have received a copy of the GNU General Public License
|
||||||
|
-- along with this program. If not, see <http:--www.gnu.org-licenses->.
|
||||||
|
---------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
library ieee;
|
||||||
|
library pkgs;
|
||||||
|
use ieee.std_logic_1164.all;
|
||||||
|
use ieee.numeric_std.all;
|
||||||
|
use ieee.math_real.all;
|
||||||
|
|
||||||
|
package tzpuFusionX_pkg is
|
||||||
|
|
||||||
|
------------------------------------------------------------
|
||||||
|
-- Constants
|
||||||
|
------------------------------------------------------------
|
||||||
|
|
||||||
|
-- Potential logic state constants.
|
||||||
|
constant YES : std_logic := '1';
|
||||||
|
constant NO : std_logic := '0';
|
||||||
|
constant HI : std_logic := '1';
|
||||||
|
constant LO : std_logic := '0';
|
||||||
|
constant ONE : std_logic := '1';
|
||||||
|
constant ZERO : std_logic := '0';
|
||||||
|
constant HIZ : std_logic := 'Z';
|
||||||
|
|
||||||
|
-- CPLD Command instructions.
|
||||||
|
constant CPLD_CMD_RESET_HOST : integer := 1;
|
||||||
|
constant CPLD_CMD_HOLD_HOST_BUS : integer := 2;
|
||||||
|
constant CPLD_CMD_RELEASE_HOST_BUS: integer := 3;
|
||||||
|
|
||||||
|
-- Target hardware modes.
|
||||||
|
constant MODE_MZ80K : integer := 0;
|
||||||
|
constant MODE_MZ80C : integer := 1;
|
||||||
|
constant MODE_MZ1200 : integer := 2;
|
||||||
|
constant MODE_MZ80A : integer := 3;
|
||||||
|
constant MODE_MZ700 : integer := 4;
|
||||||
|
constant MODE_MZ800 : integer := 5;
|
||||||
|
constant MODE_MZ80B : integer := 6;
|
||||||
|
constant MODE_MZ2000 : integer := 7;
|
||||||
|
|
||||||
|
-- Memory management modes.
|
||||||
|
constant TZMM_ORIG : integer := 00; -- Original Sharp mode, no tranZPUter features are selected except the I/O control registers (default: 0x60-063).
|
||||||
|
constant TZMM_BOOT : integer := 01; -- Original mode but E800-EFFF is mapped to tranZPUter RAM so TZFS can be booted.
|
||||||
|
constant TZMM_TZFS : integer := 02; -- TZFS main memory configuration. all memory is in tranZPUter RAM, E800-FFFF is used by TZFS, SA1510 is at 0000-1000 and RAM is 1000-CFFF, 64K Block 0 selected.
|
||||||
|
constant TZMM_TZFS2 : integer := 03; -- TZFS main memory configuration. all memory is in tranZPUter RAM, E800-EFFF is used by TZFS, SA1510 is at 0000-1000 and RAM is 1000-CFFF, 64K Block 0 selected, F000-FFFF is in 64K Block 1.
|
||||||
|
constant TZMM_TZFS3 : integer := 04; -- TZFS main memory configuration. all memory is in tranZPUter RAM, E800-EFFF is used by TZFS, SA1510 is at 0000-1000 and RAM is 1000-CFFF, 64K Block 0 selected, F000-FFFF is in 64K Block 2.
|
||||||
|
constant TZMM_TZFS4 : integer := 05; -- TZFS main memory configuration. all memory is in tranZPUter RAM, E800-EFFF is used by TZFS, SA1510 is at 0000-1000 and RAM is 1000-CFFF, 64K Block 0 selected, F000-FFFF is in 64K Block 3.
|
||||||
|
constant TZMM_CPM : integer := 06; -- CPM main memory configuration, all memory on the tranZPUter board, 64K block 4 selected. Special case for F3C0:F3FF & F7C0:F7FF (floppy disk paging vectors) which resides on the mainboard.
|
||||||
|
constant TZMM_CPM2 : integer := 07; -- CPM main memory configuration, F000-FFFF are on the tranZPUter board in block 4, 0040-CFFF and E800-EFFF are in block 5, mainboard for D000-DFFF (video), E000-E800 (Memory control) selected.
|
||||||
|
-- Special case for 0000:003F (interrupt vectors) which resides in block 4, F3FE:F3FF & F7FE:F7FF (floppy disk paging vectors) which resides on the mainboard.
|
||||||
|
constant TZMM_COMPAT : integer := 08; -- Compatibility monitor mode, monitor ROM on mainboard, RAM on tranZPUter in Block 0 1000-CFFF.
|
||||||
|
constant TZMM_HOSTACCESS : integer := 09; -- Monitor ROM 0000-0FFF and Main DRAM 0x1000-0xD000, video and memory mapped I/O are on the host machine, User/Floppy ROM E800-FFFF are in tranZPUter memory.
|
||||||
|
constant TZMM_MZ700_0 : integer := 10; -- MZ700 Mode - 0000:0FFF is on the tranZPUter board in block 6, 1000:CFFF is on the tranZPUter board in block 0, D000:FFFF is on the mainboard.
|
||||||
|
constant TZMM_MZ700_1 : integer := 11; -- MZ700 Mode - 0000:0FFF is on the tranZPUter board in block 0, 1000:CFFF is on the tranZPUter board in block 0, D000:FFFF is on the tranZPUter in block 6.
|
||||||
|
constant TZMM_MZ700_2 : integer := 12; -- MZ700 Mode - 0000:0FFF is on the tranZPUter board in block 6, 1000:CFFF is on the tranZPUter board in block 0, D000:FFFF is on the tranZPUter in block 6.
|
||||||
|
constant TZMM_MZ700_3 : integer := 13; -- MZ700 Mode - 0000:0FFF is on the tranZPUter board in block 0, 1000:CFFF is on the tranZPUter board in block 0, D000:FFFF is inaccessible.
|
||||||
|
constant TZMM_MZ700_4 : integer := 14; -- MZ700 Mode - 0000:0FFF is on the tranZPUter board in block 6, 1000:CFFF is on the tranZPUter board in block 0, D000:FFFF is inaccessible.
|
||||||
|
constant TZMM_MZ800 : integer := 15; -- MZ800 Mode - Running on MZ800 hardware, configuration set according to MZ700/MZ800 mode.
|
||||||
|
constant TZMM_MZ2000 : integer := 16; -- MZ2000 Mode - Running on MZ2000 hardware, configuration set according to runtime configuration registers.
|
||||||
|
constant TZMM_FPGA : integer := 21; -- Open up access for the K64F to the FPGA resources such as memory. All other access to RAM or mainboard is blocked.
|
||||||
|
constant TZMM_TZPUM : integer := 22; -- Everything in on mainboard, no access to tranZPUter memory.
|
||||||
|
constant TZMM_TZPU : integer := 23; -- Everything is in tranZPUter domain, no access to underlying Sharp mainboard unless memory management mode is switched. tranZPUter RAM 64K block 0 is selected.
|
||||||
|
constant TZMM_TZPU0 : integer := 24; -- Everything is in tranZPUter domain, no access to underlying Sharp mainboard unless memory management mode is switched. tranZPUter RAM 64K block 0 is selected.
|
||||||
|
constant TZMM_TZPU1 : integer := 25; -- Everything is in tranZPUter domain, no access to underlying Sharp mainboard unless memory management mode is switched. tranZPUter RAM 64K block 1 is selected.
|
||||||
|
constant TZMM_TZPU2 : integer := 26; -- Everything is in tranZPUter domain, no access to underlying Sharp mainboard unless memory management mode is switched. tranZPUter RAM 64K block 2 is selected.
|
||||||
|
constant TZMM_TZPU3 : integer := 27; -- Everything is in tranZPUter domain, no access to underlying Sharp mainboard unless memory management mode is switched. tranZPUter RAM 64K block 3 is selected.
|
||||||
|
constant TZMM_TZPU4 : integer := 28; -- Everything is in tranZPUter domain, no access to underlying Sharp mainboard unless memory management mode is switched. tranZPUter RAM 64K block 4 is selected.
|
||||||
|
constant TZMM_TZPU5 : integer := 29; -- Everything is in tranZPUter domain, no access to underlying Sharp mainboard unless memory management mode is switched. tranZPUter RAM 64K block 5 is selected.
|
||||||
|
constant TZMM_TZPU6 : integer := 30; -- Everything is in tranZPUter domain, no access to underlying Sharp mainboard unless memory management mode is switched. tranZPUter RAM 64K block 6 is selected.
|
||||||
|
constant TZMM_TZPU7 : integer := 31; -- Everything is in tranZPUter domain, no access to underlying Sharp mainboard unless memory management mode is switched. tranZPUter RAM 64K block 7 is selected.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
------------------------------------------------------------
|
||||||
|
-- Configurable parameters.
|
||||||
|
------------------------------------------------------------
|
||||||
|
-- Target hardware.
|
||||||
|
constant CPLD_HOST_HW : integer := MODE_MZ700;
|
||||||
|
|
||||||
|
-- Target video hardware.
|
||||||
|
constant CPLD_HAS_FPGA_VIDEO : std_logic := '1';
|
||||||
|
|
||||||
|
-- Version of hdl.
|
||||||
|
constant CPLD_VERSION : integer := 2;
|
||||||
|
|
||||||
|
-- Clock source for the secondary clock. If a K64F is installed then enable it otherwise use the onboard oscillator.
|
||||||
|
--
|
||||||
|
constant USE_K64F_CTL_CLOCK : integer := 1;
|
||||||
|
|
||||||
|
------------------------------------------------------------
|
||||||
|
-- Function prototypes
|
||||||
|
------------------------------------------------------------
|
||||||
|
-- Find the maximum of two integers.
|
||||||
|
function IntMax(a : in integer; b : in integer) return integer;
|
||||||
|
|
||||||
|
-- Find the number of bits required to represent an integer.
|
||||||
|
function log2ceil(arg : positive) return natural;
|
||||||
|
|
||||||
|
-- Function to calculate the number of whole 'clock' cycles in a given time period, the period being in ns.
|
||||||
|
function clockTicks(period : in integer; clock : in integer) return integer;
|
||||||
|
|
||||||
|
-- Function to reverse the order of the bits in a standard logic vector.
|
||||||
|
-- ie. 1010 becomes 0101
|
||||||
|
function reverse_vector(slv:std_logic_vector) return std_logic_vector;
|
||||||
|
|
||||||
|
-- Function to convert an integer (0 or 1) into std_logic.
|
||||||
|
--
|
||||||
|
function to_std_logic(i : in integer) return std_logic;
|
||||||
|
|
||||||
|
-- Function to return the value of a bit as an integer for array indexing etc.
|
||||||
|
function bit_to_integer( s : std_logic ) return natural;
|
||||||
|
|
||||||
|
------------------------------------------------------------
|
||||||
|
-- Records
|
||||||
|
------------------------------------------------------------
|
||||||
|
|
||||||
|
------------------------------------------------------------
|
||||||
|
-- Components
|
||||||
|
------------------------------------------------------------
|
||||||
|
|
||||||
|
end tzpuFusionX_pkg;
|
||||||
|
|
||||||
|
------------------------------------------------------------
|
||||||
|
-- Function definitions.
|
||||||
|
------------------------------------------------------------
|
||||||
|
package body tzpuFusionX_pkg is
|
||||||
|
|
||||||
|
-- Find the maximum of two integers.
|
||||||
|
function IntMax(a : in integer; b : in integer) return integer is
|
||||||
|
begin
|
||||||
|
if a > b then
|
||||||
|
return a;
|
||||||
|
else
|
||||||
|
return b;
|
||||||
|
end if;
|
||||||
|
return a;
|
||||||
|
end function IntMax;
|
||||||
|
|
||||||
|
-- Find the number of bits required to represent an integer.
|
||||||
|
function log2ceil(arg : positive) return natural is
|
||||||
|
variable tmp : positive := 1;
|
||||||
|
variable log : natural := 0;
|
||||||
|
begin
|
||||||
|
if arg = 1 then
|
||||||
|
return 0;
|
||||||
|
end if;
|
||||||
|
|
||||||
|
while arg > tmp loop
|
||||||
|
tmp := tmp * 2;
|
||||||
|
log := log + 1;
|
||||||
|
end loop;
|
||||||
|
return log;
|
||||||
|
end function;
|
||||||
|
|
||||||
|
-- Function to calculate the number of whole 'clock' cycles in a given time period, the period being in ns.
|
||||||
|
function clockTicks(period : in integer; clock : in integer) return integer is
|
||||||
|
variable ticks : real;
|
||||||
|
variable fracTicks : real;
|
||||||
|
begin
|
||||||
|
ticks := (Real(period) * Real(clock)) / 1000000000.0;
|
||||||
|
fracTicks := ticks - CEIL(ticks);
|
||||||
|
if fracTicks > 0.0001 then
|
||||||
|
return Integer(CEIL(ticks + 1.0));
|
||||||
|
else
|
||||||
|
return Integer(CEIL(ticks));
|
||||||
|
end if;
|
||||||
|
end function;
|
||||||
|
|
||||||
|
function reverse_vector(slv:std_logic_vector) return std_logic_vector is
|
||||||
|
variable target : std_logic_vector(slv'high downto slv'low);
|
||||||
|
begin
|
||||||
|
for idx in slv'high downto slv'low loop
|
||||||
|
target(idx) := slv(slv'low + (slv'high-idx));
|
||||||
|
end loop;
|
||||||
|
return target;
|
||||||
|
end reverse_vector;
|
||||||
|
|
||||||
|
function to_std_logic(i : in integer) return std_logic is
|
||||||
|
begin
|
||||||
|
if i = 0 then
|
||||||
|
return '0';
|
||||||
|
end if;
|
||||||
|
return '1';
|
||||||
|
end function;
|
||||||
|
|
||||||
|
-- Function to return the value of a bit as an integer for array indexing etc.
|
||||||
|
function bit_to_integer( s : std_logic ) return natural is
|
||||||
|
begin
|
||||||
|
if s = '1' then
|
||||||
|
return 1;
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
end if;
|
||||||
|
end function;
|
||||||
|
end package body;
|
||||||
30
CPLD/v1.0/MZ80A/build/tzpuFusionX_MZ80A.qpf
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
# -------------------------------------------------------------------------- #
|
||||||
|
#
|
||||||
|
# Copyright (C) 1991-2013 Altera Corporation
|
||||||
|
# Your use of Altera Corporation's design tools, logic functions
|
||||||
|
# and other software and tools, and its AMPP partner logic
|
||||||
|
# functions, and any output files from any of the foregoing
|
||||||
|
# (including device programming or simulation files), and any
|
||||||
|
# associated documentation or information are expressly subject
|
||||||
|
# to the terms and conditions of the Altera Program License
|
||||||
|
# Subscription Agreement, Altera MegaCore Function License
|
||||||
|
# Agreement, or other applicable license agreement, including,
|
||||||
|
# without limitation, that your use is for the sole purpose of
|
||||||
|
# programming logic devices manufactured by Altera and sold by
|
||||||
|
# Altera or its authorized distributors. Please refer to the
|
||||||
|
# applicable agreement for further details.
|
||||||
|
#
|
||||||
|
# -------------------------------------------------------------------------- #
|
||||||
|
#
|
||||||
|
# Quartus II 64-Bit
|
||||||
|
# Version 13.0.1 Build 232 06/12/2013 Service Pack 1 SJ Web Edition
|
||||||
|
# Date created = 16:29:32 June 24, 2020
|
||||||
|
#
|
||||||
|
# -------------------------------------------------------------------------- #
|
||||||
|
|
||||||
|
QUARTUS_VERSION = "13.0"
|
||||||
|
DATE = "16:29:32 September 10, 2021"
|
||||||
|
|
||||||
|
# Revisions
|
||||||
|
|
||||||
|
PROJECT_REVISION = "tzpuFusionX_MZ80A"
|
||||||
243
CPLD/v1.0/MZ80A/build/tzpuFusionX_MZ80A.qsf
Normal file
@@ -0,0 +1,243 @@
|
|||||||
|
# -------------------------------------------------------------------------- #
|
||||||
|
#
|
||||||
|
# Copyright (C) 1991-2013 Altera Corporation
|
||||||
|
# Your use of Altera Corporation's design tools, logic functions
|
||||||
|
# and other software and tools, and its AMPP partner logic
|
||||||
|
# functions, and any output files from any of the foregoing
|
||||||
|
# (including device programming or simulation files), and any
|
||||||
|
# associated documentation or information are expressly subject
|
||||||
|
# to the terms and conditions of the Altera Program License
|
||||||
|
# Subscription Agreement, Altera MegaCore Function License
|
||||||
|
# Agreement, or other applicable license agreement, including,
|
||||||
|
# without limitation, that your use is for the sole purpose of
|
||||||
|
# programming logic devices manufactured by Altera and sold by
|
||||||
|
# Altera or its authorized distributors. Please refer to the
|
||||||
|
# applicable agreement for further details.
|
||||||
|
#
|
||||||
|
# -------------------------------------------------------------------------- #
|
||||||
|
#
|
||||||
|
# Quartus II 64-Bit
|
||||||
|
# Version 13.0.1 Build 232 06/12/2013 Service Pack 1 SJ Web Edition
|
||||||
|
# Date created = 16:29:32 June 24, 2020
|
||||||
|
#
|
||||||
|
# -------------------------------------------------------------------------- #
|
||||||
|
#
|
||||||
|
# Notes:
|
||||||
|
#
|
||||||
|
# 1) The default values for assignments are stored in the file:
|
||||||
|
# tzpuFusionX.qdf
|
||||||
|
# If this file doesn't exist, see file:
|
||||||
|
# assignment_defaults.qdf
|
||||||
|
#
|
||||||
|
# 2) Altera recommends that you do not modify this file. This
|
||||||
|
# file is updated automatically by the Quartus II software
|
||||||
|
# and any changes you make may be lost or overwritten.
|
||||||
|
#
|
||||||
|
# -------------------------------------------------------------------------- #
|
||||||
|
|
||||||
|
|
||||||
|
set_global_assignment -name FAMILY MAX7000AE
|
||||||
|
set_global_assignment -name DEVICE "EPM7512AETC144-10"
|
||||||
|
set_global_assignment -name TOP_LEVEL_ENTITY tzpuFusionX_MZ80A
|
||||||
|
set_global_assignment -name ORIGINAL_QUARTUS_VERSION "13.0 SP1"
|
||||||
|
set_global_assignment -name PROJECT_CREATION_TIME_DATE "16:29:32 JUNE 24, 2020"
|
||||||
|
set_global_assignment -name LAST_QUARTUS_VERSION "13.0 SP1"
|
||||||
|
set_global_assignment -name PROJECT_OUTPUT_DIRECTORY output_files
|
||||||
|
set_global_assignment -name ERROR_CHECK_FREQUENCY_DIVISOR "-1"
|
||||||
|
set_global_assignment -name EDA_DESIGN_ENTRY_SYNTHESIS_TOOL "<None>"
|
||||||
|
set_global_assignment -name EDA_INPUT_VCC_NAME VCC -section_id eda_design_synthesis
|
||||||
|
set_global_assignment -name EDA_INPUT_DATA_FORMAT EDIF -section_id eda_design_synthesis
|
||||||
|
set_global_assignment -name EDA_SIMULATION_TOOL "ModelSim-Altera (VHDL)"
|
||||||
|
set_global_assignment -name EDA_OUTPUT_DATA_FORMAT VHDL -section_id eda_simulation
|
||||||
|
set_global_assignment -name OPTIMIZE_HOLD_TIMING OFF
|
||||||
|
set_global_assignment -name OPTIMIZE_MULTI_CORNER_TIMING OFF
|
||||||
|
set_global_assignment -name FITTER_EFFORT "STANDARD FIT"
|
||||||
|
set_global_assignment -name MAX7000_DEVICE_IO_STANDARD LVTTL
|
||||||
|
|
||||||
|
# Z80 Data Bus
|
||||||
|
# ============
|
||||||
|
set_location_assignment PIN_81 -to Z80_DATA[0]
|
||||||
|
set_location_assignment PIN_78 -to Z80_DATA[1]
|
||||||
|
set_location_assignment PIN_87 -to Z80_DATA[2]
|
||||||
|
set_location_assignment PIN_100 -to Z80_DATA[3]
|
||||||
|
set_location_assignment PIN_102 -to Z80_DATA[4]
|
||||||
|
set_location_assignment PIN_93 -to Z80_DATA[5]
|
||||||
|
set_location_assignment PIN_94 -to Z80_DATA[6]
|
||||||
|
set_location_assignment PIN_84 -to Z80_DATA[7]
|
||||||
|
|
||||||
|
# Z80 Control signals.
|
||||||
|
# ====================
|
||||||
|
set_location_assignment PIN_69 -to Z80_INTn
|
||||||
|
set_location_assignment PIN_70 -to Z80_NMIn
|
||||||
|
set_location_assignment PIN_71 -to Z80_HALTn
|
||||||
|
set_location_assignment PIN_68 -to Z80_MREQn
|
||||||
|
set_location_assignment PIN_65 -to Z80_IORQn
|
||||||
|
set_location_assignment PIN_67 -to Z80_RDn
|
||||||
|
set_location_assignment PIN_66 -to Z80_WRn
|
||||||
|
set_location_assignment PIN_63 -to Z80_BUSAKn
|
||||||
|
set_location_assignment PIN_62 -to Z80_WAITn
|
||||||
|
set_location_assignment PIN_61 -to Z80_BUSRQn
|
||||||
|
set_location_assignment PIN_79 -to Z80_RFSHn
|
||||||
|
set_location_assignment PIN_60 -to Z80_M1n
|
||||||
|
set_location_assignment PIN_56 -to Z80_RESETn
|
||||||
|
set_location_assignment PIN_101 -to Z80_CLK
|
||||||
|
|
||||||
|
# Z80 Address Bus
|
||||||
|
# ===============
|
||||||
|
set_location_assignment PIN_80 -to Z80_ADDR[0]
|
||||||
|
set_location_assignment PIN_90 -to Z80_ADDR[1]
|
||||||
|
set_location_assignment PIN_83 -to Z80_ADDR[2]
|
||||||
|
set_location_assignment PIN_86 -to Z80_ADDR[3]
|
||||||
|
set_location_assignment PIN_88 -to Z80_ADDR[4]
|
||||||
|
set_location_assignment PIN_91 -to Z80_ADDR[5]
|
||||||
|
set_location_assignment PIN_92 -to Z80_ADDR[6]
|
||||||
|
set_location_assignment PIN_96 -to Z80_ADDR[7]
|
||||||
|
set_location_assignment PIN_97 -to Z80_ADDR[8]
|
||||||
|
set_location_assignment PIN_98 -to Z80_ADDR[9]
|
||||||
|
set_location_assignment PIN_99 -to Z80_ADDR[10]
|
||||||
|
set_location_assignment PIN_110 -to Z80_ADDR[11]
|
||||||
|
set_location_assignment PIN_108 -to Z80_ADDR[12]
|
||||||
|
set_location_assignment PIN_107 -to Z80_ADDR[13]
|
||||||
|
set_location_assignment PIN_106 -to Z80_ADDR[14]
|
||||||
|
set_location_assignment PIN_103 -to Z80_ADDR[15]
|
||||||
|
|
||||||
|
# SOM SPI
|
||||||
|
# =======
|
||||||
|
set_location_assignment PIN_32 -to VSOM_SPI_CSn
|
||||||
|
set_location_assignment PIN_31 -to VSOM_SPI_CLK
|
||||||
|
set_location_assignment PIN_30 -to VSOM_SPI_MOSI
|
||||||
|
set_location_assignment PIN_29 -to VSOM_SPI_MISO
|
||||||
|
|
||||||
|
# SOM Parallel Bus
|
||||||
|
# ================
|
||||||
|
set_location_assignment PIN_41 -to VSOM_DATA_OUT[0]
|
||||||
|
set_location_assignment PIN_40 -to VSOM_DATA_OUT[1]
|
||||||
|
set_location_assignment PIN_39 -to VSOM_DATA_OUT[2]
|
||||||
|
set_location_assignment PIN_38 -to VSOM_DATA_OUT[3]
|
||||||
|
set_location_assignment PIN_37 -to VSOM_DATA_OUT[4]
|
||||||
|
set_location_assignment PIN_36 -to VSOM_DATA_OUT[5]
|
||||||
|
set_location_assignment PIN_35 -to VSOM_DATA_OUT[6]
|
||||||
|
set_location_assignment PIN_34 -to VSOM_DATA_OUT[7]
|
||||||
|
set_location_assignment PIN_132 -to VSOM_HBYTE
|
||||||
|
|
||||||
|
# SOM Reserved signals.
|
||||||
|
# =====================
|
||||||
|
set_location_assignment PIN_21 -to VSOM_RSV[1]
|
||||||
|
|
||||||
|
# SOM Control Signals
|
||||||
|
# ===================
|
||||||
|
set_location_assignment PIN_28 -to VSOM_READY
|
||||||
|
set_location_assignment PIN_18 -to VSOM_LTSTATE
|
||||||
|
set_location_assignment PIN_27 -to VSOM_BUSRQ
|
||||||
|
set_location_assignment PIN_26 -to VSOM_BUSACK
|
||||||
|
set_location_assignment PIN_19 -to VSOM_INT
|
||||||
|
set_location_assignment PIN_22 -to VSOM_NMI
|
||||||
|
set_location_assignment PIN_25 -to VSOM_WAIT
|
||||||
|
set_location_assignment PIN_23 -to VSOM_RESET
|
||||||
|
set_location_assignment PIN_16 -to PM_RESET
|
||||||
|
|
||||||
|
# VGA_Palette Control
|
||||||
|
# ===================
|
||||||
|
set_location_assignment PIN_133 -to VGA_R[7]
|
||||||
|
set_location_assignment PIN_137 -to VGA_R[8]
|
||||||
|
set_location_assignment PIN_140 -to VGA_R[9]
|
||||||
|
set_location_assignment PIN_134 -to VGA_G[7]
|
||||||
|
set_location_assignment PIN_138 -to VGA_G[8]
|
||||||
|
set_location_assignment PIN_141 -to VGA_G[9]
|
||||||
|
set_location_assignment PIN_136 -to VGA_B[8]
|
||||||
|
set_location_assignment PIN_139 -to VGA_B[9]
|
||||||
|
|
||||||
|
|
||||||
|
# VGA Control Signals
|
||||||
|
# ===================
|
||||||
|
set_location_assignment PIN_142 -to VGA_PXL_CLK
|
||||||
|
set_location_assignment PIN_14 -to VGA_DISPEN
|
||||||
|
set_location_assignment PIN_12 -to VGA_VSYNCn
|
||||||
|
set_location_assignment PIN_11 -to VGA_HSYNCn
|
||||||
|
set_location_assignment PIN_82 -to VGA_COLR
|
||||||
|
set_location_assignment PIN_109 -to VGA_CSYNCn
|
||||||
|
set_location_assignment PIN_143 -to VGA_BLANKn
|
||||||
|
|
||||||
|
# CRT Control Signals
|
||||||
|
# ===================
|
||||||
|
set_location_assignment PIN_15 -to MONO_PXL_CLK
|
||||||
|
set_location_assignment PIN_114 -to MONO_BLANKn
|
||||||
|
set_location_assignment PIN_113 -to MONO_CSYNCn
|
||||||
|
set_location_assignment PIN_116 -to MONO_RSV
|
||||||
|
|
||||||
|
# CRT Lower Chrominance Control
|
||||||
|
# =============================
|
||||||
|
set_location_assignment PIN_1 -to MONO_R[0]
|
||||||
|
set_location_assignment PIN_6 -to MONO_R[1]
|
||||||
|
set_location_assignment PIN_10 -to MONO_R[2]
|
||||||
|
set_location_assignment PIN_2 -to MONO_G[0]
|
||||||
|
set_location_assignment PIN_7 -to MONO_G[1]
|
||||||
|
set_location_assignment PIN_9 -to MONO_G[2]
|
||||||
|
set_location_assignment PIN_5 -to MONO_B[1]
|
||||||
|
set_location_assignment PIN_8 -to MONO_B[2]
|
||||||
|
|
||||||
|
# MUX Control Signals
|
||||||
|
# ===================
|
||||||
|
set_location_assignment PIN_72 -to VIDEO_SRC
|
||||||
|
set_location_assignment PIN_74 -to MONO_VIDEO_SRC
|
||||||
|
set_location_assignment PIN_77 -to AUDIO_SRC_L
|
||||||
|
set_location_assignment PIN_75 -to AUDIO_SRC_R
|
||||||
|
|
||||||
|
# Mainboard Reset Signals
|
||||||
|
# =======================
|
||||||
|
#set_location_assignment PIN_127 -to CPU_RESETn
|
||||||
|
set_location_assignment PIN_122 -to MB_RESETn
|
||||||
|
set_location_assignment PIN_111 -to MB_IPLn
|
||||||
|
|
||||||
|
# USB Power Control
|
||||||
|
# =================
|
||||||
|
set_location_assignment PIN_55 -to VBUS_EN
|
||||||
|
|
||||||
|
# Clocks
|
||||||
|
# ======
|
||||||
|
#set_location_assignment PIN_125 -to CPU_CLK
|
||||||
|
set_location_assignment PIN_128 -to CLK_50M
|
||||||
|
|
||||||
|
# Unused ports
|
||||||
|
# ============
|
||||||
|
#set_location_assignment PIN_42 -to
|
||||||
|
#set_location_assignment PIN_43 -to
|
||||||
|
#set_location_assignment PIN_44 -to
|
||||||
|
#set_location_assignment PIN_45 -to
|
||||||
|
#set_location_assignment PIN_112 -to
|
||||||
|
#set_location_assignment PIN_131 -to
|
||||||
|
#set_location_assignment PIN_117 -to
|
||||||
|
#set_location_assignment PIN_118 -to
|
||||||
|
#set_location_assignment PIN_119 -to
|
||||||
|
#set_location_assignment PIN_120 -to
|
||||||
|
#set_location_assignment PIN_121 -to
|
||||||
|
#set_location_assignment PIN_25 -to
|
||||||
|
#set_location_assignment PIN_53 -to
|
||||||
|
#set_location_assignment PIN_128 -to
|
||||||
|
#set_location_assignment PIN_47 -to
|
||||||
|
#set_location_assignment PIN_54 -to
|
||||||
|
#set_location_assignment PIN_127 -to
|
||||||
|
#set_location_assignment PIN_125 -to
|
||||||
|
#set_location_assignment PIN_48 -to
|
||||||
|
#set_location_assignment PIN_46 -to
|
||||||
|
#set_location_assignment PIN_49 -to
|
||||||
|
|
||||||
|
|
||||||
|
set_global_assignment -name VHDL_FILE ../tzpuFusionX_Toplevel.vhd
|
||||||
|
set_global_assignment -name VHDL_FILE ../tzpuFusionX_pkg.vhd
|
||||||
|
set_global_assignment -name VHDL_FILE ../tzpuFusionX.vhd
|
||||||
|
set_global_assignment -name SDC_FILE tzpuFusionX_MZ80A_constraints.sdc
|
||||||
|
|
||||||
|
set_global_assignment -name VHDL_INPUT_VERSION VHDL_2008
|
||||||
|
set_global_assignment -name VHDL_SHOW_LMF_MAPPING_MESSAGES OFF
|
||||||
|
|
||||||
|
set_global_assignment -name SYNTH_TIMING_DRIVEN_SYNTHESIS OFF
|
||||||
|
set_global_assignment -name MAX7000_OPTIMIZATION_TECHNIQUE AREA
|
||||||
|
set_global_assignment -name AUTO_RESOURCE_SHARING OFF
|
||||||
|
set_global_assignment -name PRE_MAPPING_RESYNTHESIS OFF
|
||||||
|
set_global_assignment -name USE_LOGICLOCK_CONSTRAINTS_IN_BALANCING OFF
|
||||||
|
|
||||||
|
set_global_assignment -name INFER_RAMS_FROM_RAW_LOGIC OFF
|
||||||
|
set_global_assignment -name AUTO_LCELL_INSERTION ON
|
||||||
|
|
||||||
|
set_global_assignment -name CDF_FILE output_files/tzpuFusionX_MZ80A.cdf
|
||||||
324
CPLD/v1.0/MZ80A/build/tzpuFusionX_MZ80A_constraints.sdc
Normal file
@@ -0,0 +1,324 @@
|
|||||||
|
## Generated SDC file "tzpuFusionX.out.sdc"
|
||||||
|
|
||||||
|
## Copyright (C) 1991-2013 Altera Corporation
|
||||||
|
## Your use of Altera Corporation's design tools, logic functions
|
||||||
|
## and other software and tools, and its AMPP partner logic
|
||||||
|
## functions, and any output files from any of the foregoing
|
||||||
|
## (including device programming or simulation files), and any
|
||||||
|
## associated documentation or information are expressly subject
|
||||||
|
## to the terms and conditions of the Altera Program License
|
||||||
|
## Subscription Agreement, Altera MegaCore Function License
|
||||||
|
## Agreement, or other applicable license agreement, including,
|
||||||
|
## without limitation, that your use is for the sole purpose of
|
||||||
|
## programming logic devices manufactured by Altera and sold by
|
||||||
|
## Altera or its authorized distributors. Please refer to the
|
||||||
|
## applicable agreement for further details.
|
||||||
|
|
||||||
|
|
||||||
|
## VENDOR "Altera"
|
||||||
|
## PROGRAM "Quartus II"
|
||||||
|
## VERSION "Version 13.0.1 Build 232 06/12/2013 Service Pack 1 SJ Web Edition"
|
||||||
|
|
||||||
|
## DATE "Fri Jun 26 22:10:05 2020"
|
||||||
|
|
||||||
|
##
|
||||||
|
## DEVICE "EPM7160STC100-10"
|
||||||
|
##
|
||||||
|
|
||||||
|
|
||||||
|
#**************************************************************
|
||||||
|
# Time Information
|
||||||
|
#**************************************************************
|
||||||
|
|
||||||
|
set_time_format -unit ns -decimal_places 3
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#**************************************************************
|
||||||
|
# Create Clock
|
||||||
|
#**************************************************************
|
||||||
|
|
||||||
|
# Standard mainboard clock. If using tzpuFusionX on a different host then set to the host frequency.
|
||||||
|
create_clock -name {Z80_CLK} -period 500.000 -waveform { 0.000 250.000 } [get_ports { Z80_CLK }]
|
||||||
|
|
||||||
|
# For 50MHz crystal.
|
||||||
|
create_clock -name {CLK_50M} -period 20.000 -waveform { 0.000 10.000 } [ get_ports { CLK_50M }]
|
||||||
|
|
||||||
|
# For SPI CSn
|
||||||
|
#create_clock -name {VSOM_SPI_CSn} -period 200.000 -waveform { 160.000 40.000 } [ get_ports { VSOM_SPI_CSn }]
|
||||||
|
|
||||||
|
# For SPI CLK
|
||||||
|
create_clock -name {VSOM_SPI_CLK} -period 14.000 -waveform { 0.000 7.000 } [ get_ports { VSOM_SPI_CLK }]
|
||||||
|
|
||||||
|
# For basic board with oscillator.
|
||||||
|
#create_clock -name {CTLCLK} -period 20.000 -waveform { 0.000 10.000 } [ get_ports { CTLCLK }]
|
||||||
|
#create_clock -name {cpld512:cpldl512Toplevel|CTLCLKi} -period 280.000 -waveform { 0.000 140.000 } [ get_keepers {cpld512:cpldl512Toplevel|CTLCLKi} ]
|
||||||
|
##create_clock -name {Z80_CLK} -period 50.000 -waveform { 0.000 25.000 } [get_ports { CTLCLK }]
|
||||||
|
|
||||||
|
|
||||||
|
#**************************************************************
|
||||||
|
# Create Generated Clock
|
||||||
|
#**************************************************************
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#**************************************************************
|
||||||
|
# Set Clock Latency
|
||||||
|
#**************************************************************
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#**************************************************************
|
||||||
|
# Set Clock Uncertainty
|
||||||
|
#**************************************************************
|
||||||
|
|
||||||
|
#derive_clock_uncertainty
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#**************************************************************
|
||||||
|
# Set Input Delay
|
||||||
|
#**************************************************************
|
||||||
|
|
||||||
|
#set_input_delay -add_delay -clock [get_clocks {SYSCLK}] 1.000 [get_ports {CTL_MBSEL}]
|
||||||
|
#set_input_delay -add_delay -clock [get_clocks {SYSCLK}] 1.000 [get_ports {CTL_BUSRQn}]
|
||||||
|
#set_input_delay -add_delay -clock [get_clocks {SYSCLK}] 1.000 [get_ports {CTL_WAITn}]
|
||||||
|
#set_input_delay -add_delay -clock [get_clocks {SYSCLK}] 1.000 [get_ports {SYS_BUSRQn}]
|
||||||
|
#set_input_delay -add_delay -clock [get_clocks {SYSCLK}] 1.000 [get_ports {SYS_WAITn}]
|
||||||
|
#set_input_delay -add_delay -clock [get_clocks {SYSCLK}] 1.000 [get_ports {Z80_ADDR[*]}]
|
||||||
|
#set_input_delay -add_delay -clock [get_clocks {SYSCLK}] 1.000 [get_ports {Z80_HI_ADDR[*]}]
|
||||||
|
#set_input_delay -add_delay -clock [get_clocks {SYSCLK}] 1.000 [get_ports {VZ80_ADDR[*]}]
|
||||||
|
#set_input_delay -add_delay -clock [get_clocks {SYSCLK}] 1.000 [get_ports {Z80_BUSACKn}]
|
||||||
|
#set_input_delay -add_delay -clock [get_clocks {SYSCLK}] 1.000 [get_ports {Z80_DATA[*]}]
|
||||||
|
#set_input_delay -add_delay -clock [get_clocks {SYSCLK}] 1.000 [get_ports {Z80_HALTn}]
|
||||||
|
#set_input_delay -add_delay -clock [get_clocks {SYSCLK}] 1.000 [get_ports {Z80_IORQn}]
|
||||||
|
#set_input_delay -add_delay -clock [get_clocks {SYSCLK}] 1.000 [get_ports {Z80_M1n}]
|
||||||
|
#set_input_delay -add_delay -clock [get_clocks {SYSCLK}] 1.000 [get_ports {Z80_MREQn}]
|
||||||
|
#set_input_delay -add_delay -clock [get_clocks {SYSCLK}] 1.000 [get_ports {Z80_RESETn}]
|
||||||
|
#set_input_delay -add_delay -clock [get_clocks {SYSCLK}] 1.000 [get_ports {Z80_RFSHn}]
|
||||||
|
#set_input_delay -add_delay -clock [get_clocks {SYSCLK}] 1.000 [get_ports {Z80_WRn}]
|
||||||
|
#set_input_delay -add_delay -clock [get_clocks {SYSCLK}] 1.000 [get_ports {Z80_RDn}]
|
||||||
|
#set_input_delay -add_delay -clock [get_clocks {SYSCLK}] 1.000 [get_ports {R_IN}]
|
||||||
|
#set_input_delay -add_delay -clock [get_clocks {SYSCLK}] 1.000 [get_ports {G_IN}]
|
||||||
|
#set_input_delay -add_delay -clock [get_clocks {SYSCLK}] 1.000 [get_ports {B_IN}]
|
||||||
|
#set_input_delay -add_delay -clock [get_clocks {SYSCLK}] 1.000 [get_ports {COLR_IN}]
|
||||||
|
#set_input_delay -add_delay -clock [get_clocks {SYSCLK}] 1.000 [get_ports {CSYNC_IN}]
|
||||||
|
##set_input_delay -add_delay -clock [get_clocks {SYSCLK}] 1.000 [get_ports {CVIDEO_IN}]
|
||||||
|
#set_input_delay -add_delay -clock [get_clocks {SYSCLK}] 1.000 [get_ports {HSYNC_IN}]
|
||||||
|
#set_input_delay -add_delay -clock [get_clocks {SYSCLK}] 1.000 [get_ports {VSYNC_IN}]
|
||||||
|
#set_input_delay -add_delay -clock [get_clocks {SYSCLK}] 1.000 [get_ports {VZ80_DATA[*]}]
|
||||||
|
#set_input_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {VZ80_MREQn}]
|
||||||
|
#set_input_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {VZ80_IORQn}]
|
||||||
|
#set_input_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {VZ80_WRn}]
|
||||||
|
#set_input_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {VZ80_RDn}]
|
||||||
|
#set_input_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {VZ80_M1n}]
|
||||||
|
#set_input_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {VZ80_BUSACKn}]
|
||||||
|
#set_input_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {Z80_INTn}]
|
||||||
|
#set_input_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {Z80_NMIn}]
|
||||||
|
#set_input_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {Z80_WAITn}]
|
||||||
|
#set_input_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {VWAITn_A21_V_CSYNC}]
|
||||||
|
#set_input_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {VZ80_A20_RFSHn_V_HSYNC}]
|
||||||
|
#set_input_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {VZ80_A19_HALTn_V_VSYNC}]
|
||||||
|
|
||||||
|
#**************************************************************
|
||||||
|
# Set Output Delay
|
||||||
|
#**************************************************************
|
||||||
|
|
||||||
|
#set_output_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {CTL_BUSACKn}]
|
||||||
|
#set_output_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {CTL_HALTn}]
|
||||||
|
#set_output_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {CTL_M1n}]
|
||||||
|
#set_output_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {CTL_RFSHn}]
|
||||||
|
#set_output_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {RAM_CSn}]
|
||||||
|
#set_output_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {RAM_CS2n}]
|
||||||
|
#set_output_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {RAM_OEn}]
|
||||||
|
#set_output_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {RAM_WEn}]
|
||||||
|
#set_output_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {SVCREQn}]
|
||||||
|
#set_output_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {SYS_BUSACKn}]
|
||||||
|
#set_output_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {Z80_BUSRQn}]
|
||||||
|
#set_output_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {Z80_DATA[*]}]
|
||||||
|
#set_output_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {Z80_ADDR[*]}]
|
||||||
|
#set_output_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {Z80_HI_ADDR[*]}]
|
||||||
|
#set_output_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {Z80_RA_ADDR[*]}]
|
||||||
|
#set_output_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {Z80_WAITn}]
|
||||||
|
#set_output_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {Z80_MREQn}]
|
||||||
|
#set_output_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {Z80_CLK}]
|
||||||
|
#set_output_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {VZ80_ADDR[*]}]
|
||||||
|
#set_output_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {VZ80_DATA[*]}]
|
||||||
|
#set_output_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {VZ80_CLK}]
|
||||||
|
#set_output_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {VZ80_MREQn}]
|
||||||
|
#set_output_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {VZ80_IORQn}]
|
||||||
|
#set_output_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {VZ80_RDn}]
|
||||||
|
#set_output_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {VZ80_WRn}]
|
||||||
|
#set_output_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {VZ80_M1n}]
|
||||||
|
#set_output_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {VIDEO_RDn}]
|
||||||
|
#set_output_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {VIDEO_WRn}]
|
||||||
|
#set_output_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {VZ80_A18_INTn_V_R}]
|
||||||
|
#set_output_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {VZ80_BUSRQn_V_G}]
|
||||||
|
#set_output_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {VZ80_A16_WAITn_V_B}]
|
||||||
|
#set_output_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {VZ80_A17_NMIn_V_COLR}]
|
||||||
|
#set_output_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {VWAITn_A21_V_CSYNC}]
|
||||||
|
#set_output_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {VZ80_A20_RFSHn_V_HSYNC}]
|
||||||
|
#set_output_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {VZ80_A19_HALTn_V_VSYNC}]
|
||||||
|
#set_output_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {Z80_HALTn}]
|
||||||
|
#set_output_delay -add_delay -clock [get_clocks {SYSCLK}] 5.000 [get_ports {Z80_RFSHn}]
|
||||||
|
|
||||||
|
# For K64F
|
||||||
|
#set_output_delay -add_delay -clock [get_clocks {CTLCLK}] 5.000 [get_ports {Z80_CLK}]
|
||||||
|
|
||||||
|
# For basic board with oscillator.
|
||||||
|
#set_output_delay -add_delay -clock [get_clocks {cpld512:cpldl512Toplevel|CTLCLKi}] 5.000 [get_ports {Z80_CLK}]
|
||||||
|
|
||||||
|
#**************************************************************
|
||||||
|
# Set Max Delay
|
||||||
|
#**************************************************************
|
||||||
|
#set_max_delay -from [get_ports {CTL_BUSRQn}] -to {Z80_HALTn} 30.000
|
||||||
|
#set_max_delay -from [get_ports {CTL_BUSRQn}] -to {Z80_IORQn} 30.000
|
||||||
|
#set_max_delay -from [get_ports {CTL_BUSRQn}] -to {Z80_M1n} 30.000
|
||||||
|
#set_max_delay -from [get_ports {CTL_BUSRQn}] -to {Z80_RDn} 30.000
|
||||||
|
#set_max_delay -from [get_ports {CTL_BUSRQn}] -to {Z80_WRn} 30.000
|
||||||
|
#set_max_delay -from [get_ports {CTL_BUSRQn}] -to {Z80_RFSHn} 30.000
|
||||||
|
#set_max_delay -from [get_ports {VZ80_A19_HALTn_V_VSYNC}] -to {Z80_HALTn} 30.000
|
||||||
|
#set_max_delay -from [get_ports {VZ80_IORQn}] -to {Z80_IORQn} 30.000
|
||||||
|
#set_max_delay -from [get_ports {VZ80_MREQn}] -to {Z80_IORQn} 30.000
|
||||||
|
#set_max_delay -from [get_ports {VZ80_M1n}] -to {Z80_M1n} 30.000
|
||||||
|
#set_max_delay -from [get_ports {VZ80_RDn}] -to {Z80_RDn} 30.000
|
||||||
|
#set_max_delay -from [get_ports {VZ80_WRn}] -to {Z80_WRn} 30.000
|
||||||
|
#set_max_delay -from [get_ports {VZ80_BUSACKn}] -to {Z80_HALTn} 40.000
|
||||||
|
#set_max_delay -from [get_ports {VZ80_BUSACKn}] -to {Z80_RFSHn} 40.000
|
||||||
|
#set_max_delay -from [get_ports {VZ80_BUSACKn}] -to {Z80_IORQn} 40.000
|
||||||
|
#set_max_delay -from [get_ports {VZ80_BUSACKn}] -to {Z80_M1n} 30.000
|
||||||
|
#set_max_delay -from [get_ports {VZ80_BUSACKn}] -to {Z80_RDn} 30.000
|
||||||
|
#set_max_delay -from [get_ports {VZ80_BUSACKn}] -to {Z80_WRn} 30.000
|
||||||
|
#set_max_delay -from [get_ports {VZ80_A20_RFSHn_V_HSYNC}] -to {Z80_RFSHn} 30.000
|
||||||
|
#set_max_delay -from [get_ports {Z80_BUSACKn}] -to {Z80_HALTn} 30.000
|
||||||
|
#set_max_delay -from [get_ports {Z80_BUSACKn}] -to {Z80_IORQn} 30.000
|
||||||
|
#set_max_delay -from [get_ports {Z80_BUSACKn}] -to {Z80_M1n} 30.000
|
||||||
|
#set_max_delay -from [get_ports {Z80_BUSACKn}] -to {Z80_RDn} 30.000
|
||||||
|
#set_max_delay -from [get_ports {Z80_BUSACKn}] -to {Z80_WRn} 30.000
|
||||||
|
#set_max_delay -from [get_ports {Z80_BUSACKn}] -to {Z80_RFSHn} 30.000
|
||||||
|
#set_max_delay -from {Z80_BUSACKn} -to [get_ports {Z80_HALTn}] 45.000
|
||||||
|
#set_max_delay -from {Z80_BUSACKn} -to [get_ports {Z80_IORQn}] 30.000
|
||||||
|
#set_max_delay -from {Z80_BUSACKn} -to [get_ports {Z80_M1n}] 30.000
|
||||||
|
#set_max_delay -from {Z80_BUSACKn} -to [get_ports {Z80_RDn}] 30.000
|
||||||
|
#set_max_delay -from {Z80_BUSACKn} -to [get_ports {Z80_RFSHn}] 45.000
|
||||||
|
#set_max_delay -from {Z80_BUSACKn} -to [get_ports {Z80_WRn}] 30.000
|
||||||
|
#set_max_delay -from {cpld512:cpldl512Toplevel|CPLD_CFG_DATA[*]} -to [get_ports {Z80_HALTn}] 45.000
|
||||||
|
#set_max_delay -from {cpld512:cpldl512Toplevel|CPLD_CFG_DATA[*]} -to [get_ports {Z80_IORQn}] 50.000
|
||||||
|
#set_max_delay -from {cpld512:cpldl512Toplevel|CPLD_CFG_DATA[*]} -to [get_ports {Z80_M1n}] 40.000
|
||||||
|
#set_max_delay -from {cpld512:cpldl512Toplevel|CPLD_CFG_DATA[*]} -to [get_ports {Z80_RDn}] 40.000
|
||||||
|
#set_max_delay -from {cpld512:cpldl512Toplevel|CPLD_CFG_DATA[*]} -to [get_ports {Z80_WRn}] 40.000
|
||||||
|
#set_max_delay -from {cpld512:cpldl512Toplevel|CPLD_CFG_DATA[*]} -to [get_ports {Z80_RFSHn}] 45.000
|
||||||
|
#set_max_delay -from {cpld512:cpldl512Toplevel|CPU_CFG_DATA[*]} -to [get_ports {Z80_HALTn}] 60.000
|
||||||
|
#set_max_delay -from {cpld512:cpldl512Toplevel|CPU_CFG_DATA[*]} -to [get_ports {Z80_IORQn}] 45.000
|
||||||
|
#set_max_delay -from {cpld512:cpldl512Toplevel|CPU_CFG_DATA[*]} -to [get_ports {Z80_M1n}] 40.000
|
||||||
|
#set_max_delay -from {cpld512:cpldl512Toplevel|CPU_CFG_DATA[*]} -to [get_ports {Z80_RDn}] 40.000
|
||||||
|
#set_max_delay -from {cpld512:cpldl512Toplevel|CPU_CFG_DATA[*]} -to [get_ports {Z80_WRn}] 40.000
|
||||||
|
#set_max_delay -from {cpld512:cpldl512Toplevel|CPU_CFG_DATA[*]} -to [get_ports {Z80_RFSHn}] 60.000
|
||||||
|
|
||||||
|
#**************************************************************
|
||||||
|
# Set Min Delay
|
||||||
|
#**************************************************************
|
||||||
|
#set_min_delay -from [get_ports {CTL_BUSRQn}] -to {Z80_HALTn} 1.000
|
||||||
|
#set_min_delay -from [get_ports {CTL_BUSRQn}] -to {Z80_IORQn} 1.000
|
||||||
|
#set_min_delay -from [get_ports {CTL_BUSRQn}] -to {Z80_M1n} 1.000
|
||||||
|
#set_min_delay -from [get_ports {CTL_BUSRQn}] -to {Z80_RDn} 1.000
|
||||||
|
#set_min_delay -from [get_ports {CTL_BUSRQn}] -to {Z80_WRn} 1.000
|
||||||
|
#set_min_delay -from [get_ports {CTL_BUSRQn}] -to {Z80_RFSHn} 1.000
|
||||||
|
#set_min_delay -from [get_ports {VZ80_A19_HALTn_V_VSYNC}] -to {Z80_HALTn} 1.000
|
||||||
|
#set_min_delay -from [get_ports {VZ80_IORQn}] -to {Z80_IORQn} 1.000
|
||||||
|
#set_min_delay -from [get_ports {VZ80_MREQn}] -to {Z80_IORQn} 1.000
|
||||||
|
#set_min_delay -from [get_ports {VZ80_M1n}] -to {Z80_M1n} 1.000
|
||||||
|
#set_min_delay -from [get_ports {VZ80_RDn}] -to {Z80_RDn} 1.000
|
||||||
|
#set_min_delay -from [get_ports {VZ80_WRn}] -to {Z80_WRn} 1.000
|
||||||
|
#set_min_delay -from [get_ports {VZ80_BUSACKn}] -to {Z80_HALTn} 1.000
|
||||||
|
#set_min_delay -from [get_ports {VZ80_BUSACKn}] -to {Z80_RFSHn} 1.000
|
||||||
|
#set_min_delay -from [get_ports {VZ80_BUSACKn}] -to {Z80_IORQn} 1.000
|
||||||
|
#set_min_delay -from [get_ports {VZ80_BUSACKn}] -to {Z80_M1n} 1.000
|
||||||
|
#set_min_delay -from [get_ports {VZ80_BUSACKn}] -to {Z80_RDn} 1.000
|
||||||
|
#set_min_delay -from [get_ports {VZ80_BUSACKn}] -to {Z80_WRn} 1.000
|
||||||
|
#set_min_delay -from [get_ports {VZ80_A20_RFSHn_V_HSYNC}] -to {Z80_RFSHn} 1.000
|
||||||
|
#set_min_delay -from [get_ports {Z80_BUSACKn}] -to {Z80_HALTn} 1.000
|
||||||
|
#set_min_delay -from [get_ports {Z80_BUSACKn}] -to {Z80_IORQn} 1.000
|
||||||
|
#set_min_delay -from [get_ports {Z80_BUSACKn}] -to {Z80_M1n} 1.000
|
||||||
|
#set_min_delay -from [get_ports {Z80_BUSACKn}] -to {Z80_RDn} 1.000
|
||||||
|
#set_min_delay -from [get_ports {Z80_BUSACKn}] -to {Z80_WRn} 1.000
|
||||||
|
#set_min_delay -from [get_ports {Z80_BUSACKn}] -to {Z80_RFSHn} 1.000
|
||||||
|
#set_min_delay -from {Z80_BUSACKn} -to [get_ports {Z80_HALTn}] 1.000
|
||||||
|
#set_min_delay -from {Z80_BUSACKn} -to [get_ports {Z80_IORQn}] 1.000
|
||||||
|
#set_min_delay -from {Z80_BUSACKn} -to [get_ports {Z80_M1n}] 1.000
|
||||||
|
#set_min_delay -from {Z80_BUSACKn} -to [get_ports {Z80_RDn}] 1.000
|
||||||
|
#set_min_delay -from {Z80_BUSACKn} -to [get_ports {Z80_RFSHn}] 1.000
|
||||||
|
#set_min_delay -from {Z80_BUSACKn} -to [get_ports {Z80_WRn}] 1.000
|
||||||
|
#set_min_delay -from {cpld512:cpldl512Toplevel|CPLD_CFG_DATA[*]} -to [get_ports {Z80_HALTn}] 1.000
|
||||||
|
#set_min_delay -from {cpld512:cpldl512Toplevel|CPLD_CFG_DATA[*]} -to [get_ports {Z80_IORQn}] 1.000
|
||||||
|
#set_min_delay -from {cpld512:cpldl512Toplevel|CPLD_CFG_DATA[*]} -to [get_ports {Z80_M1n}] 1.000
|
||||||
|
#set_min_delay -from {cpld512:cpldl512Toplevel|CPLD_CFG_DATA[*]} -to [get_ports {Z80_RDn}] 1.000
|
||||||
|
#set_min_delay -from {cpld512:cpldl512Toplevel|CPLD_CFG_DATA[*]} -to [get_ports {Z80_WRn}] 1.000
|
||||||
|
#set_min_delay -from {cpld512:cpldl512Toplevel|CPLD_CFG_DATA[*]} -to [get_ports {Z80_RFSHn}] 1.000
|
||||||
|
#set_min_delay -from {cpld512:cpldl512Toplevel|CPU_CFG_DATA[*]} -to [get_ports {Z80_HALTn}] 1.000
|
||||||
|
#set_min_delay -from {cpld512:cpldl512Toplevel|CPU_CFG_DATA[*]} -to [get_ports {Z80_IORQn}] 1.000
|
||||||
|
#set_min_delay -from {cpld512:cpldl512Toplevel|CPU_CFG_DATA[*]} -to [get_ports {Z80_M1n}] 1.000
|
||||||
|
#set_min_delay -from {cpld512:cpldl512Toplevel|CPU_CFG_DATA[*]} -to [get_ports {Z80_RDn}] 1.000
|
||||||
|
#set_min_delay -from {cpld512:cpldl512Toplevel|CPU_CFG_DATA[*]} -to [get_ports {Z80_WRn}] 1.000
|
||||||
|
#set_min_delay -from {cpld512:cpldl512Toplevel|CPU_CFG_DATA[*]} -to [get_ports {Z80_RFSHn}] 1.000
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#**************************************************************
|
||||||
|
# Set Clock Groups
|
||||||
|
#**************************************************************
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#**************************************************************
|
||||||
|
# Set False Path
|
||||||
|
#**************************************************************
|
||||||
|
|
||||||
|
# For K64F
|
||||||
|
#set_false_path -from [get_clocks {CTLCLK}] -to [get_clocks {SYSCLK}]
|
||||||
|
#set_false_path -from [get_clocks {SYSCLK}] -to [get_clocks {CTLCLK}]
|
||||||
|
|
||||||
|
# For basic board with oscillator.
|
||||||
|
#set_false_path -from [get_clocks {cpld512:cpldl512Toplevel|CTLCLKi}] -to [get_clocks {SYSCLK}]
|
||||||
|
#set_false_path -from [get_clocks {cpld512:cpldl512Toplevel|CTLCLKi}] -to [get_clocks {CTLCLK}]
|
||||||
|
#set_false_path -from [get_clocks {SYSCLK}] -to [get_clocks {cpld512:cpldl512Toplevel|CTLCLKi}]
|
||||||
|
#set_false_path -from [get_clocks {SYSCLK}] -to [get_clocks {CTLCLK}]
|
||||||
|
|
||||||
|
# For both configurations.
|
||||||
|
#set_false_path -from {cpld512:cpldl512Toplevel|KEY_SUBSTITUTE} -to {cpld512:cpldl512Toplevel|CTLCLK_Q}
|
||||||
|
#set_false_path -from {cpld512:cpldl512Toplevel|MEM_MODE_LATCH[*]} -to {cpld512:cpldl512Toplevel|CTLCLK_Q}
|
||||||
|
#set_false_path -from {cpld512:cpldl512Toplevel|CPU_CFG_DATA[*]} -to {cpld512:cpldl512Toplevel|CTLCLK_Q}
|
||||||
|
#set_false_path -from {cpld512:cpldl512Toplevel|CPLD_CFG_DATA[*]} -to {cpld512:cpldl512Toplevel|CTLCLK_Q}
|
||||||
|
#set_false_path -from {cpld512:cpldl512Toplevel|MZ80B_VRAM_HI_ADDR} -to {cpld512:cpldl512Toplevel|CTLCLK_Q}
|
||||||
|
#set_false_path -from {cpld512:cpldl512Toplevel|MZ80B_VRAM_LO_ADDR} -to {cpld512:cpldl512Toplevel|CTLCLK_Q}
|
||||||
|
#set_false_path -from {cpld512:cpldl512Toplevel|MODE_VIDEO_MZ80B} -to {cpld512:cpldl512Toplevel|CTLCLK_Q}
|
||||||
|
#set_false_path -from {cpld512:cpldl512Toplevel|GRAM_PAGE_ENABLE} -to {cpld512:cpldl512Toplevel|CTLCLK_Q}
|
||||||
|
|
||||||
|
#**************************************************************
|
||||||
|
# Set Multicycle Path
|
||||||
|
#**************************************************************
|
||||||
|
#set_multicycle_path -from {cpld512:cpldl512Toplevel|CTL_BUSRQni} -to {cpld512:cpldl512Toplevel|CTLCLK_Q} -setup -end 2
|
||||||
|
#set_multicycle_path -from {cpld512:cpldl512Toplevel|CTL_BUSRQni} -to {cpld512:cpldl512Toplevel|CTLCLK_Q} -hold -end 1
|
||||||
|
|
||||||
|
#set_multicycle_path -from {cpld512:cpldl512Toplevel|CTL_BUSRQni} -to {cpld512:cpldl512Toplevel|MEM_MODE_LATCH[*]} -setup -end 2
|
||||||
|
#set_multicycle_path -from {cpld512:cpldl512Toplevel|CTL_BUSRQni} -to {cpld512:cpldl512Toplevel|MEM_MODE_LATCH[*]} -hold -end 1
|
||||||
|
|
||||||
|
#set_multicycle_path -from {cpld512:cpldl512Toplevel|CPU_CFG_DATA[*]} -to {cpld512:cpldl512Toplevel|MEM_MODE_LATCH[*]} -setup -end 2
|
||||||
|
#set_multicycle_path -from {cpld512:cpldl512Toplevel|CPU_CFG_DATA[*]} -to {cpld512:cpldl512Toplevel|MEM_MODE_LATCH[*]} -hold -end 1
|
||||||
|
|
||||||
|
#**************************************************************
|
||||||
|
# Set Maximum Delay
|
||||||
|
#**************************************************************
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#**************************************************************
|
||||||
|
# Set Minimum Delay
|
||||||
|
#**************************************************************
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#**************************************************************
|
||||||
|
# Set Input Transition
|
||||||
|
#**************************************************************
|
||||||
|
|
||||||
982
CPLD/v1.0/MZ80A/tzpuFusionX.vhd
Normal file
@@ -0,0 +1,982 @@
|
|||||||
|
-------------------------------------------------------------------------------------------------------
|
||||||
|
--
|
||||||
|
-- Name: tzpuFusionX.vhd
|
||||||
|
-- Version: MZ-80A
|
||||||
|
-- Created: Nov 2022
|
||||||
|
-- Author(s): Philip Smart
|
||||||
|
-- Description: tzpuFusionX CPLD logic definition file.
|
||||||
|
-- This module contains the definition of the tzpuFusionX project plus enhancements
|
||||||
|
-- for the MZ-80A.
|
||||||
|
--
|
||||||
|
-- Credits:
|
||||||
|
-- Copyright: (c) 2018-22 Philip Smart <philip.smart@net2net.org>
|
||||||
|
--
|
||||||
|
-- History: Nov 2022 - Initial write for the MZ-2000, adaption to MZ-80A underway.
|
||||||
|
--
|
||||||
|
---------------------------------------------------------------------------------------------------------
|
||||||
|
-- This source file is free software: you can redistribute it and-or modify
|
||||||
|
-- it under the terms of the GNU General Public License as published
|
||||||
|
-- by the Free Software Foundation, either version 3 of the License, or
|
||||||
|
-- (at your option) any later version.
|
||||||
|
--
|
||||||
|
-- This source file is distributed in the hope that it will be useful,
|
||||||
|
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
-- GNU General Public License for more details.
|
||||||
|
--
|
||||||
|
-- You should have received a copy of the GNU General Public License
|
||||||
|
-- along with this program. If not, see <http:--www.gnu.org-licenses->.
|
||||||
|
---------------------------------------------------------------------------------------------------------
|
||||||
|
library ieee;
|
||||||
|
library pkgs;
|
||||||
|
use ieee.std_logic_1164.all;
|
||||||
|
use ieee.std_logic_unsigned.all;
|
||||||
|
use ieee.numeric_std.all;
|
||||||
|
use work.tzpuFusionX_pkg.all;
|
||||||
|
|
||||||
|
entity cpld512 is
|
||||||
|
generic (
|
||||||
|
SPI_CLK_POLARITY : std_logic := '0'
|
||||||
|
);
|
||||||
|
port (
|
||||||
|
-- Z80 Address Bus
|
||||||
|
Z80_ADDR : inout std_logic_vector(15 downto 0);
|
||||||
|
|
||||||
|
-- Z80 Data Bus
|
||||||
|
Z80_DATA : inout std_logic_vector(7 downto 0);
|
||||||
|
|
||||||
|
-- Z80 Control signals.
|
||||||
|
Z80_BUSRQn : in std_logic;
|
||||||
|
Z80_BUSAKn : out std_logic;
|
||||||
|
Z80_INTn : in std_logic;
|
||||||
|
Z80_IORQn : inout std_logic;
|
||||||
|
Z80_MREQn : inout std_logic;
|
||||||
|
Z80_NMIn : in std_logic;
|
||||||
|
Z80_RDn : inout std_logic;
|
||||||
|
Z80_WRn : inout std_logic;
|
||||||
|
Z80_RESETn : in std_logic; -- Host CPU Reset signal, also CPLD reset.
|
||||||
|
Z80_HALTn : out std_logic;
|
||||||
|
Z80_WAITn : in std_logic;
|
||||||
|
Z80_M1n : inout std_logic;
|
||||||
|
Z80_RFSHn : inout std_logic;
|
||||||
|
|
||||||
|
-- SOM Control Signals
|
||||||
|
VSOM_SPI_CLK : in std_logic; -- SOM SPI Channel 0 Clock.
|
||||||
|
VSOM_SPI_MOSI : in std_logic; -- MOSI Input.
|
||||||
|
VSOM_SPI_MISO : out std_logic; -- MISO Output.
|
||||||
|
VSOM_SPI_CSn : in std_logic; -- Enable.
|
||||||
|
|
||||||
|
-- SOM Parallel Bus.
|
||||||
|
VSOM_DATA_OUT : out std_logic_vector(7 downto 0); -- Address/Data bus for CPLD control registers.
|
||||||
|
VSOM_HBYTE : in std_logic; -- Parallel Bus High (1)/Low (0) byte.
|
||||||
|
VSOM_READY : out std_logic; -- FSM Ready (1), Busy (0)
|
||||||
|
VSOM_LTSTATE : out std_logic; -- Last T-State in current cycle, 1 = active.
|
||||||
|
VSOM_BUSRQ : out std_logic; -- Host device requesting Z80 Bus.
|
||||||
|
VSOM_BUSACK : out std_logic; -- Host device granted Z80 Bus
|
||||||
|
VSOM_INT : out std_logic; -- Z80 INT signal
|
||||||
|
VSOM_NMI : out std_logic; -- Z80 NMI signal
|
||||||
|
VSOM_WAIT : out std_logic; -- Z80 WAIT signal
|
||||||
|
VSOM_RESET : out std_logic; -- Z80 RESET signal
|
||||||
|
VSOM_RSV : out std_logic_vector(1 downto 1); -- Reserved pins.
|
||||||
|
|
||||||
|
-- SOM Control Signals
|
||||||
|
PM_RESET : out std_logic; -- Reset SOM
|
||||||
|
|
||||||
|
-- VGA_Palette Control
|
||||||
|
VGA_R : in std_logic_vector(9 downto 7); -- Signals used for detecting blank or no video output.
|
||||||
|
VGA_G : in std_logic_vector(9 downto 7);
|
||||||
|
VGA_B : in std_logic_vector(9 downto 8);
|
||||||
|
|
||||||
|
-- VGA Control Signals
|
||||||
|
VGA_PXL_CLK : in std_logic; -- VGA Pixel clock for DAC conversion.
|
||||||
|
VGA_DISPEN : in std_logic; -- Displayed Enabled (SOM video output).
|
||||||
|
VGA_VSYNCn : in std_logic; -- SOM VSync.
|
||||||
|
VGA_HSYNCn : in std_logic; -- SOM HSync.
|
||||||
|
VGA_COLR : out std_logic; -- COLR colour carrier frequency.
|
||||||
|
VGA_CSYNCn : out std_logic; -- VGA Composite Sync.
|
||||||
|
VGA_BLANKn : out std_logic; -- VGA Blank detected.
|
||||||
|
|
||||||
|
-- CRT Control Signals
|
||||||
|
MONO_PXL_CLK : out std_logic; -- Mono CRT pixel clock for DAC conversion.
|
||||||
|
MONO_BLANKn : out std_logic; -- Mono CRT Blank (no active pixel) detection.
|
||||||
|
MONO_CSYNCn : out std_logic; -- Mono CRT composite sync.
|
||||||
|
MONO_RSV : out std_logic;
|
||||||
|
|
||||||
|
-- CRT Lower Chrominance Control
|
||||||
|
MONO_R : out std_logic_vector(2 downto 0); -- Signals to fine tune Red level of monochrome chrominance.
|
||||||
|
MONO_G : out std_logic_vector(2 downto 0); -- Signals to fine tune Green level of monochrome chrominance.
|
||||||
|
MONO_B : out std_logic_vector(2 downto 1); -- Signals to fine tune Blue level of monochrome chrominance.
|
||||||
|
|
||||||
|
-- MUX Control Signals
|
||||||
|
VIDEO_SRC : out std_logic; -- Select video source, Mainboard or SOM.
|
||||||
|
MONO_VIDEO_SRC : out std_logic; -- Select crt video source, Mainboard or SOM.
|
||||||
|
AUDIO_SRC_L : out std_logic; -- Select Audio Source Left Channel, Mainboard or SOM.
|
||||||
|
AUDIO_SRC_R : out std_logic; -- Select Audio Source Right Channel, Mainboard or SOM.
|
||||||
|
|
||||||
|
-- Mainboard Reset Signals
|
||||||
|
MB_RESETn : in std_logic; -- Motherboard Reset pressed.
|
||||||
|
MB_IPLn : in std_logic; -- Motherboard IPL pressed.
|
||||||
|
|
||||||
|
-- USB Power Control
|
||||||
|
VBUS_EN : out std_logic; -- USB Enable Power Output
|
||||||
|
|
||||||
|
-- Clocks.
|
||||||
|
Z80_CLK : in std_logic; -- Host CPU Clock
|
||||||
|
CLK_50M : in std_logic -- 50MHz oscillator.
|
||||||
|
);
|
||||||
|
end entity;
|
||||||
|
|
||||||
|
architecture rtl of cpld512 is
|
||||||
|
|
||||||
|
-- Finite State Machine states.
|
||||||
|
type SOMFSMState is
|
||||||
|
(
|
||||||
|
IdleCycle,
|
||||||
|
FetchCycle,
|
||||||
|
FetchCycle_11,
|
||||||
|
FetchCycle_20,
|
||||||
|
FetchCycle_21,
|
||||||
|
FetchCycle_30,
|
||||||
|
RefreshCycle,
|
||||||
|
RefreshCycle_11,
|
||||||
|
RefreshCycle_20,
|
||||||
|
RefreshCycle_21,
|
||||||
|
RefreshCycle_3,
|
||||||
|
WriteCycle,
|
||||||
|
WriteCycle_11,
|
||||||
|
WriteCycle_20,
|
||||||
|
WriteCycle_21,
|
||||||
|
WriteCycle_30,
|
||||||
|
WriteCycle_31,
|
||||||
|
ReadCycle,
|
||||||
|
ReadCycle_11,
|
||||||
|
ReadCycle_20,
|
||||||
|
ReadCycle_21,
|
||||||
|
ReadCycle_30,
|
||||||
|
ReadCycle_31,
|
||||||
|
WriteIOCycle,
|
||||||
|
WriteIOCycle_11,
|
||||||
|
WriteIOCycle_20,
|
||||||
|
WriteIOCycle_21,
|
||||||
|
WriteIOCycle_30,
|
||||||
|
WriteIOCycle_31,
|
||||||
|
WriteIOCycle_40,
|
||||||
|
WriteIOCycle_41,
|
||||||
|
ReadIOCycle,
|
||||||
|
ReadIOCycle_11,
|
||||||
|
ReadIOCycle_20,
|
||||||
|
ReadIOCycle_21,
|
||||||
|
ReadIOCycle_30,
|
||||||
|
ReadIOCycle_31,
|
||||||
|
ReadIOCycle_40,
|
||||||
|
ReadIOCycle_41,
|
||||||
|
HaltCycle,
|
||||||
|
BusReqCycle
|
||||||
|
);
|
||||||
|
|
||||||
|
-- CPU Interface internal signals.
|
||||||
|
signal Z80_BUSRQni : std_logic;
|
||||||
|
signal Z80_INTni : std_logic;
|
||||||
|
signal Z80_IORQni : std_logic;
|
||||||
|
signal Z80_MREQni : std_logic;
|
||||||
|
signal Z80_NMIni : std_logic;
|
||||||
|
signal Z80_RDni : std_logic;
|
||||||
|
signal Z80_WRni : std_logic;
|
||||||
|
signal Z80_HALTni : std_logic;
|
||||||
|
signal Z80_M1ni : std_logic;
|
||||||
|
signal Z80_RFSHni : std_logic;
|
||||||
|
signal Z80_DATAi : std_logic_vector(7 downto 0);
|
||||||
|
signal Z80_BUSRQ_ACKni : std_logic;
|
||||||
|
|
||||||
|
-- Internal CPU state control.
|
||||||
|
signal CPU_ADDR : std_logic_vector(15 downto 0) := (others => '0');
|
||||||
|
signal CPU_DATA_IN : std_logic_vector(7 downto 0) := (others => '0');
|
||||||
|
signal CPU_DATA_OUT : std_logic_vector(7 downto 0) := (others => '0');
|
||||||
|
signal CPU_DATA_EN : std_logic;
|
||||||
|
|
||||||
|
-- Clocks.
|
||||||
|
signal CLK_25Mi : std_logic := '0';
|
||||||
|
|
||||||
|
-- Reset control
|
||||||
|
signal PM_RESETi : std_logic := '1';
|
||||||
|
signal VSOM_RESETni : std_logic := '1';
|
||||||
|
|
||||||
|
-- Refresh control.
|
||||||
|
signal FSM_STATE : SOMFSMState := IdleCycle;
|
||||||
|
signal NEW_SPI_CMD : std_logic := '0';
|
||||||
|
signal VCPU_CS_EDGE : std_logic_vector(1 downto 0) := "11";
|
||||||
|
signal AUTOREFRESH_CNT : integer range 0 to 7;
|
||||||
|
signal FSM_STATUS : std_logic := '0';
|
||||||
|
signal FSM_CHECK_WAIT : std_logic := '0';
|
||||||
|
signal FSM_WAIT_ACTIVE : std_logic := '0';
|
||||||
|
signal RFSH_STATUS : std_logic := '0';
|
||||||
|
signal REFRESH_ADDR : std_logic_vector(7 downto 0);
|
||||||
|
signal IPAR : std_logic_vector(7 downto 0);
|
||||||
|
signal AUTOREFRESH : std_logic;
|
||||||
|
|
||||||
|
-- Clock edge detection and flagging.
|
||||||
|
signal Z80_CLKi : std_logic;
|
||||||
|
signal Z80_CLK_LAST : std_logic_vector(1 downto 0);
|
||||||
|
signal Z80_CLK_RE : std_logic;
|
||||||
|
signal Z80_CLK_FE : std_logic;
|
||||||
|
signal Z80_CLK_TGL : std_logic;
|
||||||
|
signal CPU_T_STATE_SET : integer range 0 to 5;
|
||||||
|
signal CPU_LAST_T_STATE : std_logic := '0';
|
||||||
|
|
||||||
|
-- SPI Slave interface.
|
||||||
|
signal SPI_SHIFT_EN : std_logic;
|
||||||
|
signal SPI_TX_SREG : std_logic_vector(6 downto 0); -- TX Shift Register
|
||||||
|
signal SPI_RX_SREG : std_logic_vector(7 downto 0); -- RX Shift Register
|
||||||
|
signal SPI_TX_DATA : std_logic_vector(31 downto 0); -- Data to transmit.
|
||||||
|
signal SPI_RX_DATA : std_logic_vector(31 downto 0); -- Data received.
|
||||||
|
signal SPI_BIT_CNT : integer range 0 to 16; -- Count of bits tx/rx'd.
|
||||||
|
signal SPI_FRAME_CNT : integer range 0 to 4; -- Number of frames received (8bit chunks).
|
||||||
|
|
||||||
|
-- SPI Command interface.
|
||||||
|
signal SOM_CMD : std_logic_vector(7 downto 0) := (others => '0');
|
||||||
|
signal SPI_NEW_DATA : std_logic;
|
||||||
|
signal SPI_PROCESSING : std_logic;
|
||||||
|
signal SPI_CPU_ADDR : std_logic_vector(15 downto 0) := (others => '0');
|
||||||
|
signal SPI_CPU_DATA : std_logic_vector(7 downto 0) := (others => '0');
|
||||||
|
|
||||||
|
-- Test modes.
|
||||||
|
signal SPI_LOOPBACK_TEST : std_logic := '0';
|
||||||
|
|
||||||
|
-- Video/Audio control
|
||||||
|
signal VIDEO_SRCi : std_logic := '0';
|
||||||
|
signal MONO_VIDEO_SRCi : std_logic := '0';
|
||||||
|
signal AUDIO_SRC_Li : std_logic := '0';
|
||||||
|
signal AUDIO_SRC_Ri : std_logic := '0';
|
||||||
|
signal VBUS_ENi : std_logic := '1';
|
||||||
|
|
||||||
|
|
||||||
|
function to_std_logic(L: boolean) return std_logic is
|
||||||
|
begin
|
||||||
|
if L then
|
||||||
|
return('1');
|
||||||
|
else
|
||||||
|
return('0');
|
||||||
|
end if;
|
||||||
|
end function to_std_logic;
|
||||||
|
begin
|
||||||
|
|
||||||
|
|
||||||
|
-- System RESET.
|
||||||
|
--
|
||||||
|
-- Multiple reset sources, Z80_RESETn, MB_IPLn, MB_RESETn. On the MZ-80A, MB_RESETn is a full reset to the power on state.
|
||||||
|
-- Like the MZ-700, we trigger on Z80_RESETn after having sampled the MB_RESETn state to decide on any extra actions needed within
|
||||||
|
-- the CPLD and the signals are forwarded onto the SOM so it too can take the correct reset path.
|
||||||
|
--
|
||||||
|
-- If the external reset switch is pressed, a Z80_RESETn is invoked sending the signal low for approx 30ms.
|
||||||
|
-- On the first edge the VSOM_RESETn signal is set which allows the SOM to see it and the Z80 application to enter a reset state.
|
||||||
|
-- On the second edge, if occurring within 1 second of the first, the PM_RESET signal to the SOM is triggered, held low for 1 second,
|
||||||
|
-- forcing the SOM to reboot.
|
||||||
|
SYSRESET: process( Z80_CLKi, Z80_RESETn )
|
||||||
|
variable timer1 : integer range 0 to 354000 := 0;
|
||||||
|
variable timer100 : integer range 0 to 10 := 0;
|
||||||
|
variable timerPMReset : integer range 0 to 10 := 0;
|
||||||
|
variable resetCount : integer range 0 to 3 := 0;
|
||||||
|
variable cpuResetEdge : std_logic := '1';
|
||||||
|
begin
|
||||||
|
-- Synchronous on the HOST Clock.
|
||||||
|
if(rising_edge(Z80_CLKi)) then
|
||||||
|
|
||||||
|
-- If the PM Reset timer is active, count down and on expiry release the SOM PM_RESET line.
|
||||||
|
if(timerPMReset = 0 and PM_RESETi = '1') then
|
||||||
|
PM_RESETi <= '0';
|
||||||
|
end if;
|
||||||
|
|
||||||
|
-- If the VSOM_RESETni is active after reset timer expiry, cancel the RESET state.
|
||||||
|
if(timerPMReset = 0 and VSOM_RESETni = '0') then
|
||||||
|
VSOM_RESETni <= '1';
|
||||||
|
end if;
|
||||||
|
|
||||||
|
-- Each time the reset button is pressed, count the edges.
|
||||||
|
if(Z80_RESETn = '0' and cpuResetEdge = '1' and (resetCount = 0 or timer100 > 5)) then
|
||||||
|
resetCount := resetCount + 1;
|
||||||
|
VSOM_RESETni <= '0';
|
||||||
|
timerPMReset := 5;
|
||||||
|
timer100 := 0;
|
||||||
|
|
||||||
|
-- If there are 2 or more reset signals in a given period it means a SOM reset is required.
|
||||||
|
if(resetCount >= 2) then
|
||||||
|
PM_RESETi <= '1';
|
||||||
|
timerPMReset := 10;
|
||||||
|
resetCount := 0;
|
||||||
|
end if;
|
||||||
|
|
||||||
|
end if;
|
||||||
|
|
||||||
|
-- 100ms interval.
|
||||||
|
if(timer1 = 354000) then
|
||||||
|
timer100 := timer100 + 1;
|
||||||
|
|
||||||
|
if(timer100 >= 10) then
|
||||||
|
timer100 := 0;
|
||||||
|
resetCount := 0;
|
||||||
|
end if;
|
||||||
|
|
||||||
|
if(timerPMReset > 0) then
|
||||||
|
timerPMReset := timerPMReset - 1;
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
|
||||||
|
timer1 := timer1 - 1;
|
||||||
|
cpuResetEdge := Z80_RESETn;
|
||||||
|
end if;
|
||||||
|
end process;
|
||||||
|
|
||||||
|
-- Create Mono DAC Clock based on primary clock.
|
||||||
|
MONOCLK: process( CLK_50M )
|
||||||
|
begin
|
||||||
|
if(rising_edge(CLK_50M)) then
|
||||||
|
CLK_25Mi <= not CLK_25Mi;
|
||||||
|
end if;
|
||||||
|
end process;
|
||||||
|
|
||||||
|
-- SPI Slave input. Receive command and data from the SOM.
|
||||||
|
SPI_INPUT : process(VSOM_SPI_CLK)
|
||||||
|
begin
|
||||||
|
-- SPI_CLK_POLARITY='0' => falling edge; SPI_CLK_POLARITY='1' => rising edge
|
||||||
|
if(VSOM_SPI_CLK'event and VSOM_SPI_CLK = SPI_CLK_POLARITY) then
|
||||||
|
if(VSOM_SPI_CSn = '0') then
|
||||||
|
SPI_RX_SREG <= SPI_RX_SREG(6 downto 0) & VSOM_SPI_MOSI;
|
||||||
|
|
||||||
|
-- End of frame then store the data prior to next bit arrival.
|
||||||
|
-- Convert to Little Endian, same as SOM.
|
||||||
|
if(SPI_SHIFT_EN = '1' and SPI_FRAME_CNT = 1 and SPI_BIT_CNT = 0) then
|
||||||
|
SPI_RX_DATA(7 downto 0) <= SPI_RX_SREG(6 downto 0) & VSOM_SPI_MOSI;
|
||||||
|
|
||||||
|
elsif(SPI_SHIFT_EN = '1' and SPI_FRAME_CNT = 2 and SPI_BIT_CNT = 0) then
|
||||||
|
SPI_RX_DATA(15 downto 8) <= SPI_RX_SREG(6 downto 0) & VSOM_SPI_MOSI;
|
||||||
|
|
||||||
|
elsif(SPI_SHIFT_EN = '1' and SPI_FRAME_CNT = 3 and SPI_BIT_CNT = 0) then
|
||||||
|
SPI_RX_DATA(23 downto 16) <= SPI_RX_SREG(6 downto 0) & VSOM_SPI_MOSI;
|
||||||
|
|
||||||
|
elsif(SPI_SHIFT_EN = '1' and SPI_FRAME_CNT = 4 and SPI_BIT_CNT = 0) then
|
||||||
|
SPI_RX_DATA(31 downto 24) <= SPI_RX_SREG(6 downto 0) & VSOM_SPI_MOSI;
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
end process;
|
||||||
|
|
||||||
|
-- SPI Slave output. Return the current data set as selected by the input signals XACT.
|
||||||
|
SPI_OUTPUT : process(VSOM_SPI_CLK,VSOM_SPI_CSn,SPI_TX_DATA)
|
||||||
|
begin
|
||||||
|
if(VSOM_SPI_CSn = '1') then
|
||||||
|
SPI_SHIFT_EN <= '0';
|
||||||
|
SPI_BIT_CNT <= 15;
|
||||||
|
|
||||||
|
-- SPI_CLK_POLARITY='0' => falling edge; SPI_CLK_POLARITY='1' => risinge edge
|
||||||
|
elsif(VSOM_SPI_CLK'event and VSOM_SPI_CLK = not SPI_CLK_POLARITY) then
|
||||||
|
SPI_SHIFT_EN <= '1';
|
||||||
|
|
||||||
|
if(SPI_BIT_CNT > 0) then
|
||||||
|
SPI_BIT_CNT <= SPI_BIT_CNT - 1;
|
||||||
|
end if;
|
||||||
|
|
||||||
|
VSOM_SPI_MISO <= SPI_TX_SREG(6);
|
||||||
|
SPI_TX_SREG <= SPI_TX_SREG(5 downto 0) & '0';
|
||||||
|
|
||||||
|
-- First clock after CS goes active, load up the data to be sent to the SOM.
|
||||||
|
if(SPI_SHIFT_EN = '0' or SPI_BIT_CNT = 0) then
|
||||||
|
|
||||||
|
if(SPI_LOOPBACK_TEST = '1') then
|
||||||
|
VSOM_SPI_MISO<= SPI_RX_SREG(7);
|
||||||
|
SPI_TX_SREG <= SPI_RX_SREG(6 downto 0);
|
||||||
|
|
||||||
|
elsif(SPI_SHIFT_EN = '0') then
|
||||||
|
SPI_FRAME_CNT<= 1;
|
||||||
|
VSOM_SPI_MISO<= SPI_TX_DATA(7);
|
||||||
|
SPI_TX_SREG <= SPI_TX_DATA(6 downto 0);
|
||||||
|
elsif(SPI_FRAME_CNT = 1) then
|
||||||
|
SPI_FRAME_CNT<= 2;
|
||||||
|
VSOM_SPI_MISO<= SPI_TX_DATA(15);
|
||||||
|
SPI_TX_SREG <= SPI_TX_DATA(14 downto 8);
|
||||||
|
elsif(SPI_FRAME_CNT = 2) then
|
||||||
|
SPI_FRAME_CNT<= 3;
|
||||||
|
VSOM_SPI_MISO<= SPI_TX_DATA(23);
|
||||||
|
SPI_TX_SREG <= SPI_TX_DATA(22 downto 16);
|
||||||
|
else
|
||||||
|
-- Increment frame count for each word received. We handle 8bit (1 frame), 16bit (2 frames) or 32bit (4 frames) reception.
|
||||||
|
SPI_FRAME_CNT<= 4;
|
||||||
|
VSOM_SPI_MISO<= SPI_TX_DATA(31);
|
||||||
|
SPI_TX_SREG <= SPI_TX_DATA(30 downto 24);
|
||||||
|
end if;
|
||||||
|
|
||||||
|
SPI_BIT_CNT <= 7;
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
end process;
|
||||||
|
|
||||||
|
SPI_REGISTER : process(Z80_RESETn, VSOM_SPI_CSn, SPI_FRAME_CNT)
|
||||||
|
begin
|
||||||
|
if(Z80_RESETn = '0') then
|
||||||
|
VIDEO_SRCi <= '0';
|
||||||
|
VGA_BLANKn <= '1';
|
||||||
|
VBUS_ENi <= '1';
|
||||||
|
MONO_VIDEO_SRCi <= '1';
|
||||||
|
AUDIO_SRC_Li <= '0';
|
||||||
|
AUDIO_SRC_Ri <= '0';
|
||||||
|
AUTOREFRESH <= '0';
|
||||||
|
SPI_LOOPBACK_TEST <= '0';
|
||||||
|
SOM_CMD <= (others => '0');
|
||||||
|
SPI_CPU_ADDR <= (others => '0');
|
||||||
|
SPI_NEW_DATA <= '0';
|
||||||
|
|
||||||
|
-- On rising edge of SPI CSn a new data packet from the SOM has arrived and in the shift register SPI_RX_SREG.
|
||||||
|
-- The variable SPI_FRAME_CNT indicates which byte (frame) in a 32bit word has been transmitted. This allows
|
||||||
|
-- for 8bit, 16bit and 32bit transmissions.
|
||||||
|
-- The packet is formatted as follows:
|
||||||
|
--
|
||||||
|
-- < SPI_FRAME_CNT=4 >< SPI_FRAME=3 > < SPI_FRAME_CNT=2 >< SPI_FRAME_CNT=1>
|
||||||
|
-- < 16bit Z80 Address > < Z80 Data ><Command=00..80>
|
||||||
|
-- 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
|
||||||
|
--
|
||||||
|
-- < > < Data ><Command=F0..FF>
|
||||||
|
-- 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
|
||||||
|
--
|
||||||
|
elsif(VSOM_SPI_CSn'event and VSOM_SPI_CSn = '1') then
|
||||||
|
|
||||||
|
-- Command is always located in the upper byte of frame 1.
|
||||||
|
SOM_CMD <= SPI_RX_DATA(7 downto 0);
|
||||||
|
|
||||||
|
-- Toggle flag to indicate new data arrived.
|
||||||
|
SPI_NEW_DATA <= not SPI_NEW_DATA;
|
||||||
|
|
||||||
|
-- Process the command. Some commands require the FSM, others can be serviced immediately.
|
||||||
|
case SPI_RX_DATA(7 downto 0) is
|
||||||
|
|
||||||
|
-- Z80XACT(0..15): Setup data and address as provided then execute FSM.
|
||||||
|
when X"10" | X"11" | X"12" | X"13" | X"14" | X"15" | X"16" | X"17" | -- Fetch
|
||||||
|
X"18" | X"19" | X"1A" | X"1B" | X"1C" | X"1D" | X"1E" | X"1F" | -- Write
|
||||||
|
X"20" | X"21" | X"22" | X"23" | X"24" | X"25" | X"26" | X"27" | -- Read
|
||||||
|
X"28" | X"29" | X"2A" | X"2B" | X"2C" | X"2D" | X"2E" | X"2F" | -- WriteIO
|
||||||
|
X"30" | X"31" | X"32" | X"33" | X"34" | X"35" | X"36" | X"37" | -- ReadIO
|
||||||
|
X"38" | X"39" | X"3A" | X"3B" | X"3C" | X"3D" | X"3E" | X"3F" | --
|
||||||
|
X"40" | X"41" | X"42" | X"43" | X"44" | X"45" | X"46" | X"47" | --
|
||||||
|
X"48" | X"49" | X"4A" | X"4B" | X"4C" | X"4D" | X"4E" | X"4F" =>
|
||||||
|
|
||||||
|
-- Direct address set.
|
||||||
|
if(SPI_FRAME_CNT = 4) then
|
||||||
|
SPI_CPU_ADDR <= SPI_RX_DATA(31 downto 16);
|
||||||
|
else
|
||||||
|
-- if(SPI_CPU_ADDR >= X"D010" and SPI_CPU_ADDR < X"D020") then
|
||||||
|
-- SPI_CPU_ADDR <= std_logic_vector(X"D020" + unsigned(SPI_RX_DATA(2 downto 0)));
|
||||||
|
-- else
|
||||||
|
SPI_CPU_ADDR <= std_logic_vector(unsigned(SPI_CPU_ADDR) + unsigned(SPI_RX_DATA(2 downto 0)));
|
||||||
|
-- end if;
|
||||||
|
end if;
|
||||||
|
|
||||||
|
if(SPI_FRAME_CNT > 1) then
|
||||||
|
SPI_CPU_DATA <= SPI_RX_DATA(15 downto 8);
|
||||||
|
end if;
|
||||||
|
|
||||||
|
-- SETSIGSET1: Set control lines directly.
|
||||||
|
when X"F0" =>
|
||||||
|
VIDEO_SRCi <= SPI_RX_DATA(8);
|
||||||
|
MONO_VIDEO_SRCi <= SPI_RX_DATA(9);
|
||||||
|
AUDIO_SRC_Li <= SPI_RX_DATA(10);
|
||||||
|
AUDIO_SRC_Ri <= SPI_RX_DATA(11);
|
||||||
|
VBUS_ENi <= SPI_RX_DATA(12);
|
||||||
|
VGA_BLANKn <= not SPI_RX_DATA(13);
|
||||||
|
|
||||||
|
-- Enable auto refresh DRAM cycle.
|
||||||
|
when X"F1" =>
|
||||||
|
AUTOREFRESH <= '1';
|
||||||
|
|
||||||
|
-- Disable auto refresh DRAM cycle.
|
||||||
|
when X"F2" =>
|
||||||
|
AUTOREFRESH <= '0';
|
||||||
|
|
||||||
|
-- SETLOOPBACK: Enable loopback test mode.
|
||||||
|
when X"FE" =>
|
||||||
|
SPI_LOOPBACK_TEST<= '1';
|
||||||
|
|
||||||
|
-- No action, called to retrieve status.
|
||||||
|
when X"00" | X"FF" =>
|
||||||
|
|
||||||
|
when others =>
|
||||||
|
end case;
|
||||||
|
end if;
|
||||||
|
end process;
|
||||||
|
|
||||||
|
-- Process to detect the Z80 Clock edges. Each edge is used to recreate the Z80 external signals.
|
||||||
|
--
|
||||||
|
Z80CLK: process( CLK_50M, Z80_CLKi, Z80_RESETn )
|
||||||
|
begin
|
||||||
|
if(Z80_RESETn = '0') then
|
||||||
|
Z80_CLK_RE <= '1';
|
||||||
|
Z80_CLK_FE <= '1';
|
||||||
|
Z80_CLK_TGL <= '1';
|
||||||
|
|
||||||
|
elsif(rising_edge(CLK_50M)) then
|
||||||
|
|
||||||
|
-- Default is to clear the signals, only active for 1 clock period.
|
||||||
|
Z80_CLK_RE <= '0';
|
||||||
|
Z80_CLK_FE <= '0';
|
||||||
|
Z80_CLK_TGL <= '0';
|
||||||
|
|
||||||
|
-- Rising Edge.
|
||||||
|
if(Z80_CLKi = '1' and Z80_CLK_LAST = "00") then
|
||||||
|
Z80_CLK_RE <= '1';
|
||||||
|
|
||||||
|
-- Toggle on rising edge is delayed by one clock to allow time for command to be decoded.
|
||||||
|
elsif(Z80_CLKi = '1' and Z80_CLK_LAST = "01") then
|
||||||
|
Z80_CLK_TGL <= '1';
|
||||||
|
|
||||||
|
-- Falling Edge.
|
||||||
|
elsif(Z80_CLKi = '0' and Z80_CLK_LAST = "11") then
|
||||||
|
Z80_CLK_FE <= '1';
|
||||||
|
Z80_CLK_TGL <= '1';
|
||||||
|
end if;
|
||||||
|
Z80_CLK_LAST <= Z80_CLK_LAST(0) & Z80_CLKi;
|
||||||
|
end if;
|
||||||
|
end process;
|
||||||
|
|
||||||
|
-- SOM Finite State Machine.
|
||||||
|
--
|
||||||
|
-- A command processor, based on an FSM concept, to process requested commands, ie. Z80 Write, Z80 Read etc.
|
||||||
|
-- The external signal SOM_CMD_EN, when set, indicates a new command available in SOM_CMD.
|
||||||
|
--
|
||||||
|
SOMFSM: process( CLK_50M, Z80_CLKi, Z80_RESETn )
|
||||||
|
begin
|
||||||
|
if(Z80_RESETn = '0') then
|
||||||
|
Z80_IORQni <= '1';
|
||||||
|
Z80_MREQni <= '1';
|
||||||
|
Z80_RDni <= '1';
|
||||||
|
Z80_WRni <= '1';
|
||||||
|
Z80_HALTni <= '1';
|
||||||
|
Z80_M1ni <= '1';
|
||||||
|
Z80_RFSHni <= '1';
|
||||||
|
Z80_BUSRQ_ACKni <= '1';
|
||||||
|
FSM_CHECK_WAIT <= '0';
|
||||||
|
FSM_WAIT_ACTIVE <= '0';
|
||||||
|
FSM_STATUS <= '0';
|
||||||
|
FSM_STATE <= IdleCycle;
|
||||||
|
RFSH_STATUS <= '0';
|
||||||
|
CPU_DATA_EN <= '0';
|
||||||
|
CPU_DATA_IN <= (others => '0');
|
||||||
|
REFRESH_ADDR <= (others => '0');
|
||||||
|
AUTOREFRESH_CNT <= 7;
|
||||||
|
IPAR <= (others => '0');
|
||||||
|
NEW_SPI_CMD <= '0';
|
||||||
|
VCPU_CS_EDGE <= "11";
|
||||||
|
SPI_PROCESSING <= '0';
|
||||||
|
|
||||||
|
elsif(rising_edge(CLK_50M)) then
|
||||||
|
|
||||||
|
-- Bus request mechanism. If an externel Bus Request comes in and the FSM is idle, run the Bus Request command which
|
||||||
|
-- suspends processing and tri-states the bus.
|
||||||
|
if(Z80_BUSRQn = '0' and Z80_BUSRQ_ACKni = '1' and FSM_STATE = IdleCycle) then
|
||||||
|
FSM_STATE <= BusReqCycle;
|
||||||
|
end if;
|
||||||
|
if(Z80_BUSRQn = '1' and Z80_BUSRQ_ACKni = '0' and FSM_STATE = IdleCycle) then
|
||||||
|
Z80_BUSRQ_ACKni <= '1';
|
||||||
|
end if;
|
||||||
|
|
||||||
|
-- New command, set flag as the signal is only 1 clock wide.
|
||||||
|
if(SPI_LOOPBACK_TEST = '0' and VSOM_SPI_CSn = '1' and VCPU_CS_EDGE = "01") then
|
||||||
|
NEW_SPI_CMD <= '1';
|
||||||
|
end if;
|
||||||
|
|
||||||
|
-- Whenever we return to Idle or just prior to Refresh from a Fetch cycle set all control signals to default.
|
||||||
|
if(FSM_STATE = IdleCycle or FSM_STATE = RefreshCycle) then
|
||||||
|
CPU_DATA_EN <= '0';
|
||||||
|
Z80_MREQni <= '1';
|
||||||
|
Z80_IORQni <= '1';
|
||||||
|
Z80_RDni <= '1';
|
||||||
|
Z80_WRni <= '1';
|
||||||
|
Z80_M1ni <= '1';
|
||||||
|
FSM_STATUS <= '0';
|
||||||
|
Z80_RFSHni <= '1';
|
||||||
|
|
||||||
|
-- Auto DRAM refresh cycles. When enabled, every 7 host clock cycles, a 2 cycle refresh period commences.
|
||||||
|
-- This will be overriden if the SPI receives a new command.
|
||||||
|
--
|
||||||
|
if AUTOREFRESH = '1' and FSM_STATE = IdleCycle then
|
||||||
|
AUTOREFRESH_CNT <= AUTOREFRESH_CNT - 1;
|
||||||
|
if(AUTOREFRESH_CNT = 0) then
|
||||||
|
FSM_STATE <= RefreshCycle_3;
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
|
||||||
|
-- If new command has been given and the FSM enters idle state, load up new command for processing.
|
||||||
|
if(NEW_SPI_CMD = '1' and FSM_STATE = IdleCycle and Z80_CLK_RE = '1') then
|
||||||
|
NEW_SPI_CMD <= '0';
|
||||||
|
|
||||||
|
-- Store new address and data for this command.
|
||||||
|
CPU_ADDR <= SPI_CPU_ADDR;
|
||||||
|
if(SPI_CPU_DATA /= CPU_DATA_OUT) then
|
||||||
|
CPU_DATA_OUT <= SPI_CPU_DATA;
|
||||||
|
end if;
|
||||||
|
|
||||||
|
-- Process the SOM command. The SPI_REGISTER executes non FSM commands and stores FSM
|
||||||
|
-- data prior to this execution block, which fires 1 cycle later on the same control clock.
|
||||||
|
-- If the command is not for the FSM then the READY mechanism is held for one
|
||||||
|
-- further cycle before going inactive.
|
||||||
|
case SOM_CMD is
|
||||||
|
when X"10" | X"11" | X"12" | X"13" | X"14" | X"15" | X"16" | X"17" =>
|
||||||
|
-- Initiate a Fetch Cycle.
|
||||||
|
FSM_STATE <= FetchCycle;
|
||||||
|
|
||||||
|
when X"18" | X"19" | X"1A" | X"1B" | X"1C" | X"1D" | X"1E" | X"1F" =>
|
||||||
|
|
||||||
|
-- Set the Z80 data bus value and initiate a Write Cycle.
|
||||||
|
FSM_STATE <= WriteCycle;
|
||||||
|
|
||||||
|
when X"20" | X"21" | X"22" | X"23" | X"24" | X"25" | X"26" | X"27" =>
|
||||||
|
-- Initiate a Read Cycle.
|
||||||
|
FSM_STATE <= ReadCycle;
|
||||||
|
|
||||||
|
when X"28" | X"29" | X"2A" | X"2B" | X"2C" | X"2D" | X"2E" | X"2F" =>
|
||||||
|
-- Set the Z80 data bus value and initiate an IO Write Cycle.
|
||||||
|
-- The SOM should set 15:8 to the B register value.
|
||||||
|
FSM_STATE <= WriteIOCycle;
|
||||||
|
|
||||||
|
when X"30" | X"31" | X"32" | X"33" | X"34" | X"35" | X"36" | X"37" =>
|
||||||
|
-- Initiate a Read IO Cycle.
|
||||||
|
FSM_STATE <= ReadIOCycle;
|
||||||
|
|
||||||
|
when X"50" =>
|
||||||
|
-- Register a Halt state.
|
||||||
|
FSM_STATE <= HaltCycle;
|
||||||
|
|
||||||
|
when X"51" =>
|
||||||
|
-- Initiate a refresh cycle.
|
||||||
|
FSM_STATE <= RefreshCycle_3;
|
||||||
|
|
||||||
|
when X"E0" =>
|
||||||
|
-- Initiate a Halt Cycle.
|
||||||
|
FSM_STATE <= HaltCycle;
|
||||||
|
|
||||||
|
-- Set the Refresh Address register.
|
||||||
|
when X"E1" =>
|
||||||
|
REFRESH_ADDR <= CPU_DATA_OUT;
|
||||||
|
|
||||||
|
-- Set the Interrupt Page Address Register.
|
||||||
|
when X"E2" =>
|
||||||
|
IPAR <= CPU_DATA_OUT;
|
||||||
|
|
||||||
|
when others =>
|
||||||
|
end case;
|
||||||
|
|
||||||
|
-- Toggle the processing flag to negate the new data flag. Used to indicate device is busy.
|
||||||
|
if(SPI_NEW_DATA /= SPI_PROCESSING) then
|
||||||
|
SPI_PROCESSING <= not SPI_PROCESSING;
|
||||||
|
end if;
|
||||||
|
|
||||||
|
-- FSM Status bit. When processing a command it is set, cleared when idle. Used by SOM to determine command completion.
|
||||||
|
FSM_STATUS <= '1';
|
||||||
|
end if;
|
||||||
|
|
||||||
|
-- Refresh status bit. Indicates a Refresh cycle is under way.
|
||||||
|
if FSM_STATE = RefreshCycle or FSM_STATE = RefreshCycle_11 or FSM_STATE = RefreshCycle_20 or FSM_STATE = RefreshCycle_21 or FSM_STATE = RefreshCycle_3 then
|
||||||
|
RFSH_STATUS <= '1';
|
||||||
|
else
|
||||||
|
RFSH_STATUS <= '0';
|
||||||
|
end if;
|
||||||
|
|
||||||
|
-- If we are in a WAIT sampling 1/2 cycle and wait goes active, set the state so we repeat the full clock cycle by winding back 2 places.
|
||||||
|
if(FSM_CHECK_WAIT = '1' and Z80_WAITn = '0' and Z80_CLK_TGL = '0') then
|
||||||
|
FSM_WAIT_ACTIVE <= '1';
|
||||||
|
end if;
|
||||||
|
|
||||||
|
-- On each Z80 edge we advance the FSM to recreate the Z80 external signal transactions.
|
||||||
|
if(Z80_CLK_TGL = '1') then
|
||||||
|
|
||||||
|
-- The FSM advances to the next stage on each Z80 edge unless in Idle state.
|
||||||
|
if(FSM_STATE /= IdleCycle) then
|
||||||
|
FSM_STATE <= SOMFSMState'val(SOMFSMState'POS(FSM_STATE)+1);
|
||||||
|
end if;
|
||||||
|
|
||||||
|
-- Half cycle expired so we dont check the Z80 wait again.
|
||||||
|
FSM_CHECK_WAIT <= '0';
|
||||||
|
FSM_WAIT_ACTIVE <= '0';
|
||||||
|
|
||||||
|
-- FSM to implement all the required Z80 cycles.
|
||||||
|
--
|
||||||
|
case FSM_STATE is
|
||||||
|
|
||||||
|
when IdleCycle =>
|
||||||
|
CPU_LAST_T_STATE <= '1';
|
||||||
|
-- FSM_STATE <= IdleCycle;
|
||||||
|
|
||||||
|
-----------------------------
|
||||||
|
-- Z80 Fetch Cycle.
|
||||||
|
-----------------------------
|
||||||
|
when FetchCycle =>
|
||||||
|
Z80_M1ni <= '0';
|
||||||
|
|
||||||
|
when FetchCycle_11 =>
|
||||||
|
Z80_M1ni <= '0';
|
||||||
|
Z80_MREQni <= '0';
|
||||||
|
Z80_RDni <= '0';
|
||||||
|
|
||||||
|
when FetchCycle_20 =>
|
||||||
|
FSM_CHECK_WAIT <= '1';
|
||||||
|
|
||||||
|
when FetchCycle_21 =>
|
||||||
|
if(Z80_WAITn = '0' or FSM_WAIT_ACTIVE = '1') then
|
||||||
|
FSM_STATE <= FetchCycle_20;
|
||||||
|
end if;
|
||||||
|
|
||||||
|
when FetchCycle_30 =>
|
||||||
|
-- To meet the timing diagrams, just after Rising edge on T3 clear signals. Data wont be available until
|
||||||
|
-- a short period before the falling edge of T3 (could be an MZ-80A design restriction or the Z80 timing diagrams are a bit out).
|
||||||
|
FSM_STATE <= RefreshCycle;
|
||||||
|
|
||||||
|
-----------------------------
|
||||||
|
-- Z80 Refresh Cycle.
|
||||||
|
-----------------------------
|
||||||
|
when RefreshCycle =>
|
||||||
|
-- Latch data from mainboard.
|
||||||
|
CPU_DATA_IN <= Z80_DATA;
|
||||||
|
FSM_STATUS <= '0';
|
||||||
|
Z80_RFSHni <= '0';
|
||||||
|
|
||||||
|
when RefreshCycle_11 =>
|
||||||
|
-- Falling edge of T3 activates the MREQ line.
|
||||||
|
Z80_MREQni <= '0';
|
||||||
|
|
||||||
|
when RefreshCycle_20 =>
|
||||||
|
|
||||||
|
when RefreshCycle_21 =>
|
||||||
|
Z80_MREQni <= '1';
|
||||||
|
REFRESH_ADDR(6 downto 0) <= REFRESH_ADDR(6 downto 0) + 1;
|
||||||
|
FSM_STATE <= IdleCycle;
|
||||||
|
|
||||||
|
when RefreshCycle_3 =>
|
||||||
|
Z80_RFSHni <= '0';
|
||||||
|
FSM_STATE <= RefreshCycle_11;
|
||||||
|
|
||||||
|
-----------------------------
|
||||||
|
-- Z80 Write Cycle.
|
||||||
|
-----------------------------
|
||||||
|
when WriteCycle =>
|
||||||
|
|
||||||
|
when WriteCycle_11 =>
|
||||||
|
Z80_MREQni <= '0';
|
||||||
|
CPU_DATA_EN <= '1';
|
||||||
|
|
||||||
|
when WriteCycle_20 =>
|
||||||
|
FSM_CHECK_WAIT <= '1';
|
||||||
|
|
||||||
|
when WriteCycle_21 =>
|
||||||
|
Z80_WRni <= '0';
|
||||||
|
if(Z80_WAITn = '0' or FSM_WAIT_ACTIVE = '1') then
|
||||||
|
FSM_STATE <= WriteCycle_20;
|
||||||
|
end if;
|
||||||
|
|
||||||
|
when WriteCycle_30 =>
|
||||||
|
|
||||||
|
when WriteCycle_31 =>
|
||||||
|
FSM_STATUS <= '0';
|
||||||
|
Z80_MREQni <= '1';
|
||||||
|
Z80_WRni <= '1';
|
||||||
|
FSM_STATE <= IdleCycle;
|
||||||
|
|
||||||
|
-----------------------------
|
||||||
|
-- Z80 Read Cycle.
|
||||||
|
-----------------------------
|
||||||
|
when ReadCycle =>
|
||||||
|
|
||||||
|
when ReadCycle_11 =>
|
||||||
|
Z80_MREQni <= '0';
|
||||||
|
Z80_RDni <= '0';
|
||||||
|
|
||||||
|
when ReadCycle_20 =>
|
||||||
|
FSM_CHECK_WAIT <= '1';
|
||||||
|
|
||||||
|
when ReadCycle_21 =>
|
||||||
|
if(Z80_WAITn = '0' or FSM_WAIT_ACTIVE = '1') then
|
||||||
|
FSM_STATE <= ReadCycle_20;
|
||||||
|
end if;
|
||||||
|
|
||||||
|
when ReadCycle_30 =>
|
||||||
|
|
||||||
|
when ReadCycle_31 =>
|
||||||
|
-- Latch data from mainboard.
|
||||||
|
CPU_DATA_IN <= Z80_DATA;
|
||||||
|
FSM_STATUS <= '0';
|
||||||
|
FSM_STATE <= IdleCycle;
|
||||||
|
|
||||||
|
|
||||||
|
-----------------------------
|
||||||
|
-- Z80 IO Write Cycle.
|
||||||
|
-----------------------------
|
||||||
|
when WriteIOCycle =>
|
||||||
|
|
||||||
|
when WriteIOCycle_11 =>
|
||||||
|
CPU_DATA_EN <= '1';
|
||||||
|
|
||||||
|
when WriteIOCycle_20 =>
|
||||||
|
Z80_IORQni <= '0';
|
||||||
|
Z80_WRni <= '0';
|
||||||
|
|
||||||
|
when WriteIOCycle_21 =>
|
||||||
|
|
||||||
|
when WriteIOCycle_30 =>
|
||||||
|
FSM_CHECK_WAIT <= '1';
|
||||||
|
|
||||||
|
when WriteIOCycle_31 =>
|
||||||
|
if(Z80_WAITn = '0' or FSM_WAIT_ACTIVE = '1') then
|
||||||
|
FSM_STATE <= WriteIOCycle_20;
|
||||||
|
end if;
|
||||||
|
|
||||||
|
when WriteIOCycle_40 =>
|
||||||
|
|
||||||
|
when WriteIOCycle_41 =>
|
||||||
|
FSM_STATUS <= '0';
|
||||||
|
Z80_IORQni <= '1';
|
||||||
|
Z80_WRni <= '1';
|
||||||
|
FSM_STATE <= IdleCycle;
|
||||||
|
|
||||||
|
-----------------------------
|
||||||
|
-- Z80 IO Read Cycle.
|
||||||
|
-----------------------------
|
||||||
|
when ReadIOCycle =>
|
||||||
|
|
||||||
|
when ReadIOCycle_11 =>
|
||||||
|
|
||||||
|
when ReadIOCycle_20 =>
|
||||||
|
Z80_IORQni <= '0';
|
||||||
|
Z80_RDni <= '0';
|
||||||
|
|
||||||
|
when ReadIOCycle_21 =>
|
||||||
|
|
||||||
|
when ReadIOCycle_30 =>
|
||||||
|
FSM_CHECK_WAIT <= '1';
|
||||||
|
|
||||||
|
when ReadIOCycle_31 =>
|
||||||
|
if(Z80_WAITn = '0' or FSM_WAIT_ACTIVE = '1') then
|
||||||
|
FSM_STATE <= ReadIOCycle_20;
|
||||||
|
end if;
|
||||||
|
|
||||||
|
when ReadIOCycle_40 =>
|
||||||
|
|
||||||
|
when ReadIOCycle_41 =>
|
||||||
|
-- Latch data from mainboard.
|
||||||
|
CPU_DATA_IN <= Z80_DATA;
|
||||||
|
FSM_STATUS <= '0';
|
||||||
|
|
||||||
|
-- IORQ/RD are deactivated at idle giving 1 clock to latch the data in.
|
||||||
|
FSM_STATE <= IdleCycle;
|
||||||
|
|
||||||
|
-----------------------------
|
||||||
|
-- Halt Request.
|
||||||
|
-----------------------------
|
||||||
|
when HaltCycle =>
|
||||||
|
Z80_HALTni <= '0';
|
||||||
|
FSM_STATUS <= '0';
|
||||||
|
FSM_STATE <= IdleCycle;
|
||||||
|
|
||||||
|
-----------------------------
|
||||||
|
-- Z80 Bus Request.
|
||||||
|
-----------------------------
|
||||||
|
when BusReqCycle =>
|
||||||
|
Z80_BUSRQ_ACKni <= '0';
|
||||||
|
FSM_STATE <= IdleCycle;
|
||||||
|
|
||||||
|
when others =>
|
||||||
|
FSM_STATE <= IdleCycle;
|
||||||
|
end case;
|
||||||
|
end if;
|
||||||
|
|
||||||
|
VCPU_CS_EDGE <= VCPU_CS_EDGE(0) & VSOM_SPI_CSn;
|
||||||
|
end if;
|
||||||
|
end process;
|
||||||
|
|
||||||
|
Z80_CLKi <= not Z80_CLK;
|
||||||
|
|
||||||
|
-- CPU Interface tri-state control based on acknowledged bus request.
|
||||||
|
Z80_ADDR <= IPAR & REFRESH_ADDR when Z80_RFSHni = '0'
|
||||||
|
else
|
||||||
|
CPU_ADDR when Z80_BUSRQ_ACKni = '1'
|
||||||
|
else
|
||||||
|
(others => 'Z');
|
||||||
|
Z80_DATA <= CPU_DATA_OUT when Z80_BUSRQ_ACKni = '1' and CPU_DATA_EN = '1'
|
||||||
|
else
|
||||||
|
(others => 'Z');
|
||||||
|
-- Z80_DATAi <= Z80_DATA when Z80_RDn = '0'
|
||||||
|
-- else (others => '1');
|
||||||
|
Z80_RDn <= Z80_RDni when Z80_BUSRQ_ACKni = '1'
|
||||||
|
else 'Z';
|
||||||
|
Z80_WRn <= Z80_WRni when Z80_BUSRQ_ACKni = '1'
|
||||||
|
else 'Z';
|
||||||
|
Z80_M1n <= Z80_M1ni when Z80_BUSRQ_ACKni = '1'
|
||||||
|
else 'Z';
|
||||||
|
Z80_RFSHn <= Z80_RFSHni when Z80_BUSRQ_ACKni = '1'
|
||||||
|
else 'Z';
|
||||||
|
Z80_MREQn <= Z80_MREQni when Z80_BUSRQ_ACKni = '1'
|
||||||
|
else 'Z';
|
||||||
|
Z80_IORQn <= Z80_IORQni when Z80_BUSRQ_ACKni = '1'
|
||||||
|
else 'Z';
|
||||||
|
Z80_BUSAKn <= Z80_BUSRQ_ACKni;
|
||||||
|
|
||||||
|
-- CPU Interface single state output.
|
||||||
|
Z80_HALTn <= Z80_HALTni;
|
||||||
|
|
||||||
|
-- CPU Interface single state input.
|
||||||
|
Z80_NMIni <= Z80_NMIn;
|
||||||
|
Z80_INTni <= Z80_INTn;
|
||||||
|
Z80_BUSRQni <= Z80_BUSRQn;
|
||||||
|
|
||||||
|
-- SOM Reset.
|
||||||
|
PM_RESET <= PM_RESETi;
|
||||||
|
|
||||||
|
-- SOM to CPLD Interface.
|
||||||
|
VSOM_DATA_OUT <= CPU_DATA_IN when VSOM_HBYTE = '1'
|
||||||
|
else
|
||||||
|
FSM_STATUS & RFSH_STATUS & Z80_BUSRQ_ACKni & Z80_BUSRQni & Z80_INTni & Z80_NMIni & Z80_WAITn & Z80_RESETn when VSOM_HBYTE = '0'
|
||||||
|
else
|
||||||
|
(others => '0');
|
||||||
|
|
||||||
|
-- Loopback test, echo what was received.
|
||||||
|
SPI_TX_DATA <= SPI_RX_DATA when SPI_LOOPBACK_TEST = '1'
|
||||||
|
else
|
||||||
|
--CPU_ADDR & SOM_CMD & FSM_STATUS & RFSH_STATUS & std_logic_vector(to_unsigned(SOMFSMState'POS(FSM_STATE), 6));
|
||||||
|
CPU_ADDR & CPU_DATA_IN & FSM_STATUS & RFSH_STATUS & Z80_BUSRQ_ACKni & Z80_BUSRQni & Z80_INTni & Z80_NMIni & Z80_WAITn & Z80_RESETn;
|
||||||
|
|
||||||
|
-- Signal mirrors.
|
||||||
|
VSOM_READY <= '0' when FSM_STATUS='1' or SPI_NEW_DATA /= SPI_PROCESSING
|
||||||
|
else '1'; -- FSM Ready (1), Busy (0)
|
||||||
|
VSOM_LTSTATE <= '1' when CPU_LAST_T_STATE = '1' -- Last T-State in current cycle.
|
||||||
|
else '0';
|
||||||
|
VSOM_BUSRQ <= not Z80_BUSRQn; -- Host device requesting Z80 Bus.
|
||||||
|
VSOM_BUSACK <= not Z80_BUSRQ_ACKni; -- Host device granted Z80 Bus
|
||||||
|
VSOM_INT <= not Z80_INTn; -- Z80 INT signal
|
||||||
|
VSOM_NMI <= not Z80_NMIn; -- Z80 NMI signal
|
||||||
|
VSOM_WAIT <= not Z80_WAITn; -- Z80 WAIT signal
|
||||||
|
VSOM_RESET <= not VSOM_RESETni; -- Z80 RESET signal
|
||||||
|
VSOM_RSV <= (others => '0'); -- Reserved pins.
|
||||||
|
|
||||||
|
-- Video/Audio control signals.
|
||||||
|
VIDEO_SRC <= VIDEO_SRCi;
|
||||||
|
MONO_VIDEO_SRC <= MONO_VIDEO_SRCi;
|
||||||
|
AUDIO_SRC_L <= AUDIO_SRC_Li;
|
||||||
|
AUDIO_SRC_R <= AUDIO_SRC_Ri;
|
||||||
|
|
||||||
|
-- USB Power Supply enable.
|
||||||
|
VBUS_EN <= VBUS_ENi;
|
||||||
|
|
||||||
|
-- Monochrome output is based on the incoming VGA to give the best chrominance levels.
|
||||||
|
MONO_R <= VGA_R;
|
||||||
|
MONO_G <= VGA_G;
|
||||||
|
MONO_B <= VGA_B;
|
||||||
|
|
||||||
|
-- Blanking is active when all colour signals are at 0. The DAC converts values in range 4v .. 5v to adjust chrominance
|
||||||
|
-- but true off can obly be achieved by bringing the signal value to 0v which is achieved by a Mux activated with this blanking signal.
|
||||||
|
MONO_BLANKn <= '0' when VGA_R = "000" and VGA_G = "000" and VGA_B = "000"
|
||||||
|
else '1';
|
||||||
|
|
||||||
|
-- Generate composite sync.
|
||||||
|
VGA_CSYNCn <= VGA_HSYNCn xor not VGA_VSYNCn;
|
||||||
|
MONO_CSYNCn <= not VGA_HSYNCn xor not VGA_VSYNCn;
|
||||||
|
|
||||||
|
-- DAC clocks.
|
||||||
|
--VGA_PXL_CLK <= CLK_50M;
|
||||||
|
MONO_PXL_CLK <= VGA_PXL_CLK;
|
||||||
|
|
||||||
|
end architecture;
|
||||||
222
CPLD/v1.0/MZ80A/tzpuFusionX_Toplevel.vhd
Normal file
@@ -0,0 +1,222 @@
|
|||||||
|
---------------------------------------------------------------------------------------------------------
|
||||||
|
--
|
||||||
|
-- Name: tzpuFusionX_Toplevel.vhd
|
||||||
|
-- Version: MZ-80A
|
||||||
|
-- Created: Nov 2022
|
||||||
|
-- Author(s): Philip Smart
|
||||||
|
-- Description: tzpuFusionX CPLD Top Level module.
|
||||||
|
--
|
||||||
|
-- This module contains the basic pin definition of the CPLD<->logic needed in the
|
||||||
|
-- project which targets the MZ-80A host.
|
||||||
|
--
|
||||||
|
-- Credits:
|
||||||
|
-- Copyright: (c) 2018-22 Philip Smart <philip.smart@net2net.org>
|
||||||
|
--
|
||||||
|
-- History: Nov 2022 - Snapshot taken from the MZ-2000 version of the tzpuFusionX source.
|
||||||
|
--
|
||||||
|
---------------------------------------------------------------------------------------------------------
|
||||||
|
-- This source file is free software: you can redistribute it and-or modify
|
||||||
|
-- it under the terms of the GNU General Public License as published
|
||||||
|
-- by the Free Software Foundation, either version 3 of the License, or
|
||||||
|
-- (at your option) any later version.
|
||||||
|
--
|
||||||
|
-- This source file is distributed in the hope that it will be useful,
|
||||||
|
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
-- GNU General Public License for more details.
|
||||||
|
--
|
||||||
|
-- along with this program. If not, see <http:--www.gnu.org-licenses->.
|
||||||
|
---------------------------------------------------------------------------------------------------------
|
||||||
|
library IEEE;
|
||||||
|
use IEEE.std_logic_1164.all;
|
||||||
|
use IEEE.numeric_std.all;
|
||||||
|
use work.tzpuFusionX_pkg.all;
|
||||||
|
library altera;
|
||||||
|
use altera.altera_syn_attributes.all;
|
||||||
|
|
||||||
|
entity tzpuFusionX_MZ80A is
|
||||||
|
port (
|
||||||
|
-- Z80 Address Bus
|
||||||
|
Z80_ADDR : inout std_logic_vector(15 downto 0);
|
||||||
|
|
||||||
|
-- Z80 Data Bus
|
||||||
|
Z80_DATA : inout std_logic_vector(7 downto 0);
|
||||||
|
|
||||||
|
-- Z80 Control signals.
|
||||||
|
Z80_BUSRQn : in std_logic;
|
||||||
|
Z80_BUSAKn : out std_logic;
|
||||||
|
Z80_INTn : in std_logic;
|
||||||
|
Z80_IORQn : inout std_logic;
|
||||||
|
Z80_MREQn : inout std_logic;
|
||||||
|
Z80_NMIn : in std_logic;
|
||||||
|
Z80_RDn : inout std_logic;
|
||||||
|
Z80_WRn : inout std_logic;
|
||||||
|
Z80_RESETn : in std_logic; -- Host CPU Reset signal, also CPLD reset.
|
||||||
|
Z80_HALTn : out std_logic;
|
||||||
|
Z80_WAITn : in std_logic;
|
||||||
|
Z80_M1n : inout std_logic;
|
||||||
|
Z80_RFSHn : inout std_logic;
|
||||||
|
|
||||||
|
-- SOM SPI
|
||||||
|
VSOM_SPI_CSn : in std_logic; -- SPI Slave Select
|
||||||
|
VSOM_SPI_CLK : in std_logic; -- SPI Clock
|
||||||
|
VSOM_SPI_MOSI : in std_logic; -- SPI Master Output Slave Input
|
||||||
|
VSOM_SPI_MISO : out std_logic; -- SPI Master Input Slave Output
|
||||||
|
|
||||||
|
-- SOM Parallel Bus.
|
||||||
|
VSOM_DATA_OUT : out std_logic_vector(7 downto 0); -- Address/Data bus for CPLD control registers.
|
||||||
|
VSOM_HBYTE : in std_logic; -- Parallel Bus High (1)/Low (0) byte.
|
||||||
|
VSOM_READY : out std_logic; -- FSM Ready (1), Busy (0)
|
||||||
|
VSOM_LTSTATE : out std_logic; -- Last T-State in current cycle, 1 = active.
|
||||||
|
VSOM_BUSRQ : out std_logic; -- Host device requesting Z80 Bus.
|
||||||
|
VSOM_BUSACK : out std_logic; -- Host device granted Z80 Bus
|
||||||
|
VSOM_INT : out std_logic; -- Z80 INT signal
|
||||||
|
VSOM_NMI : out std_logic; -- Z80 NMI signal
|
||||||
|
VSOM_WAIT : out std_logic; -- Z80 WAIT signal
|
||||||
|
VSOM_RESET : out std_logic; -- Z80 RESET signal
|
||||||
|
VSOM_RSV : out std_logic_vector(1 downto 1); -- Reserved pins.
|
||||||
|
|
||||||
|
-- SOM Control Signals
|
||||||
|
PM_RESET : out std_logic; -- Reset SOM
|
||||||
|
|
||||||
|
-- VGA_Palette Control
|
||||||
|
VGA_R : in std_logic_vector(9 downto 7); -- Signals used for detecting blank or no video output.
|
||||||
|
VGA_G : in std_logic_vector(9 downto 7);
|
||||||
|
VGA_B : in std_logic_vector(9 downto 8);
|
||||||
|
|
||||||
|
-- VGA Control Signals
|
||||||
|
VGA_PXL_CLK : in std_logic; -- VGA Pixel clock for DAC conversion.
|
||||||
|
VGA_DISPEN : in std_logic; -- Displayed Enabled (SOM video output).
|
||||||
|
VGA_VSYNCn : in std_logic; -- SOM VSync.
|
||||||
|
VGA_HSYNCn : in std_logic; -- SOM HSync.
|
||||||
|
VGA_COLR : out std_logic; -- COLR colour carrier frequency.
|
||||||
|
VGA_CSYNCn : out std_logic; -- VGA Composite Sync.
|
||||||
|
VGA_BLANKn : out std_logic; -- VGA Blank detected.
|
||||||
|
|
||||||
|
-- CRT Control Signals
|
||||||
|
MONO_PXL_CLK : out std_logic; -- Mono CRT pixel clock for DAC conversion.
|
||||||
|
MONO_BLANKn : out std_logic; -- Mono CRT Blank (no active pixel) detection.
|
||||||
|
MONO_CSYNCn : out std_logic; -- Mono CRT composite sync.
|
||||||
|
MONO_RSV : out std_logic;
|
||||||
|
|
||||||
|
-- CRT Lower Chrominance Control
|
||||||
|
MONO_R : out std_logic_vector(2 downto 0); -- Signals to fine tune Red level of monochrome chrominance.
|
||||||
|
MONO_G : out std_logic_vector(2 downto 0); -- Signals to fine tune Green level of monochrome chrominance.
|
||||||
|
MONO_B : out std_logic_vector(2 downto 1); -- Signals to fine tune Blue level of monochrome chrominance.
|
||||||
|
|
||||||
|
-- MUX Control Signals
|
||||||
|
VIDEO_SRC : out std_logic; -- Select video source, Mainboard or SOM.
|
||||||
|
MONO_VIDEO_SRC : out std_logic; -- Select crt video source, Mainboard or SOM.
|
||||||
|
AUDIO_SRC_L : out std_logic; -- Select Audio Source Left Channel, Mainboard or SOM.
|
||||||
|
AUDIO_SRC_R : out std_logic; -- Select Audio Source Right Channel, Mainboard or SOM.
|
||||||
|
|
||||||
|
-- Mainboard Reset Signals
|
||||||
|
MB_RESETn : in std_logic; -- Motherboard Reset pressed.
|
||||||
|
MB_IPLn : in std_logic; -- Motherboard IPL pressed.
|
||||||
|
|
||||||
|
-- USB Power Control
|
||||||
|
VBUS_EN : out std_logic; -- USB Enable Power Output
|
||||||
|
|
||||||
|
-- Clocks.
|
||||||
|
Z80_CLK : in std_logic; -- Host CPU Clock
|
||||||
|
CLK_50M : in std_logic -- 50MHz oscillator.
|
||||||
|
);
|
||||||
|
END entity;
|
||||||
|
|
||||||
|
architecture rtl of tzpuFusionX_MZ80A is
|
||||||
|
|
||||||
|
begin
|
||||||
|
|
||||||
|
cpldl512Toplevel : entity work.cpld512
|
||||||
|
generic map (
|
||||||
|
SPI_CLK_POLARITY => '0'
|
||||||
|
)
|
||||||
|
port map
|
||||||
|
(
|
||||||
|
-- Z80 Address Bus
|
||||||
|
Z80_ADDR => Z80_ADDR,
|
||||||
|
|
||||||
|
-- Z80 Data Bus
|
||||||
|
Z80_DATA => Z80_DATA,
|
||||||
|
|
||||||
|
-- Z80 Control signals.
|
||||||
|
Z80_BUSRQn => Z80_BUSRQn,
|
||||||
|
Z80_BUSAKn => Z80_BUSAKn,
|
||||||
|
Z80_INTn => Z80_INTn,
|
||||||
|
Z80_IORQn => Z80_IORQn,
|
||||||
|
Z80_MREQn => Z80_MREQn,
|
||||||
|
Z80_NMIn => Z80_NMIn,
|
||||||
|
Z80_RDn => Z80_RDn,
|
||||||
|
Z80_WRn => Z80_WRn,
|
||||||
|
Z80_RESETn => Z80_RESETn,
|
||||||
|
Z80_HALTn => Z80_HALTn,
|
||||||
|
Z80_WAITn => Z80_WAITn,
|
||||||
|
Z80_M1n => Z80_M1n,
|
||||||
|
Z80_RFSHn => Z80_RFSHn,
|
||||||
|
|
||||||
|
-- SOM SPI
|
||||||
|
VSOM_SPI_CSn => VSOM_SPI_CSn, -- SPI Slave Select
|
||||||
|
VSOM_SPI_CLK => VSOM_SPI_CLK, -- SPI Clock
|
||||||
|
VSOM_SPI_MOSI => VSOM_SPI_MOSI, -- SPI Master Output Slave Input
|
||||||
|
VSOM_SPI_MISO => VSOM_SPI_MISO, -- SPI Master Input Slave Output
|
||||||
|
|
||||||
|
-- SOM Parallel Bus.
|
||||||
|
VSOM_DATA_OUT => VSOM_DATA_OUT, -- Address/Data bus for CPLD control registers.
|
||||||
|
VSOM_HBYTE => VSOM_HBYTE, -- Parallel Bus High (1)/Low (0) byte.
|
||||||
|
VSOM_READY => VSOM_READY, -- FSM Ready (1), Busy (0)
|
||||||
|
VSOM_LTSTATE => VSOM_LTSTATE, -- Last T-State in current cycle.
|
||||||
|
VSOM_BUSRQ => VSOM_BUSRQ, -- Host device requesting Z80 Bus.
|
||||||
|
VSOM_BUSACK => VSOM_BUSACK, -- Host device granted Z80 Bus
|
||||||
|
VSOM_INT => VSOM_INT, -- Z80 INT signal
|
||||||
|
VSOM_NMI => VSOM_NMI, -- Z80 NMI signal
|
||||||
|
VSOM_WAIT => VSOM_WAIT, -- Z80 WAIT signal
|
||||||
|
VSOM_RESET => VSOM_RESET, -- Z80 RESET signal
|
||||||
|
VSOM_RSV => VSOM_RSV, -- Reserved pins.
|
||||||
|
|
||||||
|
-- SOM Control Signals
|
||||||
|
PM_RESET => PM_RESET, -- Reset SOM
|
||||||
|
|
||||||
|
-- VGA_Palette Control
|
||||||
|
VGA_R => VGA_R, -- Signals used for detecting blank or no video output.
|
||||||
|
VGA_G => VGA_G,
|
||||||
|
VGA_B => VGA_B,
|
||||||
|
|
||||||
|
-- VGA Control Signals
|
||||||
|
VGA_PXL_CLK => VGA_PXL_CLK, -- VGA Pixel clock for DAC conversion.
|
||||||
|
VGA_DISPEN => VGA_DISPEN, -- Displayed Enabled (SOM video output).
|
||||||
|
VGA_VSYNCn => VGA_VSYNCn, -- SOM VSync.
|
||||||
|
VGA_HSYNCn => VGA_HSYNCn, -- SOM HSync.
|
||||||
|
VGA_COLR => VGA_COLR, -- COLR colour carrier frequency.
|
||||||
|
VGA_CSYNCn => VGA_CSYNCn, -- VGA Composite Sync.
|
||||||
|
VGA_BLANKn => VGA_BLANKn, -- VGA Blank detected.
|
||||||
|
|
||||||
|
-- CRT Control Signals
|
||||||
|
MONO_PXL_CLK => MONO_PXL_CLK, -- Mono CRT pixel clock for DAC conversion.
|
||||||
|
MONO_BLANKn => MONO_BLANKn, -- Mono CRT Blank (no active pixel) detection.
|
||||||
|
MONO_CSYNCn => MONO_CSYNCn, -- Mono CRT composite sync.
|
||||||
|
MONO_RSV => MONO_RSV,
|
||||||
|
|
||||||
|
-- CRT Lower Chrominance Control
|
||||||
|
MONO_R => MONO_R, -- Signals to fine tune Red level of monochrome chrominance.
|
||||||
|
MONO_G => MONO_G, -- Signals to fine tune Green level of monochrome chrominance.
|
||||||
|
MONO_B => MONO_B, -- Signals to fine tune Blue level of monochrome chrominance.
|
||||||
|
|
||||||
|
-- MUX Control Signals
|
||||||
|
VIDEO_SRC => VIDEO_SRC, -- Select video source, Mainboard or SOM.
|
||||||
|
MONO_VIDEO_SRC => MONO_VIDEO_SRC, -- Select crt video source, Mainboard or SOM.
|
||||||
|
AUDIO_SRC_L => AUDIO_SRC_L, -- Select Audio Source Left Channel, Mainboard or SOM.
|
||||||
|
AUDIO_SRC_R => AUDIO_SRC_R, -- Select Audio Source Right Channel, Mainboard or SOM.
|
||||||
|
|
||||||
|
-- Mainboard Reset Signals=> MONO_R,
|
||||||
|
MB_RESETn => MB_RESETn, -- Motherboard Reset pressed.
|
||||||
|
MB_IPLn => MB_IPLn, -- Motherboard IPL pressed.
|
||||||
|
|
||||||
|
-- USB Power Control
|
||||||
|
VBUS_EN => VBUS_EN, -- USB Enable Power Output
|
||||||
|
|
||||||
|
-- Clocks.
|
||||||
|
Z80_CLK => Z80_CLK, -- Host CPU Clock
|
||||||
|
CLK_50M => CLK_50M -- 50MHz oscillator.
|
||||||
|
);
|
||||||
|
|
||||||
|
end architecture;
|
||||||
221
CPLD/v1.0/MZ80A/tzpuFusionX_pkg.vhd
Normal file
@@ -0,0 +1,221 @@
|
|||||||
|
---------------------------------------------------------------------------------------------------------
|
||||||
|
--
|
||||||
|
-- Name: tzpuFusionX_pkg.vhd
|
||||||
|
-- Created: Nov 2022
|
||||||
|
-- Author(s): Philip Smart
|
||||||
|
-- Description: tzpuFusionX CPLD configuration file.
|
||||||
|
--
|
||||||
|
-- This module contains parameters for the CPLD in the tzpuFusionX project
|
||||||
|
-- which targets the MZ-80A host.
|
||||||
|
--
|
||||||
|
-- Credits:
|
||||||
|
-- Copyright: (c) 2018-22 Philip Smart <philip.smart@net2net.org>
|
||||||
|
--
|
||||||
|
-- History: Nov 2022 - Snapshot taken from the MZ-2000 version of the tzpuFusionX source.
|
||||||
|
--
|
||||||
|
---------------------------------------------------------------------------------------------------------
|
||||||
|
-- This source file is free software: you can redistribute it and-or modify
|
||||||
|
-- it under the terms of the GNU General Public License as published
|
||||||
|
-- by the Free Software Foundation, either version 3 of the License, or
|
||||||
|
-- (at your option) any later version.
|
||||||
|
--
|
||||||
|
-- This source file is distributed in the hope that it will be useful,
|
||||||
|
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
-- GNU General Public License for more details.
|
||||||
|
--
|
||||||
|
-- You should have received a copy of the GNU General Public License
|
||||||
|
-- along with this program. If not, see <http:--www.gnu.org-licenses->.
|
||||||
|
---------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
library ieee;
|
||||||
|
library pkgs;
|
||||||
|
use ieee.std_logic_1164.all;
|
||||||
|
use ieee.numeric_std.all;
|
||||||
|
use ieee.math_real.all;
|
||||||
|
|
||||||
|
package tzpuFusionX_pkg is
|
||||||
|
|
||||||
|
------------------------------------------------------------
|
||||||
|
-- Constants
|
||||||
|
------------------------------------------------------------
|
||||||
|
|
||||||
|
-- Potential logic state constants.
|
||||||
|
constant YES : std_logic := '1';
|
||||||
|
constant NO : std_logic := '0';
|
||||||
|
constant HI : std_logic := '1';
|
||||||
|
constant LO : std_logic := '0';
|
||||||
|
constant ONE : std_logic := '1';
|
||||||
|
constant ZERO : std_logic := '0';
|
||||||
|
constant HIZ : std_logic := 'Z';
|
||||||
|
|
||||||
|
-- CPLD Command instructions.
|
||||||
|
constant CPLD_CMD_RESET_HOST : integer := 1;
|
||||||
|
constant CPLD_CMD_HOLD_HOST_BUS : integer := 2;
|
||||||
|
constant CPLD_CMD_RELEASE_HOST_BUS: integer := 3;
|
||||||
|
|
||||||
|
-- Target hardware modes.
|
||||||
|
constant MODE_MZ80K : integer := 0;
|
||||||
|
constant MODE_MZ80C : integer := 1;
|
||||||
|
constant MODE_MZ1200 : integer := 2;
|
||||||
|
constant MODE_MZ80A : integer := 3;
|
||||||
|
constant MODE_MZ700 : integer := 4;
|
||||||
|
constant MODE_MZ800 : integer := 5;
|
||||||
|
constant MODE_MZ80B : integer := 6;
|
||||||
|
constant MODE_MZ2000 : integer := 7;
|
||||||
|
|
||||||
|
-- Memory management modes.
|
||||||
|
constant TZMM_ORIG : integer := 00; -- Original Sharp mode, no tranZPUter features are selected except the I/O control registers (default: 0x60-063).
|
||||||
|
constant TZMM_BOOT : integer := 01; -- Original mode but E800-EFFF is mapped to tranZPUter RAM so TZFS can be booted.
|
||||||
|
constant TZMM_TZFS : integer := 02; -- TZFS main memory configuration. all memory is in tranZPUter RAM, E800-FFFF is used by TZFS, SA1510 is at 0000-1000 and RAM is 1000-CFFF, 64K Block 0 selected.
|
||||||
|
constant TZMM_TZFS2 : integer := 03; -- TZFS main memory configuration. all memory is in tranZPUter RAM, E800-EFFF is used by TZFS, SA1510 is at 0000-1000 and RAM is 1000-CFFF, 64K Block 0 selected, F000-FFFF is in 64K Block 1.
|
||||||
|
constant TZMM_TZFS3 : integer := 04; -- TZFS main memory configuration. all memory is in tranZPUter RAM, E800-EFFF is used by TZFS, SA1510 is at 0000-1000 and RAM is 1000-CFFF, 64K Block 0 selected, F000-FFFF is in 64K Block 2.
|
||||||
|
constant TZMM_TZFS4 : integer := 05; -- TZFS main memory configuration. all memory is in tranZPUter RAM, E800-EFFF is used by TZFS, SA1510 is at 0000-1000 and RAM is 1000-CFFF, 64K Block 0 selected, F000-FFFF is in 64K Block 3.
|
||||||
|
constant TZMM_CPM : integer := 06; -- CPM main memory configuration, all memory on the tranZPUter board, 64K block 4 selected. Special case for F3C0:F3FF & F7C0:F7FF (floppy disk paging vectors) which resides on the mainboard.
|
||||||
|
constant TZMM_CPM2 : integer := 07; -- CPM main memory configuration, F000-FFFF are on the tranZPUter board in block 4, 0040-CFFF and E800-EFFF are in block 5, mainboard for D000-DFFF (video), E000-E800 (Memory control) selected.
|
||||||
|
-- Special case for 0000:003F (interrupt vectors) which resides in block 4, F3FE:F3FF & F7FE:F7FF (floppy disk paging vectors) which resides on the mainboard.
|
||||||
|
constant TZMM_COMPAT : integer := 08; -- Compatibility monitor mode, monitor ROM on mainboard, RAM on tranZPUter in Block 0 1000-CFFF.
|
||||||
|
constant TZMM_HOSTACCESS : integer := 09; -- Monitor ROM 0000-0FFF and Main DRAM 0x1000-0xD000, video and memory mapped I/O are on the host machine, User/Floppy ROM E800-FFFF are in tranZPUter memory.
|
||||||
|
constant TZMM_MZ700_0 : integer := 10; -- MZ700 Mode - 0000:0FFF is on the tranZPUter board in block 6, 1000:CFFF is on the tranZPUter board in block 0, D000:FFFF is on the mainboard.
|
||||||
|
constant TZMM_MZ700_1 : integer := 11; -- MZ700 Mode - 0000:0FFF is on the tranZPUter board in block 0, 1000:CFFF is on the tranZPUter board in block 0, D000:FFFF is on the tranZPUter in block 6.
|
||||||
|
constant TZMM_MZ700_2 : integer := 12; -- MZ700 Mode - 0000:0FFF is on the tranZPUter board in block 6, 1000:CFFF is on the tranZPUter board in block 0, D000:FFFF is on the tranZPUter in block 6.
|
||||||
|
constant TZMM_MZ700_3 : integer := 13; -- MZ700 Mode - 0000:0FFF is on the tranZPUter board in block 0, 1000:CFFF is on the tranZPUter board in block 0, D000:FFFF is inaccessible.
|
||||||
|
constant TZMM_MZ700_4 : integer := 14; -- MZ700 Mode - 0000:0FFF is on the tranZPUter board in block 6, 1000:CFFF is on the tranZPUter board in block 0, D000:FFFF is inaccessible.
|
||||||
|
constant TZMM_MZ800 : integer := 15; -- MZ800 Mode - Running on MZ800 hardware, configuration set according to MZ700/MZ800 mode.
|
||||||
|
constant TZMM_MZ2000 : integer := 16; -- MZ2000 Mode - Running on MZ2000 hardware, configuration set according to runtime configuration registers.
|
||||||
|
constant TZMM_FPGA : integer := 21; -- Open up access for the K64F to the FPGA resources such as memory. All other access to RAM or mainboard is blocked.
|
||||||
|
constant TZMM_TZPUM : integer := 22; -- Everything in on mainboard, no access to tranZPUter memory.
|
||||||
|
constant TZMM_TZPU : integer := 23; -- Everything is in tranZPUter domain, no access to underlying Sharp mainboard unless memory management mode is switched. tranZPUter RAM 64K block 0 is selected.
|
||||||
|
constant TZMM_TZPU0 : integer := 24; -- Everything is in tranZPUter domain, no access to underlying Sharp mainboard unless memory management mode is switched. tranZPUter RAM 64K block 0 is selected.
|
||||||
|
constant TZMM_TZPU1 : integer := 25; -- Everything is in tranZPUter domain, no access to underlying Sharp mainboard unless memory management mode is switched. tranZPUter RAM 64K block 1 is selected.
|
||||||
|
constant TZMM_TZPU2 : integer := 26; -- Everything is in tranZPUter domain, no access to underlying Sharp mainboard unless memory management mode is switched. tranZPUter RAM 64K block 2 is selected.
|
||||||
|
constant TZMM_TZPU3 : integer := 27; -- Everything is in tranZPUter domain, no access to underlying Sharp mainboard unless memory management mode is switched. tranZPUter RAM 64K block 3 is selected.
|
||||||
|
constant TZMM_TZPU4 : integer := 28; -- Everything is in tranZPUter domain, no access to underlying Sharp mainboard unless memory management mode is switched. tranZPUter RAM 64K block 4 is selected.
|
||||||
|
constant TZMM_TZPU5 : integer := 29; -- Everything is in tranZPUter domain, no access to underlying Sharp mainboard unless memory management mode is switched. tranZPUter RAM 64K block 5 is selected.
|
||||||
|
constant TZMM_TZPU6 : integer := 30; -- Everything is in tranZPUter domain, no access to underlying Sharp mainboard unless memory management mode is switched. tranZPUter RAM 64K block 6 is selected.
|
||||||
|
constant TZMM_TZPU7 : integer := 31; -- Everything is in tranZPUter domain, no access to underlying Sharp mainboard unless memory management mode is switched. tranZPUter RAM 64K block 7 is selected.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
------------------------------------------------------------
|
||||||
|
-- Configurable parameters.
|
||||||
|
------------------------------------------------------------
|
||||||
|
-- Target hardware.
|
||||||
|
constant CPLD_HOST_HW : integer := MODE_MZ700;
|
||||||
|
|
||||||
|
-- Target video hardware.
|
||||||
|
constant CPLD_HAS_FPGA_VIDEO : std_logic := '1';
|
||||||
|
|
||||||
|
-- Version of hdl.
|
||||||
|
constant CPLD_VERSION : integer := 2;
|
||||||
|
|
||||||
|
-- Clock source for the secondary clock. If a K64F is installed then enable it otherwise use the onboard oscillator.
|
||||||
|
--
|
||||||
|
constant USE_K64F_CTL_CLOCK : integer := 1;
|
||||||
|
|
||||||
|
------------------------------------------------------------
|
||||||
|
-- Function prototypes
|
||||||
|
------------------------------------------------------------
|
||||||
|
-- Find the maximum of two integers.
|
||||||
|
function IntMax(a : in integer; b : in integer) return integer;
|
||||||
|
|
||||||
|
-- Find the number of bits required to represent an integer.
|
||||||
|
function log2ceil(arg : positive) return natural;
|
||||||
|
|
||||||
|
-- Function to calculate the number of whole 'clock' cycles in a given time period, the period being in ns.
|
||||||
|
function clockTicks(period : in integer; clock : in integer) return integer;
|
||||||
|
|
||||||
|
-- Function to reverse the order of the bits in a standard logic vector.
|
||||||
|
-- ie. 1010 becomes 0101
|
||||||
|
function reverse_vector(slv:std_logic_vector) return std_logic_vector;
|
||||||
|
|
||||||
|
-- Function to convert an integer (0 or 1) into std_logic.
|
||||||
|
--
|
||||||
|
function to_std_logic(i : in integer) return std_logic;
|
||||||
|
|
||||||
|
-- Function to return the value of a bit as an integer for array indexing etc.
|
||||||
|
function bit_to_integer( s : std_logic ) return natural;
|
||||||
|
|
||||||
|
------------------------------------------------------------
|
||||||
|
-- Records
|
||||||
|
------------------------------------------------------------
|
||||||
|
|
||||||
|
------------------------------------------------------------
|
||||||
|
-- Components
|
||||||
|
------------------------------------------------------------
|
||||||
|
|
||||||
|
end tzpuFusionX_pkg;
|
||||||
|
|
||||||
|
------------------------------------------------------------
|
||||||
|
-- Function definitions.
|
||||||
|
------------------------------------------------------------
|
||||||
|
package body tzpuFusionX_pkg is
|
||||||
|
|
||||||
|
-- Find the maximum of two integers.
|
||||||
|
function IntMax(a : in integer; b : in integer) return integer is
|
||||||
|
begin
|
||||||
|
if a > b then
|
||||||
|
return a;
|
||||||
|
else
|
||||||
|
return b;
|
||||||
|
end if;
|
||||||
|
return a;
|
||||||
|
end function IntMax;
|
||||||
|
|
||||||
|
-- Find the number of bits required to represent an integer.
|
||||||
|
function log2ceil(arg : positive) return natural is
|
||||||
|
variable tmp : positive := 1;
|
||||||
|
variable log : natural := 0;
|
||||||
|
begin
|
||||||
|
if arg = 1 then
|
||||||
|
return 0;
|
||||||
|
end if;
|
||||||
|
|
||||||
|
while arg > tmp loop
|
||||||
|
tmp := tmp * 2;
|
||||||
|
log := log + 1;
|
||||||
|
end loop;
|
||||||
|
return log;
|
||||||
|
end function;
|
||||||
|
|
||||||
|
-- Function to calculate the number of whole 'clock' cycles in a given time period, the period being in ns.
|
||||||
|
function clockTicks(period : in integer; clock : in integer) return integer is
|
||||||
|
variable ticks : real;
|
||||||
|
variable fracTicks : real;
|
||||||
|
begin
|
||||||
|
ticks := (Real(period) * Real(clock)) / 1000000000.0;
|
||||||
|
fracTicks := ticks - CEIL(ticks);
|
||||||
|
if fracTicks > 0.0001 then
|
||||||
|
return Integer(CEIL(ticks + 1.0));
|
||||||
|
else
|
||||||
|
return Integer(CEIL(ticks));
|
||||||
|
end if;
|
||||||
|
end function;
|
||||||
|
|
||||||
|
function reverse_vector(slv:std_logic_vector) return std_logic_vector is
|
||||||
|
variable target : std_logic_vector(slv'high downto slv'low);
|
||||||
|
begin
|
||||||
|
for idx in slv'high downto slv'low loop
|
||||||
|
target(idx) := slv(slv'low + (slv'high-idx));
|
||||||
|
end loop;
|
||||||
|
return target;
|
||||||
|
end reverse_vector;
|
||||||
|
|
||||||
|
function to_std_logic(i : in integer) return std_logic is
|
||||||
|
begin
|
||||||
|
if i = 0 then
|
||||||
|
return '0';
|
||||||
|
end if;
|
||||||
|
return '1';
|
||||||
|
end function;
|
||||||
|
|
||||||
|
-- Function to return the value of a bit as an integer for array indexing etc.
|
||||||
|
function bit_to_integer( s : std_logic ) return natural is
|
||||||
|
begin
|
||||||
|
if s = '1' then
|
||||||
|
return 1;
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
end if;
|
||||||
|
end function;
|
||||||
|
end package body;
|
||||||
147
README.md
Normal file
@@ -0,0 +1,147 @@
|
|||||||
|
<img src='../images/tzpuFusionX_v1_0_layout.png' height='70%' width='70%' style="margin-left: auto; margin-right: auto; display: block;"/>
|
||||||
|
|
||||||
|
## <font style="color: yellow;" size="6">Foreword</font>
|
||||||
|
|
||||||
|
<div style="text-align: justify">
|
||||||
|
The tran<i>ZPU</i>ter<sup><i>FusionX</i></sup> is a spinoff concept from the tranZPUter series. It shares the same purpose, to replace the Z80 in a Sharp or similar system and provide it with features such as faster CPU, more memory, better graphics, quicker application loading etc.
|
||||||
|
<div style="padding-top: 0.8em;"></div>
|
||||||
|
|
||||||
|
It shares similarities with the tran<i>ZPU</i>ter<sup><i>Fusion</i></sup> but instead of realising it in hardware via an FPGA it realises
|
||||||
|
it in software as an application. This is made possible by a SOM (System On a Module), not much bigger than an FPGA device yet provides an abundance of features, ie. dual-core 1.2GHz Cortex-A7 ARM CPU, 128MB RAM, Wifi, HD Video, SD Card, USB port and runs the Linux operating system.
|
||||||
|
<div style="padding-top: 0.8em;"></div>
|
||||||
|
|
||||||
|
Using the same base design as the tran<i>ZPU</i>ter<sup><i>Fusion</i></sup> it incorporates a CPLD to interface the Z80 host to the SOM and provide cycle accurate Z80 timing. The SOM interfaces to the CPLD via a 16bit bus to query signal status and initiate Z80 transactions.
|
||||||
|
<div style="padding-top: 0.8em;"></div>
|
||||||
|
|
||||||
|
A Linux Kernel driver instantiates a Z80 emulation which realises a Z80 CPU in software and in turn can command and control the host system. The kernel driver along with a controlling application
|
||||||
|
can provide a wealth of features to the host through this mechanism. The SOM is also connected to an SD Drive and USB 2.0 port so there is no limit to features which can be proivded.
|
||||||
|
<div style="padding-top: 0.8em;"></div>
|
||||||
|
|
||||||
|
Like the tran<i>ZPU</i>ter<sup><i>Fusion</i></sup>, the tran<i>ZPU</i>ter<sup><i>FusionX</i></sup> can provide enhanced video and sound to the host. The SOM incorporates dual DAC audio and a 2D GPU with configurable resolutions.
|
||||||
|
<div style="padding-top: 0.8em;"></div>
|
||||||
|
|
||||||
|
To most retro users, the above wont have meaning or interest as it is primarily for software research and development. What the board can offer the end user is:
|
||||||
|
<ul style="line-height: 0.8em;"><font size="3">
|
||||||
|
<li>Original host specifications<br>- there might be slight differences in the Z80 functionality as it is implemented in software but the Z80 hardware timing is accurate.</li>
|
||||||
|
<li>Accelerator<br>- the Z80 can run at much higher speeds due to the abundance of memory and 1.2GHz dual-core processor, which would typically see performance equivalent to a 500MHz Z80.</li>
|
||||||
|
<li>Emulation<br>- it is possible to emulate all the Sharp MZ series machines in software, experiencing it through the host system keyboard, monitor and I/O.</li>
|
||||||
|
<li>Graphics<br>- all original Sharp MZ graphics modes, regardless of host, are available through GPU configuration and these can be selected and programmed via Basic etc.</li>
|
||||||
|
<li>Sound<br>- the host will have access to the dual DAC channels, which can emulate the SN76489 or basic bit/timer sound of the Sharp series.</li>
|
||||||
|
<li>Processors<br>- there are many software CPU implementations which can be ported to run on this platform, for example the BBC PiCoPro which uses the same Linux and ARM CPU platform. This in turn allows the potential for other machines, such as the BBC to run on this Sharp host.</li>
|
||||||
|
<li>Linux<br>- using the host keyboard, speaker, monitor etc, a full blooded version of Linux can be utilised at the host console.</li>
|
||||||
|
</font></ul>
|
||||||
|
|
||||||
|
|
||||||
|
The tran<i>ZPU</i>ter<sup><i>FusionX</i></sup> is under development and this source and document repository will be updated as the project progresses.
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
## <font style="color: yellow;" size="6">Daughter Boards</font>
|
||||||
|
|
||||||
|
<div style="text-align: justify">
|
||||||
|
The tranZPUter series was initially developed in the Sharp MZ-80A and was primarily a Z80 replacement. As the concept evolved and the tranZPUter SW-700 was developed for the MZ-700 it became more of an integral component of the machine, offering original and upgraded Video and Audio capabilites by intercepting and routing existing signals.
|
||||||
|
<div style="padding-top: 0.8em;"></div>
|
||||||
|
|
||||||
|
After significant developments on the tranZPUter SW-700 it became desirable to port it back to the MZ-80A and MZ-2000 but these machines had different CPU orientation and signal requirements, ie. driving internal and external monitor. This requirement led to the concept of daughter boards, where a specific board would be designed and developed for
|
||||||
|
the target host and would plug into the tranZPUter SW-700 card. Ideally I wanted to port the SW-700 to an MZ-800/MZ-1500 and X1 but the size of the card and orientation of the Z80 was a limitation.
|
||||||
|
<div style="padding-top: 0.8em;"></div>
|
||||||
|
|
||||||
|
During the design of the tran<i>ZPU</i>ter<sup><i>FusionX</i></sup> one of the main requirements was to make the board small and the Z80 orientation changeable and compatible with the tran<i>ZPU</i>ter<sup><i>Fusion</i></sup> so that it could fit many machines and be interchangeable. As the SW-700 also interfaced to the Video and Audio of the machines and each was quite different, it became apparent that the tran<i>ZPU</i>ter<sup>FusionX</sup> needed
|
||||||
|
to include a concept to allow different video/audio interfaces according to the targetted host. This concept was realised via daughter boards. Two connectors would link the tran<i>ZPU</i>ter<sup><i>FusionX</i></sup> to a daughter board which would be specifically designed for the intended host.
|
||||||
|
<div style="padding-top: 0.8em;"></div>
|
||||||
|
|
||||||
|
The daughter boards would be responsible for switching and mixing video/audio signals and to drive internal monitors and provide the correct input and output connectors for ease of installation.
|
||||||
|
<div style="padding-top: 0.8em;"></div>
|
||||||
|
|
||||||
|
Currently three daughter boards have been developed, for the MZ-700, MZ-80A and MZ-2000 and more will follow as the design progresses.
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
###### <font style="color: yellow;" size="5">MZ-700 Daughter Board</font>
|
||||||
|
|
||||||
|
<div style="text-align: justify">
|
||||||
|
The MZ-700 daughter board is designed to be inserted into mainboard modulator output and the modulator in turn connected to the daughter board.
|
||||||
|
<div style="padding-top: 0.8em;"></div>
|
||||||
|
|
||||||
|
The MZ-700 requires switching of the original mainboard video and tran<i>ZPU</i>ter<sup><i>FusionX</i></sup> FPGA video to the existing output connectors. This is accomplished with analogue MUX switches.
|
||||||
|
<div style="padding-top: 0.8em;"></div>
|
||||||
|
|
||||||
|
The sound of the MZ-700 is sent directly to a speaker and in order to inject tran<i>ZPU</i>ter<sup><i>FusionX</i></sup> sound, the mainboard speaker output is routed to the daughter board, level converted and switched. The FPGA offers stereo sound so this is selectively switched/mixed with the original sound and fed to a Class D amplifier which then drives
|
||||||
|
the internal speaker.
|
||||||
|
<div style="padding-top: 0.8em;"></div>
|
||||||
|
|
||||||
|
This setup allows for emulated machines, whilst running in the host on the FPGA such as the MZ-800/MZ-1500, to output their sound to the internal speaker. An audio output connector is provided for connection to stereo speakers if desired.
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div style='content: ""; clear: both; display: table;'>
|
||||||
|
<div style='width: 45%; padding: 5px; padding-left: 1em; float: left'>
|
||||||
|
<img src='../images/VideoInterface_MZ700_v1_0_3D_Top.png' height='100%' width='100%' style="margin-left: auto; margin-right: auto; display: block;"/>
|
||||||
|
</div>
|
||||||
|
<div style='width: 50%; padding: 5px; padding-left: 1em; float: left'>
|
||||||
|
<img src='../images/VideoInterface_MZ700_v1_0_3D_Bottom.png' height='100%' width='100%' style="margin-left: auto; margin-right: auto; display: block;"/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
###### <font style="color: yellow;" size="5">MZ-2000 Daughter Board</font>
|
||||||
|
|
||||||
|
<div style="text-align: justify">
|
||||||
|
The MZ-2000 daughter board is designed to be inserted simultaneously into the mainboard monitor and IPL connectors. The daughter board switches video source to the internal monitor, either the original mainboard video or FPGA video. The video source for the internal monitor is independent to the external moonitor source so different images can
|
||||||
|
be displayed on the internal monitor and external source at the same time.
|
||||||
|
<div style="padding-top: 0.8em;"></div>
|
||||||
|
|
||||||
|
The external video output can be fed from the original mainboard video or the FPGA video, the external video uses its own framebuffer so can be different to the internal monitor.
|
||||||
|
<div style="padding-top: 0.8em;"></div>
|
||||||
|
|
||||||
|
The audio is intercepted and switched/mixed prior to being sent to the internal audio amplifier.
|
||||||
|
<div style="padding-top: 0.8em;"></div>
|
||||||
|
|
||||||
|
The daughter board presents all the original connectors so it is easily installed.
|
||||||
|
<div style="padding-top: 0.8em;"></div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div style='content: ""; clear: both; display: table;'>
|
||||||
|
<div style='width: 50%; padding: 5px; padding-left: 1em; float: left'>
|
||||||
|
<img src='../images/VideoInterface_MZ2000_v1_0_3D_Top.png' height='100%' width='100%' style="margin-left: auto; margin-right: auto; display: block;"/>
|
||||||
|
</div>
|
||||||
|
<div style='width: 50%; padding: 5px; padding-left: 1em; float: left'>
|
||||||
|
<img src='../images/VideoInterface_MZ2000_v1_0_3D_Bottom.png' height='100%' width='100%' style="margin-left: auto; margin-right: auto; display: block;"/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
###### <font style="color: yellow;" size="5">MZ-80A Daughter Board</font>
|
||||||
|
|
||||||
|
<div style="text-align: justify">
|
||||||
|
The MZ-80A daughter board is designed to be inserted into the original Hirose monitor connector with the tape recorder plug being inserted through the gap in the daughter board. The system RESET is routed through the daughter board via 2pin connectors.
|
||||||
|
<div style="padding-top: 0.8em;"></div>
|
||||||
|
|
||||||
|
The daughter board switches video source to the internal monitor, either the original mainboard video or FPGA video. The video source for the internal monitor is independent to the external moonitor source so different images can
|
||||||
|
be displayed on the internal monitor and external source at the same time.
|
||||||
|
<div style="padding-top: 0.8em;"></div>
|
||||||
|
|
||||||
|
The external video output can be fed from the original mainboard video or the FPGA video, the external video uses its own framebuffer so can be different to the internal monitor.
|
||||||
|
<div style="padding-top: 0.8em;"></div>
|
||||||
|
|
||||||
|
The audio is intercepted and switched/mixed prior to being sent to the internal audio amplifier.
|
||||||
|
<div style="padding-top: 0.8em;"></div>
|
||||||
|
|
||||||
|
The daughter board presents all the original connectors so it is easily installed.
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div style='content: ""; clear: both; display: table;'>
|
||||||
|
<div style='width: 47%; padding: 5px; padding-left: 1em; float: left'>
|
||||||
|
<img src='../images/VideoInterface_MZ80A_V1_0_3D_Top.png' height='100%' width='100%' style="margin-left: auto; margin-right: auto; display: block;"/>
|
||||||
|
</div>
|
||||||
|
<div style='width: 50%; padding: 5px; padding-left: 1em; float: left'>
|
||||||
|
<img src='../images/VideoInterface_MZ80A_V1_0_3D_Bottom.png' height='100%' width='100%' style="margin-left: auto; margin-right: auto; display: block;"/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div style="text-align: justify">
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------------------------------
|
||||||
BIN
datasheets/ADV7123_Datasheet.pdf
Normal file
BIN
datasheets/CH340E_Datasheet.pdf
Normal file
BIN
datasheets/EP4CE75F484I7_Datasheet.pdf
Normal file
BIN
datasheets/EPCS7128_Datasheet.pdf
Normal file
28543
datasheets/EPM7512AEQFP144_Datasheet.pdf
Normal file
BIN
datasheets/ESD_Diode_vcut0714bhd1.pdf
Normal file
BIN
datasheets/HXJ8002_Datasheet.pdf
Normal file
BIN
datasheets/IS66WVO32M8DBLL_Datasheet.pdf
Normal file
BIN
datasheets/JST_GH_Connectors.pdf
Normal file
21590
datasheets/MK64FX512_Datasheet.pdf
Normal file
BIN
datasheets/REF3040_Datasheet.pdf
Normal file
BIN
datasheets/SY6280_Datasheet.pdf
Normal file
BIN
datasheets/TLC5602C_Datasheet.pdf
Normal file
BIN
datasheets/TLV62569_Datasheet.pdf
Normal file
BIN
datasheets/TMUX1134_Datasheet.pdf
Normal file
BIN
docs/Nascom_Basic_Manual.pdf
Normal file
674
license.txt
Normal file
@@ -0,0 +1,674 @@
|
|||||||
|
GNU GENERAL PUBLIC LICENSE
|
||||||
|
Version 3, 29 June 2007
|
||||||
|
|
||||||
|
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
|
||||||
|
Everyone is permitted to copy and distribute verbatim copies
|
||||||
|
of this license document, but changing it is not allowed.
|
||||||
|
|
||||||
|
Preamble
|
||||||
|
|
||||||
|
The GNU General Public License is a free, copyleft license for
|
||||||
|
software and other kinds of works.
|
||||||
|
|
||||||
|
The licenses for most software and other practical works are designed
|
||||||
|
to take away your freedom to share and change the works. By contrast,
|
||||||
|
the GNU General Public License is intended to guarantee your freedom to
|
||||||
|
share and change all versions of a program--to make sure it remains free
|
||||||
|
software for all its users. We, the Free Software Foundation, use the
|
||||||
|
GNU General Public License for most of our software; it applies also to
|
||||||
|
any other work released this way by its authors. You can apply it to
|
||||||
|
your programs, too.
|
||||||
|
|
||||||
|
When we speak of free software, we are referring to freedom, not
|
||||||
|
price. Our General Public Licenses are designed to make sure that you
|
||||||
|
have the freedom to distribute copies of free software (and charge for
|
||||||
|
them if you wish), that you receive source code or can get it if you
|
||||||
|
want it, that you can change the software or use pieces of it in new
|
||||||
|
free programs, and that you know you can do these things.
|
||||||
|
|
||||||
|
To protect your rights, we need to prevent others from denying you
|
||||||
|
these rights or asking you to surrender the rights. Therefore, you have
|
||||||
|
certain responsibilities if you distribute copies of the software, or if
|
||||||
|
you modify it: responsibilities to respect the freedom of others.
|
||||||
|
|
||||||
|
For example, if you distribute copies of such a program, whether
|
||||||
|
gratis or for a fee, you must pass on to the recipients the same
|
||||||
|
freedoms that you received. You must make sure that they, too, receive
|
||||||
|
or can get the source code. And you must show them these terms so they
|
||||||
|
know their rights.
|
||||||
|
|
||||||
|
Developers that use the GNU GPL protect your rights with two steps:
|
||||||
|
(1) assert copyright on the software, and (2) offer you this License
|
||||||
|
giving you legal permission to copy, distribute and/or modify it.
|
||||||
|
|
||||||
|
For the developers' and authors' protection, the GPL clearly explains
|
||||||
|
that there is no warranty for this free software. For both users' and
|
||||||
|
authors' sake, the GPL requires that modified versions be marked as
|
||||||
|
changed, so that their problems will not be attributed erroneously to
|
||||||
|
authors of previous versions.
|
||||||
|
|
||||||
|
Some devices are designed to deny users access to install or run
|
||||||
|
modified versions of the software inside them, although the manufacturer
|
||||||
|
can do so. This is fundamentally incompatible with the aim of
|
||||||
|
protecting users' freedom to change the software. The systematic
|
||||||
|
pattern of such abuse occurs in the area of products for individuals to
|
||||||
|
use, which is precisely where it is most unacceptable. Therefore, we
|
||||||
|
have designed this version of the GPL to prohibit the practice for those
|
||||||
|
products. If such problems arise substantially in other domains, we
|
||||||
|
stand ready to extend this provision to those domains in future versions
|
||||||
|
of the GPL, as needed to protect the freedom of users.
|
||||||
|
|
||||||
|
Finally, every program is threatened constantly by software patents.
|
||||||
|
States should not allow patents to restrict development and use of
|
||||||
|
software on general-purpose computers, but in those that do, we wish to
|
||||||
|
avoid the special danger that patents applied to a free program could
|
||||||
|
make it effectively proprietary. To prevent this, the GPL assures that
|
||||||
|
patents cannot be used to render the program non-free.
|
||||||
|
|
||||||
|
The precise terms and conditions for copying, distribution and
|
||||||
|
modification follow.
|
||||||
|
|
||||||
|
TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
0. Definitions.
|
||||||
|
|
||||||
|
"This License" refers to version 3 of the GNU General Public License.
|
||||||
|
|
||||||
|
"Copyright" also means copyright-like laws that apply to other kinds of
|
||||||
|
works, such as semiconductor masks.
|
||||||
|
|
||||||
|
"The Program" refers to any copyrightable work licensed under this
|
||||||
|
License. Each licensee is addressed as "you". "Licensees" and
|
||||||
|
"recipients" may be individuals or organizations.
|
||||||
|
|
||||||
|
To "modify" a work means to copy from or adapt all or part of the work
|
||||||
|
in a fashion requiring copyright permission, other than the making of an
|
||||||
|
exact copy. The resulting work is called a "modified version" of the
|
||||||
|
earlier work or a work "based on" the earlier work.
|
||||||
|
|
||||||
|
A "covered work" means either the unmodified Program or a work based
|
||||||
|
on the Program.
|
||||||
|
|
||||||
|
To "propagate" a work means to do anything with it that, without
|
||||||
|
permission, would make you directly or secondarily liable for
|
||||||
|
infringement under applicable copyright law, except executing it on a
|
||||||
|
computer or modifying a private copy. Propagation includes copying,
|
||||||
|
distribution (with or without modification), making available to the
|
||||||
|
public, and in some countries other activities as well.
|
||||||
|
|
||||||
|
To "convey" a work means any kind of propagation that enables other
|
||||||
|
parties to make or receive copies. Mere interaction with a user through
|
||||||
|
a computer network, with no transfer of a copy, is not conveying.
|
||||||
|
|
||||||
|
An interactive user interface displays "Appropriate Legal Notices"
|
||||||
|
to the extent that it includes a convenient and prominently visible
|
||||||
|
feature that (1) displays an appropriate copyright notice, and (2)
|
||||||
|
tells the user that there is no warranty for the work (except to the
|
||||||
|
extent that warranties are provided), that licensees may convey the
|
||||||
|
work under this License, and how to view a copy of this License. If
|
||||||
|
the interface presents a list of user commands or options, such as a
|
||||||
|
menu, a prominent item in the list meets this criterion.
|
||||||
|
|
||||||
|
1. Source Code.
|
||||||
|
|
||||||
|
The "source code" for a work means the preferred form of the work
|
||||||
|
for making modifications to it. "Object code" means any non-source
|
||||||
|
form of a work.
|
||||||
|
|
||||||
|
A "Standard Interface" means an interface that either is an official
|
||||||
|
standard defined by a recognized standards body, or, in the case of
|
||||||
|
interfaces specified for a particular programming language, one that
|
||||||
|
is widely used among developers working in that language.
|
||||||
|
|
||||||
|
The "System Libraries" of an executable work include anything, other
|
||||||
|
than the work as a whole, that (a) is included in the normal form of
|
||||||
|
packaging a Major Component, but which is not part of that Major
|
||||||
|
Component, and (b) serves only to enable use of the work with that
|
||||||
|
Major Component, or to implement a Standard Interface for which an
|
||||||
|
implementation is available to the public in source code form. A
|
||||||
|
"Major Component", in this context, means a major essential component
|
||||||
|
(kernel, window system, and so on) of the specific operating system
|
||||||
|
(if any) on which the executable work runs, or a compiler used to
|
||||||
|
produce the work, or an object code interpreter used to run it.
|
||||||
|
|
||||||
|
The "Corresponding Source" for a work in object code form means all
|
||||||
|
the source code needed to generate, install, and (for an executable
|
||||||
|
work) run the object code and to modify the work, including scripts to
|
||||||
|
control those activities. However, it does not include the work's
|
||||||
|
System Libraries, or general-purpose tools or generally available free
|
||||||
|
programs which are used unmodified in performing those activities but
|
||||||
|
which are not part of the work. For example, Corresponding Source
|
||||||
|
includes interface definition files associated with source files for
|
||||||
|
the work, and the source code for shared libraries and dynamically
|
||||||
|
linked subprograms that the work is specifically designed to require,
|
||||||
|
such as by intimate data communication or control flow between those
|
||||||
|
subprograms and other parts of the work.
|
||||||
|
|
||||||
|
The Corresponding Source need not include anything that users
|
||||||
|
can regenerate automatically from other parts of the Corresponding
|
||||||
|
Source.
|
||||||
|
|
||||||
|
The Corresponding Source for a work in source code form is that
|
||||||
|
same work.
|
||||||
|
|
||||||
|
2. Basic Permissions.
|
||||||
|
|
||||||
|
All rights granted under this License are granted for the term of
|
||||||
|
copyright on the Program, and are irrevocable provided the stated
|
||||||
|
conditions are met. This License explicitly affirms your unlimited
|
||||||
|
permission to run the unmodified Program. The output from running a
|
||||||
|
covered work is covered by this License only if the output, given its
|
||||||
|
content, constitutes a covered work. This License acknowledges your
|
||||||
|
rights of fair use or other equivalent, as provided by copyright law.
|
||||||
|
|
||||||
|
You may make, run and propagate covered works that you do not
|
||||||
|
convey, without conditions so long as your license otherwise remains
|
||||||
|
in force. You may convey covered works to others for the sole purpose
|
||||||
|
of having them make modifications exclusively for you, or provide you
|
||||||
|
with facilities for running those works, provided that you comply with
|
||||||
|
the terms of this License in conveying all material for which you do
|
||||||
|
not control copyright. Those thus making or running the covered works
|
||||||
|
for you must do so exclusively on your behalf, under your direction
|
||||||
|
and control, on terms that prohibit them from making any copies of
|
||||||
|
your copyrighted material outside their relationship with you.
|
||||||
|
|
||||||
|
Conveying under any other circumstances is permitted solely under
|
||||||
|
the conditions stated below. Sublicensing is not allowed; section 10
|
||||||
|
makes it unnecessary.
|
||||||
|
|
||||||
|
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
|
||||||
|
|
||||||
|
No covered work shall be deemed part of an effective technological
|
||||||
|
measure under any applicable law fulfilling obligations under article
|
||||||
|
11 of the WIPO copyright treaty adopted on 20 December 1996, or
|
||||||
|
similar laws prohibiting or restricting circumvention of such
|
||||||
|
measures.
|
||||||
|
|
||||||
|
When you convey a covered work, you waive any legal power to forbid
|
||||||
|
circumvention of technological measures to the extent such circumvention
|
||||||
|
is effected by exercising rights under this License with respect to
|
||||||
|
the covered work, and you disclaim any intention to limit operation or
|
||||||
|
modification of the work as a means of enforcing, against the work's
|
||||||
|
users, your or third parties' legal rights to forbid circumvention of
|
||||||
|
technological measures.
|
||||||
|
|
||||||
|
4. Conveying Verbatim Copies.
|
||||||
|
|
||||||
|
You may convey verbatim copies of the Program's source code as you
|
||||||
|
receive it, in any medium, provided that you conspicuously and
|
||||||
|
appropriately publish on each copy an appropriate copyright notice;
|
||||||
|
keep intact all notices stating that this License and any
|
||||||
|
non-permissive terms added in accord with section 7 apply to the code;
|
||||||
|
keep intact all notices of the absence of any warranty; and give all
|
||||||
|
recipients a copy of this License along with the Program.
|
||||||
|
|
||||||
|
You may charge any price or no price for each copy that you convey,
|
||||||
|
and you may offer support or warranty protection for a fee.
|
||||||
|
|
||||||
|
5. Conveying Modified Source Versions.
|
||||||
|
|
||||||
|
You may convey a work based on the Program, or the modifications to
|
||||||
|
produce it from the Program, in the form of source code under the
|
||||||
|
terms of section 4, provided that you also meet all of these conditions:
|
||||||
|
|
||||||
|
a) The work must carry prominent notices stating that you modified
|
||||||
|
it, and giving a relevant date.
|
||||||
|
|
||||||
|
b) The work must carry prominent notices stating that it is
|
||||||
|
released under this License and any conditions added under section
|
||||||
|
7. This requirement modifies the requirement in section 4 to
|
||||||
|
"keep intact all notices".
|
||||||
|
|
||||||
|
c) You must license the entire work, as a whole, under this
|
||||||
|
License to anyone who comes into possession of a copy. This
|
||||||
|
License will therefore apply, along with any applicable section 7
|
||||||
|
additional terms, to the whole of the work, and all its parts,
|
||||||
|
regardless of how they are packaged. This License gives no
|
||||||
|
permission to license the work in any other way, but it does not
|
||||||
|
invalidate such permission if you have separately received it.
|
||||||
|
|
||||||
|
d) If the work has interactive user interfaces, each must display
|
||||||
|
Appropriate Legal Notices; however, if the Program has interactive
|
||||||
|
interfaces that do not display Appropriate Legal Notices, your
|
||||||
|
work need not make them do so.
|
||||||
|
|
||||||
|
A compilation of a covered work with other separate and independent
|
||||||
|
works, which are not by their nature extensions of the covered work,
|
||||||
|
and which are not combined with it such as to form a larger program,
|
||||||
|
in or on a volume of a storage or distribution medium, is called an
|
||||||
|
"aggregate" if the compilation and its resulting copyright are not
|
||||||
|
used to limit the access or legal rights of the compilation's users
|
||||||
|
beyond what the individual works permit. Inclusion of a covered work
|
||||||
|
in an aggregate does not cause this License to apply to the other
|
||||||
|
parts of the aggregate.
|
||||||
|
|
||||||
|
6. Conveying Non-Source Forms.
|
||||||
|
|
||||||
|
You may convey a covered work in object code form under the terms
|
||||||
|
of sections 4 and 5, provided that you also convey the
|
||||||
|
machine-readable Corresponding Source under the terms of this License,
|
||||||
|
in one of these ways:
|
||||||
|
|
||||||
|
a) Convey the object code in, or embodied in, a physical product
|
||||||
|
(including a physical distribution medium), accompanied by the
|
||||||
|
Corresponding Source fixed on a durable physical medium
|
||||||
|
customarily used for software interchange.
|
||||||
|
|
||||||
|
b) Convey the object code in, or embodied in, a physical product
|
||||||
|
(including a physical distribution medium), accompanied by a
|
||||||
|
written offer, valid for at least three years and valid for as
|
||||||
|
long as you offer spare parts or customer support for that product
|
||||||
|
model, to give anyone who possesses the object code either (1) a
|
||||||
|
copy of the Corresponding Source for all the software in the
|
||||||
|
product that is covered by this License, on a durable physical
|
||||||
|
medium customarily used for software interchange, for a price no
|
||||||
|
more than your reasonable cost of physically performing this
|
||||||
|
conveying of source, or (2) access to copy the
|
||||||
|
Corresponding Source from a network server at no charge.
|
||||||
|
|
||||||
|
c) Convey individual copies of the object code with a copy of the
|
||||||
|
written offer to provide the Corresponding Source. This
|
||||||
|
alternative is allowed only occasionally and noncommercially, and
|
||||||
|
only if you received the object code with such an offer, in accord
|
||||||
|
with subsection 6b.
|
||||||
|
|
||||||
|
d) Convey the object code by offering access from a designated
|
||||||
|
place (gratis or for a charge), and offer equivalent access to the
|
||||||
|
Corresponding Source in the same way through the same place at no
|
||||||
|
further charge. You need not require recipients to copy the
|
||||||
|
Corresponding Source along with the object code. If the place to
|
||||||
|
copy the object code is a network server, the Corresponding Source
|
||||||
|
may be on a different server (operated by you or a third party)
|
||||||
|
that supports equivalent copying facilities, provided you maintain
|
||||||
|
clear directions next to the object code saying where to find the
|
||||||
|
Corresponding Source. Regardless of what server hosts the
|
||||||
|
Corresponding Source, you remain obligated to ensure that it is
|
||||||
|
available for as long as needed to satisfy these requirements.
|
||||||
|
|
||||||
|
e) Convey the object code using peer-to-peer transmission, provided
|
||||||
|
you inform other peers where the object code and Corresponding
|
||||||
|
Source of the work are being offered to the general public at no
|
||||||
|
charge under subsection 6d.
|
||||||
|
|
||||||
|
A separable portion of the object code, whose source code is excluded
|
||||||
|
from the Corresponding Source as a System Library, need not be
|
||||||
|
included in conveying the object code work.
|
||||||
|
|
||||||
|
A "User Product" is either (1) a "consumer product", which means any
|
||||||
|
tangible personal property which is normally used for personal, family,
|
||||||
|
or household purposes, or (2) anything designed or sold for incorporation
|
||||||
|
into a dwelling. In determining whether a product is a consumer product,
|
||||||
|
doubtful cases shall be resolved in favor of coverage. For a particular
|
||||||
|
product received by a particular user, "normally used" refers to a
|
||||||
|
typical or common use of that class of product, regardless of the status
|
||||||
|
of the particular user or of the way in which the particular user
|
||||||
|
actually uses, or expects or is expected to use, the product. A product
|
||||||
|
is a consumer product regardless of whether the product has substantial
|
||||||
|
commercial, industrial or non-consumer uses, unless such uses represent
|
||||||
|
the only significant mode of use of the product.
|
||||||
|
|
||||||
|
"Installation Information" for a User Product means any methods,
|
||||||
|
procedures, authorization keys, or other information required to install
|
||||||
|
and execute modified versions of a covered work in that User Product from
|
||||||
|
a modified version of its Corresponding Source. The information must
|
||||||
|
suffice to ensure that the continued functioning of the modified object
|
||||||
|
code is in no case prevented or interfered with solely because
|
||||||
|
modification has been made.
|
||||||
|
|
||||||
|
If you convey an object code work under this section in, or with, or
|
||||||
|
specifically for use in, a User Product, and the conveying occurs as
|
||||||
|
part of a transaction in which the right of possession and use of the
|
||||||
|
User Product is transferred to the recipient in perpetuity or for a
|
||||||
|
fixed term (regardless of how the transaction is characterized), the
|
||||||
|
Corresponding Source conveyed under this section must be accompanied
|
||||||
|
by the Installation Information. But this requirement does not apply
|
||||||
|
if neither you nor any third party retains the ability to install
|
||||||
|
modified object code on the User Product (for example, the work has
|
||||||
|
been installed in ROM).
|
||||||
|
|
||||||
|
The requirement to provide Installation Information does not include a
|
||||||
|
requirement to continue to provide support service, warranty, or updates
|
||||||
|
for a work that has been modified or installed by the recipient, or for
|
||||||
|
the User Product in which it has been modified or installed. Access to a
|
||||||
|
network may be denied when the modification itself materially and
|
||||||
|
adversely affects the operation of the network or violates the rules and
|
||||||
|
protocols for communication across the network.
|
||||||
|
|
||||||
|
Corresponding Source conveyed, and Installation Information provided,
|
||||||
|
in accord with this section must be in a format that is publicly
|
||||||
|
documented (and with an implementation available to the public in
|
||||||
|
source code form), and must require no special password or key for
|
||||||
|
unpacking, reading or copying.
|
||||||
|
|
||||||
|
7. Additional Terms.
|
||||||
|
|
||||||
|
"Additional permissions" are terms that supplement the terms of this
|
||||||
|
License by making exceptions from one or more of its conditions.
|
||||||
|
Additional permissions that are applicable to the entire Program shall
|
||||||
|
be treated as though they were included in this License, to the extent
|
||||||
|
that they are valid under applicable law. If additional permissions
|
||||||
|
apply only to part of the Program, that part may be used separately
|
||||||
|
under those permissions, but the entire Program remains governed by
|
||||||
|
this License without regard to the additional permissions.
|
||||||
|
|
||||||
|
When you convey a copy of a covered work, you may at your option
|
||||||
|
remove any additional permissions from that copy, or from any part of
|
||||||
|
it. (Additional permissions may be written to require their own
|
||||||
|
removal in certain cases when you modify the work.) You may place
|
||||||
|
additional permissions on material, added by you to a covered work,
|
||||||
|
for which you have or can give appropriate copyright permission.
|
||||||
|
|
||||||
|
Notwithstanding any other provision of this License, for material you
|
||||||
|
add to a covered work, you may (if authorized by the copyright holders of
|
||||||
|
that material) supplement the terms of this License with terms:
|
||||||
|
|
||||||
|
a) Disclaiming warranty or limiting liability differently from the
|
||||||
|
terms of sections 15 and 16 of this License; or
|
||||||
|
|
||||||
|
b) Requiring preservation of specified reasonable legal notices or
|
||||||
|
author attributions in that material or in the Appropriate Legal
|
||||||
|
Notices displayed by works containing it; or
|
||||||
|
|
||||||
|
c) Prohibiting misrepresentation of the origin of that material, or
|
||||||
|
requiring that modified versions of such material be marked in
|
||||||
|
reasonable ways as different from the original version; or
|
||||||
|
|
||||||
|
d) Limiting the use for publicity purposes of names of licensors or
|
||||||
|
authors of the material; or
|
||||||
|
|
||||||
|
e) Declining to grant rights under trademark law for use of some
|
||||||
|
trade names, trademarks, or service marks; or
|
||||||
|
|
||||||
|
f) Requiring indemnification of licensors and authors of that
|
||||||
|
material by anyone who conveys the material (or modified versions of
|
||||||
|
it) with contractual assumptions of liability to the recipient, for
|
||||||
|
any liability that these contractual assumptions directly impose on
|
||||||
|
those licensors and authors.
|
||||||
|
|
||||||
|
All other non-permissive additional terms are considered "further
|
||||||
|
restrictions" within the meaning of section 10. If the Program as you
|
||||||
|
received it, or any part of it, contains a notice stating that it is
|
||||||
|
governed by this License along with a term that is a further
|
||||||
|
restriction, you may remove that term. If a license document contains
|
||||||
|
a further restriction but permits relicensing or conveying under this
|
||||||
|
License, you may add to a covered work material governed by the terms
|
||||||
|
of that license document, provided that the further restriction does
|
||||||
|
not survive such relicensing or conveying.
|
||||||
|
|
||||||
|
If you add terms to a covered work in accord with this section, you
|
||||||
|
must place, in the relevant source files, a statement of the
|
||||||
|
additional terms that apply to those files, or a notice indicating
|
||||||
|
where to find the applicable terms.
|
||||||
|
|
||||||
|
Additional terms, permissive or non-permissive, may be stated in the
|
||||||
|
form of a separately written license, or stated as exceptions;
|
||||||
|
the above requirements apply either way.
|
||||||
|
|
||||||
|
8. Termination.
|
||||||
|
|
||||||
|
You may not propagate or modify a covered work except as expressly
|
||||||
|
provided under this License. Any attempt otherwise to propagate or
|
||||||
|
modify it is void, and will automatically terminate your rights under
|
||||||
|
this License (including any patent licenses granted under the third
|
||||||
|
paragraph of section 11).
|
||||||
|
|
||||||
|
However, if you cease all violation of this License, then your
|
||||||
|
license from a particular copyright holder is reinstated (a)
|
||||||
|
provisionally, unless and until the copyright holder explicitly and
|
||||||
|
finally terminates your license, and (b) permanently, if the copyright
|
||||||
|
holder fails to notify you of the violation by some reasonable means
|
||||||
|
prior to 60 days after the cessation.
|
||||||
|
|
||||||
|
Moreover, your license from a particular copyright holder is
|
||||||
|
reinstated permanently if the copyright holder notifies you of the
|
||||||
|
violation by some reasonable means, this is the first time you have
|
||||||
|
received notice of violation of this License (for any work) from that
|
||||||
|
copyright holder, and you cure the violation prior to 30 days after
|
||||||
|
your receipt of the notice.
|
||||||
|
|
||||||
|
Termination of your rights under this section does not terminate the
|
||||||
|
licenses of parties who have received copies or rights from you under
|
||||||
|
this License. If your rights have been terminated and not permanently
|
||||||
|
reinstated, you do not qualify to receive new licenses for the same
|
||||||
|
material under section 10.
|
||||||
|
|
||||||
|
9. Acceptance Not Required for Having Copies.
|
||||||
|
|
||||||
|
You are not required to accept this License in order to receive or
|
||||||
|
run a copy of the Program. Ancillary propagation of a covered work
|
||||||
|
occurring solely as a consequence of using peer-to-peer transmission
|
||||||
|
to receive a copy likewise does not require acceptance. However,
|
||||||
|
nothing other than this License grants you permission to propagate or
|
||||||
|
modify any covered work. These actions infringe copyright if you do
|
||||||
|
not accept this License. Therefore, by modifying or propagating a
|
||||||
|
covered work, you indicate your acceptance of this License to do so.
|
||||||
|
|
||||||
|
10. Automatic Licensing of Downstream Recipients.
|
||||||
|
|
||||||
|
Each time you convey a covered work, the recipient automatically
|
||||||
|
receives a license from the original licensors, to run, modify and
|
||||||
|
propagate that work, subject to this License. You are not responsible
|
||||||
|
for enforcing compliance by third parties with this License.
|
||||||
|
|
||||||
|
An "entity transaction" is a transaction transferring control of an
|
||||||
|
organization, or substantially all assets of one, or subdividing an
|
||||||
|
organization, or merging organizations. If propagation of a covered
|
||||||
|
work results from an entity transaction, each party to that
|
||||||
|
transaction who receives a copy of the work also receives whatever
|
||||||
|
licenses to the work the party's predecessor in interest had or could
|
||||||
|
give under the previous paragraph, plus a right to possession of the
|
||||||
|
Corresponding Source of the work from the predecessor in interest, if
|
||||||
|
the predecessor has it or can get it with reasonable efforts.
|
||||||
|
|
||||||
|
You may not impose any further restrictions on the exercise of the
|
||||||
|
rights granted or affirmed under this License. For example, you may
|
||||||
|
not impose a license fee, royalty, or other charge for exercise of
|
||||||
|
rights granted under this License, and you may not initiate litigation
|
||||||
|
(including a cross-claim or counterclaim in a lawsuit) alleging that
|
||||||
|
any patent claim is infringed by making, using, selling, offering for
|
||||||
|
sale, or importing the Program or any portion of it.
|
||||||
|
|
||||||
|
11. Patents.
|
||||||
|
|
||||||
|
A "contributor" is a copyright holder who authorizes use under this
|
||||||
|
License of the Program or a work on which the Program is based. The
|
||||||
|
work thus licensed is called the contributor's "contributor version".
|
||||||
|
|
||||||
|
A contributor's "essential patent claims" are all patent claims
|
||||||
|
owned or controlled by the contributor, whether already acquired or
|
||||||
|
hereafter acquired, that would be infringed by some manner, permitted
|
||||||
|
by this License, of making, using, or selling its contributor version,
|
||||||
|
but do not include claims that would be infringed only as a
|
||||||
|
consequence of further modification of the contributor version. For
|
||||||
|
purposes of this definition, "control" includes the right to grant
|
||||||
|
patent sublicenses in a manner consistent with the requirements of
|
||||||
|
this License.
|
||||||
|
|
||||||
|
Each contributor grants you a non-exclusive, worldwide, royalty-free
|
||||||
|
patent license under the contributor's essential patent claims, to
|
||||||
|
make, use, sell, offer for sale, import and otherwise run, modify and
|
||||||
|
propagate the contents of its contributor version.
|
||||||
|
|
||||||
|
In the following three paragraphs, a "patent license" is any express
|
||||||
|
agreement or commitment, however denominated, not to enforce a patent
|
||||||
|
(such as an express permission to practice a patent or covenant not to
|
||||||
|
sue for patent infringement). To "grant" such a patent license to a
|
||||||
|
party means to make such an agreement or commitment not to enforce a
|
||||||
|
patent against the party.
|
||||||
|
|
||||||
|
If you convey a covered work, knowingly relying on a patent license,
|
||||||
|
and the Corresponding Source of the work is not available for anyone
|
||||||
|
to copy, free of charge and under the terms of this License, through a
|
||||||
|
publicly available network server or other readily accessible means,
|
||||||
|
then you must either (1) cause the Corresponding Source to be so
|
||||||
|
available, or (2) arrange to deprive yourself of the benefit of the
|
||||||
|
patent license for this particular work, or (3) arrange, in a manner
|
||||||
|
consistent with the requirements of this License, to extend the patent
|
||||||
|
license to downstream recipients. "Knowingly relying" means you have
|
||||||
|
actual knowledge that, but for the patent license, your conveying the
|
||||||
|
covered work in a country, or your recipient's use of the covered work
|
||||||
|
in a country, would infringe one or more identifiable patents in that
|
||||||
|
country that you have reason to believe are valid.
|
||||||
|
|
||||||
|
If, pursuant to or in connection with a single transaction or
|
||||||
|
arrangement, you convey, or propagate by procuring conveyance of, a
|
||||||
|
covered work, and grant a patent license to some of the parties
|
||||||
|
receiving the covered work authorizing them to use, propagate, modify
|
||||||
|
or convey a specific copy of the covered work, then the patent license
|
||||||
|
you grant is automatically extended to all recipients of the covered
|
||||||
|
work and works based on it.
|
||||||
|
|
||||||
|
A patent license is "discriminatory" if it does not include within
|
||||||
|
the scope of its coverage, prohibits the exercise of, or is
|
||||||
|
conditioned on the non-exercise of one or more of the rights that are
|
||||||
|
specifically granted under this License. You may not convey a covered
|
||||||
|
work if you are a party to an arrangement with a third party that is
|
||||||
|
in the business of distributing software, under which you make payment
|
||||||
|
to the third party based on the extent of your activity of conveying
|
||||||
|
the work, and under which the third party grants, to any of the
|
||||||
|
parties who would receive the covered work from you, a discriminatory
|
||||||
|
patent license (a) in connection with copies of the covered work
|
||||||
|
conveyed by you (or copies made from those copies), or (b) primarily
|
||||||
|
for and in connection with specific products or compilations that
|
||||||
|
contain the covered work, unless you entered into that arrangement,
|
||||||
|
or that patent license was granted, prior to 28 March 2007.
|
||||||
|
|
||||||
|
Nothing in this License shall be construed as excluding or limiting
|
||||||
|
any implied license or other defenses to infringement that may
|
||||||
|
otherwise be available to you under applicable patent law.
|
||||||
|
|
||||||
|
12. No Surrender of Others' Freedom.
|
||||||
|
|
||||||
|
If conditions are imposed on you (whether by court order, agreement or
|
||||||
|
otherwise) that contradict the conditions of this License, they do not
|
||||||
|
excuse you from the conditions of this License. If you cannot convey a
|
||||||
|
covered work so as to satisfy simultaneously your obligations under this
|
||||||
|
License and any other pertinent obligations, then as a consequence you may
|
||||||
|
not convey it at all. For example, if you agree to terms that obligate you
|
||||||
|
to collect a royalty for further conveying from those to whom you convey
|
||||||
|
the Program, the only way you could satisfy both those terms and this
|
||||||
|
License would be to refrain entirely from conveying the Program.
|
||||||
|
|
||||||
|
13. Use with the GNU Affero General Public License.
|
||||||
|
|
||||||
|
Notwithstanding any other provision of this License, you have
|
||||||
|
permission to link or combine any covered work with a work licensed
|
||||||
|
under version 3 of the GNU Affero General Public License into a single
|
||||||
|
combined work, and to convey the resulting work. The terms of this
|
||||||
|
License will continue to apply to the part which is the covered work,
|
||||||
|
but the special requirements of the GNU Affero General Public License,
|
||||||
|
section 13, concerning interaction through a network will apply to the
|
||||||
|
combination as such.
|
||||||
|
|
||||||
|
14. Revised Versions of this License.
|
||||||
|
|
||||||
|
The Free Software Foundation may publish revised and/or new versions of
|
||||||
|
the GNU General Public License from time to time. Such new versions will
|
||||||
|
be similar in spirit to the present version, but may differ in detail to
|
||||||
|
address new problems or concerns.
|
||||||
|
|
||||||
|
Each version is given a distinguishing version number. If the
|
||||||
|
Program specifies that a certain numbered version of the GNU General
|
||||||
|
Public License "or any later version" applies to it, you have the
|
||||||
|
option of following the terms and conditions either of that numbered
|
||||||
|
version or of any later version published by the Free Software
|
||||||
|
Foundation. If the Program does not specify a version number of the
|
||||||
|
GNU General Public License, you may choose any version ever published
|
||||||
|
by the Free Software Foundation.
|
||||||
|
|
||||||
|
If the Program specifies that a proxy can decide which future
|
||||||
|
versions of the GNU General Public License can be used, that proxy's
|
||||||
|
public statement of acceptance of a version permanently authorizes you
|
||||||
|
to choose that version for the Program.
|
||||||
|
|
||||||
|
Later license versions may give you additional or different
|
||||||
|
permissions. However, no additional obligations are imposed on any
|
||||||
|
author or copyright holder as a result of your choosing to follow a
|
||||||
|
later version.
|
||||||
|
|
||||||
|
15. Disclaimer of Warranty.
|
||||||
|
|
||||||
|
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
|
||||||
|
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
|
||||||
|
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
|
||||||
|
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
|
||||||
|
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
|
||||||
|
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||||
|
|
||||||
|
16. Limitation of Liability.
|
||||||
|
|
||||||
|
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||||
|
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
|
||||||
|
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
|
||||||
|
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
|
||||||
|
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
|
||||||
|
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
|
||||||
|
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
|
||||||
|
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
|
||||||
|
SUCH DAMAGES.
|
||||||
|
|
||||||
|
17. Interpretation of Sections 15 and 16.
|
||||||
|
|
||||||
|
If the disclaimer of warranty and limitation of liability provided
|
||||||
|
above cannot be given local legal effect according to their terms,
|
||||||
|
reviewing courts shall apply local law that most closely approximates
|
||||||
|
an absolute waiver of all civil liability in connection with the
|
||||||
|
Program, unless a warranty or assumption of liability accompanies a
|
||||||
|
copy of the Program in return for a fee.
|
||||||
|
|
||||||
|
END OF TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
How to Apply These Terms to Your New Programs
|
||||||
|
|
||||||
|
If you develop a new program, and you want it to be of the greatest
|
||||||
|
possible use to the public, the best way to achieve this is to make it
|
||||||
|
free software which everyone can redistribute and change under these terms.
|
||||||
|
|
||||||
|
To do so, attach the following notices to the program. It is safest
|
||||||
|
to attach them to the start of each source file to most effectively
|
||||||
|
state the exclusion of warranty; and each file should have at least
|
||||||
|
the "copyright" line and a pointer to where the full notice is found.
|
||||||
|
|
||||||
|
<one line to give the program's name and a brief idea of what it does.>
|
||||||
|
Copyright (C) <year> <name of author>
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
Also add information on how to contact you by electronic and paper mail.
|
||||||
|
|
||||||
|
If the program does terminal interaction, make it output a short
|
||||||
|
notice like this when it starts in an interactive mode:
|
||||||
|
|
||||||
|
<program> Copyright (C) <year> <name of author>
|
||||||
|
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||||
|
This is free software, and you are welcome to redistribute it
|
||||||
|
under certain conditions; type `show c' for details.
|
||||||
|
|
||||||
|
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||||
|
parts of the General Public License. Of course, your program's commands
|
||||||
|
might be different; for a GUI interface, you would use an "about box".
|
||||||
|
|
||||||
|
You should also get your employer (if you work as a programmer) or school,
|
||||||
|
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
||||||
|
For more information on this, and how to apply and follow the GNU GPL, see
|
||||||
|
<https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
The GNU General Public License does not permit incorporating your program
|
||||||
|
into proprietary programs. If your program is a subroutine library, you
|
||||||
|
may consider it more useful to permit linking proprietary applications with
|
||||||
|
the library. If this is what you want to do, use the GNU Lesser General
|
||||||
|
Public License instead of this License. But first, please read
|
||||||
|
<https://www.gnu.org/licenses/why-not-lgpl.html>.
|
||||||
BIN
pcb/FusionX/v1.0/tzpuFusionX_v1_0_109x55.zip
Normal file
BIN
pcb/FusionX/v1.0/tzpuFusionX_v1_0_3D_Bottom.png
Normal file
|
After Width: | Height: | Size: 353 KiB |
BIN
pcb/FusionX/v1.0/tzpuFusionX_v1_0_3D_Top.png
Normal file
|
After Width: | Height: | Size: 489 KiB |
|
After Width: | Height: | Size: 179 KiB |
|
After Width: | Height: | Size: 227 KiB |
|
After Width: | Height: | Size: 112 KiB |
|
After Width: | Height: | Size: 128 KiB |
|
After Width: | Height: | Size: 129 KiB |
|
After Width: | Height: | Size: 145 KiB |
BIN
schematics/FusionX/v1.0/tzpuFusionX_v1_0_Schematics.pdf
Normal file
BIN
software/FusionX/bin/mspi_main
Executable file
BIN
software/FusionX/bin/z80ctrl
Executable file
14
software/FusionX/etc/cpuset.sh
Executable file
@@ -0,0 +1,14 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
for f in `ps -eaf |grep -v kthread_z80 | awk '{print $1}'`
|
||||||
|
do
|
||||||
|
taskset -pc 0 $f >/dev/null 2>/dev/null
|
||||||
|
done
|
||||||
|
|
||||||
|
for I in $(ls /proc/irq)
|
||||||
|
do
|
||||||
|
if [[ -d "/proc/irq/$I" ]]
|
||||||
|
then
|
||||||
|
echo 0 > /proc/irq/$I/smp_affinity_list 2>/dev/null
|
||||||
|
fi
|
||||||
|
done
|
||||||
14
software/FusionX/etc/fb.sh
Executable file
@@ -0,0 +1,14 @@
|
|||||||
|
#!/bin/sh -x
|
||||||
|
|
||||||
|
fbdev=/dev/fb0 ; width=1280 ; bpp=4
|
||||||
|
color="\x00\xFF\x00\x00" #red colored
|
||||||
|
|
||||||
|
function pixel()
|
||||||
|
{ xx=$1 ; yy=$2
|
||||||
|
printf "$color" | dd bs=$bpp seek=$(($yy * $width + $xx)) \
|
||||||
|
of=$fbdev &>/dev/null
|
||||||
|
}
|
||||||
|
x=0 ; y=0 ; clear
|
||||||
|
for i in {1..10000}; do
|
||||||
|
pixel $((x++)) $((y++))
|
||||||
|
done
|
||||||
21
software/FusionX/etc/testgpio.sh
Executable file
@@ -0,0 +1,21 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
for f in 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 47 48 85 86 90 73 59
|
||||||
|
do
|
||||||
|
echo "PIN: ${f} ---------------------------------------------"
|
||||||
|
sleep 1
|
||||||
|
echo "Export PIN"
|
||||||
|
echo $f > /sys/class/gpio/export
|
||||||
|
echo " Direction OUT"
|
||||||
|
echo out > /sys/class/gpio/gpio${f}/direction
|
||||||
|
echo " OUT 1"
|
||||||
|
echo 1 > /sys/class/gpio/gpio${f}/value
|
||||||
|
echo " OUT 0"
|
||||||
|
echo 0 > /sys/class/gpio/gpio${f}/value
|
||||||
|
echo " Direction IN"
|
||||||
|
echo in > /sys/class/gpio/gpio${f}/direction
|
||||||
|
echo " IN"
|
||||||
|
cat /sys/class/gpio/gpio${f}/value
|
||||||
|
echo "-------------------------------------------------------"
|
||||||
|
sleep 1
|
||||||
|
done
|
||||||
8
software/FusionX/etc/z80drv.sh
Executable file
@@ -0,0 +1,8 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
cd /customer
|
||||||
|
./cpuset.sh
|
||||||
|
rmmod z80drv 2>/dev/null
|
||||||
|
insmod z80drv.ko
|
||||||
|
#drvid=`ps -eaf | grep kthread_z80 | grep -v grep | awk '{print $1}'`
|
||||||
|
#taskset -pc 1 $drvid
|
||||||
BIN
software/FusionX/modules/z80drv.ko
Normal file
51
software/FusionX/src/driver/CMakeLists.txt
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
set(kerneldir "/srv/dvlp/Projects/tzpu/FusionX/software/linux/kernel" CACHE STRING "Path to the kernel build directory")
|
||||||
|
if("${kerneldir}" STREQUAL "")
|
||||||
|
execute_process(COMMAND uname -r OUTPUT_VARIABLE uname_r
|
||||||
|
OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||||
|
set(kerneldir "/lib/modules/${uname_r}/build")
|
||||||
|
endif()
|
||||||
|
include(GNUInstallDirs)
|
||||||
|
include_directories(${kerneldir}/include)
|
||||||
|
find_file(kernel_makefile NAMES Makefile
|
||||||
|
PATHS ${kerneldir} NO_DEFAULT_PATH)
|
||||||
|
if(NOT kernel_makefile)
|
||||||
|
message(FATAL_ERROR "There is no Makefile in kerneldir!")
|
||||||
|
endif()
|
||||||
|
add_library(mymodule-lib STATIC z80drv.c)
|
||||||
|
get_target_property(module_sources mymodule-lib SOURCES)
|
||||||
|
list(APPEND module_sources z80drv.c)
|
||||||
|
|
||||||
|
#find_package(Z80 REQUIRED Shared)
|
||||||
|
add_subdirectory(Z80)
|
||||||
|
target_link_libraries(mymodule-lib Z80)
|
||||||
|
|
||||||
|
# the name of the target operating system
|
||||||
|
set(CMAKE_SYSTEM_NAME Linux)
|
||||||
|
|
||||||
|
# which compilers to use for C and C++
|
||||||
|
set(CMAKE_C_COMPILER arm-linux-gnueabihf-gcc)
|
||||||
|
set(CMAKE_CXX_COMPILER arm-linux-gnueabihf-g++)
|
||||||
|
|
||||||
|
# adjust the default behavior of the FIND_XXX() commands:
|
||||||
|
# search programs in the host environment
|
||||||
|
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
|
||||||
|
|
||||||
|
# search headers and libraries in the target environment
|
||||||
|
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
|
||||||
|
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
|
||||||
|
|
||||||
|
string(REPLACE ";" " " module_sources_string "${module_sources}")
|
||||||
|
configure_file(Kbuild.in Kbuild @ONLY)
|
||||||
|
|
||||||
|
foreach(src ${module_sources})
|
||||||
|
configure_file(${src} ${src} COPYONLY)
|
||||||
|
endforeach()
|
||||||
|
|
||||||
|
set(module_cmd ${CMAKE_MAKE_PROGRAM} -C ${kerneldir} ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- M=${CMAKE_CURRENT_BINARY_DIR} modules)
|
||||||
|
add_custom_command(OUTPUT z80drv.ko
|
||||||
|
COMMAND ${module_cmd} modules
|
||||||
|
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
|
||||||
|
DEPENDS ${module_sources} ${CMAKE_CURRENT_BINARY_DIR}/Kbuild
|
||||||
|
VERBATIM)
|
||||||
|
add_custom_target(module DEPENDS z80drv.ko)
|
||||||
|
add_custom_target(module-clean COMMAND ${module_cmd} clean)
|
||||||
403
software/FusionX/src/driver/MZ2000/optparse.h
Normal file
@@ -0,0 +1,403 @@
|
|||||||
|
/* Optparse --- portable, reentrant, embeddable, getopt-like option parser
|
||||||
|
*
|
||||||
|
* This is free and unencumbered software released into the public domain.
|
||||||
|
*
|
||||||
|
* To get the implementation, define OPTPARSE_IMPLEMENTATION.
|
||||||
|
* Optionally define OPTPARSE_API to control the API's visibility
|
||||||
|
* and/or linkage (static, __attribute__, __declspec).
|
||||||
|
*
|
||||||
|
* The POSIX getopt() option parser has three fatal flaws. These flaws
|
||||||
|
* are solved by Optparse.
|
||||||
|
*
|
||||||
|
* 1) Parser state is stored entirely in global variables, some of
|
||||||
|
* which are static and inaccessible. This means only one thread can
|
||||||
|
* use getopt(). It also means it's not possible to recursively parse
|
||||||
|
* nested sub-arguments while in the middle of argument parsing.
|
||||||
|
* Optparse fixes this by storing all state on a local struct.
|
||||||
|
*
|
||||||
|
* 2) The POSIX standard provides no way to properly reset the parser.
|
||||||
|
* This means for portable code that getopt() is only good for one
|
||||||
|
* run, over one argv with one option string. It also means subcommand
|
||||||
|
* options cannot be processed with getopt(). Most implementations
|
||||||
|
* provide a method to reset the parser, but it's not portable.
|
||||||
|
* Optparse provides an optparse_arg() function for stepping over
|
||||||
|
* subcommands and continuing parsing of options with another option
|
||||||
|
* string. The Optparse struct itself can be passed around to
|
||||||
|
* subcommand handlers for additional subcommand option parsing. A
|
||||||
|
* full reset can be achieved by with an additional optparse_init().
|
||||||
|
*
|
||||||
|
* 3) Error messages are printed to stderr. This can be disabled with
|
||||||
|
* opterr, but the messages themselves are still inaccessible.
|
||||||
|
* Optparse solves this by writing an error message in its errmsg
|
||||||
|
* field. The downside to Optparse is that this error message will
|
||||||
|
* always be in English rather than the current locale.
|
||||||
|
*
|
||||||
|
* Optparse should be familiar with anyone accustomed to getopt(), and
|
||||||
|
* it could be a nearly drop-in replacement. The option string is the
|
||||||
|
* same and the fields have the same names as the getopt() global
|
||||||
|
* variables (optarg, optind, optopt).
|
||||||
|
*
|
||||||
|
* Optparse also supports GNU-style long options with optparse_long().
|
||||||
|
* The interface is slightly different and simpler than getopt_long().
|
||||||
|
*
|
||||||
|
* By default, argv is permuted as it is parsed, moving non-option
|
||||||
|
* arguments to the end. This can be disabled by setting the `permute`
|
||||||
|
* field to 0 after initialization.
|
||||||
|
*/
|
||||||
|
#ifndef OPTPARSE_H
|
||||||
|
#define OPTPARSE_H
|
||||||
|
|
||||||
|
#ifndef OPTPARSE_API
|
||||||
|
# define OPTPARSE_API
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct optparse {
|
||||||
|
char **argv;
|
||||||
|
int permute;
|
||||||
|
int optind;
|
||||||
|
int optopt;
|
||||||
|
char *optarg;
|
||||||
|
char errmsg[64];
|
||||||
|
int subopt;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum optparse_argtype {
|
||||||
|
OPTPARSE_NONE,
|
||||||
|
OPTPARSE_REQUIRED,
|
||||||
|
OPTPARSE_OPTIONAL
|
||||||
|
};
|
||||||
|
|
||||||
|
struct optparse_long {
|
||||||
|
const char *longname;
|
||||||
|
int shortname;
|
||||||
|
enum optparse_argtype argtype;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes the parser state.
|
||||||
|
*/
|
||||||
|
OPTPARSE_API
|
||||||
|
void optparse_init(struct optparse *options, char **argv);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read the next option in the argv array.
|
||||||
|
* @param optstring a getopt()-formatted option string.
|
||||||
|
* @return the next option character, -1 for done, or '?' for error
|
||||||
|
*
|
||||||
|
* Just like getopt(), a character followed by no colons means no
|
||||||
|
* argument. One colon means the option has a required argument. Two
|
||||||
|
* colons means the option takes an optional argument.
|
||||||
|
*/
|
||||||
|
OPTPARSE_API
|
||||||
|
int optparse(struct optparse *options, const char *optstring);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles GNU-style long options in addition to getopt() options.
|
||||||
|
* This works a lot like GNU's getopt_long(). The last option in
|
||||||
|
* longopts must be all zeros, marking the end of the array. The
|
||||||
|
* longindex argument may be NULL.
|
||||||
|
*/
|
||||||
|
OPTPARSE_API
|
||||||
|
int optparse_long(struct optparse *options,
|
||||||
|
const struct optparse_long *longopts,
|
||||||
|
int *longindex);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used for stepping over non-option arguments.
|
||||||
|
* @return the next non-option argument, or NULL for no more arguments
|
||||||
|
*
|
||||||
|
* Argument parsing can continue with optparse() after using this
|
||||||
|
* function. That would be used to parse the options for the
|
||||||
|
* subcommand returned by optparse_arg(). This function allows you to
|
||||||
|
* ignore the value of optind.
|
||||||
|
*/
|
||||||
|
OPTPARSE_API
|
||||||
|
char *optparse_arg(struct optparse *options);
|
||||||
|
|
||||||
|
/* Implementation */
|
||||||
|
#ifdef OPTPARSE_IMPLEMENTATION
|
||||||
|
|
||||||
|
#define OPTPARSE_MSG_INVALID "invalid option"
|
||||||
|
#define OPTPARSE_MSG_MISSING "option requires an argument"
|
||||||
|
#define OPTPARSE_MSG_TOOMANY "option takes no arguments"
|
||||||
|
|
||||||
|
static int
|
||||||
|
optparse_error(struct optparse *options, const char *msg, const char *data)
|
||||||
|
{
|
||||||
|
unsigned p = 0;
|
||||||
|
const char *sep = " -- '";
|
||||||
|
while (*msg)
|
||||||
|
options->errmsg[p++] = *msg++;
|
||||||
|
while (*sep)
|
||||||
|
options->errmsg[p++] = *sep++;
|
||||||
|
while (p < sizeof(options->errmsg) - 2 && *data)
|
||||||
|
options->errmsg[p++] = *data++;
|
||||||
|
options->errmsg[p++] = '\'';
|
||||||
|
options->errmsg[p++] = '\0';
|
||||||
|
return '?';
|
||||||
|
}
|
||||||
|
|
||||||
|
OPTPARSE_API
|
||||||
|
void
|
||||||
|
optparse_init(struct optparse *options, char **argv)
|
||||||
|
{
|
||||||
|
options->argv = argv;
|
||||||
|
options->permute = 1;
|
||||||
|
options->optind = 1;
|
||||||
|
options->subopt = 0;
|
||||||
|
options->optarg = 0;
|
||||||
|
options->errmsg[0] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
optparse_is_dashdash(const char *arg)
|
||||||
|
{
|
||||||
|
return arg != 0 && arg[0] == '-' && arg[1] == '-' && arg[2] == '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
optparse_is_shortopt(const char *arg)
|
||||||
|
{
|
||||||
|
return arg != 0 && arg[0] == '-' && arg[1] != '-' && arg[1] != '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
optparse_is_longopt(const char *arg)
|
||||||
|
{
|
||||||
|
return arg != 0 && arg[0] == '-' && arg[1] == '-' && arg[2] != '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
optparse_permute(struct optparse *options, int index)
|
||||||
|
{
|
||||||
|
char *nonoption = options->argv[index];
|
||||||
|
int i;
|
||||||
|
for (i = index; i < options->optind - 1; i++)
|
||||||
|
options->argv[i] = options->argv[i + 1];
|
||||||
|
options->argv[options->optind - 1] = nonoption;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
optparse_argtype(const char *optstring, char c)
|
||||||
|
{
|
||||||
|
int count = OPTPARSE_NONE;
|
||||||
|
if (c == ':')
|
||||||
|
return -1;
|
||||||
|
for (; *optstring && c != *optstring; optstring++);
|
||||||
|
if (!*optstring)
|
||||||
|
return -1;
|
||||||
|
if (optstring[1] == ':')
|
||||||
|
count += optstring[2] == ':' ? 2 : 1;
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
OPTPARSE_API
|
||||||
|
int
|
||||||
|
optparse(struct optparse *options, const char *optstring)
|
||||||
|
{
|
||||||
|
int type;
|
||||||
|
char *next;
|
||||||
|
char *option = options->argv[options->optind];
|
||||||
|
options->errmsg[0] = '\0';
|
||||||
|
options->optopt = 0;
|
||||||
|
options->optarg = 0;
|
||||||
|
if (option == 0) {
|
||||||
|
return -1;
|
||||||
|
} else if (optparse_is_dashdash(option)) {
|
||||||
|
options->optind++; /* consume "--" */
|
||||||
|
return -1;
|
||||||
|
} else if (!optparse_is_shortopt(option)) {
|
||||||
|
if (options->permute) {
|
||||||
|
int index = options->optind++;
|
||||||
|
int r = optparse(options, optstring);
|
||||||
|
optparse_permute(options, index);
|
||||||
|
options->optind--;
|
||||||
|
return r;
|
||||||
|
} else {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
option += options->subopt + 1;
|
||||||
|
options->optopt = option[0];
|
||||||
|
type = optparse_argtype(optstring, option[0]);
|
||||||
|
next = options->argv[options->optind + 1];
|
||||||
|
switch (type) {
|
||||||
|
case -1: {
|
||||||
|
char str[2] = {0, 0};
|
||||||
|
str[0] = option[0];
|
||||||
|
options->optind++;
|
||||||
|
return optparse_error(options, OPTPARSE_MSG_INVALID, str);
|
||||||
|
}
|
||||||
|
case OPTPARSE_NONE:
|
||||||
|
if (option[1]) {
|
||||||
|
options->subopt++;
|
||||||
|
} else {
|
||||||
|
options->subopt = 0;
|
||||||
|
options->optind++;
|
||||||
|
}
|
||||||
|
return option[0];
|
||||||
|
case OPTPARSE_REQUIRED:
|
||||||
|
options->subopt = 0;
|
||||||
|
options->optind++;
|
||||||
|
if (option[1]) {
|
||||||
|
options->optarg = option + 1;
|
||||||
|
} else if (next != 0) {
|
||||||
|
options->optarg = next;
|
||||||
|
options->optind++;
|
||||||
|
} else {
|
||||||
|
char str[2] = {0, 0};
|
||||||
|
str[0] = option[0];
|
||||||
|
options->optarg = 0;
|
||||||
|
return optparse_error(options, OPTPARSE_MSG_MISSING, str);
|
||||||
|
}
|
||||||
|
return option[0];
|
||||||
|
case OPTPARSE_OPTIONAL:
|
||||||
|
options->subopt = 0;
|
||||||
|
options->optind++;
|
||||||
|
if (option[1])
|
||||||
|
options->optarg = option + 1;
|
||||||
|
else
|
||||||
|
options->optarg = 0;
|
||||||
|
return option[0];
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
OPTPARSE_API
|
||||||
|
char *
|
||||||
|
optparse_arg(struct optparse *options)
|
||||||
|
{
|
||||||
|
char *option = options->argv[options->optind];
|
||||||
|
options->subopt = 0;
|
||||||
|
if (option != 0)
|
||||||
|
options->optind++;
|
||||||
|
return option;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
optparse_longopts_end(const struct optparse_long *longopts, int i)
|
||||||
|
{
|
||||||
|
return !longopts[i].longname && !longopts[i].shortname;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
optparse_from_long(const struct optparse_long *longopts, char *optstring)
|
||||||
|
{
|
||||||
|
char *p = optstring;
|
||||||
|
int i;
|
||||||
|
for (i = 0; !optparse_longopts_end(longopts, i); i++) {
|
||||||
|
if (longopts[i].shortname && longopts[i].shortname < 127) {
|
||||||
|
int a;
|
||||||
|
*p++ = longopts[i].shortname;
|
||||||
|
for (a = 0; a < (int)longopts[i].argtype; a++)
|
||||||
|
*p++ = ':';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*p = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Unlike strcmp(), handles options containing "=". */
|
||||||
|
static int
|
||||||
|
optparse_longopts_match(const char *longname, const char *option)
|
||||||
|
{
|
||||||
|
const char *a = option, *n = longname;
|
||||||
|
if (longname == 0)
|
||||||
|
return 0;
|
||||||
|
for (; *a && *n && *a != '='; a++, n++)
|
||||||
|
if (*a != *n)
|
||||||
|
return 0;
|
||||||
|
return *n == '\0' && (*a == '\0' || *a == '=');
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return the part after "=", or NULL. */
|
||||||
|
static char *
|
||||||
|
optparse_longopts_arg(char *option)
|
||||||
|
{
|
||||||
|
for (; *option && *option != '='; option++);
|
||||||
|
if (*option == '=')
|
||||||
|
return option + 1;
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
optparse_long_fallback(struct optparse *options,
|
||||||
|
const struct optparse_long *longopts,
|
||||||
|
int *longindex)
|
||||||
|
{
|
||||||
|
int result;
|
||||||
|
char optstring[96 * 3 + 1]; /* 96 ASCII printable characters */
|
||||||
|
optparse_from_long(longopts, optstring);
|
||||||
|
result = optparse(options, optstring);
|
||||||
|
if (longindex != 0) {
|
||||||
|
*longindex = -1;
|
||||||
|
if (result != -1) {
|
||||||
|
int i;
|
||||||
|
for (i = 0; !optparse_longopts_end(longopts, i); i++)
|
||||||
|
if (longopts[i].shortname == options->optopt)
|
||||||
|
*longindex = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
OPTPARSE_API
|
||||||
|
int
|
||||||
|
optparse_long(struct optparse *options,
|
||||||
|
const struct optparse_long *longopts,
|
||||||
|
int *longindex)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
char *option = options->argv[options->optind];
|
||||||
|
if (option == 0) {
|
||||||
|
return -1;
|
||||||
|
} else if (optparse_is_dashdash(option)) {
|
||||||
|
options->optind++; /* consume "--" */
|
||||||
|
return -1;
|
||||||
|
} else if (optparse_is_shortopt(option)) {
|
||||||
|
return optparse_long_fallback(options, longopts, longindex);
|
||||||
|
} else if (!optparse_is_longopt(option)) {
|
||||||
|
if (options->permute) {
|
||||||
|
int index = options->optind++;
|
||||||
|
int r = optparse_long(options, longopts, longindex);
|
||||||
|
optparse_permute(options, index);
|
||||||
|
options->optind--;
|
||||||
|
return r;
|
||||||
|
} else {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Parse as long option. */
|
||||||
|
options->errmsg[0] = '\0';
|
||||||
|
options->optopt = 0;
|
||||||
|
options->optarg = 0;
|
||||||
|
option += 2; /* skip "--" */
|
||||||
|
options->optind++;
|
||||||
|
for (i = 0; !optparse_longopts_end(longopts, i); i++) {
|
||||||
|
const char *name = longopts[i].longname;
|
||||||
|
if (optparse_longopts_match(name, option)) {
|
||||||
|
char *arg;
|
||||||
|
if (longindex)
|
||||||
|
*longindex = i;
|
||||||
|
options->optopt = longopts[i].shortname;
|
||||||
|
arg = optparse_longopts_arg(option);
|
||||||
|
if (longopts[i].argtype == OPTPARSE_NONE && arg != 0) {
|
||||||
|
return optparse_error(options, OPTPARSE_MSG_TOOMANY, name);
|
||||||
|
} if (arg != 0) {
|
||||||
|
options->optarg = arg;
|
||||||
|
} else if (longopts[i].argtype == OPTPARSE_REQUIRED) {
|
||||||
|
options->optarg = options->argv[options->optind];
|
||||||
|
if (options->optarg == 0)
|
||||||
|
return optparse_error(options, OPTPARSE_MSG_MISSING, name);
|
||||||
|
else
|
||||||
|
options->optind++;
|
||||||
|
}
|
||||||
|
return options->optopt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return optparse_error(options, OPTPARSE_MSG_INVALID, option);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* OPTPARSE_IMPLEMENTATION */
|
||||||
|
#endif /* OPTPARSE_H */
|
||||||
794
software/FusionX/src/driver/MZ2000/z80ctrl.c
Normal file
@@ -0,0 +1,794 @@
|
|||||||
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Name: z80ctrl.c
|
||||||
|
// Created: Oct 2022
|
||||||
|
// Author(s): Philip Smart
|
||||||
|
// Description: Z80 Control Interface
|
||||||
|
// This file contains a command line utility tool for controlling the z80drv device
|
||||||
|
// driver. The tool allows manipulation of the emulated Z80, inspection of its
|
||||||
|
// memory and data, transmission of adhoc commands to the underlying CPLD-Z80
|
||||||
|
// gateway and loading/saving of programs and data to/from the Z80 virtual and
|
||||||
|
// host memory.
|
||||||
|
//
|
||||||
|
// Credits: Zilog Z80 CPU Emulator v0.2 written by Manuel Sainz de Baranda y Goñi
|
||||||
|
// The Z80 CPU Emulator is the heart of the Z80 device driver.
|
||||||
|
// Copyright: (c) 2019-2022 Philip Smart <philip.smart@net2net.org>
|
||||||
|
// (c) 1999-2022 Manuel Sainz de Baranda y Goñi
|
||||||
|
//
|
||||||
|
// History: Oct 2022 - Initial write of the z80 kernel driver software.
|
||||||
|
//
|
||||||
|
// Notes: See Makefile to enable/disable conditional components
|
||||||
|
//
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// This source file is free software: you can redistribute it and#or modify
|
||||||
|
// it under the terms of the GNU General Public License as published
|
||||||
|
// by the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This source file is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <sys/mman.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <sys/select.h>
|
||||||
|
#include <termios.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <Z/constants/pointer.h>
|
||||||
|
#include <Z/macros/member.h>
|
||||||
|
#include <Z/macros/array.h>
|
||||||
|
#include <Z80.h>
|
||||||
|
#include "z80driver.h"
|
||||||
|
|
||||||
|
#define VERSION "1.0"
|
||||||
|
#define AUTHOR "P.D.Smart"
|
||||||
|
#define COPYRIGHT "(c) 2018-22"
|
||||||
|
|
||||||
|
// Getopt_long is buggy so we use optparse.
|
||||||
|
#define OPTPARSE_IMPLEMENTATION
|
||||||
|
#define OPTPARSE_API static
|
||||||
|
#include "optparse.h"
|
||||||
|
|
||||||
|
// Device driver name.
|
||||||
|
#define DEVICE_FILENAME "/dev/z80drv"
|
||||||
|
|
||||||
|
// Constants for the Sharp MZ80A MZF file format.
|
||||||
|
#define MZF_HEADER_SIZE 128 // Size of the MZF header.
|
||||||
|
#define MZF_ATTRIBUTE 0x00 // Code Type, 01 = Machine Code.
|
||||||
|
#define MZF_FILENAME 0x01 // Title/Name (17 bytes).
|
||||||
|
#define MZF_FILENAME_LEN 17 // Length of the filename, it is not NULL terminated, generally a CR can be taken as terminator but not guaranteed.
|
||||||
|
#define MZF_FILESIZE 0x12 // Size of program.
|
||||||
|
#define MZF_LOADADDR 0x14 // Load address of program.
|
||||||
|
#define MZF_EXECADDR 0x16 // Exec address of program.
|
||||||
|
#define MZF_COMMENT 0x18 // Comment, used for details of the file or startup code.
|
||||||
|
#define MZF_COMMENT_LEN 104 // Length of the comment field.
|
||||||
|
#define CMT_TYPE_OBJCD 0x001 // MZF contains a binary object.
|
||||||
|
#define CMT_TYPE_BTX1CD 0x002 // MZF contains a BASIC program.
|
||||||
|
#define CMT_TYPE_BTX2CD 0x005 // MZF contains a BASIC program.
|
||||||
|
#define CMT_TYPE_TZOBJCD0 0x0F8 // MZF contains a TZFS binary object for page 0.
|
||||||
|
#define CMT_TYPE_TZOBJCD1 0x0F9
|
||||||
|
#define CMT_TYPE_TZOBJCD2 0x0FA
|
||||||
|
#define CMT_TYPE_TZOBJCD3 0x0FB
|
||||||
|
#define CMT_TYPE_TZOBJCD4 0x0FC
|
||||||
|
#define CMT_TYPE_TZOBJCD5 0x0FD
|
||||||
|
#define CMT_TYPE_TZOBJCD6 0x0FE
|
||||||
|
#define CMT_TYPE_TZOBJCD7 0x0FF // MZF contains a TZFS binary object for page 7.
|
||||||
|
#define MZ_CMT_ADDR 0x10F0
|
||||||
|
|
||||||
|
// Structure to define a Sharp MZ80A MZF directory structure. This header appears at the beginning of every Sharp MZ80A tape (and more recently archived/emulator) images.
|
||||||
|
//
|
||||||
|
typedef struct __attribute__((__packed__)) {
|
||||||
|
uint8_t attr; // MZF attribute describing the file.
|
||||||
|
uint8_t fileName[MZF_FILENAME_LEN]; // Each directory entry is the size of an MZF filename.
|
||||||
|
uint16_t fileSize; // Size of file.
|
||||||
|
uint16_t loadAddr; // Load address for the file.
|
||||||
|
uint16_t execAddr; // Execution address where the Z80 starts processing.
|
||||||
|
uint8_t comment[MZF_COMMENT_LEN]; // Text comment field but often contains a startup machine code program.
|
||||||
|
} t_svcDirEnt;
|
||||||
|
|
||||||
|
// Possible commands to be issued to the Z80 driver.
|
||||||
|
enum CTRL_COMMANDS {
|
||||||
|
Z80_CMD_STOP = 0,
|
||||||
|
Z80_CMD_START = 1,
|
||||||
|
Z80_CMD_PAUSE = 2,
|
||||||
|
Z80_CMD_CONTINUE = 3,
|
||||||
|
Z80_CMD_RESET = 4,
|
||||||
|
Z80_CMD_SPEED = 5,
|
||||||
|
Z80_CMD_HOST_RAM = 6,
|
||||||
|
Z80_CMD_VIRTUAL_RAM = 7,
|
||||||
|
Z80_CMD_DUMP_MEMORY = 8,
|
||||||
|
Z80_CMD_MEMORY_TEST = 9,
|
||||||
|
CPLD_CMD_SEND_CMD = 10,
|
||||||
|
CPLD_CMD_SPI_TEST = 11,
|
||||||
|
CPLD_CMD_PRL_TEST = 12
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// Shared memory between this process and the Z80 driver.
|
||||||
|
static t_Z80Ctrl *Z80Ctrl = NULL;
|
||||||
|
|
||||||
|
// Method to obtain and return the output screen width.
|
||||||
|
//
|
||||||
|
uint8_t getScreenWidth(void)
|
||||||
|
{
|
||||||
|
return(MAX_SCREEN_WIDTH);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct termios orig_termios;
|
||||||
|
|
||||||
|
void reset_terminal_mode()
|
||||||
|
{
|
||||||
|
tcsetattr(0, TCSANOW, &orig_termios);
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_conio_terminal_mode()
|
||||||
|
{
|
||||||
|
struct termios new_termios;
|
||||||
|
|
||||||
|
/* take two copies - one for now, one for later */
|
||||||
|
tcgetattr(0, &orig_termios);
|
||||||
|
memcpy(&new_termios, &orig_termios, sizeof(new_termios));
|
||||||
|
|
||||||
|
/* register cleanup handler, and set the new terminal mode */
|
||||||
|
atexit(reset_terminal_mode);
|
||||||
|
cfmakeraw(&new_termios);
|
||||||
|
tcsetattr(0, TCSANOW, &new_termios);
|
||||||
|
}
|
||||||
|
|
||||||
|
int kbhit()
|
||||||
|
{
|
||||||
|
struct timeval tv = { 0L, 0L };
|
||||||
|
fd_set fds;
|
||||||
|
FD_ZERO(&fds);
|
||||||
|
FD_SET(0, &fds);
|
||||||
|
return select(1, &fds, NULL, NULL, &tv) > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int getch(uint8_t wait)
|
||||||
|
{
|
||||||
|
int r;
|
||||||
|
unsigned char c;
|
||||||
|
|
||||||
|
if(wait != 0 || (wait == 0 && kbhit()))
|
||||||
|
{
|
||||||
|
if ((r = read(0, &c, sizeof(c))) < 0) {
|
||||||
|
return r;
|
||||||
|
} else {
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void delay(int number_of_seconds)
|
||||||
|
{
|
||||||
|
// Converting time into milli_seconds
|
||||||
|
int milli_seconds = 1000 * number_of_seconds;
|
||||||
|
|
||||||
|
// Storing start time
|
||||||
|
clock_t start_time = clock();
|
||||||
|
|
||||||
|
// looping till required time is not achieved
|
||||||
|
while (clock() < start_time + milli_seconds);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Function to dump out a given section of memory via the UART.
|
||||||
|
//
|
||||||
|
int memoryDump(uint32_t memaddr, uint32_t memsize, uint8_t memoryFlag, uint32_t memwidth, uint32_t dispaddr, uint8_t dispwidth)
|
||||||
|
{
|
||||||
|
uint8_t displayWidth = dispwidth;;
|
||||||
|
uint32_t pnt = memaddr;
|
||||||
|
uint32_t endAddr = memaddr + memsize;
|
||||||
|
uint32_t addr = dispaddr;
|
||||||
|
uint32_t i = 0;
|
||||||
|
//uint32_t data;
|
||||||
|
int8_t keyIn;
|
||||||
|
int result = -1;
|
||||||
|
char c = 0;
|
||||||
|
|
||||||
|
// Sanity check. memoryFlag == 0 required kernel driver to dump so we exit as it cannot be performed here.
|
||||||
|
if(memoryFlag == 0)
|
||||||
|
return(-1);
|
||||||
|
|
||||||
|
// Reconfigure terminal to allow non-blocking key input.
|
||||||
|
//
|
||||||
|
set_conio_terminal_mode();
|
||||||
|
|
||||||
|
// If not set, calculate output line width according to connected display width.
|
||||||
|
//
|
||||||
|
if(displayWidth == 0)
|
||||||
|
{
|
||||||
|
switch(getScreenWidth())
|
||||||
|
{
|
||||||
|
case 40:
|
||||||
|
displayWidth = 8;
|
||||||
|
break;
|
||||||
|
case 80:
|
||||||
|
displayWidth = 16;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
displayWidth = 32;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
printf("%08lX", addr); // print address
|
||||||
|
printf(": ");
|
||||||
|
|
||||||
|
// print hexadecimal data
|
||||||
|
for (i=0; i < displayWidth; )
|
||||||
|
{
|
||||||
|
switch(memwidth)
|
||||||
|
{
|
||||||
|
case 16:
|
||||||
|
if(pnt+i < endAddr)
|
||||||
|
printf("%04X", memoryFlag == 1 ? (uint16_t)Z80Ctrl->memory[pnt+i] : memoryFlag == 2 ? (uint16_t)Z80Ctrl->page[pnt+i] : (uint16_t)Z80Ctrl->iopage[pnt+i]);
|
||||||
|
else
|
||||||
|
printf(" ");
|
||||||
|
i++;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 32:
|
||||||
|
if(pnt+i < endAddr)
|
||||||
|
printf("%08lX", memoryFlag == 1 ? (uint32_t)Z80Ctrl->memory[pnt+i] : memoryFlag == 2 ? (uint32_t)Z80Ctrl->page[pnt+i] : (uint32_t)Z80Ctrl->iopage[pnt+i]);
|
||||||
|
else
|
||||||
|
printf(" ");
|
||||||
|
i++;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 8:
|
||||||
|
default:
|
||||||
|
if(pnt+i < endAddr)
|
||||||
|
printf("%02X", memoryFlag == 1 ? (uint8_t)Z80Ctrl->memory[pnt+i] : memoryFlag == 2 ? (uint8_t)Z80Ctrl->page[pnt+i] : (uint8_t)Z80Ctrl->iopage[pnt+i]);
|
||||||
|
else
|
||||||
|
printf(" ");
|
||||||
|
i++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
fputc((char)' ', stdout);
|
||||||
|
}
|
||||||
|
|
||||||
|
// print ascii data
|
||||||
|
printf(" |");
|
||||||
|
|
||||||
|
// print single ascii char
|
||||||
|
for (i=0; i < displayWidth; i++)
|
||||||
|
{
|
||||||
|
c = memoryFlag == 1 ? (char)Z80Ctrl->memory[pnt+i] : memoryFlag == 2 ? (char)Z80Ctrl->page[pnt+i] : (char)Z80Ctrl->iopage[pnt+i];
|
||||||
|
if ((pnt+i < endAddr) && (c >= ' ') && (c <= '~'))
|
||||||
|
fputc((char)c, stdout);
|
||||||
|
else
|
||||||
|
fputc((char)' ', stdout);
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("|\r\n");
|
||||||
|
fflush(stdout);
|
||||||
|
|
||||||
|
// Move on one row.
|
||||||
|
pnt += displayWidth;
|
||||||
|
addr += displayWidth;
|
||||||
|
|
||||||
|
// User abort (ESC), pause (Space) or all done?
|
||||||
|
//
|
||||||
|
keyIn = getch(0);
|
||||||
|
if(keyIn == ' ')
|
||||||
|
{
|
||||||
|
do {
|
||||||
|
keyIn = getch(0);
|
||||||
|
} while(keyIn != ' ' && keyIn != 0x1b);
|
||||||
|
}
|
||||||
|
// Escape key pressed, exit with 0 to indicate this to caller.
|
||||||
|
if (keyIn == 0x1b)
|
||||||
|
{
|
||||||
|
sleep(1);
|
||||||
|
result = 0;
|
||||||
|
goto memoryDumpExit;
|
||||||
|
}
|
||||||
|
|
||||||
|
// End of buffer, exit the loop.
|
||||||
|
if(pnt >= (memaddr + memsize))
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Normal exit, return -1 to show no key pressed.
|
||||||
|
memoryDumpExit:
|
||||||
|
reset_terminal_mode();
|
||||||
|
return(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Method to load a program or data file into the Z80 memory. First load into Virtual memory and then trigger a sync to bring Host RAM in line.
|
||||||
|
//
|
||||||
|
int z80load(int fdZ80, char *fileName)
|
||||||
|
{
|
||||||
|
// Locals.
|
||||||
|
struct ioctlCmd ioctlCmd;
|
||||||
|
int ret = 0;
|
||||||
|
t_svcDirEnt mzfHeader;
|
||||||
|
|
||||||
|
// Pause the Z80.
|
||||||
|
//
|
||||||
|
ioctlCmd.cmd = IOCTL_CMD_Z80_PAUSE;
|
||||||
|
ioctl(fdZ80, IOCTL_CMD_SEND, &ioctlCmd);
|
||||||
|
|
||||||
|
// Open the file and read directly into the Virtual memory via the share.
|
||||||
|
FILE *ptr;
|
||||||
|
ptr = fopen(fileName, "rb");
|
||||||
|
if(ptr)
|
||||||
|
{
|
||||||
|
// First the header.
|
||||||
|
fread((uint8_t *)&mzfHeader, MZF_HEADER_SIZE, 1, ptr);
|
||||||
|
|
||||||
|
#if(TARGET_HOST_MZ700 == 1)
|
||||||
|
if(mzfHeader.loadAddr > 0x1000)
|
||||||
|
{
|
||||||
|
#endif
|
||||||
|
// Copy in the header.
|
||||||
|
memcpy((uint8_t *)&Z80Ctrl->memory[MZ_CMT_ADDR], (uint8_t *)&mzfHeader, MZF_HEADER_SIZE);
|
||||||
|
|
||||||
|
// Now read in the data.
|
||||||
|
fread(&Z80Ctrl->memory[mzfHeader.loadAddr], mzfHeader.fileSize, 1, ptr);
|
||||||
|
printf("Loaded %s, Size:%04x, Addr:%04x, Exec:%04x\n", fileName, mzfHeader.fileSize, mzfHeader.loadAddr, mzfHeader.execAddr);
|
||||||
|
#if(TARGET_HOST_MZ700 == 1)
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Sync the loaded image from Virtual memory to hard memory.
|
||||||
|
ioctlCmd.cmd = IOCTL_CMD_SYNC_TO_HOST_RAM;
|
||||||
|
ioctl(fdZ80, IOCTL_CMD_SEND, &ioctlCmd);
|
||||||
|
|
||||||
|
#if(TARGET_HOST_MZ2000 == 1)
|
||||||
|
// Set PC to 2 (NST) which switches to RUN mode and executes at 0000H
|
||||||
|
ioctlCmd.z80.pc = 2;
|
||||||
|
#endif
|
||||||
|
#if(TARGET_HOST_MZ700 == 1)
|
||||||
|
// MZ-700 just use the MZF header exec address.
|
||||||
|
ioctlCmd.z80.pc = mzfHeader.execAddr;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Set PC to required setting ready for run.
|
||||||
|
ioctlCmd.cmd = IOCTL_CMD_SETPC;
|
||||||
|
ioctl(fdZ80, IOCTL_CMD_SEND, &ioctlCmd);
|
||||||
|
|
||||||
|
// Resume Z80 processing.
|
||||||
|
//
|
||||||
|
ioctlCmd.cmd = IOCTL_CMD_Z80_CONTINUE;
|
||||||
|
ioctl(fdZ80, IOCTL_CMD_SEND, &ioctlCmd);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
printf("Couldnt open file\n");
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Method to request basic Z80 operations.
|
||||||
|
//
|
||||||
|
int ctrlCmd(int fdZ80, enum CTRL_COMMANDS cmd, long param1, long param2, long param3)
|
||||||
|
{
|
||||||
|
// Locals.
|
||||||
|
struct ioctlCmd ioctlCmd;
|
||||||
|
uint32_t idx;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
switch(cmd)
|
||||||
|
{
|
||||||
|
case Z80_CMD_STOP:
|
||||||
|
// Use IOCTL to request Z80 to Stop (power off) processing.
|
||||||
|
ioctlCmd.cmd = IOCTL_CMD_Z80_STOP;
|
||||||
|
ioctl(fdZ80, IOCTL_CMD_SEND, &ioctlCmd);
|
||||||
|
break;
|
||||||
|
case Z80_CMD_START:
|
||||||
|
// Use IOCTL to request Z80 to Start (power on) processing.
|
||||||
|
ioctlCmd.cmd = IOCTL_CMD_Z80_START;
|
||||||
|
ioctl(fdZ80, IOCTL_CMD_SEND, &ioctlCmd);
|
||||||
|
break;
|
||||||
|
case Z80_CMD_PAUSE:
|
||||||
|
// Use IOCTL to request Z80 to pause processing.
|
||||||
|
ioctlCmd.cmd = IOCTL_CMD_Z80_PAUSE;
|
||||||
|
ioctl(fdZ80, IOCTL_CMD_SEND, &ioctlCmd);
|
||||||
|
break;
|
||||||
|
case Z80_CMD_CONTINUE:
|
||||||
|
// Use IOCTL to request Z80 continue processing.
|
||||||
|
ioctlCmd.cmd = IOCTL_CMD_Z80_CONTINUE;
|
||||||
|
ioctl(fdZ80, IOCTL_CMD_SEND, &ioctlCmd);
|
||||||
|
break;
|
||||||
|
case Z80_CMD_RESET:
|
||||||
|
// Use IOCTL to request Z80 reset.
|
||||||
|
ioctlCmd.cmd = IOCTL_CMD_Z80_RESET;
|
||||||
|
ioctl(fdZ80, IOCTL_CMD_SEND, &ioctlCmd);
|
||||||
|
break;
|
||||||
|
case Z80_CMD_SPEED:
|
||||||
|
// Check value is in range.
|
||||||
|
for(idx=1; idx < 256; idx+=idx)
|
||||||
|
{
|
||||||
|
if((uint32_t)param1 == idx) break;
|
||||||
|
}
|
||||||
|
if(idx == 256)
|
||||||
|
{
|
||||||
|
printf("Speed factor is illegal. It must be a multiple value of the original CPU clock, ie. 1x, 2x, 4x etc\n");
|
||||||
|
ret = -1;
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
// Use IOCTL to request Z80 cpu freq change.
|
||||||
|
ioctlCmd.speed.speedMultiplier = (uint32_t)param1;
|
||||||
|
ioctlCmd.cmd = IOCTL_CMD_Z80_CPU_FREQ;
|
||||||
|
ioctl(fdZ80, IOCTL_CMD_SEND, &ioctlCmd);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case CPLD_CMD_SEND_CMD:
|
||||||
|
// Build up the IOCTL command to request the given data is sent to the CPLD.
|
||||||
|
ioctlCmd.cmd = IOCTL_CMD_CPLD_CMD;
|
||||||
|
ioctlCmd.cpld.cmd = (uint32_t)param1;
|
||||||
|
ioctl(fdZ80, IOCTL_CMD_SEND, &ioctlCmd);
|
||||||
|
break;
|
||||||
|
case Z80_CMD_DUMP_MEMORY:
|
||||||
|
// If virtual memory, we can dump it via the shared memory segment.
|
||||||
|
if((uint8_t)param1)
|
||||||
|
{
|
||||||
|
memoryDump((uint32_t)param2, (uint32_t)param3, (uint8_t)param1, (uint8_t)param1 == 2 || (uint8_t)param1 == 3 ? 32 : 8, (uint32_t)param2, 0);
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
// Build an IOCTL command to get the driver to dump the memory.
|
||||||
|
ioctlCmd.cmd = IOCTL_CMD_DUMP_MEMORY;
|
||||||
|
ioctlCmd.addr.start = (uint32_t)param2;
|
||||||
|
ioctlCmd.addr.end = (uint32_t)param2+(uint32_t)param3;
|
||||||
|
ioctlCmd.addr.size = (uint32_t)param3;
|
||||||
|
ioctl(fdZ80, IOCTL_CMD_SEND, &ioctlCmd);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case Z80_CMD_HOST_RAM:
|
||||||
|
// Use IOCTL to request change to host RAM.
|
||||||
|
ioctlCmd.cmd = IOCTL_CMD_USE_HOST_RAM;
|
||||||
|
ioctl(fdZ80, IOCTL_CMD_SEND, &ioctlCmd);
|
||||||
|
break;
|
||||||
|
case Z80_CMD_VIRTUAL_RAM:
|
||||||
|
// Use IOCTL to request change to host RAM.
|
||||||
|
ioctlCmd.cmd = IOCTL_CMD_USE_VIRTUAL_RAM;
|
||||||
|
ioctl(fdZ80, IOCTL_CMD_SEND, &ioctlCmd);
|
||||||
|
break;
|
||||||
|
case Z80_CMD_MEMORY_TEST:
|
||||||
|
// Send command to test the SPI.
|
||||||
|
ioctlCmd.cmd = IOCTL_CMD_Z80_MEMTEST;
|
||||||
|
ioctl(fdZ80, IOCTL_CMD_SEND, &ioctlCmd);
|
||||||
|
break;
|
||||||
|
case CPLD_CMD_PRL_TEST:
|
||||||
|
// Send command to test the SPI.
|
||||||
|
ioctlCmd.cmd = IOCTL_CMD_PRL_TEST;
|
||||||
|
ioctl(fdZ80, IOCTL_CMD_SEND, &ioctlCmd);
|
||||||
|
break;
|
||||||
|
case CPLD_CMD_SPI_TEST:
|
||||||
|
// Send command to test the SPI.
|
||||||
|
ioctlCmd.cmd = IOCTL_CMD_SPI_TEST;
|
||||||
|
ioctl(fdZ80, IOCTL_CMD_SEND, &ioctlCmd);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
printf("Command not supported!\n");
|
||||||
|
ret = -1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Method to perform some simple tests on the Z80 emulator.
|
||||||
|
//
|
||||||
|
int z80test(int fdZ80)
|
||||||
|
{
|
||||||
|
// Locals.
|
||||||
|
struct ioctlCmd ioctlCmd;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
// Stop the Z80.
|
||||||
|
//
|
||||||
|
printf("Send STOP\n");
|
||||||
|
ioctlCmd.cmd = IOCTL_CMD_Z80_STOP;
|
||||||
|
ioctl(fdZ80, IOCTL_CMD_SEND, &ioctlCmd);
|
||||||
|
|
||||||
|
FILE *ptr;
|
||||||
|
ptr = fopen("/customer/mz700.rom", "rb");
|
||||||
|
if(ptr)
|
||||||
|
{
|
||||||
|
fread(&Z80Ctrl->memory, 65536, 1, ptr);
|
||||||
|
} else printf("Couldnt open file\n");
|
||||||
|
|
||||||
|
// Configure the Z80.
|
||||||
|
//
|
||||||
|
printf("Send SETPC\n");
|
||||||
|
ioctlCmd.z80.pc = 0;
|
||||||
|
ioctl(fdZ80, IOCTL_CMD_SETPC, &ioctlCmd);
|
||||||
|
|
||||||
|
memoryDump(0 , 65536, 1, 8, 0, 0);
|
||||||
|
|
||||||
|
// Start the Z80.
|
||||||
|
//
|
||||||
|
printf("Send START\n");
|
||||||
|
ioctlCmd.cmd = IOCTL_CMD_Z80_START;
|
||||||
|
ioctl(fdZ80, IOCTL_CMD_SEND, &ioctlCmd);
|
||||||
|
|
||||||
|
delay(10);
|
||||||
|
|
||||||
|
printf("Send STOP\n");
|
||||||
|
ioctlCmd.cmd = IOCTL_CMD_Z80_STOP;
|
||||||
|
ioctl(fdZ80, IOCTL_CMD_SEND, &ioctlCmd);
|
||||||
|
|
||||||
|
memoryDump(0, 65536, 1, 8, 0, 0);
|
||||||
|
out:
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Output usage screen. So mamy commands you do need to be prompted!!
|
||||||
|
void showArgs(char *progName, struct optparse *options)
|
||||||
|
{
|
||||||
|
printf("%s %s %s %s\n\n", progName, VERSION, COPYRIGHT, AUTHOR);
|
||||||
|
printf("Synopsis:\n");
|
||||||
|
printf("%s --help # This help screen.\n", progName);
|
||||||
|
printf(" --cmd <command> = RESET # Reset the Z80\n");
|
||||||
|
printf(" = STOP # Stop and power off the Z80\n");
|
||||||
|
printf(" = START # Power on and start the Z80\n");
|
||||||
|
printf(" = PAUSE # Pause running Z80\n");
|
||||||
|
printf(" = CONTINUE # Continue Z80 execution\n");
|
||||||
|
printf(" = HOSTRAM # Use HOST DRAM\n");
|
||||||
|
printf(" = VIRTRAM # Use Virtual RAM\n");
|
||||||
|
printf(" = SPEED --speed <1, 2, 4, 8, 16, 32, 64, 128> # In Virtual RAM mode, set CPU speed to base clock x factor.\n");
|
||||||
|
printf(" = LOADMZF --file <mzf filename> # Load MZF file into memory.\n");
|
||||||
|
printf(" = DUMP --addr <24bit addr> --end <24bit addr> [--size <24bit>]--virtual <0 - Host RAM, 1 = Virtual RAM, 2 = PageTable, 3 = IOPageTable>\n");
|
||||||
|
printf(" = CPLDCMD --data <32bit command> # Send adhoc 32bit command to CPLD.\n");
|
||||||
|
printf(" = Z80TEST # Perform various debugging tests\n");
|
||||||
|
printf(" = SPITEST # Perform SPI testing\n");
|
||||||
|
printf(" = PRLTEST # Perform Parallel Bus testing\n");
|
||||||
|
printf(" = Z80MEMTEST # Perform HOST memory tests.\n");
|
||||||
|
printf(" --<cmd> # Some commands can be abbreviated.\n");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
int fdZ80;
|
||||||
|
char buff[64];
|
||||||
|
char cmd[64] = { 0 };
|
||||||
|
char fileName[256] = { 0 };
|
||||||
|
int opt;
|
||||||
|
uint32_t hexData = 0;
|
||||||
|
long speedMultiplier = 1;
|
||||||
|
long startAddr = 0x0000;
|
||||||
|
long endAddr = 0x1000;
|
||||||
|
int virtualMemory = 0;
|
||||||
|
int helpFlag = 0;
|
||||||
|
int verboseFlag = 0;
|
||||||
|
|
||||||
|
// Define parameters to be processed.
|
||||||
|
struct optparse options;
|
||||||
|
static struct optparse_long long_options[] =
|
||||||
|
{
|
||||||
|
{"help", 'h', OPTPARSE_NONE},
|
||||||
|
{"cmd", 'c', OPTPARSE_REQUIRED},
|
||||||
|
{"file", 'f', OPTPARSE_REQUIRED},
|
||||||
|
{"data", 'd', OPTPARSE_REQUIRED},
|
||||||
|
{"speed", 'S', OPTPARSE_REQUIRED},
|
||||||
|
{"virtual", 'V', OPTPARSE_REQUIRED},
|
||||||
|
{"addr", 'a', OPTPARSE_REQUIRED},
|
||||||
|
{"end", 'e', OPTPARSE_REQUIRED},
|
||||||
|
{"size", 's', OPTPARSE_REQUIRED},
|
||||||
|
{"verbose", 'v', OPTPARSE_NONE},
|
||||||
|
{"dump", '1', OPTPARSE_NONE},
|
||||||
|
{"loadmzf", '2', OPTPARSE_NONE},
|
||||||
|
{"reset", '3', OPTPARSE_NONE},
|
||||||
|
{"stop", '4', OPTPARSE_NONE},
|
||||||
|
{"start", '5', OPTPARSE_NONE},
|
||||||
|
{"pause", '6', OPTPARSE_NONE},
|
||||||
|
{"continue", '7', OPTPARSE_NONE},
|
||||||
|
{"speed", '8', OPTPARSE_NONE},
|
||||||
|
{"cpldcmd", '9', OPTPARSE_NONE},
|
||||||
|
{0}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Parse the command line options.
|
||||||
|
//
|
||||||
|
optparse_init(&options, argv);
|
||||||
|
while((opt = optparse_long(&options, long_options, NULL)) != -1)
|
||||||
|
{
|
||||||
|
switch(opt)
|
||||||
|
{
|
||||||
|
// Hex data.
|
||||||
|
case 'd':
|
||||||
|
// hexData = (uint32_t)strtol(options.optarg, NULL, 0);
|
||||||
|
sscanf(options.optarg, "0x%08x", &hexData);
|
||||||
|
printf("Hex data:%08x\n", hexData);
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Start address for memory operations.
|
||||||
|
case 'a':
|
||||||
|
startAddr = strtol(options.optarg, NULL, 0);
|
||||||
|
//printf("Start Addr:%04x\n", startAddr);
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Speed multiplication factor for CPU governor when running in virtual memory.
|
||||||
|
case 'S':
|
||||||
|
speedMultiplier = strtol(options.optarg, NULL, 0);
|
||||||
|
//printf("Speed = base freq x %d\n", speedFactor);
|
||||||
|
break;
|
||||||
|
|
||||||
|
// End address for memory operations.
|
||||||
|
case 'e':
|
||||||
|
endAddr = strtol(options.optarg, NULL, 0);
|
||||||
|
//printf("End Addr:%04x\n", endAddr);
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Size instead of end address for memory operations.
|
||||||
|
case 's':
|
||||||
|
endAddr = startAddr + strtol(options.optarg, NULL, 0);
|
||||||
|
//printf("End Addr:%04x\n", endAddr);
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Virtual memory flag, 0 = host, 1 = virtual memory, 2 = page table, 3 = iopage table.
|
||||||
|
case 'V':
|
||||||
|
virtualMemory = atoi(options.optarg);
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Filename.
|
||||||
|
case 'f':
|
||||||
|
strcpy(fileName, options.optarg);
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Command to execute.
|
||||||
|
case 'c':
|
||||||
|
strcpy(cmd, options.optarg);
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Quick command flags.
|
||||||
|
case '1':
|
||||||
|
strcpy(cmd, "DUMP");
|
||||||
|
break;
|
||||||
|
case '2':
|
||||||
|
strcpy(cmd, "LOADMZF");
|
||||||
|
break;
|
||||||
|
case '3':
|
||||||
|
strcpy(cmd, "RESET");
|
||||||
|
break;
|
||||||
|
case '4':
|
||||||
|
strcpy(cmd, "STOP");
|
||||||
|
break;
|
||||||
|
case '5':
|
||||||
|
strcpy(cmd, "START");
|
||||||
|
break;
|
||||||
|
case '6':
|
||||||
|
strcpy(cmd, "PAUSE");
|
||||||
|
break;
|
||||||
|
case '7':
|
||||||
|
strcpy(cmd, "CONTINUE");
|
||||||
|
break;
|
||||||
|
case '8':
|
||||||
|
strcpy(cmd, "SPEED");
|
||||||
|
break;
|
||||||
|
case '9':
|
||||||
|
strcpy(cmd, "CPLDCMD");
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Verbose mode.
|
||||||
|
case 'v':
|
||||||
|
verboseFlag = 1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Command help needed.
|
||||||
|
case 'h':
|
||||||
|
helpFlag = 1;
|
||||||
|
showArgs(argv[0], &options);
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Unrecognised, show synopsis.
|
||||||
|
case '?':
|
||||||
|
showArgs(argv[0], &options);
|
||||||
|
printf("%s: %s\n", argv[0], options.errmsg);
|
||||||
|
return(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Open the z80drv driver and attach to its shared memory, basically the Z80 control structure which includes the virtual Z80 memory.
|
||||||
|
fdZ80 = open(DEVICE_FILENAME, O_RDWR|O_NDELAY);
|
||||||
|
if(fdZ80 >= 0)
|
||||||
|
{
|
||||||
|
Z80Ctrl = (t_Z80Ctrl *)mmap(0, sizeof(t_Z80Ctrl), PROT_READ | PROT_WRITE, MAP_SHARED, fdZ80, 0);
|
||||||
|
if(Z80Ctrl == (void *)-1)
|
||||||
|
{
|
||||||
|
printf("Failed to attach to the Z80 Control structure, cannot continue, exitting....\n");
|
||||||
|
close(fdZ80);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
printf("Failed to open the Z80 Driver, exitting...\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Basic string to method mapping. Started off with just 1 or two but has grown, may need a table!
|
||||||
|
if(strcasecmp(cmd, "LOADMZF") == 0)
|
||||||
|
{
|
||||||
|
z80load(fdZ80, fileName);
|
||||||
|
} else
|
||||||
|
if(strcasecmp(cmd, "RESET") == 0)
|
||||||
|
{
|
||||||
|
ctrlCmd(fdZ80, Z80_CMD_RESET, 0, 0, 0);
|
||||||
|
} else
|
||||||
|
if(strcasecmp(cmd, "STOP") == 0)
|
||||||
|
{
|
||||||
|
ctrlCmd(fdZ80, Z80_CMD_STOP, 0, 0, 0);
|
||||||
|
} else
|
||||||
|
if(strcasecmp(cmd, "START") == 0)
|
||||||
|
{
|
||||||
|
ctrlCmd(fdZ80, Z80_CMD_START, 0, 0, 0);
|
||||||
|
} else
|
||||||
|
if(strcasecmp(cmd, "PAUSE") == 0)
|
||||||
|
{
|
||||||
|
ctrlCmd(fdZ80, Z80_CMD_PAUSE, 0, 0, 0);
|
||||||
|
} else
|
||||||
|
if(strcasecmp(cmd, "CONTINUE") == 0)
|
||||||
|
{
|
||||||
|
ctrlCmd(fdZ80, Z80_CMD_CONTINUE, 0, 0, 0);
|
||||||
|
} else
|
||||||
|
if(strcasecmp(cmd, "SPEED") == 0)
|
||||||
|
{
|
||||||
|
ctrlCmd(fdZ80, Z80_CMD_SPEED, speedMultiplier, 0, 0);
|
||||||
|
} else
|
||||||
|
if(strcasecmp(cmd, "DUMP") == 0)
|
||||||
|
{
|
||||||
|
ctrlCmd(fdZ80, Z80_CMD_DUMP_MEMORY, virtualMemory, startAddr, (endAddr - startAddr));
|
||||||
|
} else
|
||||||
|
if(strcasecmp(cmd, "HOSTRAM") == 0)
|
||||||
|
{
|
||||||
|
ctrlCmd(fdZ80, Z80_CMD_HOST_RAM, 0, 0, 0);
|
||||||
|
} else
|
||||||
|
if(strcasecmp(cmd, "VIRTRAM") == 0)
|
||||||
|
{
|
||||||
|
ctrlCmd(fdZ80, Z80_CMD_VIRTUAL_RAM, 0, 0, 0);
|
||||||
|
} else
|
||||||
|
if(strcasecmp(cmd, "CPLDCMD") == 0)
|
||||||
|
{
|
||||||
|
ctrlCmd(fdZ80, CPLD_CMD_SEND_CMD, hexData, 0, 0);
|
||||||
|
} else
|
||||||
|
|
||||||
|
// Test methods, if the code is built-in to the driver.
|
||||||
|
if(strcasecmp(cmd, "Z80TEST") == 0)
|
||||||
|
{
|
||||||
|
z80test(fdZ80);
|
||||||
|
} else
|
||||||
|
if(strcasecmp(cmd, "SPITEST") == 0)
|
||||||
|
{
|
||||||
|
ctrlCmd(fdZ80, CPLD_CMD_SPI_TEST, 0, 0, 0);
|
||||||
|
} else
|
||||||
|
if(strcasecmp(cmd, "PRLTEST") == 0)
|
||||||
|
{
|
||||||
|
ctrlCmd(fdZ80, CPLD_CMD_PRL_TEST, 0, 0, 0);
|
||||||
|
} else
|
||||||
|
if(strcasecmp(cmd, "Z80MEMTEST") == 0)
|
||||||
|
{
|
||||||
|
ctrlCmd(fdZ80, Z80_CMD_MEMORY_TEST, 0, 0, 0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
showArgs(argv[0], &options);
|
||||||
|
printf("No command given, nothing done!\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unmap shared memory and close the device.
|
||||||
|
munmap(Z80Ctrl, sizeof(t_Z80Ctrl));
|
||||||
|
close(fdZ80);
|
||||||
|
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
1616
software/FusionX/src/driver/MZ2000/z80driver.c
Normal file
326
software/FusionX/src/driver/MZ2000/z80driver.h
Normal file
@@ -0,0 +1,326 @@
|
|||||||
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Name: z80driver.h
|
||||||
|
// Created: Oct 2022
|
||||||
|
// Author(s): Philip Smart
|
||||||
|
// Description: Z80 Driver
|
||||||
|
// This file contains the declarations used in the z80drv device driver.
|
||||||
|
//
|
||||||
|
// Credits: Zilog Z80 CPU Emulator v0.2 written by Manuel Sainz de Baranda y Goñi
|
||||||
|
// The Z80 CPU Emulator is the heart of this driver and in all ways, is compatible with
|
||||||
|
// the original Z80.
|
||||||
|
// Copyright: (c) 2019-2022 Philip Smart <philip.smart@net2net.org>
|
||||||
|
// (c) 1999-2022 Manuel Sainz de Baranda y Goñi
|
||||||
|
//
|
||||||
|
// History: Oct 2022 - Initial write of the z80 kernel driver software.
|
||||||
|
//
|
||||||
|
// Notes: See Makefile to enable/disable conditional components
|
||||||
|
//
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// This source file is free software: you can redistribute it and#or modify
|
||||||
|
// it under the terms of the GNU General Public License as published
|
||||||
|
// by the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This source file is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
#ifndef Z80DRIVER_H
|
||||||
|
#define Z80DRIVER_H
|
||||||
|
|
||||||
|
// Constants.
|
||||||
|
#define TARGET_HOST_MZ700 0
|
||||||
|
#define TARGET_HOST_MZ2000 1
|
||||||
|
#define Z80_VIRTUAL_ROM_SIZE 16384 // Sized to maximum ROM which is the MZ-800 ROM.
|
||||||
|
#define Z80_VIRTUAL_RAM_SIZE (65536 * 8) // (PAGE_SIZE * 2) // max size mmaped to userspace
|
||||||
|
#define Z80_VIRTUAL_MEMORY_SIZE Z80_VIRTUAL_RAM_SIZE + Z80_VIRTUAL_ROM_SIZE
|
||||||
|
#define Z80_MEMORY_PAGE_SIZE 16
|
||||||
|
#define MAX_SCREEN_WIDTH 132
|
||||||
|
#define DEVICE_NAME "z80drv"
|
||||||
|
#define CLASS_NAME "mogu"
|
||||||
|
|
||||||
|
// Memory and IO page types. Used to create a memory page which maps type of address space to real address space on host or virtual memory.
|
||||||
|
#define MEMORY_TYPE_VIRTUAL_MASK 0x00FFFFFF
|
||||||
|
#define MEMORY_TYPE_REAL_MASK 0x0000FFFF
|
||||||
|
#define IO_TYPE_MASK 0x0000FFFF
|
||||||
|
#define MEMORY_TYPE_INHIBIT 0x00000000
|
||||||
|
#define MEMORY_TYPE_PHYSICAL_RAM 0x80000000
|
||||||
|
#define MEMORY_TYPE_PHYSICAL_ROM 0x40000000
|
||||||
|
#define MEMORY_TYPE_PHYSICAL_VRAM 0x20000000
|
||||||
|
#define MEMORY_TYPE_PHYSICAL_HW 0x10000000
|
||||||
|
#define MEMORY_TYPE_VIRTUAL_RAM 0x08000000
|
||||||
|
#define MEMORY_TYPE_VIRTUAL_ROM 0x04000000
|
||||||
|
#define MEMORY_TYPE_VIRTUAL_HW 0x02000000
|
||||||
|
#define IO_TYPE_PHYSICAL_HW 0x80000000
|
||||||
|
#define IO_TYPE_VIRTUAL_HW 0x40000000
|
||||||
|
|
||||||
|
|
||||||
|
// Approximate governor delays to regulate emulated CPU speed.
|
||||||
|
// MZ-700
|
||||||
|
#if(TARGET_HOST_MZ700 == 1)
|
||||||
|
#define INSTRUCTION_DELAY_ROM_3_54MHZ 253
|
||||||
|
#define INSTRUCTION_DELAY_ROM_7MHZ 126
|
||||||
|
#define INSTRUCTION_DELAY_ROM_14MHZ 63
|
||||||
|
#define INSTRUCTION_DELAY_ROM_28MHZ 32
|
||||||
|
#define INSTRUCTION_DELAY_ROM_56MHZ 16
|
||||||
|
#define INSTRUCTION_DELAY_ROM_112MHZ 8
|
||||||
|
#define INSTRUCTION_DELAY_ROM_224MHZ 4
|
||||||
|
#define INSTRUCTION_DELAY_ROM_448MHZ 1
|
||||||
|
#define INSTRUCTION_DELAY_RAM_3_54MHZ 253
|
||||||
|
#define INSTRUCTION_DELAY_RAM_7MHZ 126
|
||||||
|
#define INSTRUCTION_DELAY_RAM_14MHZ 63
|
||||||
|
#define INSTRUCTION_DELAY_RAM_28MHZ 32
|
||||||
|
#define INSTRUCTION_DELAY_RAM_56MHZ 16
|
||||||
|
#define INSTRUCTION_DELAY_RAM_112MHZ 8
|
||||||
|
#define INSTRUCTION_DELAY_RAM_224MHZ 4
|
||||||
|
#define INSTRUCTION_DELAY_RAM_448MHZ 1
|
||||||
|
#endif
|
||||||
|
// MZ-2000
|
||||||
|
#if(TARGET_HOST_MZ2000 == 1)
|
||||||
|
#define INSTRUCTION_DELAY_ROM_3_54MHZ 243
|
||||||
|
#define INSTRUCTION_DELAY_ROM_7MHZ 122
|
||||||
|
#define INSTRUCTION_DELAY_ROM_14MHZ 61
|
||||||
|
#define INSTRUCTION_DELAY_ROM_28MHZ 30
|
||||||
|
#define INSTRUCTION_DELAY_ROM_56MHZ 15
|
||||||
|
#define INSTRUCTION_DELAY_ROM_112MHZ 7
|
||||||
|
#define INSTRUCTION_DELAY_ROM_224MHZ 3
|
||||||
|
#define INSTRUCTION_DELAY_ROM_448MHZ 1
|
||||||
|
#define INSTRUCTION_DELAY_RAM_3_54MHZ 218
|
||||||
|
#define INSTRUCTION_DELAY_RAM_7MHZ 112
|
||||||
|
#define INSTRUCTION_DELAY_RAM_14MHZ 56
|
||||||
|
#define INSTRUCTION_DELAY_RAM_28MHZ 28
|
||||||
|
#define INSTRUCTION_DELAY_RAM_56MHZ 14
|
||||||
|
#define INSTRUCTION_DELAY_RAM_112MHZ 7
|
||||||
|
#define INSTRUCTION_DELAY_RAM_224MHZ 3
|
||||||
|
#define INSTRUCTION_DELAY_RAM_448MHZ 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// IOCTL commands. Passed from user space using the IOCTL method to command the driver to perform an action.
|
||||||
|
#define IOCTL_CMD_Z80_STOP 's'
|
||||||
|
#define IOCTL_CMD_Z80_START 'S'
|
||||||
|
#define IOCTL_CMD_Z80_PAUSE 'P'
|
||||||
|
#define IOCTL_CMD_Z80_RESET 'R'
|
||||||
|
#define IOCTL_CMD_Z80_CONTINUE 'C'
|
||||||
|
#define IOCTL_CMD_USE_HOST_RAM 'x'
|
||||||
|
#define IOCTL_CMD_USE_VIRTUAL_RAM 'X'
|
||||||
|
#define IOCTL_CMD_DUMP_MEMORY 'M'
|
||||||
|
#define IOCTL_CMD_Z80_CPU_FREQ 'F'
|
||||||
|
#define IOCTL_CMD_CPLD_CMD 'z'
|
||||||
|
#define IOCTL_CMD_SEND _IOW('c', 'c', int32_t *)
|
||||||
|
#define IOCTL_CMD_SETPC _IOW('p', 'p', int32_t *)
|
||||||
|
#define IOCTL_CMD_SYNC_TO_HOST_RAM 'V'
|
||||||
|
#define IOCTL_CMD_SPI_TEST '1'
|
||||||
|
#define IOCTL_CMD_PRL_TEST '2'
|
||||||
|
#define IOCTL_CMD_Z80_MEMTEST '3'
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Chip Select map MZ80K-MZ700.
|
||||||
|
//
|
||||||
|
// 0000 - 0FFF = CS_ROMni : R/W : MZ80K/A/700 = Monitor ROM or RAM (MZ80A rom swap)
|
||||||
|
// 1000 - CFFF = CS_RAMni : R/W : MZ80K/A/700 = RAM
|
||||||
|
// C000 - CFFF = CS_ROMni : R/W : MZ80A = Monitor ROM (MZ80A rom swap)
|
||||||
|
// D000 - D7FF = CS_VRAMni : R/W : MZ80K/A/700 = VRAM
|
||||||
|
// D800 - DFFF = CS_VRAMni : R/W : MZ700 = Colour VRAM (MZ700)
|
||||||
|
// E000 - E003 = CS_8255n : R/W : MZ80K/A/700 = 8255
|
||||||
|
// E004 - E007 = CS_8254n : R/W : MZ80K/A/700 = 8254
|
||||||
|
// E008 - E00B = CS_LS367n : R/W : MZ80K/A/700 = LS367
|
||||||
|
// E00C - E00F = CS_ESWPn : R : MZ80A = Memory Swap (MZ80A)
|
||||||
|
// E010 - E013 = CS_ESWPn : R : MZ80A = Reset Memory Swap (MZ80A)
|
||||||
|
// E014 = CS_E5n : R/W : MZ80A/700 = Normal CRT display (in Video Controller)
|
||||||
|
// E015 = CS_E6n : R/W : MZ80A/700 = Reverse CRT display (in Video Controller)
|
||||||
|
// E200 - E2FF = : R/W : MZ80A/700 = VRAM roll up/roll down.
|
||||||
|
// E800 - EFFF = : R/W : MZ80K/A/700 = User ROM socket or DD Eprom (MZ700)
|
||||||
|
// F000 - F7FF = : R/W : MZ80K/A/700 = Floppy Disk interface.
|
||||||
|
// F800 - FFFF = : R/W : MZ80K/A/700 = Floppy Disk interface.
|
||||||
|
//
|
||||||
|
// Chip Select map MZ800
|
||||||
|
//
|
||||||
|
// FC - FF = CS_PIOn : R/W : MZ800/MZ1500 = Z80 PIO Printer Interface
|
||||||
|
// F2 = CS_PSG0n : W : MZ800/MZ1500 = Programable Sound Generator, MZ-800 = Mono, MZ-1500 = Left Channel
|
||||||
|
// F3 = CS_PSG1n : W : MZ1500 = Programable Sound Generator, MZ-1500 = Right Channel
|
||||||
|
// E9 = CS_PSG(X)n: W : MZ1500 = Simultaneous write to both PSG's.
|
||||||
|
// F0 - F1 = CS_JOYSTK : R : MZ800 = Joystick 1 and 2
|
||||||
|
// CC = CS_GWF : W : MZ800 = CRTC GWF Write format Register
|
||||||
|
// CD = CS_GRF : W : MZ800 = CRTC GRF Read format Register
|
||||||
|
// CE = CS_GDMD : W : MZ800 = CRTC GDMD Mode Register
|
||||||
|
// CF = CS_GCRTC : W : MZ800 = CRTC GCRTC Control Register
|
||||||
|
// D4 - D7 = CS
|
||||||
|
// D000 - DFFF
|
||||||
|
|
||||||
|
// MZ700/MZ800 memory mode switch?
|
||||||
|
//
|
||||||
|
// MZ-700 MZ-800
|
||||||
|
// |0000:0FFF|1000:1FFF|1000:CFFF|C000:CFFF|D000:FFFF |0000:7FFF|1000:1FFF|2000:7FFF|8000:BFFF|C000:CFFF|C000:DFFF|E000:FFFF
|
||||||
|
// -------------------------------------------------- ----------------------------------------------------------------------
|
||||||
|
// OUT 0xE0 = |DRAM | | | | |DRAM | | | | | |
|
||||||
|
// OUT 0xE1 = | | | | |DRAM | | | | | | |DRAM
|
||||||
|
// OUT 0xE2 = |MONITOR | | | | |MONITOR | | | | | |
|
||||||
|
// OUT 0xE3 = | | | | |Memory Mapped I/O | | | | | | |Upper MONITOR ROM
|
||||||
|
// OUT 0xE4 = |MONITOR | |DRAM | |Memory Mapped I/O |MONITOR |CGROM |DRAM |VRAM | |DRAM |Upper MONITOR ROM
|
||||||
|
// OUT 0xE5 = | | | | |Inhibit | | | | | | |Inhibit
|
||||||
|
// OUT 0xE6 = | | | | |<return> | | | | | | |<return>
|
||||||
|
// IN 0xE0 = | |CGROM* | |VRAM* | | |CGROM | |VRAM | | |
|
||||||
|
// IN 0xE1 = | |DRAM | |DRAM | | |<return> | |DRAM | | |
|
||||||
|
//
|
||||||
|
// <return> = Return to the state prior to the complimentary command being invoked.
|
||||||
|
// * = MZ-800 host only.
|
||||||
|
|
||||||
|
// Macros to lookup and test to see if a given memory block or IO byte is of a given type. Also macros to read/write to the memory block and IO byte.
|
||||||
|
#define MEMORY_BLOCK_GRANULARITY 0x800
|
||||||
|
#define MEMORY_BLOCK_SLOTS (0x10000 / MEMORY_BLOCK_GRANULARITY)
|
||||||
|
#define MEMORY_BLOCK_MASK (0x10000 - MEMORY_BLOCK_GRANULARITY)
|
||||||
|
#define MEMORY_BLOCK_SHIFT 11
|
||||||
|
#define getPageData(a) (Z80Ctrl->page[(a & 0xF800) >> MEMORY_BLOCK_SHIFT])
|
||||||
|
#define getIOPageData(a) (Z80Ctrl->iopage[(a & 0xFFFF])
|
||||||
|
#define getPageType(a, mask) (getPageData(a) & mask)
|
||||||
|
#define getPageAddr(a, mask) ((getPageData(a) & mask) + (a & (MEMORY_BLOCK_GRANULARITY-1)))
|
||||||
|
#define getIOPageType(a, mask) (getIOPageData(a) & mask)
|
||||||
|
#define getIOPageAddr(a, mask) (getIOPageData(a) & mask)
|
||||||
|
#define realAddress(a) (Z80Ctrl->page[getPageAddr(a, MEMORY_TYPE_REAL_MASK)])
|
||||||
|
#define realPort(a) (Z80Ctrl->iopage[a & 0xFFFF] & IO_TYPE_MASK)
|
||||||
|
#define isPhysicalRAM(a) (getPageType(a, MEMORY_TYPE_PHYSICAL_RAM))
|
||||||
|
#define isPhysicalVRAM(a) (getPageType(a, MEMORY_TYPE_PHYSICAL_VRAM))
|
||||||
|
#define isPhysicalROM(a) (getPageType(a, MEMORY_TYPE_PHYSICAL_ROM))
|
||||||
|
#define isPhysicalMemory(a) (getPageType(a, (MEMORY_TYPE_PHYSICAL_ROM | MEMORY_TYPE_PHYSICAL_RAM | MEMORY_TYPE_PHYSICAL_VRAM))])
|
||||||
|
#define isPhysicalHW(a) (getPageType(a, MEMORY_TYPE_PHYSICAL_HW))
|
||||||
|
#define isPhysical(a) (getPageType(a, (MEMORY_TYPE_PHYSICAL_HW | MEMORY_TYPE_PHYSICAL_ROM | MEMORY_TYPE_PHYSICAL_RAM | MEMORY_TYPE_PHYSICAL_VRAM)))
|
||||||
|
#define isPhysicalIO(a) (Z80Ctrl->iopage[a & 0xFFFF] & IO_TYPE_PHYSICAL_HW)
|
||||||
|
#define isVirtualRAM(a) (getPageType(a, MEMORY_TYPE_VIRTUAL_RAM))
|
||||||
|
#define isVirtualROM(a) (getPageType(a, MEMORY_TYPE_VIRTUAL_ROM))
|
||||||
|
#define isVirtualMemory(a) (getPageType(a, (MEMORY_TYPE_VIRTUAL_ROM | MEMORY_TYPE_VIRTUAL_RAM)))
|
||||||
|
#define isVirtualHW(a) (getPageType(a, MEMORY_TYPE_VIRTUAL_HW))
|
||||||
|
#define isVirtualIO(a) (Z80Ctrl->iopage[a & 0xFFFF] & IO_TYPE_VIRTUAL_HW)
|
||||||
|
#define isHW(a) (getPageType(a, (MEMORY_TYPE_PHYSICAL_HW | MEMORY_TYPE_VIRTUAL_HW)))
|
||||||
|
#define readVirtualRAM(a) (Z80Ctrl->memory[ getPageAddr(a, MEMORY_TYPE_VIRTUAL_MASK) ])
|
||||||
|
#define readVirtualROM(a) (Z80Ctrl->memory[ getPageAddr(a, MEMORY_TYPE_VIRTUAL_MASK) + Z80_VIRTUAL_RAM_SIZE ])
|
||||||
|
#define writeVirtualRAM(a, d) { Z80Ctrl->memory[ getPageAddr(a, MEMORY_TYPE_VIRTUAL_MASK) ] = d; }
|
||||||
|
#define setMemoryType(_block_,_type_,_addr_) { Z80Ctrl->page[_block_] = _type_ | _addr_; }
|
||||||
|
#define backupMemoryType(_block_) { Z80Ctrl->shadowPage[_block_] = Z80Ctrl->page[_block_]; }
|
||||||
|
#define restoreMemoryType(_block_) { Z80Ctrl->page[_block_] = Z80Ctrl->shadowPage[_block_]; }
|
||||||
|
|
||||||
|
#define IO_ADDR_E0 0xE0
|
||||||
|
#define IO_ADDR_E1 0xE1
|
||||||
|
#define IO_ADDR_E2 0xE2
|
||||||
|
#define IO_ADDR_E3 0xE3
|
||||||
|
#define IO_ADDR_E4 0xE4
|
||||||
|
#define IO_ADDR_E5 0xE5
|
||||||
|
#define IO_ADDR_E6 0xE6
|
||||||
|
#define IO_ADDR_E7 0xE7
|
||||||
|
#define IO_ADDR_E8 0xE8
|
||||||
|
#define IO_ADDR_E9 0xE9
|
||||||
|
#define IO_ADDR_EA 0xEA
|
||||||
|
#define IO_ADDR_EB 0xEB
|
||||||
|
|
||||||
|
|
||||||
|
enum Z80_RUN_STATES {
|
||||||
|
Z80_STOP = 0x00,
|
||||||
|
Z80_STOPPED = 0x01,
|
||||||
|
Z80_PAUSE = 0x02,
|
||||||
|
Z80_PAUSED = 0x03,
|
||||||
|
Z80_CONTINUE = 0x04,
|
||||||
|
Z80_RUNNING = 0x05,
|
||||||
|
};
|
||||||
|
enum Z80_MEMORY_PROFILE {
|
||||||
|
USE_PHYSICAL_RAM = 0x00,
|
||||||
|
USE_VIRTUAL_RAM = 0x01
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
// Main memory, linear but indexed as though it were banks in 1K pages.
|
||||||
|
uint8_t memory[Z80_VIRTUAL_MEMORY_SIZE];
|
||||||
|
|
||||||
|
// Page pointer map.
|
||||||
|
//
|
||||||
|
// Each pointer points to a byte or block of bytes in the Z80 Memory frame, 64K Real + Banked.
|
||||||
|
// This is currently set at a block of size 0x800 per memory pointer for the MZ-700.
|
||||||
|
// The LSB of the pointer is a direct memory index to a byte or block of bytes, the upper byte of the pointer indicates type of memory space.
|
||||||
|
// 0x80<FFFFFF> - physical host RAM
|
||||||
|
// 0x40<FFFFFF> - physical host ROM
|
||||||
|
// 0x20<FFFFFF> - physical host VRAM
|
||||||
|
// 0x10<FFFFFF> - physical host hardware
|
||||||
|
// 0x08<FFFFFF> - virtual host RAM
|
||||||
|
// 0x04<FFFFFF> - virtual host ROM
|
||||||
|
// 0x02<FFFFFF> - virtual host hardware
|
||||||
|
// 16bit Input Address -> map -> Pointer to 24bit memory address + type flag.
|
||||||
|
// -> Pointer+<low bits of address> to 24bit memory address + type flag.
|
||||||
|
uint32_t page[MEMORY_BLOCK_SLOTS];
|
||||||
|
uint32_t shadowPage[MEMORY_BLOCK_SLOTS];
|
||||||
|
|
||||||
|
// I/O Page map.
|
||||||
|
//
|
||||||
|
// This is a map to indicate the use of the I/O page and allow any required remapping.
|
||||||
|
// <0x80>FF<I/O Address> - physical host hardware
|
||||||
|
// <0x40>FF<I/O Address> - virtual host hardware
|
||||||
|
// 16bit Input Address -> map -> Actual 16bit address to use + type flag.
|
||||||
|
uint32_t iopage[65536];
|
||||||
|
|
||||||
|
// Default page mode configured. This value reflects the default page and iotable map.
|
||||||
|
uint8_t defaultPageMode;
|
||||||
|
|
||||||
|
// Refresh DRAM mode. 1 = Refresh, 0 = No refresh. Only applicable when running code in virtual Kernel RAM.
|
||||||
|
uint8_t refreshDRAM;
|
||||||
|
|
||||||
|
// Inhibit mode is where certain memory ranges are inhibitted. The memory page is set to inhibit and this flag
|
||||||
|
// blocks actions which arent allowed during inhibit.
|
||||||
|
uint8_t inhibitMode;
|
||||||
|
|
||||||
|
// Address caching. Used to minimise instruction length sent to CPLD.
|
||||||
|
uint16_t z80PrevAddr;
|
||||||
|
uint16_t z80PrevPort;
|
||||||
|
|
||||||
|
#if(TARGET_HOST_MZ2000 == 1)
|
||||||
|
uint8_t lowMemorySwap;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Keyboard strobe and data. Required to detect hotkey press.
|
||||||
|
uint8_t keyportStrobe;
|
||||||
|
uint8_t keyportShiftCtrl;
|
||||||
|
uint8_t keyportHotKey;
|
||||||
|
|
||||||
|
// Governor is the delay in a 32bit loop per Z80 opcode, used to govern execution speed when using virtual memory.
|
||||||
|
// This mechanism will eventually be tied into the M/T-state calculation for a more precise delay, but at the moment,
|
||||||
|
// with the Z80 assigned to an isolated CPU, it allows time sensitive tasks such as the tape recorder to work.
|
||||||
|
// The lower the value the faster the CPU speed. Two values are present as the optimiser, seeing ROM code not changing
|
||||||
|
// is quicker than RAM (both are in the same kernel memory) as a pointer calculation needs to be made.
|
||||||
|
uint32_t cpuGovernorDelayROM;
|
||||||
|
uint32_t cpuGovernorDelayRAM;
|
||||||
|
} t_Z80Ctrl;
|
||||||
|
|
||||||
|
// IOCTL structure for passing data from user space to driver to perform commands.
|
||||||
|
//
|
||||||
|
struct z80_addr {
|
||||||
|
uint32_t start;
|
||||||
|
uint32_t end;
|
||||||
|
uint32_t size;
|
||||||
|
};
|
||||||
|
struct z80_ctrl {
|
||||||
|
uint16_t pc;
|
||||||
|
};
|
||||||
|
struct speed {
|
||||||
|
uint32_t speedMultiplier;
|
||||||
|
};
|
||||||
|
struct cpld_ctrl {
|
||||||
|
uint32_t cmd;
|
||||||
|
};
|
||||||
|
struct ioctlCmd {
|
||||||
|
int32_t cmd;
|
||||||
|
union {
|
||||||
|
struct z80_addr addr;
|
||||||
|
struct z80_ctrl z80;
|
||||||
|
struct speed speed;
|
||||||
|
struct cpld_ctrl cpld;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// Prototypes.
|
||||||
|
void setupMemory(enum Z80_MEMORY_PROFILE mode);
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
428
software/FusionX/src/driver/MZ2000/z80io.c
Normal file
@@ -0,0 +1,428 @@
|
|||||||
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Name: z80io.c
|
||||||
|
// Created: Oct 2022
|
||||||
|
// Author(s): Philip Smart
|
||||||
|
// Description: Z80 IO Interface
|
||||||
|
// This file contains the methods used in interfacing the SOM to the Z80 socket
|
||||||
|
// and host hardware via a CPLD.
|
||||||
|
// Credits:
|
||||||
|
// Copyright: (c) 2019-2022 Philip Smart <philip.smart@net2net.org>
|
||||||
|
//
|
||||||
|
// History: Oct 2022 - Initial write of the z80 kernel driver software.
|
||||||
|
//
|
||||||
|
// Notes: See Makefile to enable/disable conditional components
|
||||||
|
//
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// This source file is free software: you can redistribute it and#or modify
|
||||||
|
// it under the terms of the GNU General Public License as published
|
||||||
|
// by the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This source file is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
|
||||||
|
//#include <stdio.h>
|
||||||
|
//#include <stdlib.h>
|
||||||
|
//#include <string.h>
|
||||||
|
#include <linux/module.h>
|
||||||
|
#include <linux/init.h>
|
||||||
|
#include <linux/kernel.h>
|
||||||
|
#include <linux/device.h>
|
||||||
|
#include <linux/fs.h>
|
||||||
|
#include <linux/mm.h>
|
||||||
|
#include <asm/uaccess.h>
|
||||||
|
#include <linux/slab.h>
|
||||||
|
#include <linux/string.h>
|
||||||
|
#include <linux/kthread.h>
|
||||||
|
#include <linux/sched.h>
|
||||||
|
#include <linux/delay.h>
|
||||||
|
#include <linux/time.h>
|
||||||
|
#include "z80io.h"
|
||||||
|
|
||||||
|
#include <gpio_table.h>
|
||||||
|
#include <asm/io.h>
|
||||||
|
#include <infinity2m/gpio.h>
|
||||||
|
#include <infinity2m/registers.h>
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// User space driver access.
|
||||||
|
//
|
||||||
|
//-------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Initialise the SOM hardware used to communicate with the z80 socket and host hardware.
|
||||||
|
// The SOM interfaces to a CPLD which provides voltage level translation and also encapsulates the Z80 timing cycles as recreating
|
||||||
|
// them within the SOM is much more tricky.
|
||||||
|
//
|
||||||
|
// As this is an embedded device and performance/latency are priorities, minimal structured code is used to keep call stack and
|
||||||
|
// generated code to a mimimum without relying on the optimiser.
|
||||||
|
int z80io_init(void)
|
||||||
|
{
|
||||||
|
// Locals.
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
// Initialise GPIO. We call the HAL api to minimise time but for actual bit set/reset and read we go directly to registers to save time, increase throughput and minimise latency.
|
||||||
|
// Initialise the HAL.
|
||||||
|
MHal_GPIO_Init();
|
||||||
|
|
||||||
|
// Set the pads as GPIO devices. The HAL takes care of allocating and deallocating the padmux resources.
|
||||||
|
MHal_GPIO_Pad_Set(PAD_Z80IO_IN_DATA_0); // Word (16bit) bidirectional bus. Default is read with data set.
|
||||||
|
MHal_GPIO_Pad_Set(PAD_Z80IO_IN_DATA_1);
|
||||||
|
MHal_GPIO_Pad_Set(PAD_Z80IO_IN_DATA_2);
|
||||||
|
MHal_GPIO_Pad_Set(PAD_Z80IO_IN_DATA_3);
|
||||||
|
MHal_GPIO_Pad_Set(PAD_Z80IO_IN_DATA_4);
|
||||||
|
MHal_GPIO_Pad_Set(PAD_Z80IO_IN_DATA_5);
|
||||||
|
MHal_GPIO_Pad_Set(PAD_Z80IO_IN_DATA_6);
|
||||||
|
MHal_GPIO_Pad_Set(PAD_Z80IO_IN_DATA_7);
|
||||||
|
MHal_GPIO_Pad_Set(PAD_Z80IO_HIGH_BYTE);
|
||||||
|
//MHal_GPIO_Pad_Set(PAD_GPIO8); // SPIO 4wire control lines setup by the spidev driver but controlled directly in this driver.
|
||||||
|
//MHal_GPIO_Pad_Set(PAD_GPIO9);
|
||||||
|
//MHal_GPIO_Pad_Set(PAD_GPIO10);
|
||||||
|
//MHal_GPIO_Pad_Set(PAD_GPIO11);
|
||||||
|
MHal_GPIO_Pad_Set(PAD_Z80IO_READY);
|
||||||
|
MHal_GPIO_Pad_Set(PAD_Z80IO_LTSTATE);
|
||||||
|
MHal_GPIO_Pad_Set(PAD_Z80IO_BUSRQ);
|
||||||
|
MHal_GPIO_Pad_Set(PAD_Z80IO_BUSACK);
|
||||||
|
MHal_GPIO_Pad_Set(PAD_Z80IO_INT);
|
||||||
|
MHal_GPIO_Pad_Set(PAD_Z80IO_NMI);
|
||||||
|
MHal_GPIO_Pad_Set(PAD_Z80IO_WAIT);
|
||||||
|
MHal_GPIO_Pad_Set(PAD_Z80IO_RESET);
|
||||||
|
MHal_GPIO_Pad_Set(PAD_Z80IO_RSV1);
|
||||||
|
#ifdef NOTNEEDED
|
||||||
|
MHal_GPIO_Pad_Set(PAD_Z80IO_OUT_DATA_0);
|
||||||
|
MHal_GPIO_Pad_Set(PAD_Z80IO_OUT_DATA_1);
|
||||||
|
MHal_GPIO_Pad_Set(PAD_Z80IO_OUT_DATA_2);
|
||||||
|
MHal_GPIO_Pad_Set(PAD_Z80IO_OUT_DATA_3);
|
||||||
|
MHal_GPIO_Pad_Set(PAD_Z80IO_OUT_DATA_4);
|
||||||
|
MHal_GPIO_Pad_Set(PAD_Z80IO_OUT_DATA_5);
|
||||||
|
MHal_GPIO_Pad_Set(PAD_Z80IO_OUT_DATA_6);
|
||||||
|
MHal_GPIO_Pad_Set(PAD_Z80IO_OUT_DATA_7);
|
||||||
|
MHal_GPIO_Pad_Set(PAD_Z80IO_WRITE);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Set required input pads.
|
||||||
|
MHal_GPIO_Pad_Odn(PAD_Z80IO_IN_DATA_0);
|
||||||
|
MHal_GPIO_Pad_Odn(PAD_Z80IO_IN_DATA_1);
|
||||||
|
MHal_GPIO_Pad_Odn(PAD_Z80IO_IN_DATA_2);
|
||||||
|
MHal_GPIO_Pad_Odn(PAD_Z80IO_IN_DATA_3);
|
||||||
|
MHal_GPIO_Pad_Odn(PAD_Z80IO_IN_DATA_4);
|
||||||
|
MHal_GPIO_Pad_Odn(PAD_Z80IO_IN_DATA_5);
|
||||||
|
MHal_GPIO_Pad_Odn(PAD_Z80IO_IN_DATA_6);
|
||||||
|
MHal_GPIO_Pad_Odn(PAD_Z80IO_IN_DATA_7);
|
||||||
|
MHal_GPIO_Pad_Odn(PAD_Z80IO_READY);
|
||||||
|
MHal_GPIO_Pad_Odn(PAD_Z80IO_LTSTATE);
|
||||||
|
MHal_GPIO_Pad_Odn(PAD_Z80IO_BUSRQ);
|
||||||
|
MHal_GPIO_Pad_Odn(PAD_Z80IO_BUSACK);
|
||||||
|
MHal_GPIO_Pad_Odn(PAD_Z80IO_INT);
|
||||||
|
MHal_GPIO_Pad_Odn(PAD_Z80IO_NMI);
|
||||||
|
MHal_GPIO_Pad_Odn(PAD_Z80IO_WAIT);
|
||||||
|
MHal_GPIO_Pad_Odn(PAD_Z80IO_RESET);
|
||||||
|
MHal_GPIO_Pad_Odn(PAD_Z80IO_RSV1);
|
||||||
|
|
||||||
|
// Set required output pads.
|
||||||
|
#ifdef NOTNEEDED
|
||||||
|
MHal_GPIO_Pad_Oen(PAD_Z80IO_OUT_DATA_0);
|
||||||
|
MHal_GPIO_Pad_Oen(PAD_Z80IO_OUT_DATA_1);
|
||||||
|
MHal_GPIO_Pad_Oen(PAD_Z80IO_OUT_DATA_2);
|
||||||
|
MHal_GPIO_Pad_Oen(PAD_Z80IO_OUT_DATA_3);
|
||||||
|
MHal_GPIO_Pad_Oen(PAD_Z80IO_OUT_DATA_4);
|
||||||
|
MHal_GPIO_Pad_Oen(PAD_Z80IO_OUT_DATA_5);
|
||||||
|
MHal_GPIO_Pad_Oen(PAD_Z80IO_OUT_DATA_6);
|
||||||
|
MHal_GPIO_Pad_Oen(PAD_Z80IO_OUT_DATA_7);
|
||||||
|
MHal_GPIO_Pad_Oen(PAD_Z80IO_WRITE);
|
||||||
|
MHal_GPIO_Pull_High(PAD_Z80IO_WRITE);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Control signals.
|
||||||
|
MHal_GPIO_Pad_Oen(PAD_Z80IO_HIGH_BYTE);
|
||||||
|
MHal_GPIO_Pull_High(PAD_Z80IO_HIGH_BYTE);
|
||||||
|
|
||||||
|
// Setup the MSPI0 device.
|
||||||
|
//
|
||||||
|
// Setup control, interrupts are not used.
|
||||||
|
MSPI_WRITE(MSPI_CTRL_OFFSET, MSPI_CPU_CLOCK_1_2 | MSPI_CTRL_CPOL_LOW | MSPI_CTRL_CPHA_HIGH | MSPI_CTRL_RESET | MSPI_CTRL_ENABLE_SPI);
|
||||||
|
|
||||||
|
// Setup LSB First mode.
|
||||||
|
MSPI_WRITE(MSPI_LSB_FIRST_OFFSET, 0x0);
|
||||||
|
|
||||||
|
// Setup clock.
|
||||||
|
CLK_WRITE(MSPI0_CLK_CFG, 0x1100)
|
||||||
|
|
||||||
|
// Setup the frame size (all buffers to 8bits).
|
||||||
|
MSPI_WRITE(MSPI_FRAME_WBIT_OFFSET, 0xfff);
|
||||||
|
MSPI_WRITE(MSPI_FRAME_WBIT_OFFSET+1, 0xfff);
|
||||||
|
MSPI_WRITE(MSPI_FRAME_RBIT_OFFSET, 0xfff);
|
||||||
|
MSPI_WRITE(MSPI_FRAME_RBIT_OFFSET+1, 0xfff);
|
||||||
|
|
||||||
|
// Setup Chip Selects to inactive.
|
||||||
|
MSPI_WRITE(MSPI_CHIP_SELECT_OFFSET, MSPI_CS8_DISABLE | MSPI_CS7_DISABLE | MSPI_CS6_DISABLE | MSPI_CS5_DISABLE | MSPI_CS4_DISABLE | MSPI_CS3_DISABLE | MSPI_CS2_DISABLE | MSPI_CS1_DISABLE);
|
||||||
|
|
||||||
|
// Switch Video and Audio to host.
|
||||||
|
z80io_SPI_Send16(0x00f0, NULL);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//--------------------------------------------------------
|
||||||
|
// Parallel bus Methods.
|
||||||
|
//--------------------------------------------------------
|
||||||
|
|
||||||
|
// Methods to read data from the parallel bus.
|
||||||
|
// The CPLD returns status and Z80 data on the 8bit bus as it is marginally quicker than retrieving it over the SPI bus.
|
||||||
|
//
|
||||||
|
inline uint8_t z80io_PRL_Read8(uint8_t dataFlag)
|
||||||
|
{
|
||||||
|
// Locals.
|
||||||
|
uint8_t result = 0;
|
||||||
|
|
||||||
|
// Byte according to flag.
|
||||||
|
if(dataFlag)
|
||||||
|
SET_CPLD_READ_DATA()
|
||||||
|
else
|
||||||
|
SET_CPLD_READ_STATUS()
|
||||||
|
|
||||||
|
// Read the input registers and set value accordingly.
|
||||||
|
result = READ_CPLD_DATA_IN();
|
||||||
|
|
||||||
|
// Return 16bit value read from CPLD.
|
||||||
|
return(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline uint16_t z80io_PRL_Read16(void)
|
||||||
|
{
|
||||||
|
// Locals.
|
||||||
|
uint16_t result = 0;
|
||||||
|
|
||||||
|
// Low byte first.
|
||||||
|
CLEAR_CPLD_HIGH_BYTE();
|
||||||
|
|
||||||
|
// Read the input registers and set value accordingly.
|
||||||
|
result = (uint16_t)READ_CPLD_DATA_IN();
|
||||||
|
|
||||||
|
// High byte next.
|
||||||
|
SET_CPLD_HIGH_BYTE();
|
||||||
|
|
||||||
|
// Read the input registers and set value accordingly.
|
||||||
|
result |= (uint16_t)(READ_CPLD_DATA_IN() << 8);
|
||||||
|
|
||||||
|
// Return 16bit value read from CPLD.
|
||||||
|
return(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Parallel Bus methods were tried and tested but due to the GPIO bits being controlled by individual registers per bit, the setup time was longer
|
||||||
|
// than the transmission time of SPI. These methods are thus deprecated and a fusion of SPI and 8bit parallel is now used.
|
||||||
|
#ifdef NOTNEEDED
|
||||||
|
inline uint8_t z80io_PRL_Send8(uint8_t txData)
|
||||||
|
{
|
||||||
|
// Locals.
|
||||||
|
//
|
||||||
|
|
||||||
|
// Low byte only.
|
||||||
|
MHal_RIU_REG(gpio_table[PAD_Z80IO_HIGH_BYTE].r_out) &= (~gpio_table[PAD_Z80IO_HIGH_BYTE ].m_out);
|
||||||
|
|
||||||
|
// Setup data.
|
||||||
|
if(txData & 0x0080) { MHal_RIU_REG(gpio_table[PAD_Z80IO_OUT_DATA_7].r_out) |= gpio_table[PAD_Z80IO_OUT_DATA_7].m_out; } else { MHal_RIU_REG(gpio_table[PAD_Z80IO_OUT_DATA_7].r_out) &= (~gpio_table[PAD_Z80IO_OUT_DATA_7].m_out); }
|
||||||
|
if(txData & 0x0040) { MHal_RIU_REG(gpio_table[PAD_Z80IO_OUT_DATA_6].r_out) |= gpio_table[PAD_Z80IO_OUT_DATA_6].m_out; } else { MHal_RIU_REG(gpio_table[PAD_Z80IO_OUT_DATA_6].r_out) &= (~gpio_table[PAD_Z80IO_OUT_DATA_6].m_out); }
|
||||||
|
if(txData & 0x0020) { MHal_RIU_REG(gpio_table[PAD_Z80IO_OUT_DATA_5].r_out) |= gpio_table[PAD_Z80IO_OUT_DATA_5].m_out; } else { MHal_RIU_REG(gpio_table[PAD_Z80IO_OUT_DATA_5].r_out) &= (~gpio_table[PAD_Z80IO_OUT_DATA_5].m_out); }
|
||||||
|
if(txData & 0x0010) { MHal_RIU_REG(gpio_table[PAD_Z80IO_OUT_DATA_4].r_out) |= gpio_table[PAD_Z80IO_OUT_DATA_4].m_out; } else { MHal_RIU_REG(gpio_table[PAD_Z80IO_OUT_DATA_4].r_out) &= (~gpio_table[PAD_Z80IO_OUT_DATA_4].m_out); }
|
||||||
|
if(txData & 0x0008) { MHal_RIU_REG(gpio_table[PAD_Z80IO_OUT_DATA_3].r_out) |= gpio_table[PAD_Z80IO_OUT_DATA_3].m_out; } else { MHal_RIU_REG(gpio_table[PAD_Z80IO_OUT_DATA_3].r_out) &= (~gpio_table[PAD_Z80IO_OUT_DATA_3].m_out); }
|
||||||
|
if(txData & 0x0004) { MHal_RIU_REG(gpio_table[PAD_Z80IO_OUT_DATA_2].r_out) |= gpio_table[PAD_Z80IO_OUT_DATA_2].m_out; } else { MHal_RIU_REG(gpio_table[PAD_Z80IO_OUT_DATA_2].r_out) &= (~gpio_table[PAD_Z80IO_OUT_DATA_2].m_out); }
|
||||||
|
if(txData & 0x0002) { MHal_RIU_REG(gpio_table[PAD_Z80IO_OUT_DATA_1].r_out) |= gpio_table[PAD_Z80IO_OUT_DATA_1].m_out; } else { MHal_RIU_REG(gpio_table[PAD_Z80IO_OUT_DATA_1].r_out) &= (~gpio_table[PAD_Z80IO_OUT_DATA_1].m_out); }
|
||||||
|
if(txData & 0x0001) { MHal_RIU_REG(gpio_table[PAD_Z80IO_OUT_DATA_0].r_out) |= gpio_table[PAD_Z80IO_OUT_DATA_0].m_out; } else { MHal_RIU_REG(gpio_table[PAD_Z80IO_OUT_DATA_0].r_out) &= (~gpio_table[PAD_Z80IO_OUT_DATA_0].m_out); }
|
||||||
|
|
||||||
|
// Clock data.
|
||||||
|
MHal_RIU_REG(gpio_table[PAD_Z80IO_WRITE].r_out) &= (~gpio_table[PAD_Z80IO_WRITE ].m_out);
|
||||||
|
MHal_RIU_REG(gpio_table[PAD_Z80IO_WRITE].r_out) |= gpio_table[PAD_Z80IO_WRITE ].m_out;
|
||||||
|
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline uint8_t z80io_PRL_Send16(uint16_t txData)
|
||||||
|
{
|
||||||
|
// Locals.
|
||||||
|
//
|
||||||
|
|
||||||
|
// Low byte first.
|
||||||
|
MHal_RIU_REG(gpio_table[PAD_Z80IO_HIGH_BYTE].r_out) &= (~gpio_table[PAD_Z80IO_HIGH_BYTE ].m_out);
|
||||||
|
|
||||||
|
// Setup data.
|
||||||
|
if(txData & 0x0080) { MHal_RIU_REG(gpio_table[PAD_Z80IO_OUT_DATA_7].r_out) |= gpio_table[PAD_Z80IO_OUT_DATA_7].m_out; } else { MHal_RIU_REG(gpio_table[PAD_Z80IO_OUT_DATA_7].r_out) &= (~gpio_table[PAD_Z80IO_OUT_DATA_7].m_out); }
|
||||||
|
if(txData & 0x0040) { MHal_RIU_REG(gpio_table[PAD_Z80IO_OUT_DATA_6].r_out) |= gpio_table[PAD_Z80IO_OUT_DATA_6].m_out; } else { MHal_RIU_REG(gpio_table[PAD_Z80IO_OUT_DATA_6].r_out) &= (~gpio_table[PAD_Z80IO_OUT_DATA_6].m_out); }
|
||||||
|
if(txData & 0x0020) { MHal_RIU_REG(gpio_table[PAD_Z80IO_OUT_DATA_5].r_out) |= gpio_table[PAD_Z80IO_OUT_DATA_5].m_out; } else { MHal_RIU_REG(gpio_table[PAD_Z80IO_OUT_DATA_5].r_out) &= (~gpio_table[PAD_Z80IO_OUT_DATA_5].m_out); }
|
||||||
|
if(txData & 0x0010) { MHal_RIU_REG(gpio_table[PAD_Z80IO_OUT_DATA_4].r_out) |= gpio_table[PAD_Z80IO_OUT_DATA_4].m_out; } else { MHal_RIU_REG(gpio_table[PAD_Z80IO_OUT_DATA_4].r_out) &= (~gpio_table[PAD_Z80IO_OUT_DATA_4].m_out); }
|
||||||
|
if(txData & 0x0008) { MHal_RIU_REG(gpio_table[PAD_Z80IO_OUT_DATA_3].r_out) |= gpio_table[PAD_Z80IO_OUT_DATA_3].m_out; } else { MHal_RIU_REG(gpio_table[PAD_Z80IO_OUT_DATA_3].r_out) &= (~gpio_table[PAD_Z80IO_OUT_DATA_3].m_out); }
|
||||||
|
if(txData & 0x0004) { MHal_RIU_REG(gpio_table[PAD_Z80IO_OUT_DATA_2].r_out) |= gpio_table[PAD_Z80IO_OUT_DATA_2].m_out; } else { MHal_RIU_REG(gpio_table[PAD_Z80IO_OUT_DATA_2].r_out) &= (~gpio_table[PAD_Z80IO_OUT_DATA_2].m_out); }
|
||||||
|
if(txData & 0x0002) { MHal_RIU_REG(gpio_table[PAD_Z80IO_OUT_DATA_1].r_out) |= gpio_table[PAD_Z80IO_OUT_DATA_1].m_out; } else { MHal_RIU_REG(gpio_table[PAD_Z80IO_OUT_DATA_1].r_out) &= (~gpio_table[PAD_Z80IO_OUT_DATA_1].m_out); }
|
||||||
|
if(txData & 0x0001) { MHal_RIU_REG(gpio_table[PAD_Z80IO_OUT_DATA_0].r_out) |= gpio_table[PAD_Z80IO_OUT_DATA_0].m_out; } else { MHal_RIU_REG(gpio_table[PAD_Z80IO_OUT_DATA_0].r_out) &= (~gpio_table[PAD_Z80IO_OUT_DATA_0].m_out); }
|
||||||
|
|
||||||
|
// Clock data.
|
||||||
|
MHal_RIU_REG(gpio_table[PAD_Z80IO_WRITE].r_out) &= (~gpio_table[PAD_Z80IO_WRITE ].m_out);
|
||||||
|
MHal_RIU_REG(gpio_table[PAD_Z80IO_WRITE].r_out) |= gpio_table[PAD_Z80IO_WRITE ].m_out;
|
||||||
|
|
||||||
|
// High byte next.
|
||||||
|
MHal_RIU_REG(gpio_table[PAD_Z80IO_HIGH_BYTE ].r_out) |= gpio_table[PAD_Z80IO_HIGH_BYTE ].m_out;
|
||||||
|
|
||||||
|
// Setup high byte.
|
||||||
|
if(txData & 0x8000) { MHal_RIU_REG(gpio_table[PAD_Z80IO_OUT_DATA_7].r_out) |= gpio_table[PAD_Z80IO_OUT_DATA_7].m_out; } else { MHal_RIU_REG(gpio_table[PAD_Z80IO_OUT_DATA_7].r_out) &= (~gpio_table[PAD_Z80IO_OUT_DATA_7].m_out); }
|
||||||
|
if(txData & 0x4000) { MHal_RIU_REG(gpio_table[PAD_Z80IO_OUT_DATA_6].r_out) |= gpio_table[PAD_Z80IO_OUT_DATA_6].m_out; } else { MHal_RIU_REG(gpio_table[PAD_Z80IO_OUT_DATA_6].r_out) &= (~gpio_table[PAD_Z80IO_OUT_DATA_6].m_out); }
|
||||||
|
if(txData & 0x2000) { MHal_RIU_REG(gpio_table[PAD_Z80IO_OUT_DATA_5].r_out) |= gpio_table[PAD_Z80IO_OUT_DATA_5].m_out; } else { MHal_RIU_REG(gpio_table[PAD_Z80IO_OUT_DATA_5].r_out) &= (~gpio_table[PAD_Z80IO_OUT_DATA_5].m_out); }
|
||||||
|
if(txData & 0x1000) { MHal_RIU_REG(gpio_table[PAD_Z80IO_OUT_DATA_4].r_out) |= gpio_table[PAD_Z80IO_OUT_DATA_4].m_out; } else { MHal_RIU_REG(gpio_table[PAD_Z80IO_OUT_DATA_4].r_out) &= (~gpio_table[PAD_Z80IO_OUT_DATA_4].m_out); }
|
||||||
|
if(txData & 0x0800) { MHal_RIU_REG(gpio_table[PAD_Z80IO_OUT_DATA_3].r_out) |= gpio_table[PAD_Z80IO_OUT_DATA_3].m_out; } else { MHal_RIU_REG(gpio_table[PAD_Z80IO_OUT_DATA_3].r_out) &= (~gpio_table[PAD_Z80IO_OUT_DATA_3].m_out); }
|
||||||
|
if(txData & 0x0400) { MHal_RIU_REG(gpio_table[PAD_Z80IO_OUT_DATA_2].r_out) |= gpio_table[PAD_Z80IO_OUT_DATA_2].m_out; } else { MHal_RIU_REG(gpio_table[PAD_Z80IO_OUT_DATA_2].r_out) &= (~gpio_table[PAD_Z80IO_OUT_DATA_2].m_out); }
|
||||||
|
if(txData & 0x0200) { MHal_RIU_REG(gpio_table[PAD_Z80IO_OUT_DATA_1].r_out) |= gpio_table[PAD_Z80IO_OUT_DATA_1].m_out; } else { MHal_RIU_REG(gpio_table[PAD_Z80IO_OUT_DATA_1].r_out) &= (~gpio_table[PAD_Z80IO_OUT_DATA_1].m_out); }
|
||||||
|
if(txData & 0x0100) { MHal_RIU_REG(gpio_table[PAD_Z80IO_OUT_DATA_0].r_out) |= gpio_table[PAD_Z80IO_OUT_DATA_0].m_out; } else { MHal_RIU_REG(gpio_table[PAD_Z80IO_OUT_DATA_0].r_out) &= (~gpio_table[PAD_Z80IO_OUT_DATA_0].m_out); }
|
||||||
|
|
||||||
|
// Clock data.
|
||||||
|
MHal_RIU_REG(gpio_table[PAD_Z80IO_WRITE].r_out) &= (~gpio_table[PAD_Z80IO_WRITE ].m_out);
|
||||||
|
MHal_RIU_REG(gpio_table[PAD_Z80IO_WRITE].r_out) |= gpio_table[PAD_Z80IO_WRITE ].m_out;
|
||||||
|
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
//--------------------------------------------------------
|
||||||
|
// SPI Methods.
|
||||||
|
//--------------------------------------------------------
|
||||||
|
|
||||||
|
// Methods to send 8,16 or 32 bits. Each method is seperate to minimise logic and execution time, 8bit being most sensitive.
|
||||||
|
// Macros have also been defined for inline inclusion which dont read back the response data.
|
||||||
|
//
|
||||||
|
uint8_t z80io_SPI_Send8(uint8_t txData, uint8_t *rxData)
|
||||||
|
{
|
||||||
|
// Locals.
|
||||||
|
uint32_t timeout = MAX_CHECK_CNT;
|
||||||
|
|
||||||
|
// Insert data into write buffers.
|
||||||
|
MSPI_WRITE(MSPI_WRITE_BUF_OFFSET, (uint16_t)txData);
|
||||||
|
MSPI_WRITE(MSPI_WBF_SIZE_OFFSET, 1);
|
||||||
|
|
||||||
|
// Enable SPI select.
|
||||||
|
MSPI_WRITE(MSPI_CHIP_SELECT_OFFSET, MSPI_CS8_DISABLE | MSPI_CS7_DISABLE | MSPI_CS6_DISABLE | MSPI_CS5_DISABLE | MSPI_CS4_DISABLE | MSPI_CS3_DISABLE | MSPI_CS2_DISABLE | MSPI_CS1_ENABLE);
|
||||||
|
|
||||||
|
// Send.
|
||||||
|
MSPI_WRITE(MSPI_TRIGGER_OFFSET, MSPI_TRIGGER);
|
||||||
|
|
||||||
|
// Wait for completion.
|
||||||
|
while((MSPI_READ(MSPI_DONE_OFFSET) & MSPI_DONE_FLAG) == 0)
|
||||||
|
{
|
||||||
|
if(--timeout == 0)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Disable SPI select.
|
||||||
|
MSPI_WRITE(MSPI_CHIP_SELECT_OFFSET, MSPI_CS8_DISABLE | MSPI_CS7_DISABLE | MSPI_CS6_DISABLE | MSPI_CS5_DISABLE | MSPI_CS4_DISABLE | MSPI_CS3_DISABLE | MSPI_CS2_DISABLE | MSPI_CS1_DISABLE);
|
||||||
|
|
||||||
|
// Clear flag.
|
||||||
|
MSPI_WRITE(MSPI_DONE_CLEAR_OFFSET, MSPI_CLEAR_DONE);
|
||||||
|
|
||||||
|
// Fetch data.
|
||||||
|
if(rxData != NULL) *rxData = (uint8_t)MSPI_READ(MSPI_FULL_DEPLUX_RD00);
|
||||||
|
|
||||||
|
// Done.
|
||||||
|
return(timeout == 0);
|
||||||
|
}
|
||||||
|
uint8_t z80io_SPI_Send16(uint16_t txData, uint16_t *rxData)
|
||||||
|
{
|
||||||
|
// Locals.
|
||||||
|
uint32_t timeout = MAX_CHECK_CNT;
|
||||||
|
|
||||||
|
// Insert data into write buffers.
|
||||||
|
MSPI_WRITE(MSPI_WRITE_BUF_OFFSET, txData);
|
||||||
|
MSPI_WRITE(MSPI_WBF_SIZE_OFFSET, 2);
|
||||||
|
|
||||||
|
// Enable SPI select.
|
||||||
|
MSPI_WRITE(MSPI_CHIP_SELECT_OFFSET, MSPI_CS8_DISABLE | MSPI_CS7_DISABLE | MSPI_CS6_DISABLE | MSPI_CS5_DISABLE | MSPI_CS4_DISABLE | MSPI_CS3_DISABLE | MSPI_CS2_DISABLE | MSPI_CS1_ENABLE);
|
||||||
|
|
||||||
|
// Send.
|
||||||
|
MSPI_WRITE(MSPI_TRIGGER_OFFSET, MSPI_TRIGGER);
|
||||||
|
|
||||||
|
// Wait for completion.
|
||||||
|
while((MSPI_READ(MSPI_DONE_OFFSET) & MSPI_DONE_FLAG) == 0)
|
||||||
|
{
|
||||||
|
if(--timeout == 0)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Disable SPI select.
|
||||||
|
MSPI_WRITE(MSPI_CHIP_SELECT_OFFSET, MSPI_CS8_DISABLE | MSPI_CS7_DISABLE | MSPI_CS6_DISABLE | MSPI_CS5_DISABLE | MSPI_CS4_DISABLE | MSPI_CS3_DISABLE | MSPI_CS2_DISABLE | MSPI_CS1_DISABLE);
|
||||||
|
|
||||||
|
// Clear flag.
|
||||||
|
MSPI_WRITE(MSPI_DONE_CLEAR_OFFSET, MSPI_CLEAR_DONE);
|
||||||
|
|
||||||
|
// Fetch data.
|
||||||
|
if(rxData != NULL) *rxData = MSPI_READ(MSPI_FULL_DEPLUX_RD00);
|
||||||
|
|
||||||
|
// Done.
|
||||||
|
return(timeout == 0);
|
||||||
|
}
|
||||||
|
uint8_t z80io_SPI_Send32(uint32_t txData, uint32_t *rxData)
|
||||||
|
{
|
||||||
|
// Locals.
|
||||||
|
uint32_t timeout = MAX_CHECK_CNT;
|
||||||
|
|
||||||
|
// Insert data into write buffers.
|
||||||
|
MSPI_WRITE(MSPI_WRITE_BUF_OFFSET, (uint16_t)txData);
|
||||||
|
MSPI_WRITE(MSPI_WRITE_BUF_OFFSET+1, (uint16_t)(txData >> 16));
|
||||||
|
MSPI_WRITE(MSPI_WBF_SIZE_OFFSET, 4);
|
||||||
|
|
||||||
|
// Enable SPI select.
|
||||||
|
MSPI_WRITE(MSPI_CHIP_SELECT_OFFSET, MSPI_CS8_DISABLE | MSPI_CS7_DISABLE | MSPI_CS6_DISABLE | MSPI_CS5_DISABLE | MSPI_CS4_DISABLE | MSPI_CS3_DISABLE | MSPI_CS2_DISABLE | MSPI_CS1_ENABLE);
|
||||||
|
|
||||||
|
// Send.
|
||||||
|
MSPI_WRITE(MSPI_TRIGGER_OFFSET, MSPI_TRIGGER);
|
||||||
|
|
||||||
|
// Wait for completion.
|
||||||
|
while((MSPI_READ(MSPI_DONE_OFFSET) & MSPI_DONE_FLAG) == 0)
|
||||||
|
{
|
||||||
|
if(--timeout == 0)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Disable SPI select.
|
||||||
|
MSPI_WRITE(MSPI_CHIP_SELECT_OFFSET, MSPI_CS8_DISABLE | MSPI_CS7_DISABLE | MSPI_CS6_DISABLE | MSPI_CS5_DISABLE | MSPI_CS4_DISABLE | MSPI_CS3_DISABLE | MSPI_CS2_DISABLE | MSPI_CS1_DISABLE);
|
||||||
|
|
||||||
|
// Clear flag.
|
||||||
|
MSPI_WRITE(MSPI_DONE_CLEAR_OFFSET, MSPI_CLEAR_DONE);
|
||||||
|
|
||||||
|
// Fetch data.
|
||||||
|
if(rxData != NULL) *rxData = (uint32_t)(MSPI_READ(MSPI_FULL_DEPLUX_RD00) | (MSPI_READ(MSPI_FULL_DEPLUX_RD02) << 16));
|
||||||
|
|
||||||
|
// Done.
|
||||||
|
return(timeout == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------
|
||||||
|
// Test Methods.
|
||||||
|
//--------------------------------------------------------
|
||||||
|
#ifdef INCLUDE_TEST_METHODS
|
||||||
|
#include "z80io_test.c"
|
||||||
|
#else
|
||||||
|
uint8_t z80io_Z80_TestMemory(void)
|
||||||
|
{
|
||||||
|
pr_info("Z80 Test Memory functionality not built-in.\n");
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
uint8_t z80io_SPI_Test(void)
|
||||||
|
{
|
||||||
|
pr_info("SPI Test functionality not built-in.\n");
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
uint8_t z80io_PRL_Test(void)
|
||||||
|
{
|
||||||
|
pr_info("Parallel Bus Test functionality not built-in.\n");
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
483
software/FusionX/src/driver/MZ2000/z80io.h
Executable file
@@ -0,0 +1,483 @@
|
|||||||
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Name: z80io.h
|
||||||
|
// Created: Oct 2022
|
||||||
|
// Author(s): Philip Smart
|
||||||
|
// Description: Z80 IO Interface
|
||||||
|
// This file contains the declarations used in interfacing the SOM to the Z80 socket
|
||||||
|
// and host hardware via a CPLD.
|
||||||
|
// Credits:
|
||||||
|
// Copyright: (c) 2019-2022 Philip Smart <philip.smart@net2net.org>
|
||||||
|
//
|
||||||
|
// History: Oct 2022 - Initial write of the z80 kernel driver software.
|
||||||
|
//
|
||||||
|
// Notes: See Makefile to enable/disable conditional components
|
||||||
|
//
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// This source file is free software: you can redistribute it and#or modify
|
||||||
|
// it under the terms of the GNU General Public License as published
|
||||||
|
// by the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This source file is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
#ifndef Z80IO_H
|
||||||
|
#define Z80IO_H
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Definitions to control compilation.
|
||||||
|
#define INCLUDE_TEST_METHODS 1
|
||||||
|
|
||||||
|
// CPLD Commands.
|
||||||
|
#define CPLD_CMD_FETCH_ADDR 0x10
|
||||||
|
#define CPLD_CMD_FETCH_ADDR_P1 0x11
|
||||||
|
#define CPLD_CMD_FETCH_ADDR_P2 0x12
|
||||||
|
#define CPLD_CMD_FETCH_ADDR_P3 0x13
|
||||||
|
#define CPLD_CMD_FETCH_ADDR_P4 0x14
|
||||||
|
#define CPLD_CMD_FETCH_ADDR_P5 0x15
|
||||||
|
#define CPLD_CMD_FETCH_ADDR_P6 0x16
|
||||||
|
#define CPLD_CMD_FETCH_ADDR_P7 0x17
|
||||||
|
#define CPLD_CMD_WRITE_ADDR 0x18
|
||||||
|
#define CPLD_CMD_WRITE_ADDR_P1 0x19
|
||||||
|
#define CPLD_CMD_WRITE_ADDR_P2 0x1A
|
||||||
|
#define CPLD_CMD_WRITE_ADDR_P3 0x1B
|
||||||
|
#define CPLD_CMD_WRITE_ADDR_P4 0x1C
|
||||||
|
#define CPLD_CMD_WRITE_ADDR_P5 0x1D
|
||||||
|
#define CPLD_CMD_WRITE_ADDR_P6 0x1E
|
||||||
|
#define CPLD_CMD_WRITE_ADDR_P7 0x1F
|
||||||
|
#define CPLD_CMD_READ_ADDR 0x20
|
||||||
|
#define CPLD_CMD_READ_ADDR_P1 0x21
|
||||||
|
#define CPLD_CMD_READ_ADDR_P2 0x22
|
||||||
|
#define CPLD_CMD_READ_ADDR_P3 0x23
|
||||||
|
#define CPLD_CMD_READ_ADDR_P4 0x24
|
||||||
|
#define CPLD_CMD_READ_ADDR_P5 0x25
|
||||||
|
#define CPLD_CMD_READ_ADDR_P6 0x26
|
||||||
|
#define CPLD_CMD_READ_ADDR_P7 0x27
|
||||||
|
#define CPLD_CMD_WRITEIO_ADDR 0x28
|
||||||
|
#define CPLD_CMD_WRITEIO_ADDR_P1 0x29
|
||||||
|
#define CPLD_CMD_WRITEIO_ADDR_P2 0x2A
|
||||||
|
#define CPLD_CMD_WRITEIO_ADDR_P3 0x2B
|
||||||
|
#define CPLD_CMD_WRITEIO_ADDR_P4 0x2C
|
||||||
|
#define CPLD_CMD_WRITEIO_ADDR_P5 0x2D
|
||||||
|
#define CPLD_CMD_WRITEIO_ADDR_P6 0x2E
|
||||||
|
#define CPLD_CMD_WRITEIO_ADDR_P7 0x2F
|
||||||
|
#define CPLD_CMD_READIO_ADDR 0x30
|
||||||
|
#define CPLD_CMD_READIO_ADDR_P1 0x31
|
||||||
|
#define CPLD_CMD_READIO_ADDR_P2 0x32
|
||||||
|
#define CPLD_CMD_READIO_ADDR_P3 0x33
|
||||||
|
#define CPLD_CMD_READIO_ADDR_P4 0x34
|
||||||
|
#define CPLD_CMD_READIO_ADDR_P5 0x35
|
||||||
|
#define CPLD_CMD_READIO_ADDR_P6 0x36
|
||||||
|
#define CPLD_CMD_READIO_ADDR_P7 0x37
|
||||||
|
#define CPLD_CMD_HALT 0x50
|
||||||
|
#define CPLD_CMD_REFRESH 0x51
|
||||||
|
#define CPLD_CMD_SET_SIGROUP1 0xF0
|
||||||
|
#define CPLD_CMD_SET_AUTO_REFRESH 0xF1
|
||||||
|
#define CPLD_CMD_CLEAR_AUTO_REFRESH 0xF2
|
||||||
|
#define CPLD_CMD_SET_SPI_LOOPBACK 0xFE
|
||||||
|
#define CPLD_CMD_NOP1 0x00
|
||||||
|
#define CPLD_CMD_NOP2 0xFF
|
||||||
|
|
||||||
|
|
||||||
|
// Pad numbers for using the MHal GPIO library.
|
||||||
|
#define PAD_Z80IO_IN_DATA_0 PAD_GPIO0
|
||||||
|
#define PAD_Z80IO_IN_DATA_1 PAD_GPIO1
|
||||||
|
#define PAD_Z80IO_IN_DATA_2 PAD_GPIO2
|
||||||
|
#define PAD_Z80IO_IN_DATA_3 PAD_GPIO3
|
||||||
|
#define PAD_Z80IO_IN_DATA_4 PAD_GPIO4
|
||||||
|
#define PAD_Z80IO_IN_DATA_5 PAD_GPIO5
|
||||||
|
#define PAD_Z80IO_IN_DATA_6 PAD_GPIO6
|
||||||
|
#define PAD_Z80IO_IN_DATA_7 PAD_GPIO7
|
||||||
|
#define PAD_SPIO_0 PAD_GPIO8
|
||||||
|
#define PAD_SPIO_1 PAD_GPIO9
|
||||||
|
#define PAD_SPIO_2 PAD_GPIO10
|
||||||
|
#define PAD_SPIO_3 PAD_GPIO11
|
||||||
|
#define PAD_Z80IO_HIGH_BYTE PAD_SAR_GPIO2 // Byte requiured, 0 = Low Byte, 1 = High Byte.
|
||||||
|
#define PAD_Z80IO_READY PAD_GPIO12
|
||||||
|
#define PAD_Z80IO_LTSTATE PAD_PM_IRIN // IRIN
|
||||||
|
#define PAD_Z80IO_BUSRQ PAD_GPIO13
|
||||||
|
#define PAD_Z80IO_BUSACK PAD_GPIO14
|
||||||
|
#define PAD_Z80IO_INT PAD_UART0_RX // GPIO47
|
||||||
|
#define PAD_Z80IO_NMI PAD_UART0_TX // GPIO48
|
||||||
|
#define PAD_Z80IO_WAIT PAD_HSYNC_OUT // GPIO85
|
||||||
|
#define PAD_Z80IO_RESET PAD_VSYNC_OUT // GPIO86
|
||||||
|
#define PAD_Z80IO_RSV1 PAD_SATA_GPIO // GPIO90
|
||||||
|
|
||||||
|
// Physical register addresses.
|
||||||
|
#define PAD_Z80IO_IN_DATA_0_ADDR 0x103C00
|
||||||
|
#define PAD_Z80IO_IN_DATA_1_ADDR 0x103C02
|
||||||
|
#define PAD_Z80IO_IN_DATA_2_ADDR 0x103C04
|
||||||
|
#define PAD_Z80IO_IN_DATA_3_ADDR 0x103C06
|
||||||
|
#define PAD_Z80IO_IN_DATA_4_ADDR 0x103C08
|
||||||
|
#define PAD_Z80IO_IN_DATA_5_ADDR 0x103C0A
|
||||||
|
#define PAD_Z80IO_IN_DATA_6_ADDR 0x103C0C
|
||||||
|
#define PAD_Z80IO_IN_DATA_7_ADDR 0x103C0E
|
||||||
|
#define PAD_SPIO_0_ADDR 0x103C10
|
||||||
|
#define PAD_SPIO_1_ADDR 0x103C12
|
||||||
|
#define PAD_SPIO_2_ADDR 0x103C14
|
||||||
|
#define PAD_SPIO_3_ADDR 0x103C16
|
||||||
|
#define PAD_Z80IO_HIGH_BYTE_ADDR 0x1425
|
||||||
|
#define PAD_Z80IO_READY_ADDR 0x103C18
|
||||||
|
#define PAD_Z80IO_LTSTATE_ADDR 0xF28 // IRIN
|
||||||
|
#define PAD_Z80IO_BUSRQ_ADDR 0x103C1A
|
||||||
|
#define PAD_Z80IO_BUSACK_ADDR 0x103C1C
|
||||||
|
#define PAD_Z80IO_INT_ADDR 0x103C30 // GPIO47
|
||||||
|
#define PAD_Z80IO_NMI_ADDR 0x103C32 // GPIO48
|
||||||
|
#define PAD_Z80IO_WAIT_ADDR 0x103C80 // GPIO85
|
||||||
|
#define PAD_Z80IO_RESET_ADDR 0x103C82 // GPIO86
|
||||||
|
#define PAD_Z80IO_RSV1_ADDR 0x103C8A // GPIO90
|
||||||
|
|
||||||
|
#ifdef NOTNEEDED
|
||||||
|
#define PAD_Z80IO_OUT_DATA_0 PAD_GPIO12
|
||||||
|
#define PAD_Z80IO_OUT_DATA_1 PAD_GPIO13
|
||||||
|
#define PAD_Z80IO_OUT_DATA_2 PAD_GPIO14
|
||||||
|
#define PAD_Z80IO_OUT_DATA_3 PAD_UART0_RX // GPIO47
|
||||||
|
#define PAD_Z80IO_OUT_DATA_4 PAD_UART0_TX // GPIO48
|
||||||
|
#define PAD_Z80IO_OUT_DATA_5 PAD_HSYNC_OUT // GPIO85
|
||||||
|
#define PAD_Z80IO_OUT_DATA_6 PAD_VSYNC_OUT // GPIO86
|
||||||
|
#define PAD_Z80IO_OUT_DATA_7 PAD_SATA_GPIO // GPIO90
|
||||||
|
#define PAD_Z80IO_WRITE PAD_PM_IRIN // Write data clock.
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------------------------------
|
||||||
|
// The definitions below come from SigmaStar kernel drivers. No header file exists hence the
|
||||||
|
// duplication.
|
||||||
|
//-------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#define SUPPORT_SPI_1 0
|
||||||
|
#define MAX_SUPPORT_BITS 16
|
||||||
|
|
||||||
|
#define BANK_TO_ADDR32(b) (b<<9)
|
||||||
|
#define BANK_SIZE 0x200
|
||||||
|
|
||||||
|
#define MS_BASE_REG_RIU_PA 0x1F000000
|
||||||
|
#define gChipBaseAddr 0xFD203C00
|
||||||
|
#define gPmSleepBaseAddr 0xFD001C00
|
||||||
|
#define gSarBaseAddr 0xFD002800
|
||||||
|
#define gRIUBaseAddr 0xFD000000
|
||||||
|
#define gMOVDMAAddr 0xFD201600
|
||||||
|
#define gClkBaseAddr 0xFD207000
|
||||||
|
#define gMspBaseAddr 0xfd222000
|
||||||
|
|
||||||
|
#define MHal_CHIPTOP_REG(addr) (*(volatile U8*)((gChipBaseAddr) + (((addr) & ~1)<<1) + (addr & 1)))
|
||||||
|
#define MHal_PM_SLEEP_REG(addr) (*(volatile U8*)((gPmSleepBaseAddr) + (((addr) & ~1)<<1) + (addr & 1)))
|
||||||
|
#define MHal_SAR_GPIO_REG(addr) (*(volatile U8*)((gSarBaseAddr) + (((addr) & ~1)<<1) + (addr & 1)))
|
||||||
|
#define MHal_RIU_REG(addr) (*(volatile U8*)((gRIUBaseAddr) + (((addr) & ~1)<<1) + (addr & 1)))
|
||||||
|
|
||||||
|
|
||||||
|
#define MSPI0_BANK_ADDR 0x1110
|
||||||
|
#define MSPI1_BANK_ADDR 0x1111
|
||||||
|
#define CLK__BANK_ADDR 0x1038
|
||||||
|
#define CHIPTOP_BANK_ADDR 0x101E
|
||||||
|
#define MOVDMA_BANK_ADDR 0x100B
|
||||||
|
|
||||||
|
#define BASE_REG_MSPI0_ADDR MSPI0_BANK_ADDR*0x200 //GET_BASE_ADDR_BY_BANK(IO_ADDRESS(MS_BASE_REG_RIU_PA), 0x111000)
|
||||||
|
#define BASE_REG_MSPI1_ADDR MSPI1_BANK_ADDR*0x200 //GET_BASE_ADDR_BY_BANK(IO_ADDRESS(MS_BASE_REG_RIU_PA), 0x111100)
|
||||||
|
#define BASE_REG_CLK_ADDR CLK__BANK_ADDR*0x200 //GET_BASE_ADDR_BY_BANK(IO_ADDRESS(MS_BASE_REG_RIU_PA), 0x103800)
|
||||||
|
#define BASE_REG_CHIPTOP_ADDR CHIPTOP_BANK_ADDR*0x200 //GET_BASE_ADDR_BY_BANK(IO_ADDRESS(MS_BASE_REG_RIU_PA), 0x101E00)
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------------------------------
|
||||||
|
// Hardware Register Capability
|
||||||
|
//-------------------------------------------------------------------------------------------------
|
||||||
|
#define MSPI_WRITE_BUF_OFFSET 0x40
|
||||||
|
#define MSPI_READ_BUF_OFFSET 0x44
|
||||||
|
#define MSPI_WBF_SIZE_OFFSET 0x48
|
||||||
|
#define MSPI_RBF_SIZE_OFFSET 0x48
|
||||||
|
// read/ write buffer size
|
||||||
|
#define MSPI_RWSIZE_MASK 0xFF
|
||||||
|
#define MSPI_RSIZE_BIT_OFFSET 0x8
|
||||||
|
#define MAX_READ_BUF_SIZE 0x8
|
||||||
|
#define MAX_WRITE_BUF_SIZE 0x8
|
||||||
|
// CLK config
|
||||||
|
#define MSPI_CTRL_OFFSET 0x49
|
||||||
|
#define MSPI_CLK_CLOCK_OFFSET 0x49
|
||||||
|
#define MSPI_CLK_CLOCK_BIT_OFFSET 0x08
|
||||||
|
#define MSPI_CLK_CLOCK_MASK 0xFF
|
||||||
|
#define MSPI_CLK_PHASE_MASK 0x40
|
||||||
|
#define MSPI_CLK_PHASE_BIT_OFFSET 0x06
|
||||||
|
#define MSPI_CLK_POLARITY_MASK 0x80
|
||||||
|
#define MSPI_CLK_POLARITY_BIT_OFFSET 0x07
|
||||||
|
#define MSPI_CLK_PHASE_MAX 0x1
|
||||||
|
#define MSPI_CLK_POLARITY_MAX 0x1
|
||||||
|
#define MSPI_CLK_CLOCK_MAX 0x7
|
||||||
|
#define MSPI_CTRL_CPOL_LOW 0x00
|
||||||
|
#define MSPI_CTRL_CPOL_HIGH 0x80
|
||||||
|
#define MSPI_CTRL_CPHA_LOW 0x00
|
||||||
|
#define MSPI_CTRL_CPHA_HIGH 0x40
|
||||||
|
#define MSPI_CTRL_3WIRE 0x10
|
||||||
|
#define MSPI_CTRL_INTEN 0x04
|
||||||
|
#define MSPI_CTRL_RESET 0x02
|
||||||
|
#define MSPI_CTRL_ENABLE_SPI 0x01
|
||||||
|
// DC config
|
||||||
|
#define MSPI_DC_MASK 0xFF
|
||||||
|
#define MSPI_DC_BIT_OFFSET 0x08
|
||||||
|
#define MSPI_DC_TR_START_OFFSET 0x4A
|
||||||
|
#define MSPI_DC_TRSTART_MAX 0xFF
|
||||||
|
#define MSPI_DC_TR_END_OFFSET 0x4A
|
||||||
|
#define MSPI_DC_TREND_MAX 0xFF
|
||||||
|
#define MSPI_DC_TB_OFFSET 0x4B
|
||||||
|
#define MSPI_DC_TB_MAX 0xFF
|
||||||
|
#define MSPI_DC_TRW_OFFSET 0x4B
|
||||||
|
#define MSPI_DC_TRW_MAX 0xFF
|
||||||
|
// Frame Config
|
||||||
|
#define MSPI_FRAME_WBIT_OFFSET 0x4C
|
||||||
|
#define MSPI_FRAME_RBIT_OFFSET 0x4E
|
||||||
|
#define MSPI_FRAME_BIT_MAX 0x07
|
||||||
|
#define MSPI_FRAME_BIT_MASK 0x07
|
||||||
|
#define MSPI_FRAME_BIT_FIELD 0x03
|
||||||
|
#define MSPI_LSB_FIRST_OFFSET 0x50
|
||||||
|
#define MSPI_TRIGGER_OFFSET 0x5A
|
||||||
|
#define MSPI_DONE_OFFSET 0x5B
|
||||||
|
#define MSPI_DONE_CLEAR_OFFSET 0x5C
|
||||||
|
#define MSPI_CHIP_SELECT_OFFSET 0x5F
|
||||||
|
#define MSPI_CS1_DISABLE 0x01
|
||||||
|
#define MSPI_CS1_ENABLE 0x00
|
||||||
|
#define MSPI_CS2_DISABLE 0x02
|
||||||
|
#define MSPI_CS2_ENABLE 0x00
|
||||||
|
#define MSPI_CS3_DISABLE 0x04
|
||||||
|
#define MSPI_CS3_ENABLE 0x00
|
||||||
|
#define MSPI_CS4_DISABLE 0x08
|
||||||
|
#define MSPI_CS4_ENABLE 0x00
|
||||||
|
#define MSPI_CS5_DISABLE 0x10
|
||||||
|
#define MSPI_CS5_ENABLE 0x00
|
||||||
|
#define MSPI_CS6_DISABLE 0x20
|
||||||
|
#define MSPI_CS6_ENABLE 0x00
|
||||||
|
#define MSPI_CS7_DISABLE 0x40
|
||||||
|
#define MSPI_CS7_ENABLE 0x00
|
||||||
|
#define MSPI_CS8_DISABLE 0x80
|
||||||
|
#define MSPI_CS8_ENABLE 0x00
|
||||||
|
|
||||||
|
#define MSPI_FULL_DEPLUX_RD_CNT (0x77)
|
||||||
|
#define MSPI_FULL_DEPLUX_RD00 (0x78)
|
||||||
|
#define MSPI_FULL_DEPLUX_RD01 (0x78)
|
||||||
|
#define MSPI_FULL_DEPLUX_RD02 (0x79)
|
||||||
|
#define MSPI_FULL_DEPLUX_RD03 (0x79)
|
||||||
|
#define MSPI_FULL_DEPLUX_RD04 (0x7a)
|
||||||
|
#define MSPI_FULL_DEPLUX_RD05 (0x7a)
|
||||||
|
#define MSPI_FULL_DEPLUX_RD06 (0x7b)
|
||||||
|
#define MSPI_FULL_DEPLUX_RD07 (0x7b)
|
||||||
|
|
||||||
|
#define MSPI_FULL_DEPLUX_RD08 (0x7c)
|
||||||
|
#define MSPI_FULL_DEPLUX_RD09 (0x7c)
|
||||||
|
#define MSPI_FULL_DEPLUX_RD10 (0x7d)
|
||||||
|
#define MSPI_FULL_DEPLUX_RD11 (0x7d)
|
||||||
|
#define MSPI_FULL_DEPLUX_RD12 (0x7e)
|
||||||
|
#define MSPI_FULL_DEPLUX_RD13 (0x7e)
|
||||||
|
#define MSPI_FULL_DEPLUX_RD14 (0x7f)
|
||||||
|
#define MSPI_FULL_DEPLUX_RD15 (0x7f)
|
||||||
|
|
||||||
|
//chip select bit map
|
||||||
|
#define MSPI_CHIP_SELECT_MAX 0x07
|
||||||
|
|
||||||
|
// control bit
|
||||||
|
#define MSPI_DONE_FLAG 0x01
|
||||||
|
#define MSPI_TRIGGER 0x01
|
||||||
|
#define MSPI_CLEAR_DONE 0x01
|
||||||
|
#define MSPI_INT_ENABLE 0x04
|
||||||
|
#define MSPI_RESET 0x02
|
||||||
|
#define MSPI_ENABLE 0x01
|
||||||
|
|
||||||
|
// clk_mspi0
|
||||||
|
#define MSPI0_CLK_CFG 0x33 //bit 2 ~bit 3
|
||||||
|
#define MSPI0_CLK_108M 0x00
|
||||||
|
#define MSPI0_CLK_54M 0x04
|
||||||
|
#define MSPI0_CLK_12M 0x08
|
||||||
|
#define MSPI0_CLK_MASK 0x0F
|
||||||
|
|
||||||
|
// clk_mspi1
|
||||||
|
#define MSPI1_CLK_CFG 0x33 //bit 10 ~bit 11
|
||||||
|
#define MSPI1_CLK_108M 0x0000
|
||||||
|
#define MSPI1_CLK_54M 0x0400
|
||||||
|
#define MSPI1_CLK_12M 0x0800
|
||||||
|
#define MSPI1_CLK_MASK 0x0F00
|
||||||
|
|
||||||
|
// clk_mspi
|
||||||
|
#define MSPI_CLK_CFG 0x33
|
||||||
|
#define MSPI_SELECT_0 0x0000
|
||||||
|
#define MSPI_SELECT_1 0x4000
|
||||||
|
#define MSPI_CLK_MASK 0xF000
|
||||||
|
|
||||||
|
// Clock settings
|
||||||
|
#define MSPI_CPU_CLOCK_1_2 0x0000
|
||||||
|
#define MSPI_CPU_CLOCK_1_4 0x0100
|
||||||
|
#define MSPI_CPU_CLOCK_1_8 0x0200
|
||||||
|
#define MSPI_CPU_CLOCK_1_16 0x0300
|
||||||
|
#define MSPI_CPU_CLOCK_1_32 0x0400
|
||||||
|
#define MSPI_CPU_CLOCK_1_64 0x0500
|
||||||
|
#define MSPI_CPU_CLOCK_1_128 0x0600
|
||||||
|
#define MSPI_CPU_CLOCK_1_256 0x0700
|
||||||
|
|
||||||
|
//CHITOP 101E mspi mode select
|
||||||
|
#define MSPI0_MODE 0x0C //bit0~bit1
|
||||||
|
#define MSPI0_MODE_MASK 0x07
|
||||||
|
#define MSPI1_MODE 0x0C //bit4~bit5
|
||||||
|
#define MSPI1_MODE_MASK 0x70
|
||||||
|
#define EJTAG_MODE 0xF
|
||||||
|
#define EJTAG_MODE_1 0x01
|
||||||
|
#define EJTAG_MODE_2 0x02
|
||||||
|
#define EJTAG_MODE_3 0x03
|
||||||
|
#define EJTAG_MODE_MASK 0x03
|
||||||
|
|
||||||
|
//MOVDMA 100B
|
||||||
|
#define MOV_DMA_SRC_ADDR_L 0x03
|
||||||
|
#define MOV_DMA_SRC_ADDR_H 0x04
|
||||||
|
#define MOV_DMA_DST_ADDR_L 0x05
|
||||||
|
#define MOV_DMA_DST_ADDR_H 0x06
|
||||||
|
#define MOV_DMA_BYTE_CNT_L 0x07
|
||||||
|
#define MOV_DMA_BYTE_CNT_H 0x08
|
||||||
|
#define DMA_MOVE0_IRQ_CLR 0x28
|
||||||
|
#define MOV_DMA_IRQ_FINAL_STATUS 0x2A
|
||||||
|
#define DMA_MOVE0_ENABLE 0x00
|
||||||
|
#define DMA_RW 0x50 //0 for dma write to device, 1 for dma read from device
|
||||||
|
#define DMA_READ 0x01
|
||||||
|
#define DMA_WRITE 0x00
|
||||||
|
#define DMA_DEVICE_MODE 0x51
|
||||||
|
#define DMA_DEVICE_SEL 0x52
|
||||||
|
|
||||||
|
//spi dma
|
||||||
|
#define MSPI_DMA_DATA_LENGTH_L 0x30
|
||||||
|
#define MSPI_DMA_DATA_LENGTH_H 0x31
|
||||||
|
#define MSPI_DMA_ENABLE 0x32
|
||||||
|
#define MSPI_DMA_RW_MODE 0x33
|
||||||
|
#define MSPI_DMA_WRITE 0x00
|
||||||
|
#define MSPI_DMA_READ 0x01
|
||||||
|
|
||||||
|
#define MSTAR_SPI_TIMEOUT_MS 30000
|
||||||
|
#define MSTAR_SPI_MODE_BITS (SPI_CPOL | SPI_CPHA /*| SPI_CS_HIGH | SPI_NO_CS | SPI_LSB_FIRST*/)
|
||||||
|
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------------------------------
|
||||||
|
// Macros
|
||||||
|
//-------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
#define MHal_CHIPTOP_REG(addr) (*(volatile U8*)((gChipBaseAddr) + (((addr) & ~1)<<1) + (addr & 1)))
|
||||||
|
#define MHal_PM_SLEEP_REG(addr) (*(volatile U8*)((gPmSleepBaseAddr) + (((addr) & ~1)<<1) + (addr & 1)))
|
||||||
|
#define MHal_SAR_GPIO_REG(addr) (*(volatile U8*)((gSarBaseAddr) + (((addr) & ~1)<<1) + (addr & 1)))
|
||||||
|
#define MHal_RIU_REG(addr) (*(volatile U8*)((gRIUBaseAddr) + (((addr) & ~1)<<1) + (addr & 1)))
|
||||||
|
#define READ_BYTE(_reg) (*(volatile u8*)(_reg))
|
||||||
|
#define READ_WORD(_reg) (*(volatile u16*)(_reg))
|
||||||
|
#define READ_LONG(_reg) (*(volatile u32*)(_reg))
|
||||||
|
#define WRITE_BYTE(_reg, _val) {(*((volatile u8*)(_reg))) = (u8)(_val); }
|
||||||
|
#define WRITE_WORD(_reg, _val) {(*((volatile u16*)(_reg))) = (u16)(_val); }
|
||||||
|
#define WRITE_LONG(_reg, _val) {(*((volatile u32*)(_reg))) = (u32)(_val); }
|
||||||
|
#define WRITE_WORD_MASK(_reg, _val, _mask) {(*((volatile u16*)(_reg))) = ((*((volatile u16*)(_reg))) & ~(_mask)) | ((u16)(_val) & (_mask)); }
|
||||||
|
#define READ_CPLD_DATA_IN() ((MHal_RIU_REG(PAD_Z80IO_IN_DATA_7_ADDR) & 0x1) << 7 | (MHal_RIU_REG(PAD_Z80IO_IN_DATA_6_ADDR) & 0x1) << 6 | (MHal_RIU_REG(PAD_Z80IO_IN_DATA_5_ADDR) & 0x1) << 5 | (MHal_RIU_REG(PAD_Z80IO_IN_DATA_4_ADDR) & 0x1) << 4 |\
|
||||||
|
(MHal_RIU_REG(PAD_Z80IO_IN_DATA_3_ADDR) & 0x1) << 3 | (MHal_RIU_REG(PAD_Z80IO_IN_DATA_2_ADDR) & 0x1) << 2 | (MHal_RIU_REG(PAD_Z80IO_IN_DATA_1_ADDR) & 0x1) << 1 | (MHal_RIU_REG(PAD_Z80IO_IN_DATA_0_ADDR) & 0x1))
|
||||||
|
#define SET_CPLD_READ_DATA() {MHal_RIU_REG(PAD_Z80IO_HIGH_BYTE_ADDR) |= 0x4;}
|
||||||
|
#define SET_CPLD_READ_STATUS() {MHal_RIU_REG(PAD_Z80IO_HIGH_BYTE_ADDR) &= ~0x4;}
|
||||||
|
#define SET_CPLD_HIGH_BYTE() {MHal_RIU_REG(PAD_Z80IO_HIGH_BYTE_ADDR) |= 0x4;}
|
||||||
|
#define CLEAR_CPLD_HIGH_BYTE() {MHal_RIU_REG(PAD_Z80IO_HIGH_BYTE_ADDR) &= ~0x4;}
|
||||||
|
#define CPLD_READY() (MHal_RIU_REG(PAD_Z80IO_READY_ADDR) & 0x1)
|
||||||
|
#define CPLD_RESET() (MHal_RIU_REG(PAD_Z80IO_RESET_ADDR) & 0x1)
|
||||||
|
#define CPLD_LAST_TSTATE() (MHal_RIU_REG(PAD_Z80IO_LTSTATE_ADDR) & 0x4)
|
||||||
|
#define SPI_SEND8(_d_) { uint32_t timeout = MAX_CHECK_CNT; \
|
||||||
|
MSPI_WRITE(MSPI_WRITE_BUF_OFFSET, (uint16_t)(_d_)); \
|
||||||
|
MSPI_WRITE(MSPI_WBF_SIZE_OFFSET, 1); \
|
||||||
|
while((MHal_RIU_REG(PAD_Z80IO_READY_ADDR) & 0x1) == 0);\
|
||||||
|
MSPI_WRITE(MSPI_CHIP_SELECT_OFFSET, MSPI_CS8_DISABLE | MSPI_CS7_DISABLE | MSPI_CS6_DISABLE | MSPI_CS5_DISABLE | MSPI_CS4_DISABLE | MSPI_CS3_DISABLE | MSPI_CS2_DISABLE | MSPI_CS1_ENABLE); \
|
||||||
|
MSPI_WRITE(MSPI_TRIGGER_OFFSET, MSPI_TRIGGER); \
|
||||||
|
while((MSPI_READ(MSPI_DONE_OFFSET) & MSPI_DONE_FLAG) == 0) { if(--timeout == 0) break; } \
|
||||||
|
MSPI_WRITE(MSPI_CHIP_SELECT_OFFSET, MSPI_CS8_DISABLE | MSPI_CS7_DISABLE | MSPI_CS6_DISABLE | MSPI_CS5_DISABLE | MSPI_CS4_DISABLE | MSPI_CS3_DISABLE | MSPI_CS2_DISABLE | MSPI_CS1_DISABLE); \
|
||||||
|
MSPI_WRITE(MSPI_DONE_CLEAR_OFFSET, MSPI_CLEAR_DONE);\
|
||||||
|
}
|
||||||
|
#define SPI_SEND16(_d_) { uint32_t timeout = MAX_CHECK_CNT; \
|
||||||
|
MSPI_WRITE(MSPI_WRITE_BUF_OFFSET, (uint16_t)(_d_)); \
|
||||||
|
MSPI_WRITE(MSPI_WBF_SIZE_OFFSET, 2); \
|
||||||
|
while((MHal_RIU_REG(PAD_Z80IO_READY_ADDR) & 0x1) == 0);\
|
||||||
|
MSPI_WRITE(MSPI_CHIP_SELECT_OFFSET, MSPI_CS8_DISABLE | MSPI_CS7_DISABLE | MSPI_CS6_DISABLE | MSPI_CS5_DISABLE | MSPI_CS4_DISABLE | MSPI_CS3_DISABLE | MSPI_CS2_DISABLE | MSPI_CS1_ENABLE); \
|
||||||
|
MSPI_WRITE(MSPI_TRIGGER_OFFSET, MSPI_TRIGGER); \
|
||||||
|
while((MSPI_READ(MSPI_DONE_OFFSET) & MSPI_DONE_FLAG) == 0) { if(--timeout == 0) break; } \
|
||||||
|
MSPI_WRITE(MSPI_CHIP_SELECT_OFFSET, MSPI_CS8_DISABLE | MSPI_CS7_DISABLE | MSPI_CS6_DISABLE | MSPI_CS5_DISABLE | MSPI_CS4_DISABLE | MSPI_CS3_DISABLE | MSPI_CS2_DISABLE | MSPI_CS1_DISABLE); \
|
||||||
|
MSPI_WRITE(MSPI_DONE_CLEAR_OFFSET, MSPI_CLEAR_DONE); \
|
||||||
|
}
|
||||||
|
#define SPI_SEND32(_d_) { uint32_t timeout = MAX_CHECK_CNT; \
|
||||||
|
MSPI_WRITE(MSPI_WRITE_BUF_OFFSET, (uint16_t)(_d_)); \
|
||||||
|
MSPI_WRITE(MSPI_WRITE_BUF_OFFSET+1, (uint16_t)((_d_) >> 16)); \
|
||||||
|
MSPI_WRITE(MSPI_WBF_SIZE_OFFSET, 4); \
|
||||||
|
while((MHal_RIU_REG(PAD_Z80IO_READY_ADDR) & 0x1) == 0);\
|
||||||
|
MSPI_WRITE(MSPI_CHIP_SELECT_OFFSET, MSPI_CS8_DISABLE | MSPI_CS7_DISABLE | MSPI_CS6_DISABLE | MSPI_CS5_DISABLE | MSPI_CS4_DISABLE | MSPI_CS3_DISABLE | MSPI_CS2_DISABLE | MSPI_CS1_ENABLE); \
|
||||||
|
MSPI_WRITE(MSPI_TRIGGER_OFFSET, MSPI_TRIGGER); \
|
||||||
|
while((MSPI_READ(MSPI_DONE_OFFSET) & MSPI_DONE_FLAG) == 0) { if(--timeout == 0) break; } \
|
||||||
|
MSPI_WRITE(MSPI_CHIP_SELECT_OFFSET, MSPI_CS8_DISABLE | MSPI_CS7_DISABLE | MSPI_CS6_DISABLE | MSPI_CS5_DISABLE | MSPI_CS4_DISABLE | MSPI_CS3_DISABLE | MSPI_CS2_DISABLE | MSPI_CS1_DISABLE); \
|
||||||
|
MSPI_WRITE(MSPI_DONE_CLEAR_OFFSET, MSPI_CLEAR_DONE); \
|
||||||
|
}
|
||||||
|
|
||||||
|
// read 2 byte
|
||||||
|
#define MSPI_READ(_reg_) READ_WORD(gMspBaseAddr + ((_reg_)<<2))
|
||||||
|
// write 2 byte
|
||||||
|
//#define MSPI_WRITE(_reg_, _val_) {pr_info("PDS: MSPI_WRITE(0x%x, 0x%x, 0x%x)\n", _reg_, _val_, gMspBaseAddr + ((_reg_)<<2)); WRITE_WORD(gMspBaseAddr + ((_reg_)<<2), (_val_)); }
|
||||||
|
#define MSPI_WRITE(_reg_, _val_) WRITE_WORD(gMspBaseAddr + ((_reg_)<<2), (_val_));
|
||||||
|
//write 2 byte mask
|
||||||
|
//#define MSPI_WRITE_MASK(_reg_, _val_, mask) {pr_info("PDS: WRITE_LONG(0x%x, 0x%x, mask=0x%x)\n", _reg_, _val_, mask); WRITE_WORD_MASK(gMspBaseAddr + ((_reg_)<<2), (_val_), (mask)); }
|
||||||
|
#define MSPI_WRITE_MASK(_reg_, _val_, mask) WRITE_WORD_MASK(gMspBaseAddr + ((_reg_)<<2), (_val_), (mask));
|
||||||
|
|
||||||
|
#define CLK_READ(_reg_) READ_WORD(gClkBaseAddr + ((_reg_)<<2))
|
||||||
|
//#define CLK_WRITE(_reg_, _val_) {pr_info("PDS: CLK_WRITE(0x%x, 0x%x)\n", _reg_, _val_); WRITE_WORD(gClkBaseAddr + ((_reg_)<<2), (_val_)); }
|
||||||
|
#define CLK_WRITE(_reg_, _val_) WRITE_WORD(gClkBaseAddr + ((_reg_)<<2), (_val_));
|
||||||
|
|
||||||
|
#define CHIPTOP_READ(_reg_) READ_WORD(gChipBaseAddr + ((_reg_)<<2))
|
||||||
|
//#define CHIPTOP_WRITE(_reg_, _val_) {pr_info("PDS: CHIPTOP_WRITE(0x%x, 0x%x)\n", _reg_, _val_); WRITE_WORD(gChipBaseAddr + ((_reg_)<<2), (_val_)); }
|
||||||
|
#define CHIPTOP_WRITE(_reg_, _val_) WRITE_WORD(gChipBaseAddr + ((_reg_)<<2), (_val_));
|
||||||
|
|
||||||
|
#define MOVDMA_READ(_reg_) READ_WORD(gMOVDMAAddr + ((_reg_)<<2))
|
||||||
|
//#define MOVDMA_WRITE(_reg_, _val_) {pr_info("PDS: MOVDMA_WRITE(0x%x, 0x%x)\n", _reg_, _val_); WRITE_WORD(gMOVDMAAddr + ((_reg_)<<2), (_val_)); }
|
||||||
|
#define MOVDMA_WRITE(_reg_, _val_) WRITE_WORD(gMOVDMAAddr + ((_reg_)<<2), (_val_));
|
||||||
|
|
||||||
|
#define _HAL_MSPI_ClearDone() MSPI_WRITE(MSPI_DONE_CLEAR_OFFSET,MSPI_CLEAR_DONE)
|
||||||
|
#define MAX_CHECK_CNT 2000
|
||||||
|
|
||||||
|
#define MSPI_READ_INDEX 0x0
|
||||||
|
#define MSPI_WRITE_INDEX 0x1
|
||||||
|
|
||||||
|
#define SPI_MIU0_BUS_BASE 0x20000000
|
||||||
|
#define SPI_MIU1_BUS_BASE 0xFFFFFFFF
|
||||||
|
|
||||||
|
|
||||||
|
// Function definitions.
|
||||||
|
//
|
||||||
|
int z80io_init(void);
|
||||||
|
uint8_t z80io_SPI_Send8(uint8_t txData, uint8_t *rxData);
|
||||||
|
uint8_t z80io_SPI_Send16(uint16_t txData, uint16_t *rxData);
|
||||||
|
uint8_t z80io_SPI_Send32(uint32_t txData, uint32_t *rxData);
|
||||||
|
#ifdef NOTNEEDED
|
||||||
|
uint8_t z80io_PRL_Send8(uint8_t txData);
|
||||||
|
uint8_t z680io_PRL_Send16(uint16_t txData);
|
||||||
|
#endif
|
||||||
|
uint8_t z80io_PRL_Read8(uint8_t dataFlag);
|
||||||
|
uint16_t z80io_PRL_Read16(void);
|
||||||
|
uint8_t z80io_SPI_Test(void);
|
||||||
|
uint8_t z80io_PRL_Test(void);
|
||||||
|
uint8_t z80io_Z80_TestMemory(void);
|
||||||
|
|
||||||
|
extern void MHal_GPIO_Init(void);
|
||||||
|
extern void MHal_GPIO_Pad_Set(uint8_t u8IndexGPIO);
|
||||||
|
extern int MHal_GPIO_PadGroupMode_Set(uint32_t u32PadMode);
|
||||||
|
extern int MHal_GPIO_PadVal_Set(uint8_t u8IndexGPIO, uint32_t u32PadMode);
|
||||||
|
extern void MHal_GPIO_Pad_Oen(uint8_t u8IndexGPIO);
|
||||||
|
extern void MHal_GPIO_Pad_Odn(uint8_t u8IndexGPIO);
|
||||||
|
extern uint8_t MHal_GPIO_Pad_Level(uint8_t u8IndexGPIO);
|
||||||
|
extern uint8_t MHal_GPIO_Pad_InOut(uint8_t u8IndexGPIO);
|
||||||
|
extern void MHal_GPIO_Pull_High(uint8_t u8IndexGPIO);
|
||||||
|
extern void MHal_GPIO_Pull_Low(uint8_t u8IndexGPIO);
|
||||||
|
extern void MHal_GPIO_Set_High(uint8_t u8IndexGPIO);
|
||||||
|
extern void MHal_GPIO_Set_Low(uint8_t u8IndexGPIO);
|
||||||
|
extern void MHal_Enable_GPIO_INT(uint8_t u8IndexGPIO);
|
||||||
|
extern int MHal_GPIO_To_Irq(uint8_t u8IndexGPIO);
|
||||||
|
extern void MHal_GPIO_Set_POLARITY(uint8_t u8IndexGPIO, uint8_t reverse);
|
||||||
|
extern void MHal_GPIO_Set_Driving(uint8_t u8IndexGPIO, uint8_t setHigh);
|
||||||
|
extern void MHal_GPIO_PAD_32K_OUT(uint8_t u8Enable);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#endif // Z80IO_H
|
||||||
541
software/FusionX/src/driver/MZ2000/z80io_test.c
Normal file
@@ -0,0 +1,541 @@
|
|||||||
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Name: z80io_test.c
|
||||||
|
// Created: Oct 2022
|
||||||
|
// Author(s): Philip Smart
|
||||||
|
// Description: Z80 IO Interface Test Methods
|
||||||
|
// This file contains the methods used to test the SOM to CPLD interface and evaluate
|
||||||
|
// it's performance. Production builds wont include these methods.
|
||||||
|
// Credits:
|
||||||
|
// Copyright: (c) 2019-2022 Philip Smart <philip.smart@net2net.org>
|
||||||
|
//
|
||||||
|
// History: Oct 2022 - Initial write of the z80 kernel driver software.
|
||||||
|
//
|
||||||
|
// Notes: See Makefile to enable/disable conditional components
|
||||||
|
//
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// This source file is free software: you can redistribute it and#or modify
|
||||||
|
// it under the terms of the GNU General Public License as published
|
||||||
|
// by the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This source file is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#include <linux/module.h>
|
||||||
|
#include <linux/kernel.h>
|
||||||
|
#include <linux/semaphore.h>
|
||||||
|
#include <linux/kthread.h>
|
||||||
|
#include <linux/sched.h>
|
||||||
|
|
||||||
|
//--------------------------------------------------------
|
||||||
|
// Test Methods.
|
||||||
|
//--------------------------------------------------------
|
||||||
|
uint8_t z80io_Z80_TestMemory(void)
|
||||||
|
{
|
||||||
|
// Locals.
|
||||||
|
//
|
||||||
|
uint32_t addr;
|
||||||
|
uint32_t fullCmd;
|
||||||
|
uint8_t cmd;
|
||||||
|
struct timeval start, stop;
|
||||||
|
uint32_t iterations = 100;
|
||||||
|
uint32_t errorCount;
|
||||||
|
uint32_t idx;
|
||||||
|
long totalTime;
|
||||||
|
long bytesMSec;
|
||||||
|
uint8_t result;
|
||||||
|
spinlock_t spinLock;
|
||||||
|
unsigned long flags;
|
||||||
|
|
||||||
|
SPI_SEND8(CPLD_CMD_CLEAR_AUTO_REFRESH);
|
||||||
|
|
||||||
|
SPI_SEND32(0x00E30000 | (0x07 << 8) | CPLD_CMD_WRITEIO_ADDR);
|
||||||
|
udelay(100);
|
||||||
|
SPI_SEND32(0x00E80000 | (0x82 << 8) | CPLD_CMD_WRITEIO_ADDR);
|
||||||
|
udelay(100);
|
||||||
|
SPI_SEND32(0x00E20000 | (0x58 << 8) | CPLD_CMD_WRITEIO_ADDR);
|
||||||
|
udelay(100);
|
||||||
|
SPI_SEND32(0x00E00000 | (0xF7 << 8) | CPLD_CMD_WRITEIO_ADDR);
|
||||||
|
udelay(100);
|
||||||
|
SPI_SEND32(0x00E90000 | (0x0F << 8) | CPLD_CMD_WRITEIO_ADDR);
|
||||||
|
udelay(100);
|
||||||
|
SPI_SEND32(0x00EB0000 | (0xCF << 8) | CPLD_CMD_WRITEIO_ADDR);
|
||||||
|
udelay(100);
|
||||||
|
SPI_SEND32(0x00EB0000 | (0xFF << 8) | CPLD_CMD_WRITEIO_ADDR);
|
||||||
|
udelay(100);
|
||||||
|
pr_info("Z80 Host Test - IO.\n");
|
||||||
|
// for(idx=0; idx < 1000000; idx++)
|
||||||
|
// {
|
||||||
|
// SPI_SEND32(0x00E80000 | (0xD3 << 8) | CPLD_CMD_WRITEIO_ADDR);
|
||||||
|
// SPI_SEND32(0xD0000000 | (0x41 << 8) | CPLD_CMD_WRITE_ADDR);
|
||||||
|
// SPI_SEND32(0xD0100000 | (0x41 << 8) | CPLD_CMD_WRITE_ADDR);
|
||||||
|
// SPI_SEND32(0xD0200000 | (0x41 << 8) | CPLD_CMD_WRITE_ADDR);
|
||||||
|
// SPI_SEND32(0xD0300000 | (0x41 << 8) | CPLD_CMD_WRITE_ADDR);
|
||||||
|
// SPI_SEND32(0xD0400000 | (0x41 << 8) | CPLD_CMD_WRITE_ADDR);
|
||||||
|
// SPI_SEND32(0xD0500000 | (0x41 << 8) | CPLD_CMD_WRITE_ADDR);
|
||||||
|
// }
|
||||||
|
|
||||||
|
spin_lock_init(&spinLock);
|
||||||
|
pr_info("Z80 Host Test - Testing IO Write performance.\n");
|
||||||
|
do_gettimeofday(&start);
|
||||||
|
spin_lock_irqsave(&spinLock, flags);
|
||||||
|
for(idx=0; idx < iterations; idx++)
|
||||||
|
{
|
||||||
|
for(addr=0x0000; addr < 0x10000; addr++)
|
||||||
|
{
|
||||||
|
fullCmd = 0x00000000| ((uint8_t)addr) << 8 | CPLD_CMD_WRITEIO_ADDR;
|
||||||
|
SPI_SEND32(fullCmd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
spin_unlock_irqrestore(&spinLock, flags);
|
||||||
|
do_gettimeofday(&stop);
|
||||||
|
totalTime = (stop.tv_sec - start.tv_sec) * 1000000 + stop.tv_usec - start.tv_usec;
|
||||||
|
bytesMSec = (long)(1*iterations*0xC000)/((long)totalTime/1000);
|
||||||
|
pr_info("Loop mode time=%ldms, %ldBytes/sec\n", totalTime/1000, (bytesMSec*1000));
|
||||||
|
|
||||||
|
spin_lock_init(&spinLock);
|
||||||
|
pr_info("Z80 Host Test - Testing IO Read performance.\n");
|
||||||
|
do_gettimeofday(&start);
|
||||||
|
spin_lock_irqsave(&spinLock, flags);
|
||||||
|
for(idx=0; idx < iterations; idx++)
|
||||||
|
{
|
||||||
|
// Go through all the accessible IO ports and write to it.
|
||||||
|
for(addr=0x0000; addr < 0x10000; addr++)
|
||||||
|
{
|
||||||
|
fullCmd = 0x00000000 | ((uint8_t)addr) << 8 | CPLD_CMD_READIO_ADDR;
|
||||||
|
SPI_SEND32(fullCmd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
spin_unlock_irqrestore(&spinLock, flags);
|
||||||
|
do_gettimeofday(&stop);
|
||||||
|
totalTime = (stop.tv_sec - start.tv_sec) * 1000000 + stop.tv_usec - start.tv_usec;
|
||||||
|
bytesMSec = (long)(1*iterations*0xC000)/((long)totalTime/1000);
|
||||||
|
pr_info("Loop mode time=%ldms, %ldBytes/sec\n", totalTime/1000, (bytesMSec*1000));
|
||||||
|
|
||||||
|
spin_lock_init(&spinLock);
|
||||||
|
pr_info("Z80 Host Test - Testing RAM Write performance.\n");
|
||||||
|
do_gettimeofday(&start);
|
||||||
|
spin_lock_irqsave(&spinLock, flags);
|
||||||
|
for(idx=0; idx < iterations; idx++)
|
||||||
|
{
|
||||||
|
// Go through all the accessible RAM and write to it.
|
||||||
|
for(addr=0x1000; addr < 0xD000; addr++)
|
||||||
|
{
|
||||||
|
fullCmd = (addr << 16) | ((uint8_t)addr) << 8 | 0x18;
|
||||||
|
SPI_SEND32(fullCmd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
spin_unlock_irqrestore(&spinLock, flags);
|
||||||
|
do_gettimeofday(&stop);
|
||||||
|
totalTime = (stop.tv_sec - start.tv_sec) * 1000000 + stop.tv_usec - start.tv_usec;
|
||||||
|
bytesMSec = (long)(1*iterations*0xC000)/((long)totalTime/1000);
|
||||||
|
pr_info("Loop mode time=%ldms, %ldBytes/sec\n", totalTime/1000, (bytesMSec*1000));
|
||||||
|
|
||||||
|
pr_info("Z80 Host Test - Testing RAM Write performance (opt).\n");
|
||||||
|
do_gettimeofday(&start);
|
||||||
|
spin_lock_irqsave(&spinLock, flags);
|
||||||
|
for(idx=0; idx < iterations; idx++)
|
||||||
|
{
|
||||||
|
// Go through all the accessible RAM and write to it.
|
||||||
|
for(addr=0x1000; addr < 0xD000; addr++)
|
||||||
|
{
|
||||||
|
if(addr == 0x1000)
|
||||||
|
{
|
||||||
|
fullCmd = (addr << 16) | ((uint8_t)addr) << 8 | 0x18;
|
||||||
|
SPI_SEND32(fullCmd);
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
cmd = 0x19;
|
||||||
|
SPI_SEND16(((uint8_t)addr) << 8 | cmd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
spin_unlock_irqrestore(&spinLock, flags);
|
||||||
|
do_gettimeofday(&stop);
|
||||||
|
totalTime = (stop.tv_sec - start.tv_sec) * 1000000 + stop.tv_usec - start.tv_usec;
|
||||||
|
bytesMSec = (long)(1*iterations*0xC000)/((long)totalTime/1000);
|
||||||
|
pr_info("Loop mode time=%ldms, %ldBytes/sec\n", totalTime/1000, (bytesMSec*1000));
|
||||||
|
|
||||||
|
pr_info("Z80 Host Test - Testing RAM Write/Fetch performance (opt).\n");
|
||||||
|
errorCount = 0;
|
||||||
|
SET_CPLD_READ_DATA();
|
||||||
|
//MHal_RIU_REG(gpio_table[PAD_Z80IO_HIGH_BYTE ].r_out) |= gpio_table[PAD_Z80IO_HIGH_BYTE ].m_out;
|
||||||
|
do_gettimeofday(&start);
|
||||||
|
for(idx=0; idx < iterations; idx++)
|
||||||
|
{
|
||||||
|
// Go through all the accessible RAM and write to it.
|
||||||
|
for(addr=0x8000; addr < 0xD000; addr++)
|
||||||
|
{
|
||||||
|
if(addr == 0x8000)
|
||||||
|
{
|
||||||
|
fullCmd = (addr << 16) | ((uint8_t)addr) << 8 | 0x18;
|
||||||
|
SPI_SEND32(fullCmd);
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
cmd = 0x19;
|
||||||
|
SPI_SEND16(((uint8_t)addr) << 8 | cmd);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read back the same byte.
|
||||||
|
cmd = 0x10;
|
||||||
|
SPI_SEND8(cmd);
|
||||||
|
while(CPLD_READY() == 0);
|
||||||
|
|
||||||
|
result = READ_CPLD_DATA_IN();
|
||||||
|
if(result != (uint8_t)addr)
|
||||||
|
{
|
||||||
|
if(errorCount < 50) pr_info("Read byte:0x%x, Written:0x%x\n", result, (uint8_t)addr);
|
||||||
|
errorCount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
do_gettimeofday(&stop);
|
||||||
|
totalTime = (stop.tv_sec - start.tv_sec) * 1000000 + stop.tv_usec - start.tv_usec;
|
||||||
|
bytesMSec = (long)(1*iterations*0xC000)/((long)totalTime/1000);
|
||||||
|
pr_info("Loop mode time=%ldms, errorCount=%d, %ldBytes/sec\n", totalTime/1000, errorCount, (bytesMSec*1000));
|
||||||
|
|
||||||
|
pr_info("Z80 Host Test - Testing RAM Write/Read performance (opt).\n");
|
||||||
|
errorCount = 0;
|
||||||
|
SET_CPLD_READ_DATA();
|
||||||
|
//MHal_RIU_REG(gpio_table[PAD_Z80IO_HIGH_BYTE ].r_out) |= gpio_table[PAD_Z80IO_HIGH_BYTE ].m_out;
|
||||||
|
do_gettimeofday(&start);
|
||||||
|
for(idx=0; idx < iterations; idx++)
|
||||||
|
{
|
||||||
|
// Go through all the accessible RAM and write to it.
|
||||||
|
for(addr=0x8000; addr < 0xD000; addr++)
|
||||||
|
{
|
||||||
|
if(addr == 0x8000)
|
||||||
|
{
|
||||||
|
fullCmd = (addr << 16) | ((uint8_t)addr) << 8 | 0x18;
|
||||||
|
SPI_SEND32(fullCmd);
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
cmd = 0x19;
|
||||||
|
SPI_SEND16(((uint8_t)addr) << 8 | cmd);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read back the same byte.
|
||||||
|
cmd = 0x20;
|
||||||
|
SPI_SEND8(cmd);
|
||||||
|
while(CPLD_READY() == 0);
|
||||||
|
|
||||||
|
result = READ_CPLD_DATA_IN();
|
||||||
|
if(result != (uint8_t)addr)
|
||||||
|
{
|
||||||
|
if(errorCount < 50) pr_info("Read byte:0x%x, Written:0x%x\n", result, (uint8_t)addr);
|
||||||
|
errorCount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
do_gettimeofday(&stop);
|
||||||
|
totalTime = (stop.tv_sec - start.tv_sec) * 1000000 + stop.tv_usec - start.tv_usec;
|
||||||
|
bytesMSec = (long)(1*iterations*0xC000)/((long)totalTime/1000);
|
||||||
|
pr_info("Loop mode time=%ldms, errorCount=%d, %ldBytes/sec\n", totalTime/1000, errorCount, (bytesMSec*1000));
|
||||||
|
|
||||||
|
pr_info("Z80 Host Test - Testing RAM Fetch performance.\n");
|
||||||
|
SET_CPLD_READ_DATA();
|
||||||
|
do_gettimeofday(&start);
|
||||||
|
for(idx=0; idx < iterations; idx++)
|
||||||
|
{
|
||||||
|
// Go through all the accessible RAM and read from it.
|
||||||
|
for(addr=0x1000; addr < 0xD000; addr++)
|
||||||
|
{
|
||||||
|
if(addr == 0x1000)
|
||||||
|
{
|
||||||
|
fullCmd = (addr << 16) | ((uint8_t)addr) << 8 | 0x10;
|
||||||
|
SPI_SEND32(fullCmd);
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
cmd = 0x11;
|
||||||
|
SPI_SEND8(cmd);
|
||||||
|
}
|
||||||
|
while(CPLD_READY() == 0);
|
||||||
|
result = READ_CPLD_DATA_IN();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
do_gettimeofday(&stop);
|
||||||
|
totalTime = (stop.tv_sec - start.tv_sec) * 1000000 + stop.tv_usec - start.tv_usec;
|
||||||
|
bytesMSec = (long)(1*iterations*0xC000)/((long)totalTime/1000);
|
||||||
|
pr_info("Loop mode time=%ldms, %ldBytes/sec\n", totalTime/1000, (bytesMSec*1000));
|
||||||
|
|
||||||
|
pr_info("Z80 Host Test - Testing RAM Read performance (opt).\n");
|
||||||
|
SET_CPLD_READ_DATA();
|
||||||
|
do_gettimeofday(&start);
|
||||||
|
for(idx=0; idx < iterations; idx++)
|
||||||
|
{
|
||||||
|
// Go through all the accessible RAM and read from it.
|
||||||
|
for(addr=0x1000; addr < 0xD000; addr++)
|
||||||
|
{
|
||||||
|
if(addr == 0x1000)
|
||||||
|
{
|
||||||
|
fullCmd = (addr << 16) | ((uint8_t)addr) << 8 | 0x20;
|
||||||
|
SPI_SEND32(fullCmd);
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
cmd = 0x21;
|
||||||
|
SPI_SEND8(cmd);
|
||||||
|
}
|
||||||
|
while(CPLD_READY() == 0);
|
||||||
|
result = READ_CPLD_DATA_IN();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
do_gettimeofday(&stop);
|
||||||
|
totalTime = (stop.tv_sec - start.tv_sec) * 1000000 + stop.tv_usec - start.tv_usec;
|
||||||
|
bytesMSec = (long)(1*iterations*0xC000)/((long)totalTime/1000);
|
||||||
|
pr_info("Loop mode time=%ldms, %ldBytes/sec\n", totalTime/1000, (bytesMSec*1000));
|
||||||
|
|
||||||
|
// Go through all the accessible attribute VRAM and initialise it.
|
||||||
|
pr_info("Z80 Host Test - Testing VRAM Write performance.\n");
|
||||||
|
SPI_SEND32(0x00E80000 | (0xD3 << 8) | CPLD_CMD_WRITEIO_ADDR);
|
||||||
|
iterations = 256*10;
|
||||||
|
do_gettimeofday(&start);
|
||||||
|
for(addr=0xD800; addr < 0xE000; addr++)
|
||||||
|
{
|
||||||
|
//while(CPLD_READY() == 0);
|
||||||
|
if(addr == 0xD800)
|
||||||
|
{
|
||||||
|
fullCmd = (addr << 16) |(0x71 << 8) | 0x18;
|
||||||
|
SPI_SEND32(fullCmd);
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
cmd = 0x19;
|
||||||
|
SPI_SEND8(cmd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for(idx=0; idx < iterations; idx++)
|
||||||
|
{
|
||||||
|
// Go through all the accessible VRAM and write to it.
|
||||||
|
for(addr=0xD000; addr < 0xD800; addr++)
|
||||||
|
{
|
||||||
|
//while(CPLD_READY() == 0);
|
||||||
|
if(addr == 0xD000)
|
||||||
|
{
|
||||||
|
fullCmd = (addr << 16) | ((uint8_t)idx << 8) | 0x18;
|
||||||
|
SPI_SEND32(fullCmd);
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
cmd = 0x19;
|
||||||
|
SPI_SEND8(cmd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
do_gettimeofday(&stop);
|
||||||
|
totalTime = (stop.tv_sec - start.tv_sec) * 1000000 + stop.tv_usec - start.tv_usec;
|
||||||
|
bytesMSec = (long)((1*iterations*0x800)+0x800)/((long)totalTime/1000);
|
||||||
|
pr_info("Loop mode time=%ldms, %ldBytes/sec\n", totalTime/1000, (bytesMSec*1000));
|
||||||
|
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// A simple test to verify the SOM to CPLD SPI connectivity and give an estimate of its performance.
|
||||||
|
// The performance is based on the SPI setup and transmit time along with the close and received data processing.
|
||||||
|
// In real use, the driver will just send a command and generally ignore received data so increased throughput can be achieved.
|
||||||
|
//
|
||||||
|
uint8_t z80io_SPI_Test(void)
|
||||||
|
{
|
||||||
|
// Locals.
|
||||||
|
//
|
||||||
|
struct timeval start, stop;
|
||||||
|
uint32_t iterations = 10000000;
|
||||||
|
uint32_t idx;
|
||||||
|
uint8_t rxData8;
|
||||||
|
uint16_t rxData16;
|
||||||
|
uint16_t rxData16Last;
|
||||||
|
uint32_t rxData32;
|
||||||
|
uint32_t rxData32Last;
|
||||||
|
uint32_t errorCount;
|
||||||
|
long totalTime;
|
||||||
|
long bytesMSec;
|
||||||
|
|
||||||
|
// Place the CPLD into echo test mode.
|
||||||
|
z80io_SPI_Send8(0xfe, &rxData8);
|
||||||
|
|
||||||
|
// 1st. test, 8bit.
|
||||||
|
pr_info("SPI Test - Testing 8 bit performance.\n");
|
||||||
|
errorCount=0;
|
||||||
|
do_gettimeofday(&start);
|
||||||
|
for(idx=0; idx < iterations; idx++)
|
||||||
|
{
|
||||||
|
z80io_SPI_Send8((uint8_t)idx, &rxData8);
|
||||||
|
if(idx > 1 && (uint8_t)(idx-1) != rxData8)
|
||||||
|
{
|
||||||
|
if(errorCount < 20)
|
||||||
|
pr_info("0x%x: Last(0x%x) /= New(0x%x)\n",idx, (uint8_t)(idx-1), rxData8 );
|
||||||
|
errorCount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
do_gettimeofday(&stop);
|
||||||
|
totalTime = (stop.tv_sec - start.tv_sec) * 1000000 + stop.tv_usec - start.tv_usec;
|
||||||
|
bytesMSec = (long)(1*iterations)/((long)totalTime/1000);
|
||||||
|
pr_info("Loop mode errorCount: %d, time=%ldms, %ldBytes/sec\n", errorCount, totalTime/1000, (bytesMSec*1000));
|
||||||
|
|
||||||
|
// 2nd. test, 16bit.
|
||||||
|
pr_info("SPI Test - Testing 16 bit performance.\n");
|
||||||
|
errorCount=0;
|
||||||
|
do_gettimeofday(&start);
|
||||||
|
for(idx=0; idx < iterations; idx++)
|
||||||
|
{
|
||||||
|
// Byte re-ordering required as the CPLD echo's back the last 8bits received, it doesnt know if a transmission is 8/16/32bits.
|
||||||
|
z80io_SPI_Send16((uint16_t)idx, &rxData16);
|
||||||
|
if(idx > 0 && (uint16_t)(idx-1) != (uint16_t)(((rxData16&0x00ff) << 8) | ((rxData16Last & 0xff00) >> 8)))
|
||||||
|
{
|
||||||
|
if(errorCount < 20)
|
||||||
|
pr_info("0x%x: Last(0x%x) /= New(0x%x)\n",idx, (uint16_t)(idx-1), (uint16_t)(((rxData16&0x00ff) << 8) | ((rxData16Last & 0xff00) >> 8)));
|
||||||
|
errorCount++;
|
||||||
|
}
|
||||||
|
rxData16Last = rxData16;
|
||||||
|
}
|
||||||
|
do_gettimeofday(&stop);
|
||||||
|
totalTime = (stop.tv_sec - start.tv_sec) * 1000000 + stop.tv_usec - start.tv_usec;
|
||||||
|
bytesMSec = (long)(2*iterations)/((long)totalTime/1000);
|
||||||
|
pr_info("Loop mode errorCount: %d, time=%ldms, %ldBytes/sec\n", errorCount, totalTime/1000, (bytesMSec*1000));
|
||||||
|
|
||||||
|
// 3rd. test, 32bit.
|
||||||
|
pr_info("SPI Test - Testing 32 bit performance.\n");
|
||||||
|
errorCount=0;
|
||||||
|
do_gettimeofday(&start);
|
||||||
|
for(idx=0; idx < iterations; idx++)
|
||||||
|
{
|
||||||
|
z80io_SPI_Send32((uint32_t)idx, &rxData32);
|
||||||
|
if(idx > 0 && (uint32_t)(idx-1) != (uint32_t)(((rxData32&0x00ff) << 8) | ((rxData32Last & 0xff000000) >> 8) | ((rxData32Last & 0xff0000) >> 8) | ((rxData32Last & 0xff00) >> 8)))
|
||||||
|
{
|
||||||
|
if(errorCount < 20)
|
||||||
|
pr_info("0x%x: Last(0x%x) /= New(0x%x)\n",idx, (uint32_t)(idx-1), (uint32_t)(((rxData32&0x00ff) << 8) | ((rxData32Last & 0xff000000) >> 8) | ((rxData32Last & 0xff0000) >> 8) | ((rxData32Last & 0xff00) >> 8)));
|
||||||
|
errorCount++;
|
||||||
|
}
|
||||||
|
rxData32Last = rxData32;
|
||||||
|
}
|
||||||
|
do_gettimeofday(&stop);
|
||||||
|
totalTime = (stop.tv_sec - start.tv_sec) * 1000000 + stop.tv_usec - start.tv_usec;
|
||||||
|
bytesMSec = (long)(4*iterations)/((long)totalTime/1000);
|
||||||
|
pr_info("Loop mode errorCount: %d, time=%ldms, %ldBytes/sec\n", errorCount, totalTime/1000, (bytesMSec*1000));
|
||||||
|
|
||||||
|
pr_info("Press host RESET button Once to reset the CPLD.\n");
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Method to test the parallel bus, verifying integrity and assessing performance.
|
||||||
|
uint8_t z80io_PRL_Test(void)
|
||||||
|
{
|
||||||
|
// Locals.
|
||||||
|
//
|
||||||
|
struct timeval start, stop;
|
||||||
|
uint32_t iterations = 10000000;
|
||||||
|
uint32_t idx;
|
||||||
|
uint8_t rxData8;
|
||||||
|
uint16_t rxData16;
|
||||||
|
long totalTime;
|
||||||
|
long bytesMSec;
|
||||||
|
#ifdef NOTNEEDED
|
||||||
|
uint32_t errorCount;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Place the CPLD into echo test mode.
|
||||||
|
|
||||||
|
// 1st. test, 8bit RW.
|
||||||
|
#ifdef NOTNEEDED
|
||||||
|
pr_info("Parallel Test - Testing 8 bit r/w performance.\n");
|
||||||
|
errorCount=0;
|
||||||
|
do_gettimeofday(&start);
|
||||||
|
for(idx=0; idx < iterations; idx++)
|
||||||
|
{
|
||||||
|
// Write byte and readback to compare.
|
||||||
|
z80io_PRL_Send8((uint8_t)idx);
|
||||||
|
rxData8 = z80io_PRL_Read8();
|
||||||
|
if((uint8_t)idx != rxData8)
|
||||||
|
{
|
||||||
|
pr_info("0x%x: Written(0x%x) /= Read(0x%x)\n", idx, (uint8_t)(idx), rxData8);
|
||||||
|
errorCount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
do_gettimeofday(&stop);
|
||||||
|
totalTime = (stop.tv_sec - start.tv_sec) * 1000000 + stop.tv_usec - start.tv_usec;
|
||||||
|
bytesMSec = (long)(iterations)/((long)totalTime/1000);
|
||||||
|
pr_info("Loop mode errorCount: %d, time=%ldms, %ldBytes/sec\n", errorCount, totalTime/1000, (bytesMSec*1000));
|
||||||
|
|
||||||
|
// 2nd. test, 8bit Write.
|
||||||
|
pr_info("Parallel Test - Testing 8 bit write performance.\n");
|
||||||
|
do_gettimeofday(&start);
|
||||||
|
for(idx=0; idx < iterations; idx++)
|
||||||
|
{
|
||||||
|
// Write byte.
|
||||||
|
z80io_PRL_Send8((uint8_t)idx);
|
||||||
|
}
|
||||||
|
do_gettimeofday(&stop);
|
||||||
|
totalTime = (stop.tv_sec - start.tv_sec) * 1000000 + stop.tv_usec - start.tv_usec;
|
||||||
|
bytesMSec = (long)(iterations)/((long)totalTime/1000);
|
||||||
|
pr_info("Loop mode time=%ldms, %ldBytes/sec\n", totalTime/1000, (bytesMSec*1000));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// 3rd. test, 8bit Read.
|
||||||
|
pr_info("Parallel Test - Testing 8 bit read performance.\n");
|
||||||
|
do_gettimeofday(&start);
|
||||||
|
for(idx=0; idx < iterations; idx++)
|
||||||
|
{
|
||||||
|
// Read byte.
|
||||||
|
rxData8 = z80io_PRL_Read8(0);
|
||||||
|
}
|
||||||
|
do_gettimeofday(&stop);
|
||||||
|
totalTime = (stop.tv_sec - start.tv_sec) * 1000000 + stop.tv_usec - start.tv_usec;
|
||||||
|
bytesMSec = (long)(iterations)/((long)totalTime/1000);
|
||||||
|
pr_info("Loop mode time=%ldms, %ldBytes/sec\n", totalTime/1000, (bytesMSec*1000));
|
||||||
|
|
||||||
|
#ifdef NOTNEEDED
|
||||||
|
// 4th test, 16bit.
|
||||||
|
pr_info("Parallel Test - Testing 16 bit r/w performance.\n");
|
||||||
|
errorCount=0;
|
||||||
|
do_gettimeofday(&start);
|
||||||
|
for(idx=0; idx < iterations; idx++)
|
||||||
|
{
|
||||||
|
// Byte re-ordering required as the CPLD echo's back the last 8bits received, it doesnt know if a transmission is 8/16/32bits.
|
||||||
|
z80io_PRL_Send16((uint16_t)idx);
|
||||||
|
rxData16 = z80io_PRL_Read16();
|
||||||
|
if((uint16_t)idx != rxData16)
|
||||||
|
{
|
||||||
|
pr_info("0x%x: Written(0x%x) /= Read(0x%x)\n", idx, (uint16_t)(idx), rxData16);
|
||||||
|
errorCount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
do_gettimeofday(&stop);
|
||||||
|
totalTime = (stop.tv_sec - start.tv_sec) * 1000000 + stop.tv_usec - start.tv_usec;
|
||||||
|
bytesMSec = (long)(2*iterations)/((long)totalTime/1000);
|
||||||
|
pr_info("Loop mode errorCount: %d, time=%ldms, %ldBytes/sec\n", errorCount, totalTime/1000, (bytesMSec*1000));
|
||||||
|
|
||||||
|
// 5th test, 16bit Write.
|
||||||
|
pr_info("Parallel Test - Testing 16 bit write performance.\n");
|
||||||
|
do_gettimeofday(&start);
|
||||||
|
for(idx=0; idx < iterations; idx++)
|
||||||
|
{
|
||||||
|
// Write word.
|
||||||
|
z80io_PRL_Send16((uint16_t)idx);
|
||||||
|
}
|
||||||
|
do_gettimeofday(&stop);
|
||||||
|
totalTime = (stop.tv_sec - start.tv_sec) * 1000000 + stop.tv_usec - start.tv_usec;
|
||||||
|
bytesMSec = (long)(2*iterations)/((long)totalTime/1000);
|
||||||
|
pr_info("Loop mode time=%ldms, %ldBytes/sec\n", totalTime/1000, (bytesMSec*1000));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// 6th test, 16bit Read.
|
||||||
|
pr_info("Parallel Test - Testing 16 bit read performance.\n");
|
||||||
|
do_gettimeofday(&start);
|
||||||
|
for(idx=0; idx < iterations; idx++)
|
||||||
|
{
|
||||||
|
// Read word.
|
||||||
|
rxData16 = z80io_PRL_Read16();
|
||||||
|
}
|
||||||
|
do_gettimeofday(&stop);
|
||||||
|
totalTime = (stop.tv_sec - start.tv_sec) * 1000000 + stop.tv_usec - start.tv_usec;
|
||||||
|
bytesMSec = (long)(2*iterations)/((long)totalTime/1000);
|
||||||
|
pr_info("Loop mode time=%ldms, %ldBytes/sec\n", totalTime/1000, (bytesMSec*1000));
|
||||||
|
|
||||||
|
pr_info("Press host RESET button Once to reset the CPLD.\n");
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
57
software/FusionX/src/driver/MZ2000/z80menu.c
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Name: z80menu.c
|
||||||
|
// Created: Oct 2022
|
||||||
|
// Author(s): Philip Smart
|
||||||
|
// Description: Z80 User Menu
|
||||||
|
// This file contains the methods used to present a menu of options to a user to aid
|
||||||
|
// in configuration and load/save of applications and data.
|
||||||
|
// Credits:
|
||||||
|
// Copyright: (c) 2019-2022 Philip Smart <philip.smart@net2net.org>
|
||||||
|
//
|
||||||
|
// History: Oct 2022 - Initial write of the z80 kernel driver software.
|
||||||
|
//
|
||||||
|
// Notes: See Makefile to enable/disable conditional components
|
||||||
|
//
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// This source file is free software: you can redistribute it and#or modify
|
||||||
|
// it under the terms of the GNU General Public License as published
|
||||||
|
// by the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This source file is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
|
||||||
|
#include <linux/module.h>
|
||||||
|
#include <linux/init.h>
|
||||||
|
#include <linux/kernel.h>
|
||||||
|
#include <linux/device.h>
|
||||||
|
#include <linux/fs.h>
|
||||||
|
#include <linux/mm.h>
|
||||||
|
#include <asm/uaccess.h>
|
||||||
|
#include <linux/slab.h>
|
||||||
|
#include <linux/string.h>
|
||||||
|
#include <linux/kthread.h>
|
||||||
|
#include <linux/sched.h>
|
||||||
|
#include <linux/delay.h>
|
||||||
|
#include <linux/time.h>
|
||||||
|
#include "z80io.h"
|
||||||
|
#include "z80menu.h"
|
||||||
|
|
||||||
|
#include <gpio_table.h>
|
||||||
|
#include <asm/io.h>
|
||||||
|
#include <infinity2m/gpio.h>
|
||||||
|
#include <infinity2m/registers.h>
|
||||||
|
|
||||||
|
void z80menu(void)
|
||||||
|
{
|
||||||
|
// Locals.
|
||||||
|
|
||||||
|
}
|
||||||
44
software/FusionX/src/driver/MZ2000/z80menu.h
Executable file
@@ -0,0 +1,44 @@
|
|||||||
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Name: z80menu.h
|
||||||
|
// Created: Oct 2022
|
||||||
|
// Author(s): Philip Smart
|
||||||
|
// Description: Z80 User Interface Menu
|
||||||
|
// This file contains the declarations required to provide a menu system allowing a
|
||||||
|
// user to configure and load/save applications/data.
|
||||||
|
// Credits:
|
||||||
|
// Copyright: (c) 2019-2022 Philip Smart <philip.smart@net2net.org>
|
||||||
|
//
|
||||||
|
// History: Oct 2022 - Initial write of the z80 kernel driver software.
|
||||||
|
//
|
||||||
|
// Notes: See Makefile to enable/disable conditional components
|
||||||
|
//
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// This source file is free software: you can redistribute it and#or modify
|
||||||
|
// it under the terms of the GNU General Public License as published
|
||||||
|
// by the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This source file is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
#ifndef Z80MENU_H
|
||||||
|
#define Z80MENU_H
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Function definitions.
|
||||||
|
//
|
||||||
|
void z80menu(void);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#endif // Z80MENU_H
|
||||||
403
software/FusionX/src/driver/MZ700/optparse.h
Normal file
@@ -0,0 +1,403 @@
|
|||||||
|
/* Optparse --- portable, reentrant, embeddable, getopt-like option parser
|
||||||
|
*
|
||||||
|
* This is free and unencumbered software released into the public domain.
|
||||||
|
*
|
||||||
|
* To get the implementation, define OPTPARSE_IMPLEMENTATION.
|
||||||
|
* Optionally define OPTPARSE_API to control the API's visibility
|
||||||
|
* and/or linkage (static, __attribute__, __declspec).
|
||||||
|
*
|
||||||
|
* The POSIX getopt() option parser has three fatal flaws. These flaws
|
||||||
|
* are solved by Optparse.
|
||||||
|
*
|
||||||
|
* 1) Parser state is stored entirely in global variables, some of
|
||||||
|
* which are static and inaccessible. This means only one thread can
|
||||||
|
* use getopt(). It also means it's not possible to recursively parse
|
||||||
|
* nested sub-arguments while in the middle of argument parsing.
|
||||||
|
* Optparse fixes this by storing all state on a local struct.
|
||||||
|
*
|
||||||
|
* 2) The POSIX standard provides no way to properly reset the parser.
|
||||||
|
* This means for portable code that getopt() is only good for one
|
||||||
|
* run, over one argv with one option string. It also means subcommand
|
||||||
|
* options cannot be processed with getopt(). Most implementations
|
||||||
|
* provide a method to reset the parser, but it's not portable.
|
||||||
|
* Optparse provides an optparse_arg() function for stepping over
|
||||||
|
* subcommands and continuing parsing of options with another option
|
||||||
|
* string. The Optparse struct itself can be passed around to
|
||||||
|
* subcommand handlers for additional subcommand option parsing. A
|
||||||
|
* full reset can be achieved by with an additional optparse_init().
|
||||||
|
*
|
||||||
|
* 3) Error messages are printed to stderr. This can be disabled with
|
||||||
|
* opterr, but the messages themselves are still inaccessible.
|
||||||
|
* Optparse solves this by writing an error message in its errmsg
|
||||||
|
* field. The downside to Optparse is that this error message will
|
||||||
|
* always be in English rather than the current locale.
|
||||||
|
*
|
||||||
|
* Optparse should be familiar with anyone accustomed to getopt(), and
|
||||||
|
* it could be a nearly drop-in replacement. The option string is the
|
||||||
|
* same and the fields have the same names as the getopt() global
|
||||||
|
* variables (optarg, optind, optopt).
|
||||||
|
*
|
||||||
|
* Optparse also supports GNU-style long options with optparse_long().
|
||||||
|
* The interface is slightly different and simpler than getopt_long().
|
||||||
|
*
|
||||||
|
* By default, argv is permuted as it is parsed, moving non-option
|
||||||
|
* arguments to the end. This can be disabled by setting the `permute`
|
||||||
|
* field to 0 after initialization.
|
||||||
|
*/
|
||||||
|
#ifndef OPTPARSE_H
|
||||||
|
#define OPTPARSE_H
|
||||||
|
|
||||||
|
#ifndef OPTPARSE_API
|
||||||
|
# define OPTPARSE_API
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct optparse {
|
||||||
|
char **argv;
|
||||||
|
int permute;
|
||||||
|
int optind;
|
||||||
|
int optopt;
|
||||||
|
char *optarg;
|
||||||
|
char errmsg[64];
|
||||||
|
int subopt;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum optparse_argtype {
|
||||||
|
OPTPARSE_NONE,
|
||||||
|
OPTPARSE_REQUIRED,
|
||||||
|
OPTPARSE_OPTIONAL
|
||||||
|
};
|
||||||
|
|
||||||
|
struct optparse_long {
|
||||||
|
const char *longname;
|
||||||
|
int shortname;
|
||||||
|
enum optparse_argtype argtype;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes the parser state.
|
||||||
|
*/
|
||||||
|
OPTPARSE_API
|
||||||
|
void optparse_init(struct optparse *options, char **argv);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read the next option in the argv array.
|
||||||
|
* @param optstring a getopt()-formatted option string.
|
||||||
|
* @return the next option character, -1 for done, or '?' for error
|
||||||
|
*
|
||||||
|
* Just like getopt(), a character followed by no colons means no
|
||||||
|
* argument. One colon means the option has a required argument. Two
|
||||||
|
* colons means the option takes an optional argument.
|
||||||
|
*/
|
||||||
|
OPTPARSE_API
|
||||||
|
int optparse(struct optparse *options, const char *optstring);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles GNU-style long options in addition to getopt() options.
|
||||||
|
* This works a lot like GNU's getopt_long(). The last option in
|
||||||
|
* longopts must be all zeros, marking the end of the array. The
|
||||||
|
* longindex argument may be NULL.
|
||||||
|
*/
|
||||||
|
OPTPARSE_API
|
||||||
|
int optparse_long(struct optparse *options,
|
||||||
|
const struct optparse_long *longopts,
|
||||||
|
int *longindex);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used for stepping over non-option arguments.
|
||||||
|
* @return the next non-option argument, or NULL for no more arguments
|
||||||
|
*
|
||||||
|
* Argument parsing can continue with optparse() after using this
|
||||||
|
* function. That would be used to parse the options for the
|
||||||
|
* subcommand returned by optparse_arg(). This function allows you to
|
||||||
|
* ignore the value of optind.
|
||||||
|
*/
|
||||||
|
OPTPARSE_API
|
||||||
|
char *optparse_arg(struct optparse *options);
|
||||||
|
|
||||||
|
/* Implementation */
|
||||||
|
#ifdef OPTPARSE_IMPLEMENTATION
|
||||||
|
|
||||||
|
#define OPTPARSE_MSG_INVALID "invalid option"
|
||||||
|
#define OPTPARSE_MSG_MISSING "option requires an argument"
|
||||||
|
#define OPTPARSE_MSG_TOOMANY "option takes no arguments"
|
||||||
|
|
||||||
|
static int
|
||||||
|
optparse_error(struct optparse *options, const char *msg, const char *data)
|
||||||
|
{
|
||||||
|
unsigned p = 0;
|
||||||
|
const char *sep = " -- '";
|
||||||
|
while (*msg)
|
||||||
|
options->errmsg[p++] = *msg++;
|
||||||
|
while (*sep)
|
||||||
|
options->errmsg[p++] = *sep++;
|
||||||
|
while (p < sizeof(options->errmsg) - 2 && *data)
|
||||||
|
options->errmsg[p++] = *data++;
|
||||||
|
options->errmsg[p++] = '\'';
|
||||||
|
options->errmsg[p++] = '\0';
|
||||||
|
return '?';
|
||||||
|
}
|
||||||
|
|
||||||
|
OPTPARSE_API
|
||||||
|
void
|
||||||
|
optparse_init(struct optparse *options, char **argv)
|
||||||
|
{
|
||||||
|
options->argv = argv;
|
||||||
|
options->permute = 1;
|
||||||
|
options->optind = 1;
|
||||||
|
options->subopt = 0;
|
||||||
|
options->optarg = 0;
|
||||||
|
options->errmsg[0] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
optparse_is_dashdash(const char *arg)
|
||||||
|
{
|
||||||
|
return arg != 0 && arg[0] == '-' && arg[1] == '-' && arg[2] == '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
optparse_is_shortopt(const char *arg)
|
||||||
|
{
|
||||||
|
return arg != 0 && arg[0] == '-' && arg[1] != '-' && arg[1] != '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
optparse_is_longopt(const char *arg)
|
||||||
|
{
|
||||||
|
return arg != 0 && arg[0] == '-' && arg[1] == '-' && arg[2] != '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
optparse_permute(struct optparse *options, int index)
|
||||||
|
{
|
||||||
|
char *nonoption = options->argv[index];
|
||||||
|
int i;
|
||||||
|
for (i = index; i < options->optind - 1; i++)
|
||||||
|
options->argv[i] = options->argv[i + 1];
|
||||||
|
options->argv[options->optind - 1] = nonoption;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
optparse_argtype(const char *optstring, char c)
|
||||||
|
{
|
||||||
|
int count = OPTPARSE_NONE;
|
||||||
|
if (c == ':')
|
||||||
|
return -1;
|
||||||
|
for (; *optstring && c != *optstring; optstring++);
|
||||||
|
if (!*optstring)
|
||||||
|
return -1;
|
||||||
|
if (optstring[1] == ':')
|
||||||
|
count += optstring[2] == ':' ? 2 : 1;
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
OPTPARSE_API
|
||||||
|
int
|
||||||
|
optparse(struct optparse *options, const char *optstring)
|
||||||
|
{
|
||||||
|
int type;
|
||||||
|
char *next;
|
||||||
|
char *option = options->argv[options->optind];
|
||||||
|
options->errmsg[0] = '\0';
|
||||||
|
options->optopt = 0;
|
||||||
|
options->optarg = 0;
|
||||||
|
if (option == 0) {
|
||||||
|
return -1;
|
||||||
|
} else if (optparse_is_dashdash(option)) {
|
||||||
|
options->optind++; /* consume "--" */
|
||||||
|
return -1;
|
||||||
|
} else if (!optparse_is_shortopt(option)) {
|
||||||
|
if (options->permute) {
|
||||||
|
int index = options->optind++;
|
||||||
|
int r = optparse(options, optstring);
|
||||||
|
optparse_permute(options, index);
|
||||||
|
options->optind--;
|
||||||
|
return r;
|
||||||
|
} else {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
option += options->subopt + 1;
|
||||||
|
options->optopt = option[0];
|
||||||
|
type = optparse_argtype(optstring, option[0]);
|
||||||
|
next = options->argv[options->optind + 1];
|
||||||
|
switch (type) {
|
||||||
|
case -1: {
|
||||||
|
char str[2] = {0, 0};
|
||||||
|
str[0] = option[0];
|
||||||
|
options->optind++;
|
||||||
|
return optparse_error(options, OPTPARSE_MSG_INVALID, str);
|
||||||
|
}
|
||||||
|
case OPTPARSE_NONE:
|
||||||
|
if (option[1]) {
|
||||||
|
options->subopt++;
|
||||||
|
} else {
|
||||||
|
options->subopt = 0;
|
||||||
|
options->optind++;
|
||||||
|
}
|
||||||
|
return option[0];
|
||||||
|
case OPTPARSE_REQUIRED:
|
||||||
|
options->subopt = 0;
|
||||||
|
options->optind++;
|
||||||
|
if (option[1]) {
|
||||||
|
options->optarg = option + 1;
|
||||||
|
} else if (next != 0) {
|
||||||
|
options->optarg = next;
|
||||||
|
options->optind++;
|
||||||
|
} else {
|
||||||
|
char str[2] = {0, 0};
|
||||||
|
str[0] = option[0];
|
||||||
|
options->optarg = 0;
|
||||||
|
return optparse_error(options, OPTPARSE_MSG_MISSING, str);
|
||||||
|
}
|
||||||
|
return option[0];
|
||||||
|
case OPTPARSE_OPTIONAL:
|
||||||
|
options->subopt = 0;
|
||||||
|
options->optind++;
|
||||||
|
if (option[1])
|
||||||
|
options->optarg = option + 1;
|
||||||
|
else
|
||||||
|
options->optarg = 0;
|
||||||
|
return option[0];
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
OPTPARSE_API
|
||||||
|
char *
|
||||||
|
optparse_arg(struct optparse *options)
|
||||||
|
{
|
||||||
|
char *option = options->argv[options->optind];
|
||||||
|
options->subopt = 0;
|
||||||
|
if (option != 0)
|
||||||
|
options->optind++;
|
||||||
|
return option;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
optparse_longopts_end(const struct optparse_long *longopts, int i)
|
||||||
|
{
|
||||||
|
return !longopts[i].longname && !longopts[i].shortname;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
optparse_from_long(const struct optparse_long *longopts, char *optstring)
|
||||||
|
{
|
||||||
|
char *p = optstring;
|
||||||
|
int i;
|
||||||
|
for (i = 0; !optparse_longopts_end(longopts, i); i++) {
|
||||||
|
if (longopts[i].shortname && longopts[i].shortname < 127) {
|
||||||
|
int a;
|
||||||
|
*p++ = longopts[i].shortname;
|
||||||
|
for (a = 0; a < (int)longopts[i].argtype; a++)
|
||||||
|
*p++ = ':';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*p = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Unlike strcmp(), handles options containing "=". */
|
||||||
|
static int
|
||||||
|
optparse_longopts_match(const char *longname, const char *option)
|
||||||
|
{
|
||||||
|
const char *a = option, *n = longname;
|
||||||
|
if (longname == 0)
|
||||||
|
return 0;
|
||||||
|
for (; *a && *n && *a != '='; a++, n++)
|
||||||
|
if (*a != *n)
|
||||||
|
return 0;
|
||||||
|
return *n == '\0' && (*a == '\0' || *a == '=');
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return the part after "=", or NULL. */
|
||||||
|
static char *
|
||||||
|
optparse_longopts_arg(char *option)
|
||||||
|
{
|
||||||
|
for (; *option && *option != '='; option++);
|
||||||
|
if (*option == '=')
|
||||||
|
return option + 1;
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
optparse_long_fallback(struct optparse *options,
|
||||||
|
const struct optparse_long *longopts,
|
||||||
|
int *longindex)
|
||||||
|
{
|
||||||
|
int result;
|
||||||
|
char optstring[96 * 3 + 1]; /* 96 ASCII printable characters */
|
||||||
|
optparse_from_long(longopts, optstring);
|
||||||
|
result = optparse(options, optstring);
|
||||||
|
if (longindex != 0) {
|
||||||
|
*longindex = -1;
|
||||||
|
if (result != -1) {
|
||||||
|
int i;
|
||||||
|
for (i = 0; !optparse_longopts_end(longopts, i); i++)
|
||||||
|
if (longopts[i].shortname == options->optopt)
|
||||||
|
*longindex = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
OPTPARSE_API
|
||||||
|
int
|
||||||
|
optparse_long(struct optparse *options,
|
||||||
|
const struct optparse_long *longopts,
|
||||||
|
int *longindex)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
char *option = options->argv[options->optind];
|
||||||
|
if (option == 0) {
|
||||||
|
return -1;
|
||||||
|
} else if (optparse_is_dashdash(option)) {
|
||||||
|
options->optind++; /* consume "--" */
|
||||||
|
return -1;
|
||||||
|
} else if (optparse_is_shortopt(option)) {
|
||||||
|
return optparse_long_fallback(options, longopts, longindex);
|
||||||
|
} else if (!optparse_is_longopt(option)) {
|
||||||
|
if (options->permute) {
|
||||||
|
int index = options->optind++;
|
||||||
|
int r = optparse_long(options, longopts, longindex);
|
||||||
|
optparse_permute(options, index);
|
||||||
|
options->optind--;
|
||||||
|
return r;
|
||||||
|
} else {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Parse as long option. */
|
||||||
|
options->errmsg[0] = '\0';
|
||||||
|
options->optopt = 0;
|
||||||
|
options->optarg = 0;
|
||||||
|
option += 2; /* skip "--" */
|
||||||
|
options->optind++;
|
||||||
|
for (i = 0; !optparse_longopts_end(longopts, i); i++) {
|
||||||
|
const char *name = longopts[i].longname;
|
||||||
|
if (optparse_longopts_match(name, option)) {
|
||||||
|
char *arg;
|
||||||
|
if (longindex)
|
||||||
|
*longindex = i;
|
||||||
|
options->optopt = longopts[i].shortname;
|
||||||
|
arg = optparse_longopts_arg(option);
|
||||||
|
if (longopts[i].argtype == OPTPARSE_NONE && arg != 0) {
|
||||||
|
return optparse_error(options, OPTPARSE_MSG_TOOMANY, name);
|
||||||
|
} if (arg != 0) {
|
||||||
|
options->optarg = arg;
|
||||||
|
} else if (longopts[i].argtype == OPTPARSE_REQUIRED) {
|
||||||
|
options->optarg = options->argv[options->optind];
|
||||||
|
if (options->optarg == 0)
|
||||||
|
return optparse_error(options, OPTPARSE_MSG_MISSING, name);
|
||||||
|
else
|
||||||
|
options->optind++;
|
||||||
|
}
|
||||||
|
return options->optopt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return optparse_error(options, OPTPARSE_MSG_INVALID, option);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* OPTPARSE_IMPLEMENTATION */
|
||||||
|
#endif /* OPTPARSE_H */
|
||||||
734
software/FusionX/src/driver/MZ700/z80ctrl.c
Normal file
@@ -0,0 +1,734 @@
|
|||||||
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Name: z80ctrl.c
|
||||||
|
// Created: Oct 2022
|
||||||
|
// Author(s): Philip Smart
|
||||||
|
// Description: Z80 Control Interface
|
||||||
|
// This file contains a command line utility tool for controlling the z80drv device
|
||||||
|
// driver. The tool allows manipulation of the emulated Z80, inspection of its
|
||||||
|
// memory and data, transmission of adhoc commands to the underlying CPLD-Z80
|
||||||
|
// gateway and loading/saving of programs and data to/from the Z80 virtual and
|
||||||
|
// host memory.
|
||||||
|
//
|
||||||
|
// Credits: Zilog Z80 CPU Emulator v0.2 written by Manuel Sainz de Baranda y Goñi
|
||||||
|
// The Z80 CPU Emulator is the heart of the Z80 device driver.
|
||||||
|
// Copyright: (c) 2019-2022 Philip Smart <philip.smart@net2net.org>
|
||||||
|
// (c) 1999-2022 Manuel Sainz de Baranda y Goñi
|
||||||
|
//
|
||||||
|
// History: Oct 2022 - Initial write of the z80 kernel driver software.
|
||||||
|
//
|
||||||
|
// Notes: See Makefile to enable/disable conditional components
|
||||||
|
//
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// This source file is free software: you can redistribute it and#or modify
|
||||||
|
// it under the terms of the GNU General Public License as published
|
||||||
|
// by the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This source file is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <sys/mman.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <sys/select.h>
|
||||||
|
#include <termios.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <Z/constants/pointer.h>
|
||||||
|
#include <Z/macros/member.h>
|
||||||
|
#include <Z/macros/array.h>
|
||||||
|
#include <Z80.h>
|
||||||
|
#include "z80driver.h"
|
||||||
|
|
||||||
|
#define VERSION "1.0"
|
||||||
|
#define AUTHOR "P.D.Smart"
|
||||||
|
#define COPYRIGHT "(c) 2018-22"
|
||||||
|
|
||||||
|
// Getopt_long is buggy so we use optparse.
|
||||||
|
#define OPTPARSE_IMPLEMENTATION
|
||||||
|
#define OPTPARSE_API static
|
||||||
|
#include "optparse.h"
|
||||||
|
|
||||||
|
// Device driver name.
|
||||||
|
#define DEVICE_FILENAME "/dev/z80drv"
|
||||||
|
|
||||||
|
// Constants for the Sharp MZ80A MZF file format.
|
||||||
|
#define MZF_HEADER_SIZE 128 // Size of the MZF header.
|
||||||
|
#define MZF_ATTRIBUTE 0x00 // Code Type, 01 = Machine Code.
|
||||||
|
#define MZF_FILENAME 0x01 // Title/Name (17 bytes).
|
||||||
|
#define MZF_FILENAME_LEN 17 // Length of the filename, it is not NULL terminated, generally a CR can be taken as terminator but not guaranteed.
|
||||||
|
#define MZF_FILESIZE 0x12 // Size of program.
|
||||||
|
#define MZF_LOADADDR 0x14 // Load address of program.
|
||||||
|
#define MZF_EXECADDR 0x16 // Exec address of program.
|
||||||
|
#define MZF_COMMENT 0x18 // Comment, used for details of the file or startup code.
|
||||||
|
#define MZF_COMMENT_LEN 104 // Length of the comment field.
|
||||||
|
#define CMT_TYPE_OBJCD 0x001 // MZF contains a binary object.
|
||||||
|
#define CMT_TYPE_BTX1CD 0x002 // MZF contains a BASIC program.
|
||||||
|
#define CMT_TYPE_BTX2CD 0x005 // MZF contains a BASIC program.
|
||||||
|
#define CMT_TYPE_TZOBJCD0 0x0F8 // MZF contains a TZFS binary object for page 0.
|
||||||
|
#define CMT_TYPE_TZOBJCD1 0x0F9
|
||||||
|
#define CMT_TYPE_TZOBJCD2 0x0FA
|
||||||
|
#define CMT_TYPE_TZOBJCD3 0x0FB
|
||||||
|
#define CMT_TYPE_TZOBJCD4 0x0FC
|
||||||
|
#define CMT_TYPE_TZOBJCD5 0x0FD
|
||||||
|
#define CMT_TYPE_TZOBJCD6 0x0FE
|
||||||
|
#define CMT_TYPE_TZOBJCD7 0x0FF // MZF contains a TZFS binary object for page 7.
|
||||||
|
#define MZ_CMT_ADDR 0x10F0
|
||||||
|
|
||||||
|
// Structure to define a Sharp MZ80A MZF directory structure. This header appears at the beginning of every Sharp MZ80A tape (and more recently archived/emulator) images.
|
||||||
|
//
|
||||||
|
typedef struct __attribute__((__packed__)) {
|
||||||
|
uint8_t attr; // MZF attribute describing the file.
|
||||||
|
uint8_t fileName[MZF_FILENAME_LEN]; // Each directory entry is the size of an MZF filename.
|
||||||
|
uint16_t fileSize; // Size of file.
|
||||||
|
uint16_t loadAddr; // Load address for the file.
|
||||||
|
uint16_t execAddr; // Execution address where the Z80 starts processing.
|
||||||
|
uint8_t comment[MZF_COMMENT_LEN]; // Text comment field but often contains a startup machine code program.
|
||||||
|
} t_svcDirEnt;
|
||||||
|
|
||||||
|
// Possible commands to be issued to the Z80 driver.
|
||||||
|
enum CTRL_COMMANDS {
|
||||||
|
Z80_CMD_STOP = 0,
|
||||||
|
Z80_CMD_START = 1,
|
||||||
|
Z80_CMD_PAUSE = 2,
|
||||||
|
Z80_CMD_CONTINUE = 3,
|
||||||
|
Z80_CMD_RESET = 4,
|
||||||
|
Z80_CMD_SPEED = 5,
|
||||||
|
Z80_CMD_HOST_RAM = 6,
|
||||||
|
Z80_CMD_VIRTUAL_RAM = 7,
|
||||||
|
Z80_CMD_DUMP_MEMORY = 8,
|
||||||
|
Z80_CMD_MEMORY_TEST = 9,
|
||||||
|
CPLD_CMD_SEND_CMD = 10,
|
||||||
|
CPLD_CMD_SPI_TEST = 11,
|
||||||
|
CPLD_CMD_PRL_TEST = 12
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// Shared memory between this process and the Z80 driver.
|
||||||
|
static t_Z80Ctrl *Z80Ctrl = NULL;
|
||||||
|
|
||||||
|
// Method to obtain and return the output screen width.
|
||||||
|
//
|
||||||
|
uint8_t getScreenWidth(void)
|
||||||
|
{
|
||||||
|
return(MAX_SCREEN_WIDTH);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct termios orig_termios;
|
||||||
|
|
||||||
|
void reset_terminal_mode()
|
||||||
|
{
|
||||||
|
tcsetattr(0, TCSANOW, &orig_termios);
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_conio_terminal_mode()
|
||||||
|
{
|
||||||
|
struct termios new_termios;
|
||||||
|
|
||||||
|
/* take two copies - one for now, one for later */
|
||||||
|
tcgetattr(0, &orig_termios);
|
||||||
|
memcpy(&new_termios, &orig_termios, sizeof(new_termios));
|
||||||
|
|
||||||
|
/* register cleanup handler, and set the new terminal mode */
|
||||||
|
atexit(reset_terminal_mode);
|
||||||
|
cfmakeraw(&new_termios);
|
||||||
|
tcsetattr(0, TCSANOW, &new_termios);
|
||||||
|
}
|
||||||
|
|
||||||
|
int kbhit()
|
||||||
|
{
|
||||||
|
struct timeval tv = { 0L, 0L };
|
||||||
|
fd_set fds;
|
||||||
|
FD_ZERO(&fds);
|
||||||
|
FD_SET(0, &fds);
|
||||||
|
return select(1, &fds, NULL, NULL, &tv) > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int getch(uint8_t wait)
|
||||||
|
{
|
||||||
|
int r;
|
||||||
|
unsigned char c;
|
||||||
|
|
||||||
|
if(wait != 0 || (wait == 0 && kbhit()))
|
||||||
|
{
|
||||||
|
if ((r = read(0, &c, sizeof(c))) < 0) {
|
||||||
|
return r;
|
||||||
|
} else {
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void delay(int number_of_seconds)
|
||||||
|
{
|
||||||
|
// Converting time into milli_seconds
|
||||||
|
int milli_seconds = 1000 * number_of_seconds;
|
||||||
|
|
||||||
|
// Storing start time
|
||||||
|
clock_t start_time = clock();
|
||||||
|
|
||||||
|
// looping till required time is not achieved
|
||||||
|
while (clock() < start_time + milli_seconds);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Function to dump out a given section of memory via the UART.
|
||||||
|
//
|
||||||
|
int memoryDump(uint32_t memaddr, uint32_t memsize, uint8_t memoryFlag, uint32_t memwidth, uint32_t dispaddr, uint8_t dispwidth)
|
||||||
|
{
|
||||||
|
uint8_t displayWidth = dispwidth;;
|
||||||
|
uint32_t pnt = memaddr;
|
||||||
|
uint32_t endAddr = memaddr + memsize;
|
||||||
|
uint32_t addr = dispaddr;
|
||||||
|
uint32_t i = 0;
|
||||||
|
//uint32_t data;
|
||||||
|
int8_t keyIn;
|
||||||
|
int result = -1;
|
||||||
|
char c = 0;
|
||||||
|
|
||||||
|
// Sanity check. memoryFlag == 0 required kernel driver to dump so we exit as it cannot be performed here.
|
||||||
|
if(memoryFlag == 0)
|
||||||
|
return(-1);
|
||||||
|
|
||||||
|
// Reconfigure terminal to allow non-blocking key input.
|
||||||
|
//
|
||||||
|
set_conio_terminal_mode();
|
||||||
|
|
||||||
|
// If not set, calculate output line width according to connected display width.
|
||||||
|
//
|
||||||
|
if(displayWidth == 0)
|
||||||
|
{
|
||||||
|
switch(getScreenWidth())
|
||||||
|
{
|
||||||
|
case 40:
|
||||||
|
displayWidth = 8;
|
||||||
|
break;
|
||||||
|
case 80:
|
||||||
|
displayWidth = 16;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
displayWidth = 32;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
printf("%08lX", addr); // print address
|
||||||
|
printf(": ");
|
||||||
|
|
||||||
|
// print hexadecimal data
|
||||||
|
for (i=0; i < displayWidth; )
|
||||||
|
{
|
||||||
|
switch(memwidth)
|
||||||
|
{
|
||||||
|
case 16:
|
||||||
|
if(pnt+i < endAddr)
|
||||||
|
printf("%04X", memoryFlag == 1 ? (uint16_t)Z80Ctrl->memory[pnt+i] : memoryFlag == 2 ? (uint16_t)Z80Ctrl->page[pnt+i] : (uint16_t)Z80Ctrl->iopage[pnt+i]);
|
||||||
|
else
|
||||||
|
printf(" ");
|
||||||
|
i++;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 32:
|
||||||
|
if(pnt+i < endAddr)
|
||||||
|
printf("%08lX", memoryFlag == 1 ? (uint32_t)Z80Ctrl->memory[pnt+i] : memoryFlag == 2 ? (uint32_t)Z80Ctrl->page[pnt+i] : (uint32_t)Z80Ctrl->iopage[pnt+i]);
|
||||||
|
else
|
||||||
|
printf(" ");
|
||||||
|
i++;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 8:
|
||||||
|
default:
|
||||||
|
if(pnt+i < endAddr)
|
||||||
|
printf("%02X", memoryFlag == 1 ? (uint8_t)Z80Ctrl->memory[pnt+i] : memoryFlag == 2 ? (uint8_t)Z80Ctrl->page[pnt+i] : (uint8_t)Z80Ctrl->iopage[pnt+i]);
|
||||||
|
else
|
||||||
|
printf(" ");
|
||||||
|
i++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
fputc((char)' ', stdout);
|
||||||
|
}
|
||||||
|
|
||||||
|
// print ascii data
|
||||||
|
printf(" |");
|
||||||
|
|
||||||
|
// print single ascii char
|
||||||
|
for (i=0; i < displayWidth; i++)
|
||||||
|
{
|
||||||
|
c = memoryFlag == 1 ? (char)Z80Ctrl->memory[pnt+i] : memoryFlag == 2 ? (char)Z80Ctrl->page[pnt+i] : (char)Z80Ctrl->iopage[pnt+i];
|
||||||
|
if ((pnt+i < endAddr) && (c >= ' ') && (c <= '~'))
|
||||||
|
fputc((char)c, stdout);
|
||||||
|
else
|
||||||
|
fputc((char)' ', stdout);
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("|\r\n");
|
||||||
|
fflush(stdout);
|
||||||
|
|
||||||
|
// Move on one row.
|
||||||
|
pnt += displayWidth;
|
||||||
|
addr += displayWidth;
|
||||||
|
|
||||||
|
// User abort (ESC), pause (Space) or all done?
|
||||||
|
//
|
||||||
|
keyIn = getch(0);
|
||||||
|
if(keyIn == ' ')
|
||||||
|
{
|
||||||
|
do {
|
||||||
|
keyIn = getch(0);
|
||||||
|
} while(keyIn != ' ' && keyIn != 0x1b);
|
||||||
|
}
|
||||||
|
// Escape key pressed, exit with 0 to indicate this to caller.
|
||||||
|
if (keyIn == 0x1b)
|
||||||
|
{
|
||||||
|
sleep(1);
|
||||||
|
result = 0;
|
||||||
|
goto memoryDumpExit;
|
||||||
|
}
|
||||||
|
|
||||||
|
// End of buffer, exit the loop.
|
||||||
|
if(pnt >= (memaddr + memsize))
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Normal exit, return -1 to show no key pressed.
|
||||||
|
memoryDumpExit:
|
||||||
|
reset_terminal_mode();
|
||||||
|
return(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Method to load a program or data file into the Z80 memory. First load into Virtual memory and then trigger a sync to bring Host RAM in line.
|
||||||
|
//
|
||||||
|
int z80load(int fdZ80, char *fileName)
|
||||||
|
{
|
||||||
|
// Locals.
|
||||||
|
struct ioctlCmd ioctlCmd;
|
||||||
|
int ret = 0;
|
||||||
|
t_svcDirEnt mzfHeader;
|
||||||
|
|
||||||
|
// Pause the Z80.
|
||||||
|
//
|
||||||
|
ioctlCmd.cmd = IOCTL_CMD_Z80_PAUSE;
|
||||||
|
ioctl(fdZ80, IOCTL_CMD_SEND, &ioctlCmd);
|
||||||
|
|
||||||
|
// Open the file and read directly into the Virtual memory via the share.
|
||||||
|
FILE *ptr;
|
||||||
|
ptr = fopen(fileName, "rb");
|
||||||
|
if(ptr)
|
||||||
|
{
|
||||||
|
printf("File:%s\n", fileName);
|
||||||
|
// First the header.
|
||||||
|
fread((uint8_t *)&mzfHeader, MZF_HEADER_SIZE, 1, ptr);
|
||||||
|
printf("Load:%x\n", mzfHeader.loadAddr);
|
||||||
|
if(mzfHeader.loadAddr > 0x1000)
|
||||||
|
{
|
||||||
|
printf("Memcpy:%x,%x\n", mzfHeader.loadAddr, mzfHeader.fileSize);
|
||||||
|
// Copy in the header.
|
||||||
|
memcpy((uint8_t *)&Z80Ctrl->memory[MZ_CMT_ADDR], (uint8_t *)&mzfHeader, MZF_HEADER_SIZE);
|
||||||
|
|
||||||
|
printf("Memcpy:%x,%x\n", mzfHeader.loadAddr, mzfHeader.fileSize);
|
||||||
|
// Now read in the data.
|
||||||
|
fread(&Z80Ctrl->memory[mzfHeader.loadAddr], mzfHeader.fileSize, 1, ptr);
|
||||||
|
printf("Memcpy:%x,%x\n", mzfHeader.loadAddr, mzfHeader.fileSize);
|
||||||
|
printf("Loaded %s, Size:%04x, Addr:%04x, Exec:%04x\n", fileName, mzfHeader.fileSize, mzfHeader.loadAddr, mzfHeader.execAddr);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sync the loaded image from Virtual memory to hard memory.
|
||||||
|
ioctlCmd.cmd = IOCTL_CMD_SYNC_TO_HOST_RAM;
|
||||||
|
ioctl(fdZ80, IOCTL_CMD_SEND, &ioctlCmd);
|
||||||
|
|
||||||
|
// Resume Z80 processing.
|
||||||
|
//
|
||||||
|
ioctlCmd.cmd = IOCTL_CMD_Z80_CONTINUE;
|
||||||
|
ioctl(fdZ80, IOCTL_CMD_SEND, &ioctlCmd);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
printf("Couldnt open file\n");
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Method to request basic Z80 operations.
|
||||||
|
//
|
||||||
|
int ctrlCmd(int fdZ80, enum CTRL_COMMANDS cmd, long param1, long param2, long param3)
|
||||||
|
{
|
||||||
|
// Locals.
|
||||||
|
struct ioctlCmd ioctlCmd;
|
||||||
|
uint32_t idx;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
switch(cmd)
|
||||||
|
{
|
||||||
|
case Z80_CMD_STOP:
|
||||||
|
// Use IOCTL to request Z80 to Stop (power off) processing.
|
||||||
|
ioctlCmd.cmd = IOCTL_CMD_Z80_STOP;
|
||||||
|
ioctl(fdZ80, IOCTL_CMD_SEND, &ioctlCmd);
|
||||||
|
break;
|
||||||
|
case Z80_CMD_START:
|
||||||
|
// Use IOCTL to request Z80 to Start (power on) processing.
|
||||||
|
ioctlCmd.cmd = IOCTL_CMD_Z80_START;
|
||||||
|
ioctl(fdZ80, IOCTL_CMD_SEND, &ioctlCmd);
|
||||||
|
break;
|
||||||
|
case Z80_CMD_PAUSE:
|
||||||
|
// Use IOCTL to request Z80 to pause processing.
|
||||||
|
ioctlCmd.cmd = IOCTL_CMD_Z80_PAUSE;
|
||||||
|
ioctl(fdZ80, IOCTL_CMD_SEND, &ioctlCmd);
|
||||||
|
break;
|
||||||
|
case Z80_CMD_CONTINUE:
|
||||||
|
// Use IOCTL to request Z80 continue processing.
|
||||||
|
ioctlCmd.cmd = IOCTL_CMD_Z80_CONTINUE;
|
||||||
|
ioctl(fdZ80, IOCTL_CMD_SEND, &ioctlCmd);
|
||||||
|
break;
|
||||||
|
case Z80_CMD_RESET:
|
||||||
|
// Use IOCTL to request Z80 reset.
|
||||||
|
ioctlCmd.cmd = IOCTL_CMD_Z80_RESET;
|
||||||
|
ioctl(fdZ80, IOCTL_CMD_SEND, &ioctlCmd);
|
||||||
|
break;
|
||||||
|
case Z80_CMD_SPEED:
|
||||||
|
// Check value is in range.
|
||||||
|
for(idx=1; idx < 256; idx+=idx)
|
||||||
|
{
|
||||||
|
if((uint32_t)param1 == idx) break;
|
||||||
|
}
|
||||||
|
if(idx == 256)
|
||||||
|
{
|
||||||
|
printf("Speed factor is illegal. It must be a multiple value of the original CPU clock, ie. 1x, 2x, 4x etc\n");
|
||||||
|
ret = -1;
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
// Use IOCTL to request Z80 cpu freq change.
|
||||||
|
ioctlCmd.speed.speedMultiplier = (uint32_t)param1;
|
||||||
|
ioctlCmd.cmd = IOCTL_CMD_Z80_CPU_FREQ;
|
||||||
|
ioctl(fdZ80, IOCTL_CMD_SEND, &ioctlCmd);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case CPLD_CMD_SEND_CMD:
|
||||||
|
// Build up the IOCTL command to request the given data is sent to the CPLD.
|
||||||
|
ioctlCmd.cmd = IOCTL_CMD_CPLD_CMD;
|
||||||
|
ioctlCmd.cpld.cmd = (uint32_t)param1;
|
||||||
|
ioctl(fdZ80, IOCTL_CMD_SEND, &ioctlCmd);
|
||||||
|
break;
|
||||||
|
case Z80_CMD_DUMP_MEMORY:
|
||||||
|
// If virtual memory, we can dump it via the shared memory segment.
|
||||||
|
if((uint8_t)param1)
|
||||||
|
{
|
||||||
|
memoryDump((uint32_t)param2, (uint32_t)param3, (uint8_t)param1, (uint8_t)param1 == 2 || (uint8_t)param1 == 3 ? 32 : 8, (uint32_t)param2, 0);
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
// Build an IOCTL command to get the driver to dump the memory.
|
||||||
|
ioctlCmd.cmd = IOCTL_CMD_DUMP_MEMORY;
|
||||||
|
ioctlCmd.addr.start = (uint32_t)param2;
|
||||||
|
ioctlCmd.addr.end = (uint32_t)param2+(uint32_t)param3;
|
||||||
|
ioctlCmd.addr.size = (uint32_t)param3;
|
||||||
|
ioctl(fdZ80, IOCTL_CMD_SEND, &ioctlCmd);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case Z80_CMD_HOST_RAM:
|
||||||
|
// Use IOCTL to request change to host RAM.
|
||||||
|
ioctlCmd.cmd = IOCTL_CMD_USE_HOST_RAM;
|
||||||
|
ioctl(fdZ80, IOCTL_CMD_SEND, &ioctlCmd);
|
||||||
|
break;
|
||||||
|
case Z80_CMD_VIRTUAL_RAM:
|
||||||
|
// Use IOCTL to request change to host RAM.
|
||||||
|
ioctlCmd.cmd = IOCTL_CMD_USE_VIRTUAL_RAM;
|
||||||
|
ioctl(fdZ80, IOCTL_CMD_SEND, &ioctlCmd);
|
||||||
|
break;
|
||||||
|
case Z80_CMD_MEMORY_TEST:
|
||||||
|
// Send command to test the SPI.
|
||||||
|
ioctlCmd.cmd = IOCTL_CMD_Z80_MEMTEST;
|
||||||
|
ioctl(fdZ80, IOCTL_CMD_SEND, &ioctlCmd);
|
||||||
|
break;
|
||||||
|
case CPLD_CMD_PRL_TEST:
|
||||||
|
// Send command to test the SPI.
|
||||||
|
ioctlCmd.cmd = IOCTL_CMD_PRL_TEST;
|
||||||
|
ioctl(fdZ80, IOCTL_CMD_SEND, &ioctlCmd);
|
||||||
|
break;
|
||||||
|
case CPLD_CMD_SPI_TEST:
|
||||||
|
// Send command to test the SPI.
|
||||||
|
ioctlCmd.cmd = IOCTL_CMD_SPI_TEST;
|
||||||
|
ioctl(fdZ80, IOCTL_CMD_SEND, &ioctlCmd);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
printf("Command not supported!\n");
|
||||||
|
ret = -1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Method to perform some simple tests on the Z80 emulator.
|
||||||
|
//
|
||||||
|
int z80test(int fdZ80)
|
||||||
|
{
|
||||||
|
// Locals.
|
||||||
|
struct ioctlCmd ioctlCmd;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
// Stop the Z80.
|
||||||
|
//
|
||||||
|
printf("Send STOP\n");
|
||||||
|
ioctlCmd.cmd = IOCTL_CMD_Z80_STOP;
|
||||||
|
ioctl(fdZ80, IOCTL_CMD_SEND, &ioctlCmd);
|
||||||
|
|
||||||
|
FILE *ptr;
|
||||||
|
ptr = fopen("/customer/mz700.rom", "rb");
|
||||||
|
if(ptr)
|
||||||
|
{
|
||||||
|
fread(&Z80Ctrl->memory, 65536, 1, ptr);
|
||||||
|
} else printf("Couldnt open file\n");
|
||||||
|
|
||||||
|
// Configure the Z80.
|
||||||
|
//
|
||||||
|
printf("Send SETPC\n");
|
||||||
|
ioctlCmd.z80.pc = 0;
|
||||||
|
ioctl(fdZ80, IOCTL_CMD_SETPC, &ioctlCmd);
|
||||||
|
|
||||||
|
memoryDump(0 , 65536, 1, 8, 0, 0);
|
||||||
|
|
||||||
|
// Start the Z80.
|
||||||
|
//
|
||||||
|
printf("Send START\n");
|
||||||
|
ioctlCmd.cmd = IOCTL_CMD_Z80_START;
|
||||||
|
ioctl(fdZ80, IOCTL_CMD_SEND, &ioctlCmd);
|
||||||
|
|
||||||
|
delay(10);
|
||||||
|
|
||||||
|
printf("Send STOP\n");
|
||||||
|
ioctlCmd.cmd = IOCTL_CMD_Z80_STOP;
|
||||||
|
ioctl(fdZ80, IOCTL_CMD_SEND, &ioctlCmd);
|
||||||
|
|
||||||
|
memoryDump(0, 65536, 1, 8, 0, 0);
|
||||||
|
out:
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Output usage screen. So mamy commands you do need to be prompted!!
|
||||||
|
void showArgs(char *progName, struct optparse *options)
|
||||||
|
{
|
||||||
|
printf("%s %s %s %s\n\n", progName, VERSION, COPYRIGHT, AUTHOR);
|
||||||
|
printf("Synopsis:\n");
|
||||||
|
printf("%s --help # This help screen.\n", progName);
|
||||||
|
printf(" --cmd <command> = RESET # Reset the Z80\n");
|
||||||
|
printf(" = STOP # Stop and power off the Z80\n");
|
||||||
|
printf(" = START # Power on and start the Z80\n");
|
||||||
|
printf(" = PAUSE # Pause running Z80\n");
|
||||||
|
printf(" = CONTINUE # Continue Z80 execution\n");
|
||||||
|
printf(" = HOSTRAM # Use HOST DRAM\n");
|
||||||
|
printf(" = VIRTRAM # Use Virtual RAM\n");
|
||||||
|
printf(" = SPEED --speed <1, 2, 4, 8, 16, 32, 64, 128> # In Virtual RAM mode, set CPU speed to base clock x factor.\n");
|
||||||
|
printf(" = LOADMZF --file <mzf filename> # Load MZF file into memory.\n");
|
||||||
|
printf(" = DUMP --start <24bit addr> --end <24bit addr> --virtual <0 - Host RAM, 1 = Virtual RAM, 2 = PageTable, 3 = IOPageTable>\n");
|
||||||
|
printf(" = CPLDCMD --data <32bit command> # Send adhoc 32bit command to CPLD.\n");
|
||||||
|
printf(" = Z80TEST # Perform various debugging tests\n");
|
||||||
|
printf(" = SPITEST # Perform SPI testing\n");
|
||||||
|
printf(" = PRLTEST # Perform Parallel Bus testing\n");
|
||||||
|
printf(" = Z80MEMTEST # Perform HOST memory tests.\n");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
int fdZ80;
|
||||||
|
char buff[64];
|
||||||
|
char cmd[64] = { 0 };
|
||||||
|
char fileName[256] = { 0 };
|
||||||
|
int opt;
|
||||||
|
long hexData = 0;
|
||||||
|
long speedMultiplier = 1;
|
||||||
|
long startAddr = 0x0000;
|
||||||
|
long endAddr = 0x1000;
|
||||||
|
int virtualMemory = 0;
|
||||||
|
int helpFlag = 0;
|
||||||
|
int verboseFlag = 0;
|
||||||
|
|
||||||
|
// Define parameters to be processed.
|
||||||
|
struct optparse options;
|
||||||
|
static struct optparse_long long_options[] =
|
||||||
|
{
|
||||||
|
{"help", 'h', OPTPARSE_NONE},
|
||||||
|
{"cmd", 'c', OPTPARSE_REQUIRED},
|
||||||
|
{"file", 'f', OPTPARSE_REQUIRED},
|
||||||
|
{"data", 'd', OPTPARSE_REQUIRED},
|
||||||
|
{"speed", 'S', OPTPARSE_REQUIRED},
|
||||||
|
{"virtual", 'V', OPTPARSE_REQUIRED},
|
||||||
|
{"start", 's', OPTPARSE_REQUIRED},
|
||||||
|
{"end", 'e', OPTPARSE_REQUIRED},
|
||||||
|
{"verbose", 'v', OPTPARSE_NONE},
|
||||||
|
{0}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Parse the command line options.
|
||||||
|
//
|
||||||
|
optparse_init(&options, argv);
|
||||||
|
while((opt = optparse_long(&options, long_options, NULL)) != -1)
|
||||||
|
{
|
||||||
|
switch(opt)
|
||||||
|
{
|
||||||
|
// Hex data.
|
||||||
|
case 'd':
|
||||||
|
hexData = strtol(options.optarg, NULL, 0);
|
||||||
|
//printf("Hex data:%08x\n", hexData);
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Start address for memory operations.
|
||||||
|
case 's':
|
||||||
|
startAddr = strtol(options.optarg, NULL, 0);
|
||||||
|
//printf("Start Addr:%04x\n", startAddr);
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Speed multiplication factor for CPU governor when running in virtual memory.
|
||||||
|
case 'S':
|
||||||
|
speedMultiplier = strtol(options.optarg, NULL, 0);
|
||||||
|
//printf("Speed = base freq x %d\n", speedFactor);
|
||||||
|
break;
|
||||||
|
|
||||||
|
// End address for memory operations.
|
||||||
|
case 'e':
|
||||||
|
endAddr = strtol(options.optarg, NULL, 0);
|
||||||
|
//printf("End Addr:%04x\n", endAddr);
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Virtual memory flag, 0 = host, 1 = virtual memory, 2 = page table, 3 = iopage table.
|
||||||
|
case 'V':
|
||||||
|
virtualMemory = atoi(options.optarg);
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Filename.
|
||||||
|
case 'f':
|
||||||
|
strcpy(fileName, options.optarg);
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Command to execute.
|
||||||
|
case 'c':
|
||||||
|
strcpy(cmd, options.optarg);
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Verbose mode.
|
||||||
|
case 'v':
|
||||||
|
verboseFlag = 1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Command help needed.
|
||||||
|
case 'h':
|
||||||
|
helpFlag = 1;
|
||||||
|
showArgs(argv[0], &options);
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Unrecognised, show synopsis.
|
||||||
|
case '?':
|
||||||
|
showArgs(argv[0], &options);
|
||||||
|
printf("%s: %s\n", argv[0], options.errmsg);
|
||||||
|
return(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Open the z80drv driver and attach to its shared memory, basically the Z80 control structure which includes the virtual Z80 memory.
|
||||||
|
fdZ80 = open(DEVICE_FILENAME, O_RDWR|O_NDELAY);
|
||||||
|
if(fdZ80 >= 0)
|
||||||
|
{
|
||||||
|
Z80Ctrl = (t_Z80Ctrl *)mmap(0, sizeof(t_Z80Ctrl), PROT_READ | PROT_WRITE, MAP_SHARED, fdZ80, 0);
|
||||||
|
if(Z80Ctrl == (void *)-1)
|
||||||
|
{
|
||||||
|
printf("Failed to attach to the Z80 Control structure, cannot continue, exitting....\n");
|
||||||
|
close(fdZ80);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
printf("Failed to open the Z80 Driver, exitting...\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Basic string to method mapping. Started off with just 1 or two but has grown, may need a table!
|
||||||
|
if(strcasecmp(cmd, "LOADMZF") == 0)
|
||||||
|
{
|
||||||
|
z80load(fdZ80, fileName);
|
||||||
|
} else
|
||||||
|
if(strcasecmp(cmd, "RESET") == 0)
|
||||||
|
{
|
||||||
|
ctrlCmd(fdZ80, Z80_CMD_RESET, 0, 0, 0);
|
||||||
|
} else
|
||||||
|
if(strcasecmp(cmd, "STOP") == 0)
|
||||||
|
{
|
||||||
|
ctrlCmd(fdZ80, Z80_CMD_STOP, 0, 0, 0);
|
||||||
|
} else
|
||||||
|
if(strcasecmp(cmd, "START") == 0)
|
||||||
|
{
|
||||||
|
ctrlCmd(fdZ80, Z80_CMD_START, 0, 0, 0);
|
||||||
|
} else
|
||||||
|
if(strcasecmp(cmd, "PAUSE") == 0)
|
||||||
|
{
|
||||||
|
ctrlCmd(fdZ80, Z80_CMD_PAUSE, 0, 0, 0);
|
||||||
|
} else
|
||||||
|
if(strcasecmp(cmd, "CONTINUE") == 0)
|
||||||
|
{
|
||||||
|
ctrlCmd(fdZ80, Z80_CMD_CONTINUE, 0, 0, 0);
|
||||||
|
} else
|
||||||
|
if(strcasecmp(cmd, "SPEED") == 0)
|
||||||
|
{
|
||||||
|
ctrlCmd(fdZ80, Z80_CMD_SPEED, speedMultiplier, 0, 0);
|
||||||
|
} else
|
||||||
|
if(strcasecmp(cmd, "DUMP") == 0)
|
||||||
|
{
|
||||||
|
ctrlCmd(fdZ80, Z80_CMD_DUMP_MEMORY, virtualMemory, startAddr, (endAddr - startAddr));
|
||||||
|
} else
|
||||||
|
if(strcasecmp(cmd, "HOSTRAM") == 0)
|
||||||
|
{
|
||||||
|
ctrlCmd(fdZ80, Z80_CMD_HOST_RAM, 0, 0, 0);
|
||||||
|
} else
|
||||||
|
if(strcasecmp(cmd, "VIRTRAM") == 0)
|
||||||
|
{
|
||||||
|
ctrlCmd(fdZ80, Z80_CMD_VIRTUAL_RAM, 0, 0, 0);
|
||||||
|
} else
|
||||||
|
if(strcasecmp(cmd, "CPLDCMD") == 0)
|
||||||
|
{
|
||||||
|
ctrlCmd(fdZ80, CPLD_CMD_SEND_CMD, hexData, 0, 0);
|
||||||
|
} else
|
||||||
|
|
||||||
|
// Test methods, if the code is built-in to the driver.
|
||||||
|
if(strcasecmp(cmd, "Z80TEST") == 0)
|
||||||
|
{
|
||||||
|
z80test(fdZ80);
|
||||||
|
} else
|
||||||
|
if(strcasecmp(cmd, "SPITEST") == 0)
|
||||||
|
{
|
||||||
|
ctrlCmd(fdZ80, CPLD_CMD_SPI_TEST, 0, 0, 0);
|
||||||
|
} else
|
||||||
|
if(strcasecmp(cmd, "PRLTEST") == 0)
|
||||||
|
{
|
||||||
|
ctrlCmd(fdZ80, CPLD_CMD_PRL_TEST, 0, 0, 0);
|
||||||
|
} else
|
||||||
|
if(strcasecmp(cmd, "Z80MEMTEST") == 0)
|
||||||
|
{
|
||||||
|
ctrlCmd(fdZ80, Z80_CMD_MEMORY_TEST, 0, 0, 0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
showArgs(argv[0], &options);
|
||||||
|
printf("No command given, nothing done!\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unmap shared memory and close the device.
|
||||||
|
munmap(Z80Ctrl, sizeof(t_Z80Ctrl));
|
||||||
|
close(fdZ80);
|
||||||
|
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
1477
software/FusionX/src/driver/MZ700/z80driver.c
Normal file
284
software/FusionX/src/driver/MZ700/z80driver.h
Normal file
@@ -0,0 +1,284 @@
|
|||||||
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Name: z80driver.h
|
||||||
|
// Created: Oct 2022
|
||||||
|
// Author(s): Philip Smart
|
||||||
|
// Description: Z80 Driver
|
||||||
|
// This file contains the declarations used in the z80drv device driver.
|
||||||
|
//
|
||||||
|
// Credits: Zilog Z80 CPU Emulator v0.2 written by Manuel Sainz de Baranda y Goñi
|
||||||
|
// The Z80 CPU Emulator is the heart of this driver and in all ways, is compatible with
|
||||||
|
// the original Z80.
|
||||||
|
// Copyright: (c) 2019-2022 Philip Smart <philip.smart@net2net.org>
|
||||||
|
// (c) 1999-2022 Manuel Sainz de Baranda y Goñi
|
||||||
|
//
|
||||||
|
// History: Oct 2022 - Initial write of the z80 kernel driver software.
|
||||||
|
//
|
||||||
|
// Notes: See Makefile to enable/disable conditional components
|
||||||
|
//
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// This source file is free software: you can redistribute it and#or modify
|
||||||
|
// it under the terms of the GNU General Public License as published
|
||||||
|
// by the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This source file is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
#ifndef Z80DRIVER_H
|
||||||
|
#define Z80DRIVER_H
|
||||||
|
|
||||||
|
// Constants.
|
||||||
|
#define Z80_VIRTUAL_ROM_SIZE 16384 // Sized to maximum ROM which is the MZ-800 ROM.
|
||||||
|
#define Z80_VIRTUAL_RAM_SIZE (65536 * 8) // (PAGE_SIZE * 2) // max size mmaped to userspace
|
||||||
|
#define Z80_VIRTUAL_MEMORY_SIZE Z80_VIRTUAL_RAM_SIZE + Z80_VIRTUAL_ROM_SIZE
|
||||||
|
#define Z80_MEMORY_PAGE_SIZE 16
|
||||||
|
#define MAX_SCREEN_WIDTH 132
|
||||||
|
#define DEVICE_NAME "z80drv"
|
||||||
|
#define CLASS_NAME "mogu"
|
||||||
|
|
||||||
|
// Memory and IO page types. Used to create a memory page which maps type of address space to real address space on host or virtual memory.
|
||||||
|
#define MEMORY_TYPE_VIRTUAL_MASK 0x00FFFFFF
|
||||||
|
#define MEMORY_TYPE_REAL_MASK 0x0000FFFF
|
||||||
|
#define IO_TYPE_MASK 0x0000FFFF
|
||||||
|
#define MEMORY_TYPE_INHIBIT 0x00000000
|
||||||
|
#define MEMORY_TYPE_PHYSICAL_RAM 0x80000000
|
||||||
|
#define MEMORY_TYPE_PHYSICAL_ROM 0x40000000
|
||||||
|
#define MEMORY_TYPE_PHYSICAL_VRAM 0x20000000
|
||||||
|
#define MEMORY_TYPE_PHYSICAL_HW 0x10000000
|
||||||
|
#define MEMORY_TYPE_VIRTUAL_RAM 0x08000000
|
||||||
|
#define MEMORY_TYPE_VIRTUAL_ROM 0x04000000
|
||||||
|
#define MEMORY_TYPE_VIRTUAL_HW 0x02000000
|
||||||
|
#define IO_TYPE_PHYSICAL_HW 0x80000000
|
||||||
|
#define IO_TYPE_VIRTUAL_HW 0x40000000
|
||||||
|
|
||||||
|
|
||||||
|
// Approximate governor delays to regulate emulated CPU speed.
|
||||||
|
#define MZ700_INSTRUCTION_DELAY_3_54MHZ 253
|
||||||
|
#define MZ700_INSTRUCTION_DELAY_7MHZ 126
|
||||||
|
#define MZ700_INSTRUCTION_DELAY_14MHZ 63
|
||||||
|
#define MZ700_INSTRUCTION_DELAY_28MHZ 32
|
||||||
|
#define MZ700_INSTRUCTION_DELAY_56MHZ 16
|
||||||
|
#define MZ700_INSTRUCTION_DELAY_112MHZ 8
|
||||||
|
#define MZ700_INSTRUCTION_DELAY_224MHZ 4
|
||||||
|
#define MZ700_INSTRUCTION_DELAY_448MHZ 1
|
||||||
|
|
||||||
|
// IOCTL commands. Passed from user space using the IOCTL method to command the driver to perform an action.
|
||||||
|
#define IOCTL_CMD_Z80_STOP 's'
|
||||||
|
#define IOCTL_CMD_Z80_START 'S'
|
||||||
|
#define IOCTL_CMD_Z80_PAUSE 'P'
|
||||||
|
#define IOCTL_CMD_Z80_RESET 'R'
|
||||||
|
#define IOCTL_CMD_Z80_CONTINUE 'C'
|
||||||
|
#define IOCTL_CMD_USE_HOST_RAM 'x'
|
||||||
|
#define IOCTL_CMD_USE_VIRTUAL_RAM 'X'
|
||||||
|
#define IOCTL_CMD_DUMP_MEMORY 'M'
|
||||||
|
#define IOCTL_CMD_Z80_CPU_FREQ 'F'
|
||||||
|
#define IOCTL_CMD_CPLD_CMD 'z'
|
||||||
|
#define IOCTL_CMD_SEND _IOW('c', 'c', int32_t *)
|
||||||
|
#define IOCTL_CMD_SETPC _IOW('p', 'p', int32_t *)
|
||||||
|
#define IOCTL_CMD_SYNC_TO_HOST_RAM 'V'
|
||||||
|
#define IOCTL_CMD_SPI_TEST '1'
|
||||||
|
#define IOCTL_CMD_PRL_TEST '2'
|
||||||
|
#define IOCTL_CMD_Z80_MEMTEST '3'
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Chip Select map MZ80K-MZ700.
|
||||||
|
//
|
||||||
|
// 0000 - 0FFF = CS_ROMni : R/W : MZ80K/A/700 = Monitor ROM or RAM (MZ80A rom swap)
|
||||||
|
// 1000 - CFFF = CS_RAMni : R/W : MZ80K/A/700 = RAM
|
||||||
|
// C000 - CFFF = CS_ROMni : R/W : MZ80A = Monitor ROM (MZ80A rom swap)
|
||||||
|
// D000 - D7FF = CS_VRAMni : R/W : MZ80K/A/700 = VRAM
|
||||||
|
// D800 - DFFF = CS_VRAMni : R/W : MZ700 = Colour VRAM (MZ700)
|
||||||
|
// E000 - E003 = CS_8255n : R/W : MZ80K/A/700 = 8255
|
||||||
|
// E004 - E007 = CS_8254n : R/W : MZ80K/A/700 = 8254
|
||||||
|
// E008 - E00B = CS_LS367n : R/W : MZ80K/A/700 = LS367
|
||||||
|
// E00C - E00F = CS_ESWPn : R : MZ80A = Memory Swap (MZ80A)
|
||||||
|
// E010 - E013 = CS_ESWPn : R : MZ80A = Reset Memory Swap (MZ80A)
|
||||||
|
// E014 = CS_E5n : R/W : MZ80A/700 = Normal CRT display (in Video Controller)
|
||||||
|
// E015 = CS_E6n : R/W : MZ80A/700 = Reverse CRT display (in Video Controller)
|
||||||
|
// E200 - E2FF = : R/W : MZ80A/700 = VRAM roll up/roll down.
|
||||||
|
// E800 - EFFF = : R/W : MZ80K/A/700 = User ROM socket or DD Eprom (MZ700)
|
||||||
|
// F000 - F7FF = : R/W : MZ80K/A/700 = Floppy Disk interface.
|
||||||
|
// F800 - FFFF = : R/W : MZ80K/A/700 = Floppy Disk interface.
|
||||||
|
//
|
||||||
|
// Chip Select map MZ800
|
||||||
|
//
|
||||||
|
// FC - FF = CS_PIOn : R/W : MZ800/MZ1500 = Z80 PIO Printer Interface
|
||||||
|
// F2 = CS_PSG0n : W : MZ800/MZ1500 = Programable Sound Generator, MZ-800 = Mono, MZ-1500 = Left Channel
|
||||||
|
// F3 = CS_PSG1n : W : MZ1500 = Programable Sound Generator, MZ-1500 = Right Channel
|
||||||
|
// E9 = CS_PSG(X)n: W : MZ1500 = Simultaneous write to both PSG's.
|
||||||
|
// F0 - F1 = CS_JOYSTK : R : MZ800 = Joystick 1 and 2
|
||||||
|
// CC = CS_GWF : W : MZ800 = CRTC GWF Write format Register
|
||||||
|
// CD = CS_GRF : W : MZ800 = CRTC GRF Read format Register
|
||||||
|
// CE = CS_GDMD : W : MZ800 = CRTC GDMD Mode Register
|
||||||
|
// CF = CS_GCRTC : W : MZ800 = CRTC GCRTC Control Register
|
||||||
|
// D4 - D7 = CS
|
||||||
|
// D000 - DFFF
|
||||||
|
|
||||||
|
// MZ700/MZ800 memory mode switch?
|
||||||
|
//
|
||||||
|
// MZ-700 MZ-800
|
||||||
|
// |0000:0FFF|1000:1FFF|1000:CFFF|C000:CFFF|D000:FFFF |0000:7FFF|1000:1FFF|2000:7FFF|8000:BFFF|C000:CFFF|C000:DFFF|E000:FFFF
|
||||||
|
// -------------------------------------------------- ----------------------------------------------------------------------
|
||||||
|
// OUT 0xE0 = |DRAM | | | | |DRAM | | | | | |
|
||||||
|
// OUT 0xE1 = | | | | |DRAM | | | | | | |DRAM
|
||||||
|
// OUT 0xE2 = |MONITOR | | | | |MONITOR | | | | | |
|
||||||
|
// OUT 0xE3 = | | | | |Memory Mapped I/O | | | | | | |Upper MONITOR ROM
|
||||||
|
// OUT 0xE4 = |MONITOR | |DRAM | |Memory Mapped I/O |MONITOR |CGROM |DRAM |VRAM | |DRAM |Upper MONITOR ROM
|
||||||
|
// OUT 0xE5 = | | | | |Inhibit | | | | | | |Inhibit
|
||||||
|
// OUT 0xE6 = | | | | |<return> | | | | | | |<return>
|
||||||
|
// IN 0xE0 = | |CGROM* | |VRAM* | | |CGROM | |VRAM | | |
|
||||||
|
// IN 0xE1 = | |DRAM | |DRAM | | |<return> | |DRAM | | |
|
||||||
|
//
|
||||||
|
// <return> = Return to the state prior to the complimentary command being invoked.
|
||||||
|
// * = MZ-800 host only.
|
||||||
|
|
||||||
|
// Macros to lookup and test to see if a given memory block or IO byte is of a given type. Also macros to read/write to the memory block and IO byte.
|
||||||
|
#define MEMORY_BLOCK_GRANULARITY 0x800
|
||||||
|
#define MEMORY_BLOCK_SLOTS (0x10000 / MEMORY_BLOCK_GRANULARITY)
|
||||||
|
#define MEMORY_BLOCK_MASK (0x10000 - MEMORY_BLOCK_GRANULARITY)
|
||||||
|
#define MEMORY_BLOCK_SHIFT 11
|
||||||
|
#define getPageData(a) (Z80Ctrl->page[(a & 0xF800) >> MEMORY_BLOCK_SHIFT])
|
||||||
|
#define getIOPageData(a) (Z80Ctrl->iopage[(a & 0xFFFF])
|
||||||
|
#define getPageType(a, mask) (getPageData(a) & mask)
|
||||||
|
#define getPageAddr(a, mask) ((getPageData(a) & mask) + (a & (MEMORY_BLOCK_GRANULARITY-1)))
|
||||||
|
#define getIOPageType(a, mask) (getIOPageData(a) & mask)
|
||||||
|
#define getIOPageAddr(a, mask) (getIOPageData(a) & mask)
|
||||||
|
#define realAddress(a) (Z80Ctrl->page[getPageAddr(a, MEMORY_TYPE_REAL_MASK)])
|
||||||
|
#define realPort(a) (Z80Ctrl->iopage[a & 0xFFFF] & IO_TYPE_MASK)
|
||||||
|
#define isPhysicalRAM(a) (getPageType(a, MEMORY_TYPE_PHYSICAL_RAM))
|
||||||
|
#define isPhysicalVRAM(a) (getPageType(a, MEMORY_TYPE_PHYSICAL_VRAM))
|
||||||
|
#define isPhysicalROM(a) (getPageType(a, MEMORY_TYPE_PHYSICAL_ROM))
|
||||||
|
#define isPhysicalMemory(a) (getPageType(a, (MEMORY_TYPE_PHYSICAL_ROM | MEMORY_TYPE_PHYSICAL_RAM | MEMORY_TYPE_PHYSICAL_VRAM))])
|
||||||
|
#define isPhysicalHW(a) (getPageType(a, MEMORY_TYPE_PHYSICAL_HW))
|
||||||
|
#define isPhysical(a) (getPageType(a, (MEMORY_TYPE_PHYSICAL_HW | MEMORY_TYPE_PHYSICAL_ROM | MEMORY_TYPE_PHYSICAL_RAM | MEMORY_TYPE_PHYSICAL_VRAM)))
|
||||||
|
#define isPhysicalIO(a) (Z80Ctrl->iopage[a & 0xFFFF] & IO_TYPE_PHYSICAL_HW)
|
||||||
|
#define isVirtualRAM(a) (getPageType(a, MEMORY_TYPE_VIRTUAL_RAM))
|
||||||
|
#define isVirtualROM(a) (getPageType(a, MEMORY_TYPE_VIRTUAL_ROM))
|
||||||
|
#define isVirtualMemory(a) (getPageType(a, (MEMORY_TYPE_VIRTUAL_ROM | MEMORY_TYPE_VIRTUAL_RAM)))
|
||||||
|
#define isVirtualHW(a) (getPageType(a, MEMORY_TYPE_VIRTUAL_HW))
|
||||||
|
#define isVirtualIO(a) (Z80Ctrl->iopage[a & 0xFFFF] & IO_TYPE_VIRTUAL_HW)
|
||||||
|
#define isHW(a) (getPageType(a, (MEMORY_TYPE_PHYSICAL_HW | MEMORY_TYPE_VIRTUAL_HW)))
|
||||||
|
#define readVirtualRAM(a) (Z80Ctrl->memory[ getPageAddr(a, MEMORY_TYPE_VIRTUAL_MASK) ])
|
||||||
|
#define readVirtualROM(a) (Z80Ctrl->memory[ getPageAddr(a, MEMORY_TYPE_VIRTUAL_MASK) + Z80_VIRTUAL_RAM_SIZE ])
|
||||||
|
#define writeVirtualRAM(a, d) { Z80Ctrl->memory[ getPageAddr(a, MEMORY_TYPE_VIRTUAL_MASK) ] = d; }
|
||||||
|
#define setMemoryType(_block_,_type_,_addr_) { Z80Ctrl->page[_block_] = _type_ | _addr_; }
|
||||||
|
#define backupMemoryType(_block_) { Z80Ctrl->shadowPage[_block_] = Z80Ctrl->page[_block_]; }
|
||||||
|
#define restoreMemoryType(_block_) { Z80Ctrl->page[_block_] = Z80Ctrl->shadowPage[_block_]; }
|
||||||
|
|
||||||
|
#define IO_ADDR_E0 0xE0
|
||||||
|
#define IO_ADDR_E1 0xE1
|
||||||
|
#define IO_ADDR_E2 0xE2
|
||||||
|
#define IO_ADDR_E3 0xE3
|
||||||
|
#define IO_ADDR_E4 0xE4
|
||||||
|
#define IO_ADDR_E5 0xE5
|
||||||
|
#define IO_ADDR_E6 0xE6
|
||||||
|
#define IO_ADDR_E7 0xE7
|
||||||
|
|
||||||
|
|
||||||
|
enum Z80_RUN_STATES {
|
||||||
|
Z80_STOP = 0x00,
|
||||||
|
Z80_STOPPED = 0x01,
|
||||||
|
Z80_PAUSE = 0x02,
|
||||||
|
Z80_PAUSED = 0x03,
|
||||||
|
Z80_CONTINUE = 0x04,
|
||||||
|
Z80_RUNNING = 0x05,
|
||||||
|
};
|
||||||
|
enum Z80_MEMORY_PROFILE {
|
||||||
|
USE_PHYSICAL_RAM = 0x00,
|
||||||
|
USE_VIRTUAL_RAM = 0x01
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
// Main memory, linear but indexed as though it were banks in 1K pages.
|
||||||
|
uint8_t memory[Z80_VIRTUAL_MEMORY_SIZE];
|
||||||
|
|
||||||
|
// Page pointer map.
|
||||||
|
//
|
||||||
|
// Each pointer points to a byte or block of bytes in the Z80 Memory frame, 64K Real + Banked.
|
||||||
|
// This is currently set at a block of size 0x800 per memory pointer for the MZ-700.
|
||||||
|
// The LSB of the pointer is a direct memory index to a byte or block of bytes, the upper byte of the pointer indicates type of memory space.
|
||||||
|
// 0x80<FFFFFF> - physical host RAM
|
||||||
|
// 0x40<FFFFFF> - physical host ROM
|
||||||
|
// 0x20<FFFFFF> - physical host VRAM
|
||||||
|
// 0x10<FFFFFF> - physical host hardware
|
||||||
|
// 0x08<FFFFFF> - virtual host RAM
|
||||||
|
// 0x04<FFFFFF> - virtual host ROM
|
||||||
|
// 0x02<FFFFFF> - virtual host hardware
|
||||||
|
// 16bit Input Address -> map -> Pointer to 24bit memory address + type flag.
|
||||||
|
// -> Pointer+<low bits of address> to 24bit memory address + type flag.
|
||||||
|
uint32_t page[MEMORY_BLOCK_SLOTS];
|
||||||
|
uint32_t shadowPage[MEMORY_BLOCK_SLOTS];
|
||||||
|
|
||||||
|
// I/O Page map.
|
||||||
|
//
|
||||||
|
// This is a map to indicate the use of the I/O page and allow any required remapping.
|
||||||
|
// <0x80>FF<I/O Address> - physical host hardware
|
||||||
|
// <0x40>FF<I/O Address> - virtual host hardware
|
||||||
|
// 16bit Input Address -> map -> Actual 16bit address to use + type flag.
|
||||||
|
uint32_t iopage[65536];
|
||||||
|
|
||||||
|
// Default page mode configured. This value reflects the default page and iotable map.
|
||||||
|
uint8_t defaultPageMode;
|
||||||
|
|
||||||
|
// Refresh DRAM mode. 1 = Refresh, 0 = No refresh. Only applicable when running code in virtual Kernel RAM.
|
||||||
|
uint8_t refreshDRAM;
|
||||||
|
|
||||||
|
// Inhibit mode is where certain memory ranges are inhibitted. The memory page is set to inhibit and this flag
|
||||||
|
// blocks actions which arent allowed during inhibit.
|
||||||
|
uint8_t inhibitMode;
|
||||||
|
|
||||||
|
// Address caching. Used to minimise instruction length sent to CPLD.
|
||||||
|
uint16_t z80PrevAddr;
|
||||||
|
uint16_t z80PrevPort;
|
||||||
|
|
||||||
|
// Keyboard strobe and data. Required to detect hotkey press.
|
||||||
|
uint8_t keyportStrobe;
|
||||||
|
uint8_t keyportShiftCtrl;
|
||||||
|
uint8_t keyportHotKey;
|
||||||
|
|
||||||
|
// Governor is the delay in a 32bit loop per Z80 opcode, used to govern execution speed when using virtual memory.
|
||||||
|
// This mechanism will eventually be tied into the M/T-state calculation for a more precise delay, but at the moment,
|
||||||
|
// with the Z80 assigned to an isolated CPU, it allows time sensitive tasks such as the tape recorder to work.
|
||||||
|
// The lower the value the faster the CPU speed.
|
||||||
|
uint32_t cpuGovernorDelay;
|
||||||
|
} t_Z80Ctrl;
|
||||||
|
|
||||||
|
// IOCTL structure for passing data from user space to driver to perform commands.
|
||||||
|
//
|
||||||
|
struct z80_addr {
|
||||||
|
uint32_t start;
|
||||||
|
uint32_t end;
|
||||||
|
uint32_t size;
|
||||||
|
};
|
||||||
|
struct z80_ctrl {
|
||||||
|
uint16_t pc;
|
||||||
|
};
|
||||||
|
struct speed {
|
||||||
|
uint32_t speedMultiplier;
|
||||||
|
};
|
||||||
|
struct cpld_ctrl {
|
||||||
|
uint32_t cmd;
|
||||||
|
};
|
||||||
|
struct ioctlCmd {
|
||||||
|
int32_t cmd;
|
||||||
|
union {
|
||||||
|
struct z80_addr addr;
|
||||||
|
struct z80_ctrl z80;
|
||||||
|
struct speed speed;
|
||||||
|
struct cpld_ctrl cpld;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// Prototypes.
|
||||||
|
void setupMemory(enum Z80_MEMORY_PROFILE mode);
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
428
software/FusionX/src/driver/MZ700/z80io.c
Normal file
@@ -0,0 +1,428 @@
|
|||||||
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Name: z80io.c
|
||||||
|
// Created: Oct 2022
|
||||||
|
// Author(s): Philip Smart
|
||||||
|
// Description: Z80 IO Interface
|
||||||
|
// This file contains the methods used in interfacing the SOM to the Z80 socket
|
||||||
|
// and host hardware via a CPLD.
|
||||||
|
// Credits:
|
||||||
|
// Copyright: (c) 2019-2022 Philip Smart <philip.smart@net2net.org>
|
||||||
|
//
|
||||||
|
// History: Oct 2022 - Initial write of the z80 kernel driver software.
|
||||||
|
//
|
||||||
|
// Notes: See Makefile to enable/disable conditional components
|
||||||
|
//
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// This source file is free software: you can redistribute it and#or modify
|
||||||
|
// it under the terms of the GNU General Public License as published
|
||||||
|
// by the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This source file is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
|
||||||
|
//#include <stdio.h>
|
||||||
|
//#include <stdlib.h>
|
||||||
|
//#include <string.h>
|
||||||
|
#include <linux/module.h>
|
||||||
|
#include <linux/init.h>
|
||||||
|
#include <linux/kernel.h>
|
||||||
|
#include <linux/device.h>
|
||||||
|
#include <linux/fs.h>
|
||||||
|
#include <linux/mm.h>
|
||||||
|
#include <asm/uaccess.h>
|
||||||
|
#include <linux/slab.h>
|
||||||
|
#include <linux/string.h>
|
||||||
|
#include <linux/kthread.h>
|
||||||
|
#include <linux/sched.h>
|
||||||
|
#include <linux/delay.h>
|
||||||
|
#include <linux/time.h>
|
||||||
|
#include "z80io.h"
|
||||||
|
|
||||||
|
#include <gpio_table.h>
|
||||||
|
#include <asm/io.h>
|
||||||
|
#include <infinity2m/gpio.h>
|
||||||
|
#include <infinity2m/registers.h>
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// User space driver access.
|
||||||
|
//
|
||||||
|
//-------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Initialise the SOM hardware used to communicate with the z80 socket and host hardware.
|
||||||
|
// The SOM interfaces to a CPLD which provides voltage level translation and also encapsulates the Z80 timing cycles as recreating
|
||||||
|
// them within the SOM is much more tricky.
|
||||||
|
//
|
||||||
|
// As this is an embedded device and performance/latency are priorities, minimal structured code is used to keep call stack and
|
||||||
|
// generated code to a mimimum without relying on the optimiser.
|
||||||
|
int z80io_init(void)
|
||||||
|
{
|
||||||
|
// Locals.
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
// Initialise GPIO. We call the HAL api to minimise time but for actual bit set/reset and read we go directly to registers to save time, increase throughput and minimise latency.
|
||||||
|
// Initialise the HAL.
|
||||||
|
MHal_GPIO_Init();
|
||||||
|
|
||||||
|
// Set the pads as GPIO devices. The HAL takes care of allocating and deallocating the padmux resources.
|
||||||
|
MHal_GPIO_Pad_Set(PAD_Z80IO_IN_DATA_0); // Word (16bit) bidirectional bus. Default is read with data set.
|
||||||
|
MHal_GPIO_Pad_Set(PAD_Z80IO_IN_DATA_1);
|
||||||
|
MHal_GPIO_Pad_Set(PAD_Z80IO_IN_DATA_2);
|
||||||
|
MHal_GPIO_Pad_Set(PAD_Z80IO_IN_DATA_3);
|
||||||
|
MHal_GPIO_Pad_Set(PAD_Z80IO_IN_DATA_4);
|
||||||
|
MHal_GPIO_Pad_Set(PAD_Z80IO_IN_DATA_5);
|
||||||
|
MHal_GPIO_Pad_Set(PAD_Z80IO_IN_DATA_6);
|
||||||
|
MHal_GPIO_Pad_Set(PAD_Z80IO_IN_DATA_7);
|
||||||
|
MHal_GPIO_Pad_Set(PAD_Z80IO_HIGH_BYTE);
|
||||||
|
//MHal_GPIO_Pad_Set(PAD_GPIO8); // SPIO 4wire control lines setup by the spidev driver but controlled directly in this driver.
|
||||||
|
//MHal_GPIO_Pad_Set(PAD_GPIO9);
|
||||||
|
//MHal_GPIO_Pad_Set(PAD_GPIO10);
|
||||||
|
//MHal_GPIO_Pad_Set(PAD_GPIO11);
|
||||||
|
MHal_GPIO_Pad_Set(PAD_Z80IO_READY);
|
||||||
|
MHal_GPIO_Pad_Set(PAD_Z80IO_LTSTATE);
|
||||||
|
MHal_GPIO_Pad_Set(PAD_Z80IO_BUSRQ);
|
||||||
|
MHal_GPIO_Pad_Set(PAD_Z80IO_BUSACK);
|
||||||
|
MHal_GPIO_Pad_Set(PAD_Z80IO_INT);
|
||||||
|
MHal_GPIO_Pad_Set(PAD_Z80IO_NMI);
|
||||||
|
MHal_GPIO_Pad_Set(PAD_Z80IO_WAIT);
|
||||||
|
MHal_GPIO_Pad_Set(PAD_Z80IO_RESET);
|
||||||
|
MHal_GPIO_Pad_Set(PAD_Z80IO_RSV1);
|
||||||
|
#ifdef NOTNEEDED
|
||||||
|
MHal_GPIO_Pad_Set(PAD_Z80IO_OUT_DATA_0);
|
||||||
|
MHal_GPIO_Pad_Set(PAD_Z80IO_OUT_DATA_1);
|
||||||
|
MHal_GPIO_Pad_Set(PAD_Z80IO_OUT_DATA_2);
|
||||||
|
MHal_GPIO_Pad_Set(PAD_Z80IO_OUT_DATA_3);
|
||||||
|
MHal_GPIO_Pad_Set(PAD_Z80IO_OUT_DATA_4);
|
||||||
|
MHal_GPIO_Pad_Set(PAD_Z80IO_OUT_DATA_5);
|
||||||
|
MHal_GPIO_Pad_Set(PAD_Z80IO_OUT_DATA_6);
|
||||||
|
MHal_GPIO_Pad_Set(PAD_Z80IO_OUT_DATA_7);
|
||||||
|
MHal_GPIO_Pad_Set(PAD_Z80IO_WRITE);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Set required input pads.
|
||||||
|
MHal_GPIO_Pad_Odn(PAD_Z80IO_IN_DATA_0);
|
||||||
|
MHal_GPIO_Pad_Odn(PAD_Z80IO_IN_DATA_1);
|
||||||
|
MHal_GPIO_Pad_Odn(PAD_Z80IO_IN_DATA_2);
|
||||||
|
MHal_GPIO_Pad_Odn(PAD_Z80IO_IN_DATA_3);
|
||||||
|
MHal_GPIO_Pad_Odn(PAD_Z80IO_IN_DATA_4);
|
||||||
|
MHal_GPIO_Pad_Odn(PAD_Z80IO_IN_DATA_5);
|
||||||
|
MHal_GPIO_Pad_Odn(PAD_Z80IO_IN_DATA_6);
|
||||||
|
MHal_GPIO_Pad_Odn(PAD_Z80IO_IN_DATA_7);
|
||||||
|
MHal_GPIO_Pad_Odn(PAD_Z80IO_READY);
|
||||||
|
MHal_GPIO_Pad_Odn(PAD_Z80IO_LTSTATE);
|
||||||
|
MHal_GPIO_Pad_Odn(PAD_Z80IO_BUSRQ);
|
||||||
|
MHal_GPIO_Pad_Odn(PAD_Z80IO_BUSACK);
|
||||||
|
MHal_GPIO_Pad_Odn(PAD_Z80IO_INT);
|
||||||
|
MHal_GPIO_Pad_Odn(PAD_Z80IO_NMI);
|
||||||
|
MHal_GPIO_Pad_Odn(PAD_Z80IO_WAIT);
|
||||||
|
MHal_GPIO_Pad_Odn(PAD_Z80IO_RESET);
|
||||||
|
MHal_GPIO_Pad_Odn(PAD_Z80IO_RSV1);
|
||||||
|
|
||||||
|
// Set required output pads.
|
||||||
|
#ifdef NOTNEEDED
|
||||||
|
MHal_GPIO_Pad_Oen(PAD_Z80IO_OUT_DATA_0);
|
||||||
|
MHal_GPIO_Pad_Oen(PAD_Z80IO_OUT_DATA_1);
|
||||||
|
MHal_GPIO_Pad_Oen(PAD_Z80IO_OUT_DATA_2);
|
||||||
|
MHal_GPIO_Pad_Oen(PAD_Z80IO_OUT_DATA_3);
|
||||||
|
MHal_GPIO_Pad_Oen(PAD_Z80IO_OUT_DATA_4);
|
||||||
|
MHal_GPIO_Pad_Oen(PAD_Z80IO_OUT_DATA_5);
|
||||||
|
MHal_GPIO_Pad_Oen(PAD_Z80IO_OUT_DATA_6);
|
||||||
|
MHal_GPIO_Pad_Oen(PAD_Z80IO_OUT_DATA_7);
|
||||||
|
MHal_GPIO_Pad_Oen(PAD_Z80IO_WRITE);
|
||||||
|
MHal_GPIO_Pull_High(PAD_Z80IO_WRITE);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Control signals.
|
||||||
|
MHal_GPIO_Pad_Oen(PAD_Z80IO_HIGH_BYTE);
|
||||||
|
MHal_GPIO_Pull_High(PAD_Z80IO_HIGH_BYTE);
|
||||||
|
|
||||||
|
// Setup the MSPI0 device.
|
||||||
|
//
|
||||||
|
// Setup control, interrupts are not used.
|
||||||
|
MSPI_WRITE(MSPI_CTRL_OFFSET, MSPI_CPU_CLOCK_1_2 | MSPI_CTRL_CPOL_LOW | MSPI_CTRL_CPHA_HIGH | MSPI_CTRL_RESET | MSPI_CTRL_ENABLE_SPI);
|
||||||
|
|
||||||
|
// Setup LSB First mode.
|
||||||
|
MSPI_WRITE(MSPI_LSB_FIRST_OFFSET, 0x0);
|
||||||
|
|
||||||
|
// Setup clock.
|
||||||
|
CLK_WRITE(MSPI0_CLK_CFG, 0x1100)
|
||||||
|
|
||||||
|
// Setup the frame size (all buffers to 8bits).
|
||||||
|
MSPI_WRITE(MSPI_FRAME_WBIT_OFFSET, 0xfff);
|
||||||
|
MSPI_WRITE(MSPI_FRAME_WBIT_OFFSET+1, 0xfff);
|
||||||
|
MSPI_WRITE(MSPI_FRAME_RBIT_OFFSET, 0xfff);
|
||||||
|
MSPI_WRITE(MSPI_FRAME_RBIT_OFFSET+1, 0xfff);
|
||||||
|
|
||||||
|
// Setup Chip Selects to inactive.
|
||||||
|
MSPI_WRITE(MSPI_CHIP_SELECT_OFFSET, MSPI_CS8_DISABLE | MSPI_CS7_DISABLE | MSPI_CS6_DISABLE | MSPI_CS5_DISABLE | MSPI_CS4_DISABLE | MSPI_CS3_DISABLE | MSPI_CS2_DISABLE | MSPI_CS1_DISABLE);
|
||||||
|
|
||||||
|
// Switch Video and Audio to host.
|
||||||
|
z80io_SPI_Send16(0x00f0, NULL);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//--------------------------------------------------------
|
||||||
|
// Parallel bus Methods.
|
||||||
|
//--------------------------------------------------------
|
||||||
|
|
||||||
|
// Methods to read data from the parallel bus.
|
||||||
|
// The CPLD returns status and Z80 data on the 8bit bus as it is marginally quicker than retrieving it over the SPI bus.
|
||||||
|
//
|
||||||
|
inline uint8_t z80io_PRL_Read8(uint8_t dataFlag)
|
||||||
|
{
|
||||||
|
// Locals.
|
||||||
|
uint8_t result = 0;
|
||||||
|
|
||||||
|
// Byte according to flag.
|
||||||
|
if(dataFlag)
|
||||||
|
SET_CPLD_READ_DATA()
|
||||||
|
else
|
||||||
|
SET_CPLD_READ_STATUS()
|
||||||
|
|
||||||
|
// Read the input registers and set value accordingly.
|
||||||
|
result = READ_CPLD_DATA_IN();
|
||||||
|
|
||||||
|
// Return 16bit value read from CPLD.
|
||||||
|
return(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline uint16_t z80io_PRL_Read16(void)
|
||||||
|
{
|
||||||
|
// Locals.
|
||||||
|
uint16_t result = 0;
|
||||||
|
|
||||||
|
// Low byte first.
|
||||||
|
CLEAR_CPLD_HIGH_BYTE();
|
||||||
|
|
||||||
|
// Read the input registers and set value accordingly.
|
||||||
|
result = (uint16_t)READ_CPLD_DATA_IN();
|
||||||
|
|
||||||
|
// High byte next.
|
||||||
|
SET_CPLD_HIGH_BYTE();
|
||||||
|
|
||||||
|
// Read the input registers and set value accordingly.
|
||||||
|
result |= (uint16_t)(READ_CPLD_DATA_IN() << 8);
|
||||||
|
|
||||||
|
// Return 16bit value read from CPLD.
|
||||||
|
return(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Parallel Bus methods were tried and tested but due to the GPIO bits being controlled by individual registers per bit, the setup time was longer
|
||||||
|
// than the transmission time of SPI. These methods are thus deprecated and a fusion of SPI and 8bit parallel is now used.
|
||||||
|
#ifdef NOTNEEDED
|
||||||
|
inline uint8_t z80io_PRL_Send8(uint8_t txData)
|
||||||
|
{
|
||||||
|
// Locals.
|
||||||
|
//
|
||||||
|
|
||||||
|
// Low byte only.
|
||||||
|
MHal_RIU_REG(gpio_table[PAD_Z80IO_HIGH_BYTE].r_out) &= (~gpio_table[PAD_Z80IO_HIGH_BYTE ].m_out);
|
||||||
|
|
||||||
|
// Setup data.
|
||||||
|
if(txData & 0x0080) { MHal_RIU_REG(gpio_table[PAD_Z80IO_OUT_DATA_7].r_out) |= gpio_table[PAD_Z80IO_OUT_DATA_7].m_out; } else { MHal_RIU_REG(gpio_table[PAD_Z80IO_OUT_DATA_7].r_out) &= (~gpio_table[PAD_Z80IO_OUT_DATA_7].m_out); }
|
||||||
|
if(txData & 0x0040) { MHal_RIU_REG(gpio_table[PAD_Z80IO_OUT_DATA_6].r_out) |= gpio_table[PAD_Z80IO_OUT_DATA_6].m_out; } else { MHal_RIU_REG(gpio_table[PAD_Z80IO_OUT_DATA_6].r_out) &= (~gpio_table[PAD_Z80IO_OUT_DATA_6].m_out); }
|
||||||
|
if(txData & 0x0020) { MHal_RIU_REG(gpio_table[PAD_Z80IO_OUT_DATA_5].r_out) |= gpio_table[PAD_Z80IO_OUT_DATA_5].m_out; } else { MHal_RIU_REG(gpio_table[PAD_Z80IO_OUT_DATA_5].r_out) &= (~gpio_table[PAD_Z80IO_OUT_DATA_5].m_out); }
|
||||||
|
if(txData & 0x0010) { MHal_RIU_REG(gpio_table[PAD_Z80IO_OUT_DATA_4].r_out) |= gpio_table[PAD_Z80IO_OUT_DATA_4].m_out; } else { MHal_RIU_REG(gpio_table[PAD_Z80IO_OUT_DATA_4].r_out) &= (~gpio_table[PAD_Z80IO_OUT_DATA_4].m_out); }
|
||||||
|
if(txData & 0x0008) { MHal_RIU_REG(gpio_table[PAD_Z80IO_OUT_DATA_3].r_out) |= gpio_table[PAD_Z80IO_OUT_DATA_3].m_out; } else { MHal_RIU_REG(gpio_table[PAD_Z80IO_OUT_DATA_3].r_out) &= (~gpio_table[PAD_Z80IO_OUT_DATA_3].m_out); }
|
||||||
|
if(txData & 0x0004) { MHal_RIU_REG(gpio_table[PAD_Z80IO_OUT_DATA_2].r_out) |= gpio_table[PAD_Z80IO_OUT_DATA_2].m_out; } else { MHal_RIU_REG(gpio_table[PAD_Z80IO_OUT_DATA_2].r_out) &= (~gpio_table[PAD_Z80IO_OUT_DATA_2].m_out); }
|
||||||
|
if(txData & 0x0002) { MHal_RIU_REG(gpio_table[PAD_Z80IO_OUT_DATA_1].r_out) |= gpio_table[PAD_Z80IO_OUT_DATA_1].m_out; } else { MHal_RIU_REG(gpio_table[PAD_Z80IO_OUT_DATA_1].r_out) &= (~gpio_table[PAD_Z80IO_OUT_DATA_1].m_out); }
|
||||||
|
if(txData & 0x0001) { MHal_RIU_REG(gpio_table[PAD_Z80IO_OUT_DATA_0].r_out) |= gpio_table[PAD_Z80IO_OUT_DATA_0].m_out; } else { MHal_RIU_REG(gpio_table[PAD_Z80IO_OUT_DATA_0].r_out) &= (~gpio_table[PAD_Z80IO_OUT_DATA_0].m_out); }
|
||||||
|
|
||||||
|
// Clock data.
|
||||||
|
MHal_RIU_REG(gpio_table[PAD_Z80IO_WRITE].r_out) &= (~gpio_table[PAD_Z80IO_WRITE ].m_out);
|
||||||
|
MHal_RIU_REG(gpio_table[PAD_Z80IO_WRITE].r_out) |= gpio_table[PAD_Z80IO_WRITE ].m_out;
|
||||||
|
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline uint8_t z80io_PRL_Send16(uint16_t txData)
|
||||||
|
{
|
||||||
|
// Locals.
|
||||||
|
//
|
||||||
|
|
||||||
|
// Low byte first.
|
||||||
|
MHal_RIU_REG(gpio_table[PAD_Z80IO_HIGH_BYTE].r_out) &= (~gpio_table[PAD_Z80IO_HIGH_BYTE ].m_out);
|
||||||
|
|
||||||
|
// Setup data.
|
||||||
|
if(txData & 0x0080) { MHal_RIU_REG(gpio_table[PAD_Z80IO_OUT_DATA_7].r_out) |= gpio_table[PAD_Z80IO_OUT_DATA_7].m_out; } else { MHal_RIU_REG(gpio_table[PAD_Z80IO_OUT_DATA_7].r_out) &= (~gpio_table[PAD_Z80IO_OUT_DATA_7].m_out); }
|
||||||
|
if(txData & 0x0040) { MHal_RIU_REG(gpio_table[PAD_Z80IO_OUT_DATA_6].r_out) |= gpio_table[PAD_Z80IO_OUT_DATA_6].m_out; } else { MHal_RIU_REG(gpio_table[PAD_Z80IO_OUT_DATA_6].r_out) &= (~gpio_table[PAD_Z80IO_OUT_DATA_6].m_out); }
|
||||||
|
if(txData & 0x0020) { MHal_RIU_REG(gpio_table[PAD_Z80IO_OUT_DATA_5].r_out) |= gpio_table[PAD_Z80IO_OUT_DATA_5].m_out; } else { MHal_RIU_REG(gpio_table[PAD_Z80IO_OUT_DATA_5].r_out) &= (~gpio_table[PAD_Z80IO_OUT_DATA_5].m_out); }
|
||||||
|
if(txData & 0x0010) { MHal_RIU_REG(gpio_table[PAD_Z80IO_OUT_DATA_4].r_out) |= gpio_table[PAD_Z80IO_OUT_DATA_4].m_out; } else { MHal_RIU_REG(gpio_table[PAD_Z80IO_OUT_DATA_4].r_out) &= (~gpio_table[PAD_Z80IO_OUT_DATA_4].m_out); }
|
||||||
|
if(txData & 0x0008) { MHal_RIU_REG(gpio_table[PAD_Z80IO_OUT_DATA_3].r_out) |= gpio_table[PAD_Z80IO_OUT_DATA_3].m_out; } else { MHal_RIU_REG(gpio_table[PAD_Z80IO_OUT_DATA_3].r_out) &= (~gpio_table[PAD_Z80IO_OUT_DATA_3].m_out); }
|
||||||
|
if(txData & 0x0004) { MHal_RIU_REG(gpio_table[PAD_Z80IO_OUT_DATA_2].r_out) |= gpio_table[PAD_Z80IO_OUT_DATA_2].m_out; } else { MHal_RIU_REG(gpio_table[PAD_Z80IO_OUT_DATA_2].r_out) &= (~gpio_table[PAD_Z80IO_OUT_DATA_2].m_out); }
|
||||||
|
if(txData & 0x0002) { MHal_RIU_REG(gpio_table[PAD_Z80IO_OUT_DATA_1].r_out) |= gpio_table[PAD_Z80IO_OUT_DATA_1].m_out; } else { MHal_RIU_REG(gpio_table[PAD_Z80IO_OUT_DATA_1].r_out) &= (~gpio_table[PAD_Z80IO_OUT_DATA_1].m_out); }
|
||||||
|
if(txData & 0x0001) { MHal_RIU_REG(gpio_table[PAD_Z80IO_OUT_DATA_0].r_out) |= gpio_table[PAD_Z80IO_OUT_DATA_0].m_out; } else { MHal_RIU_REG(gpio_table[PAD_Z80IO_OUT_DATA_0].r_out) &= (~gpio_table[PAD_Z80IO_OUT_DATA_0].m_out); }
|
||||||
|
|
||||||
|
// Clock data.
|
||||||
|
MHal_RIU_REG(gpio_table[PAD_Z80IO_WRITE].r_out) &= (~gpio_table[PAD_Z80IO_WRITE ].m_out);
|
||||||
|
MHal_RIU_REG(gpio_table[PAD_Z80IO_WRITE].r_out) |= gpio_table[PAD_Z80IO_WRITE ].m_out;
|
||||||
|
|
||||||
|
// High byte next.
|
||||||
|
MHal_RIU_REG(gpio_table[PAD_Z80IO_HIGH_BYTE ].r_out) |= gpio_table[PAD_Z80IO_HIGH_BYTE ].m_out;
|
||||||
|
|
||||||
|
// Setup high byte.
|
||||||
|
if(txData & 0x8000) { MHal_RIU_REG(gpio_table[PAD_Z80IO_OUT_DATA_7].r_out) |= gpio_table[PAD_Z80IO_OUT_DATA_7].m_out; } else { MHal_RIU_REG(gpio_table[PAD_Z80IO_OUT_DATA_7].r_out) &= (~gpio_table[PAD_Z80IO_OUT_DATA_7].m_out); }
|
||||||
|
if(txData & 0x4000) { MHal_RIU_REG(gpio_table[PAD_Z80IO_OUT_DATA_6].r_out) |= gpio_table[PAD_Z80IO_OUT_DATA_6].m_out; } else { MHal_RIU_REG(gpio_table[PAD_Z80IO_OUT_DATA_6].r_out) &= (~gpio_table[PAD_Z80IO_OUT_DATA_6].m_out); }
|
||||||
|
if(txData & 0x2000) { MHal_RIU_REG(gpio_table[PAD_Z80IO_OUT_DATA_5].r_out) |= gpio_table[PAD_Z80IO_OUT_DATA_5].m_out; } else { MHal_RIU_REG(gpio_table[PAD_Z80IO_OUT_DATA_5].r_out) &= (~gpio_table[PAD_Z80IO_OUT_DATA_5].m_out); }
|
||||||
|
if(txData & 0x1000) { MHal_RIU_REG(gpio_table[PAD_Z80IO_OUT_DATA_4].r_out) |= gpio_table[PAD_Z80IO_OUT_DATA_4].m_out; } else { MHal_RIU_REG(gpio_table[PAD_Z80IO_OUT_DATA_4].r_out) &= (~gpio_table[PAD_Z80IO_OUT_DATA_4].m_out); }
|
||||||
|
if(txData & 0x0800) { MHal_RIU_REG(gpio_table[PAD_Z80IO_OUT_DATA_3].r_out) |= gpio_table[PAD_Z80IO_OUT_DATA_3].m_out; } else { MHal_RIU_REG(gpio_table[PAD_Z80IO_OUT_DATA_3].r_out) &= (~gpio_table[PAD_Z80IO_OUT_DATA_3].m_out); }
|
||||||
|
if(txData & 0x0400) { MHal_RIU_REG(gpio_table[PAD_Z80IO_OUT_DATA_2].r_out) |= gpio_table[PAD_Z80IO_OUT_DATA_2].m_out; } else { MHal_RIU_REG(gpio_table[PAD_Z80IO_OUT_DATA_2].r_out) &= (~gpio_table[PAD_Z80IO_OUT_DATA_2].m_out); }
|
||||||
|
if(txData & 0x0200) { MHal_RIU_REG(gpio_table[PAD_Z80IO_OUT_DATA_1].r_out) |= gpio_table[PAD_Z80IO_OUT_DATA_1].m_out; } else { MHal_RIU_REG(gpio_table[PAD_Z80IO_OUT_DATA_1].r_out) &= (~gpio_table[PAD_Z80IO_OUT_DATA_1].m_out); }
|
||||||
|
if(txData & 0x0100) { MHal_RIU_REG(gpio_table[PAD_Z80IO_OUT_DATA_0].r_out) |= gpio_table[PAD_Z80IO_OUT_DATA_0].m_out; } else { MHal_RIU_REG(gpio_table[PAD_Z80IO_OUT_DATA_0].r_out) &= (~gpio_table[PAD_Z80IO_OUT_DATA_0].m_out); }
|
||||||
|
|
||||||
|
// Clock data.
|
||||||
|
MHal_RIU_REG(gpio_table[PAD_Z80IO_WRITE].r_out) &= (~gpio_table[PAD_Z80IO_WRITE ].m_out);
|
||||||
|
MHal_RIU_REG(gpio_table[PAD_Z80IO_WRITE].r_out) |= gpio_table[PAD_Z80IO_WRITE ].m_out;
|
||||||
|
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
//--------------------------------------------------------
|
||||||
|
// SPI Methods.
|
||||||
|
//--------------------------------------------------------
|
||||||
|
|
||||||
|
// Methods to send 8,16 or 32 bits. Each method is seperate to minimise logic and execution time, 8bit being most sensitive.
|
||||||
|
// Macros have also been defined for inline inclusion which dont read back the response data.
|
||||||
|
//
|
||||||
|
uint8_t z80io_SPI_Send8(uint8_t txData, uint8_t *rxData)
|
||||||
|
{
|
||||||
|
// Locals.
|
||||||
|
uint32_t timeout = MAX_CHECK_CNT;
|
||||||
|
|
||||||
|
// Insert data into write buffers.
|
||||||
|
MSPI_WRITE(MSPI_WRITE_BUF_OFFSET, (uint16_t)txData);
|
||||||
|
MSPI_WRITE(MSPI_WBF_SIZE_OFFSET, 1);
|
||||||
|
|
||||||
|
// Enable SPI select.
|
||||||
|
MSPI_WRITE(MSPI_CHIP_SELECT_OFFSET, MSPI_CS8_DISABLE | MSPI_CS7_DISABLE | MSPI_CS6_DISABLE | MSPI_CS5_DISABLE | MSPI_CS4_DISABLE | MSPI_CS3_DISABLE | MSPI_CS2_DISABLE | MSPI_CS1_ENABLE);
|
||||||
|
|
||||||
|
// Send.
|
||||||
|
MSPI_WRITE(MSPI_TRIGGER_OFFSET, MSPI_TRIGGER);
|
||||||
|
|
||||||
|
// Wait for completion.
|
||||||
|
while((MSPI_READ(MSPI_DONE_OFFSET) & MSPI_DONE_FLAG) == 0)
|
||||||
|
{
|
||||||
|
if(--timeout == 0)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Disable SPI select.
|
||||||
|
MSPI_WRITE(MSPI_CHIP_SELECT_OFFSET, MSPI_CS8_DISABLE | MSPI_CS7_DISABLE | MSPI_CS6_DISABLE | MSPI_CS5_DISABLE | MSPI_CS4_DISABLE | MSPI_CS3_DISABLE | MSPI_CS2_DISABLE | MSPI_CS1_DISABLE);
|
||||||
|
|
||||||
|
// Clear flag.
|
||||||
|
MSPI_WRITE(MSPI_DONE_CLEAR_OFFSET, MSPI_CLEAR_DONE);
|
||||||
|
|
||||||
|
// Fetch data.
|
||||||
|
if(rxData != NULL) *rxData = (uint8_t)MSPI_READ(MSPI_FULL_DEPLUX_RD00);
|
||||||
|
|
||||||
|
// Done.
|
||||||
|
return(timeout == 0);
|
||||||
|
}
|
||||||
|
uint8_t z80io_SPI_Send16(uint16_t txData, uint16_t *rxData)
|
||||||
|
{
|
||||||
|
// Locals.
|
||||||
|
uint32_t timeout = MAX_CHECK_CNT;
|
||||||
|
|
||||||
|
// Insert data into write buffers.
|
||||||
|
MSPI_WRITE(MSPI_WRITE_BUF_OFFSET, txData);
|
||||||
|
MSPI_WRITE(MSPI_WBF_SIZE_OFFSET, 2);
|
||||||
|
|
||||||
|
// Enable SPI select.
|
||||||
|
MSPI_WRITE(MSPI_CHIP_SELECT_OFFSET, MSPI_CS8_DISABLE | MSPI_CS7_DISABLE | MSPI_CS6_DISABLE | MSPI_CS5_DISABLE | MSPI_CS4_DISABLE | MSPI_CS3_DISABLE | MSPI_CS2_DISABLE | MSPI_CS1_ENABLE);
|
||||||
|
|
||||||
|
// Send.
|
||||||
|
MSPI_WRITE(MSPI_TRIGGER_OFFSET, MSPI_TRIGGER);
|
||||||
|
|
||||||
|
// Wait for completion.
|
||||||
|
while((MSPI_READ(MSPI_DONE_OFFSET) & MSPI_DONE_FLAG) == 0)
|
||||||
|
{
|
||||||
|
if(--timeout == 0)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Disable SPI select.
|
||||||
|
MSPI_WRITE(MSPI_CHIP_SELECT_OFFSET, MSPI_CS8_DISABLE | MSPI_CS7_DISABLE | MSPI_CS6_DISABLE | MSPI_CS5_DISABLE | MSPI_CS4_DISABLE | MSPI_CS3_DISABLE | MSPI_CS2_DISABLE | MSPI_CS1_DISABLE);
|
||||||
|
|
||||||
|
// Clear flag.
|
||||||
|
MSPI_WRITE(MSPI_DONE_CLEAR_OFFSET, MSPI_CLEAR_DONE);
|
||||||
|
|
||||||
|
// Fetch data.
|
||||||
|
if(rxData != NULL) *rxData = MSPI_READ(MSPI_FULL_DEPLUX_RD00);
|
||||||
|
|
||||||
|
// Done.
|
||||||
|
return(timeout == 0);
|
||||||
|
}
|
||||||
|
uint8_t z80io_SPI_Send32(uint32_t txData, uint32_t *rxData)
|
||||||
|
{
|
||||||
|
// Locals.
|
||||||
|
uint32_t timeout = MAX_CHECK_CNT;
|
||||||
|
|
||||||
|
// Insert data into write buffers.
|
||||||
|
MSPI_WRITE(MSPI_WRITE_BUF_OFFSET, (uint16_t)txData);
|
||||||
|
MSPI_WRITE(MSPI_WRITE_BUF_OFFSET+1, (uint16_t)(txData >> 16));
|
||||||
|
MSPI_WRITE(MSPI_WBF_SIZE_OFFSET, 4);
|
||||||
|
|
||||||
|
// Enable SPI select.
|
||||||
|
MSPI_WRITE(MSPI_CHIP_SELECT_OFFSET, MSPI_CS8_DISABLE | MSPI_CS7_DISABLE | MSPI_CS6_DISABLE | MSPI_CS5_DISABLE | MSPI_CS4_DISABLE | MSPI_CS3_DISABLE | MSPI_CS2_DISABLE | MSPI_CS1_ENABLE);
|
||||||
|
|
||||||
|
// Send.
|
||||||
|
MSPI_WRITE(MSPI_TRIGGER_OFFSET, MSPI_TRIGGER);
|
||||||
|
|
||||||
|
// Wait for completion.
|
||||||
|
while((MSPI_READ(MSPI_DONE_OFFSET) & MSPI_DONE_FLAG) == 0)
|
||||||
|
{
|
||||||
|
if(--timeout == 0)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Disable SPI select.
|
||||||
|
MSPI_WRITE(MSPI_CHIP_SELECT_OFFSET, MSPI_CS8_DISABLE | MSPI_CS7_DISABLE | MSPI_CS6_DISABLE | MSPI_CS5_DISABLE | MSPI_CS4_DISABLE | MSPI_CS3_DISABLE | MSPI_CS2_DISABLE | MSPI_CS1_DISABLE);
|
||||||
|
|
||||||
|
// Clear flag.
|
||||||
|
MSPI_WRITE(MSPI_DONE_CLEAR_OFFSET, MSPI_CLEAR_DONE);
|
||||||
|
|
||||||
|
// Fetch data.
|
||||||
|
if(rxData != NULL) *rxData = (uint32_t)(MSPI_READ(MSPI_FULL_DEPLUX_RD00) | (MSPI_READ(MSPI_FULL_DEPLUX_RD02) << 16));
|
||||||
|
|
||||||
|
// Done.
|
||||||
|
return(timeout == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------
|
||||||
|
// Test Methods.
|
||||||
|
//--------------------------------------------------------
|
||||||
|
#ifdef INCLUDE_TEST_METHODS
|
||||||
|
#include "z80io_test.c"
|
||||||
|
#else
|
||||||
|
uint8_t z80io_Z80_TestMemory(void)
|
||||||
|
{
|
||||||
|
pr_info("Z80 Test Memory functionality not built-in.\n");
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
uint8_t z80io_SPI_Test(void)
|
||||||
|
{
|
||||||
|
pr_info("SPI Test functionality not built-in.\n");
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
uint8_t z80io_PRL_Test(void)
|
||||||
|
{
|
||||||
|
pr_info("Parallel Bus Test functionality not built-in.\n");
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
483
software/FusionX/src/driver/MZ700/z80io.h
Executable file
@@ -0,0 +1,483 @@
|
|||||||
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Name: z80io.h
|
||||||
|
// Created: Oct 2022
|
||||||
|
// Author(s): Philip Smart
|
||||||
|
// Description: Z80 IO Interface
|
||||||
|
// This file contains the declarations used in interfacing the SOM to the Z80 socket
|
||||||
|
// and host hardware via a CPLD.
|
||||||
|
// Credits:
|
||||||
|
// Copyright: (c) 2019-2022 Philip Smart <philip.smart@net2net.org>
|
||||||
|
//
|
||||||
|
// History: Oct 2022 - Initial write of the z80 kernel driver software.
|
||||||
|
//
|
||||||
|
// Notes: See Makefile to enable/disable conditional components
|
||||||
|
//
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// This source file is free software: you can redistribute it and#or modify
|
||||||
|
// it under the terms of the GNU General Public License as published
|
||||||
|
// by the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This source file is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
#ifndef Z80IO_H
|
||||||
|
#define Z80IO_H
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Definitions to control compilation.
|
||||||
|
#define INCLUDE_TEST_METHODS 1
|
||||||
|
|
||||||
|
// CPLD Commands.
|
||||||
|
#define CPLD_CMD_FETCH_ADDR 0x10
|
||||||
|
#define CPLD_CMD_FETCH_ADDR_P1 0x11
|
||||||
|
#define CPLD_CMD_FETCH_ADDR_P2 0x12
|
||||||
|
#define CPLD_CMD_FETCH_ADDR_P3 0x13
|
||||||
|
#define CPLD_CMD_FETCH_ADDR_P4 0x14
|
||||||
|
#define CPLD_CMD_FETCH_ADDR_P5 0x15
|
||||||
|
#define CPLD_CMD_FETCH_ADDR_P6 0x16
|
||||||
|
#define CPLD_CMD_FETCH_ADDR_P7 0x17
|
||||||
|
#define CPLD_CMD_WRITE_ADDR 0x18
|
||||||
|
#define CPLD_CMD_WRITE_ADDR_P1 0x19
|
||||||
|
#define CPLD_CMD_WRITE_ADDR_P2 0x1A
|
||||||
|
#define CPLD_CMD_WRITE_ADDR_P3 0x1B
|
||||||
|
#define CPLD_CMD_WRITE_ADDR_P4 0x1C
|
||||||
|
#define CPLD_CMD_WRITE_ADDR_P5 0x1D
|
||||||
|
#define CPLD_CMD_WRITE_ADDR_P6 0x1E
|
||||||
|
#define CPLD_CMD_WRITE_ADDR_P7 0x1F
|
||||||
|
#define CPLD_CMD_READ_ADDR 0x20
|
||||||
|
#define CPLD_CMD_READ_ADDR_P1 0x21
|
||||||
|
#define CPLD_CMD_READ_ADDR_P2 0x22
|
||||||
|
#define CPLD_CMD_READ_ADDR_P3 0x23
|
||||||
|
#define CPLD_CMD_READ_ADDR_P4 0x24
|
||||||
|
#define CPLD_CMD_READ_ADDR_P5 0x25
|
||||||
|
#define CPLD_CMD_READ_ADDR_P6 0x26
|
||||||
|
#define CPLD_CMD_READ_ADDR_P7 0x27
|
||||||
|
#define CPLD_CMD_WRITEIO_ADDR 0x28
|
||||||
|
#define CPLD_CMD_WRITEIO_ADDR_P1 0x29
|
||||||
|
#define CPLD_CMD_WRITEIO_ADDR_P2 0x2A
|
||||||
|
#define CPLD_CMD_WRITEIO_ADDR_P3 0x2B
|
||||||
|
#define CPLD_CMD_WRITEIO_ADDR_P4 0x2C
|
||||||
|
#define CPLD_CMD_WRITEIO_ADDR_P5 0x2D
|
||||||
|
#define CPLD_CMD_WRITEIO_ADDR_P6 0x2E
|
||||||
|
#define CPLD_CMD_WRITEIO_ADDR_P7 0x2F
|
||||||
|
#define CPLD_CMD_READIO_ADDR 0x30
|
||||||
|
#define CPLD_CMD_READIO_ADDR_P1 0x31
|
||||||
|
#define CPLD_CMD_READIO_ADDR_P2 0x32
|
||||||
|
#define CPLD_CMD_READIO_ADDR_P3 0x33
|
||||||
|
#define CPLD_CMD_READIO_ADDR_P4 0x34
|
||||||
|
#define CPLD_CMD_READIO_ADDR_P5 0x35
|
||||||
|
#define CPLD_CMD_READIO_ADDR_P6 0x36
|
||||||
|
#define CPLD_CMD_READIO_ADDR_P7 0x37
|
||||||
|
#define CPLD_CMD_HALT 0x50
|
||||||
|
#define CPLD_CMD_REFRESH 0x51
|
||||||
|
#define CPLD_CMD_SET_SIGROUP1 0xF0
|
||||||
|
#define CPLD_CMD_SET_AUTO_REFRESH 0xF1
|
||||||
|
#define CPLD_CMD_CLEAR_AUTO_REFRESH 0xF2
|
||||||
|
#define CPLD_CMD_SET_SPI_LOOPBACK 0xFE
|
||||||
|
#define CPLD_CMD_NOP1 0x00
|
||||||
|
#define CPLD_CMD_NOP2 0xFF
|
||||||
|
|
||||||
|
|
||||||
|
// Pad numbers for using the MHal GPIO library.
|
||||||
|
#define PAD_Z80IO_IN_DATA_0 PAD_GPIO0
|
||||||
|
#define PAD_Z80IO_IN_DATA_1 PAD_GPIO1
|
||||||
|
#define PAD_Z80IO_IN_DATA_2 PAD_GPIO2
|
||||||
|
#define PAD_Z80IO_IN_DATA_3 PAD_GPIO3
|
||||||
|
#define PAD_Z80IO_IN_DATA_4 PAD_GPIO4
|
||||||
|
#define PAD_Z80IO_IN_DATA_5 PAD_GPIO5
|
||||||
|
#define PAD_Z80IO_IN_DATA_6 PAD_GPIO6
|
||||||
|
#define PAD_Z80IO_IN_DATA_7 PAD_GPIO7
|
||||||
|
#define PAD_SPIO_0 PAD_GPIO8
|
||||||
|
#define PAD_SPIO_1 PAD_GPIO9
|
||||||
|
#define PAD_SPIO_2 PAD_GPIO10
|
||||||
|
#define PAD_SPIO_3 PAD_GPIO11
|
||||||
|
#define PAD_Z80IO_HIGH_BYTE PAD_SAR_GPIO2 // Byte requiured, 0 = Low Byte, 1 = High Byte.
|
||||||
|
#define PAD_Z80IO_READY PAD_GPIO12
|
||||||
|
#define PAD_Z80IO_LTSTATE PAD_PM_IRIN // IRIN
|
||||||
|
#define PAD_Z80IO_BUSRQ PAD_GPIO13
|
||||||
|
#define PAD_Z80IO_BUSACK PAD_GPIO14
|
||||||
|
#define PAD_Z80IO_INT PAD_UART0_RX // GPIO47
|
||||||
|
#define PAD_Z80IO_NMI PAD_UART0_TX // GPIO48
|
||||||
|
#define PAD_Z80IO_WAIT PAD_HSYNC_OUT // GPIO85
|
||||||
|
#define PAD_Z80IO_RESET PAD_VSYNC_OUT // GPIO86
|
||||||
|
#define PAD_Z80IO_RSV1 PAD_SATA_GPIO // GPIO90
|
||||||
|
|
||||||
|
// Physical register addresses.
|
||||||
|
#define PAD_Z80IO_IN_DATA_0_ADDR 0x103C00
|
||||||
|
#define PAD_Z80IO_IN_DATA_1_ADDR 0x103C02
|
||||||
|
#define PAD_Z80IO_IN_DATA_2_ADDR 0x103C04
|
||||||
|
#define PAD_Z80IO_IN_DATA_3_ADDR 0x103C06
|
||||||
|
#define PAD_Z80IO_IN_DATA_4_ADDR 0x103C08
|
||||||
|
#define PAD_Z80IO_IN_DATA_5_ADDR 0x103C0A
|
||||||
|
#define PAD_Z80IO_IN_DATA_6_ADDR 0x103C0C
|
||||||
|
#define PAD_Z80IO_IN_DATA_7_ADDR 0x103C0E
|
||||||
|
#define PAD_SPIO_0_ADDR 0x103C10
|
||||||
|
#define PAD_SPIO_1_ADDR 0x103C12
|
||||||
|
#define PAD_SPIO_2_ADDR 0x103C14
|
||||||
|
#define PAD_SPIO_3_ADDR 0x103C16
|
||||||
|
#define PAD_Z80IO_HIGH_BYTE_ADDR 0x1425
|
||||||
|
#define PAD_Z80IO_READY_ADDR 0x103C18
|
||||||
|
#define PAD_Z80IO_LTSTATE_ADDR 0xF28 // IRIN
|
||||||
|
#define PAD_Z80IO_BUSRQ_ADDR 0x103C1A
|
||||||
|
#define PAD_Z80IO_BUSACK_ADDR 0x103C1C
|
||||||
|
#define PAD_Z80IO_INT_ADDR 0x103C30 // GPIO47
|
||||||
|
#define PAD_Z80IO_NMI_ADDR 0x103C32 // GPIO48
|
||||||
|
#define PAD_Z80IO_WAIT_ADDR 0x103C80 // GPIO85
|
||||||
|
#define PAD_Z80IO_RESET_ADDR 0x103C82 // GPIO86
|
||||||
|
#define PAD_Z80IO_RSV1_ADDR 0x103C8A // GPIO90
|
||||||
|
|
||||||
|
#ifdef NOTNEEDED
|
||||||
|
#define PAD_Z80IO_OUT_DATA_0 PAD_GPIO12
|
||||||
|
#define PAD_Z80IO_OUT_DATA_1 PAD_GPIO13
|
||||||
|
#define PAD_Z80IO_OUT_DATA_2 PAD_GPIO14
|
||||||
|
#define PAD_Z80IO_OUT_DATA_3 PAD_UART0_RX // GPIO47
|
||||||
|
#define PAD_Z80IO_OUT_DATA_4 PAD_UART0_TX // GPIO48
|
||||||
|
#define PAD_Z80IO_OUT_DATA_5 PAD_HSYNC_OUT // GPIO85
|
||||||
|
#define PAD_Z80IO_OUT_DATA_6 PAD_VSYNC_OUT // GPIO86
|
||||||
|
#define PAD_Z80IO_OUT_DATA_7 PAD_SATA_GPIO // GPIO90
|
||||||
|
#define PAD_Z80IO_WRITE PAD_PM_IRIN // Write data clock.
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------------------------------
|
||||||
|
// The definitions below come from SigmaStar kernel drivers. No header file exists hence the
|
||||||
|
// duplication.
|
||||||
|
//-------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#define SUPPORT_SPI_1 0
|
||||||
|
#define MAX_SUPPORT_BITS 16
|
||||||
|
|
||||||
|
#define BANK_TO_ADDR32(b) (b<<9)
|
||||||
|
#define BANK_SIZE 0x200
|
||||||
|
|
||||||
|
#define MS_BASE_REG_RIU_PA 0x1F000000
|
||||||
|
#define gChipBaseAddr 0xFD203C00
|
||||||
|
#define gPmSleepBaseAddr 0xFD001C00
|
||||||
|
#define gSarBaseAddr 0xFD002800
|
||||||
|
#define gRIUBaseAddr 0xFD000000
|
||||||
|
#define gMOVDMAAddr 0xFD201600
|
||||||
|
#define gClkBaseAddr 0xFD207000
|
||||||
|
#define gMspBaseAddr 0xfd222000
|
||||||
|
|
||||||
|
#define MHal_CHIPTOP_REG(addr) (*(volatile U8*)((gChipBaseAddr) + (((addr) & ~1)<<1) + (addr & 1)))
|
||||||
|
#define MHal_PM_SLEEP_REG(addr) (*(volatile U8*)((gPmSleepBaseAddr) + (((addr) & ~1)<<1) + (addr & 1)))
|
||||||
|
#define MHal_SAR_GPIO_REG(addr) (*(volatile U8*)((gSarBaseAddr) + (((addr) & ~1)<<1) + (addr & 1)))
|
||||||
|
#define MHal_RIU_REG(addr) (*(volatile U8*)((gRIUBaseAddr) + (((addr) & ~1)<<1) + (addr & 1)))
|
||||||
|
|
||||||
|
|
||||||
|
#define MSPI0_BANK_ADDR 0x1110
|
||||||
|
#define MSPI1_BANK_ADDR 0x1111
|
||||||
|
#define CLK__BANK_ADDR 0x1038
|
||||||
|
#define CHIPTOP_BANK_ADDR 0x101E
|
||||||
|
#define MOVDMA_BANK_ADDR 0x100B
|
||||||
|
|
||||||
|
#define BASE_REG_MSPI0_ADDR MSPI0_BANK_ADDR*0x200 //GET_BASE_ADDR_BY_BANK(IO_ADDRESS(MS_BASE_REG_RIU_PA), 0x111000)
|
||||||
|
#define BASE_REG_MSPI1_ADDR MSPI1_BANK_ADDR*0x200 //GET_BASE_ADDR_BY_BANK(IO_ADDRESS(MS_BASE_REG_RIU_PA), 0x111100)
|
||||||
|
#define BASE_REG_CLK_ADDR CLK__BANK_ADDR*0x200 //GET_BASE_ADDR_BY_BANK(IO_ADDRESS(MS_BASE_REG_RIU_PA), 0x103800)
|
||||||
|
#define BASE_REG_CHIPTOP_ADDR CHIPTOP_BANK_ADDR*0x200 //GET_BASE_ADDR_BY_BANK(IO_ADDRESS(MS_BASE_REG_RIU_PA), 0x101E00)
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------------------------------
|
||||||
|
// Hardware Register Capability
|
||||||
|
//-------------------------------------------------------------------------------------------------
|
||||||
|
#define MSPI_WRITE_BUF_OFFSET 0x40
|
||||||
|
#define MSPI_READ_BUF_OFFSET 0x44
|
||||||
|
#define MSPI_WBF_SIZE_OFFSET 0x48
|
||||||
|
#define MSPI_RBF_SIZE_OFFSET 0x48
|
||||||
|
// read/ write buffer size
|
||||||
|
#define MSPI_RWSIZE_MASK 0xFF
|
||||||
|
#define MSPI_RSIZE_BIT_OFFSET 0x8
|
||||||
|
#define MAX_READ_BUF_SIZE 0x8
|
||||||
|
#define MAX_WRITE_BUF_SIZE 0x8
|
||||||
|
// CLK config
|
||||||
|
#define MSPI_CTRL_OFFSET 0x49
|
||||||
|
#define MSPI_CLK_CLOCK_OFFSET 0x49
|
||||||
|
#define MSPI_CLK_CLOCK_BIT_OFFSET 0x08
|
||||||
|
#define MSPI_CLK_CLOCK_MASK 0xFF
|
||||||
|
#define MSPI_CLK_PHASE_MASK 0x40
|
||||||
|
#define MSPI_CLK_PHASE_BIT_OFFSET 0x06
|
||||||
|
#define MSPI_CLK_POLARITY_MASK 0x80
|
||||||
|
#define MSPI_CLK_POLARITY_BIT_OFFSET 0x07
|
||||||
|
#define MSPI_CLK_PHASE_MAX 0x1
|
||||||
|
#define MSPI_CLK_POLARITY_MAX 0x1
|
||||||
|
#define MSPI_CLK_CLOCK_MAX 0x7
|
||||||
|
#define MSPI_CTRL_CPOL_LOW 0x00
|
||||||
|
#define MSPI_CTRL_CPOL_HIGH 0x80
|
||||||
|
#define MSPI_CTRL_CPHA_LOW 0x00
|
||||||
|
#define MSPI_CTRL_CPHA_HIGH 0x40
|
||||||
|
#define MSPI_CTRL_3WIRE 0x10
|
||||||
|
#define MSPI_CTRL_INTEN 0x04
|
||||||
|
#define MSPI_CTRL_RESET 0x02
|
||||||
|
#define MSPI_CTRL_ENABLE_SPI 0x01
|
||||||
|
// DC config
|
||||||
|
#define MSPI_DC_MASK 0xFF
|
||||||
|
#define MSPI_DC_BIT_OFFSET 0x08
|
||||||
|
#define MSPI_DC_TR_START_OFFSET 0x4A
|
||||||
|
#define MSPI_DC_TRSTART_MAX 0xFF
|
||||||
|
#define MSPI_DC_TR_END_OFFSET 0x4A
|
||||||
|
#define MSPI_DC_TREND_MAX 0xFF
|
||||||
|
#define MSPI_DC_TB_OFFSET 0x4B
|
||||||
|
#define MSPI_DC_TB_MAX 0xFF
|
||||||
|
#define MSPI_DC_TRW_OFFSET 0x4B
|
||||||
|
#define MSPI_DC_TRW_MAX 0xFF
|
||||||
|
// Frame Config
|
||||||
|
#define MSPI_FRAME_WBIT_OFFSET 0x4C
|
||||||
|
#define MSPI_FRAME_RBIT_OFFSET 0x4E
|
||||||
|
#define MSPI_FRAME_BIT_MAX 0x07
|
||||||
|
#define MSPI_FRAME_BIT_MASK 0x07
|
||||||
|
#define MSPI_FRAME_BIT_FIELD 0x03
|
||||||
|
#define MSPI_LSB_FIRST_OFFSET 0x50
|
||||||
|
#define MSPI_TRIGGER_OFFSET 0x5A
|
||||||
|
#define MSPI_DONE_OFFSET 0x5B
|
||||||
|
#define MSPI_DONE_CLEAR_OFFSET 0x5C
|
||||||
|
#define MSPI_CHIP_SELECT_OFFSET 0x5F
|
||||||
|
#define MSPI_CS1_DISABLE 0x01
|
||||||
|
#define MSPI_CS1_ENABLE 0x00
|
||||||
|
#define MSPI_CS2_DISABLE 0x02
|
||||||
|
#define MSPI_CS2_ENABLE 0x00
|
||||||
|
#define MSPI_CS3_DISABLE 0x04
|
||||||
|
#define MSPI_CS3_ENABLE 0x00
|
||||||
|
#define MSPI_CS4_DISABLE 0x08
|
||||||
|
#define MSPI_CS4_ENABLE 0x00
|
||||||
|
#define MSPI_CS5_DISABLE 0x10
|
||||||
|
#define MSPI_CS5_ENABLE 0x00
|
||||||
|
#define MSPI_CS6_DISABLE 0x20
|
||||||
|
#define MSPI_CS6_ENABLE 0x00
|
||||||
|
#define MSPI_CS7_DISABLE 0x40
|
||||||
|
#define MSPI_CS7_ENABLE 0x00
|
||||||
|
#define MSPI_CS8_DISABLE 0x80
|
||||||
|
#define MSPI_CS8_ENABLE 0x00
|
||||||
|
|
||||||
|
#define MSPI_FULL_DEPLUX_RD_CNT (0x77)
|
||||||
|
#define MSPI_FULL_DEPLUX_RD00 (0x78)
|
||||||
|
#define MSPI_FULL_DEPLUX_RD01 (0x78)
|
||||||
|
#define MSPI_FULL_DEPLUX_RD02 (0x79)
|
||||||
|
#define MSPI_FULL_DEPLUX_RD03 (0x79)
|
||||||
|
#define MSPI_FULL_DEPLUX_RD04 (0x7a)
|
||||||
|
#define MSPI_FULL_DEPLUX_RD05 (0x7a)
|
||||||
|
#define MSPI_FULL_DEPLUX_RD06 (0x7b)
|
||||||
|
#define MSPI_FULL_DEPLUX_RD07 (0x7b)
|
||||||
|
|
||||||
|
#define MSPI_FULL_DEPLUX_RD08 (0x7c)
|
||||||
|
#define MSPI_FULL_DEPLUX_RD09 (0x7c)
|
||||||
|
#define MSPI_FULL_DEPLUX_RD10 (0x7d)
|
||||||
|
#define MSPI_FULL_DEPLUX_RD11 (0x7d)
|
||||||
|
#define MSPI_FULL_DEPLUX_RD12 (0x7e)
|
||||||
|
#define MSPI_FULL_DEPLUX_RD13 (0x7e)
|
||||||
|
#define MSPI_FULL_DEPLUX_RD14 (0x7f)
|
||||||
|
#define MSPI_FULL_DEPLUX_RD15 (0x7f)
|
||||||
|
|
||||||
|
//chip select bit map
|
||||||
|
#define MSPI_CHIP_SELECT_MAX 0x07
|
||||||
|
|
||||||
|
// control bit
|
||||||
|
#define MSPI_DONE_FLAG 0x01
|
||||||
|
#define MSPI_TRIGGER 0x01
|
||||||
|
#define MSPI_CLEAR_DONE 0x01
|
||||||
|
#define MSPI_INT_ENABLE 0x04
|
||||||
|
#define MSPI_RESET 0x02
|
||||||
|
#define MSPI_ENABLE 0x01
|
||||||
|
|
||||||
|
// clk_mspi0
|
||||||
|
#define MSPI0_CLK_CFG 0x33 //bit 2 ~bit 3
|
||||||
|
#define MSPI0_CLK_108M 0x00
|
||||||
|
#define MSPI0_CLK_54M 0x04
|
||||||
|
#define MSPI0_CLK_12M 0x08
|
||||||
|
#define MSPI0_CLK_MASK 0x0F
|
||||||
|
|
||||||
|
// clk_mspi1
|
||||||
|
#define MSPI1_CLK_CFG 0x33 //bit 10 ~bit 11
|
||||||
|
#define MSPI1_CLK_108M 0x0000
|
||||||
|
#define MSPI1_CLK_54M 0x0400
|
||||||
|
#define MSPI1_CLK_12M 0x0800
|
||||||
|
#define MSPI1_CLK_MASK 0x0F00
|
||||||
|
|
||||||
|
// clk_mspi
|
||||||
|
#define MSPI_CLK_CFG 0x33
|
||||||
|
#define MSPI_SELECT_0 0x0000
|
||||||
|
#define MSPI_SELECT_1 0x4000
|
||||||
|
#define MSPI_CLK_MASK 0xF000
|
||||||
|
|
||||||
|
// Clock settings
|
||||||
|
#define MSPI_CPU_CLOCK_1_2 0x0000
|
||||||
|
#define MSPI_CPU_CLOCK_1_4 0x0100
|
||||||
|
#define MSPI_CPU_CLOCK_1_8 0x0200
|
||||||
|
#define MSPI_CPU_CLOCK_1_16 0x0300
|
||||||
|
#define MSPI_CPU_CLOCK_1_32 0x0400
|
||||||
|
#define MSPI_CPU_CLOCK_1_64 0x0500
|
||||||
|
#define MSPI_CPU_CLOCK_1_128 0x0600
|
||||||
|
#define MSPI_CPU_CLOCK_1_256 0x0700
|
||||||
|
|
||||||
|
//CHITOP 101E mspi mode select
|
||||||
|
#define MSPI0_MODE 0x0C //bit0~bit1
|
||||||
|
#define MSPI0_MODE_MASK 0x07
|
||||||
|
#define MSPI1_MODE 0x0C //bit4~bit5
|
||||||
|
#define MSPI1_MODE_MASK 0x70
|
||||||
|
#define EJTAG_MODE 0xF
|
||||||
|
#define EJTAG_MODE_1 0x01
|
||||||
|
#define EJTAG_MODE_2 0x02
|
||||||
|
#define EJTAG_MODE_3 0x03
|
||||||
|
#define EJTAG_MODE_MASK 0x03
|
||||||
|
|
||||||
|
//MOVDMA 100B
|
||||||
|
#define MOV_DMA_SRC_ADDR_L 0x03
|
||||||
|
#define MOV_DMA_SRC_ADDR_H 0x04
|
||||||
|
#define MOV_DMA_DST_ADDR_L 0x05
|
||||||
|
#define MOV_DMA_DST_ADDR_H 0x06
|
||||||
|
#define MOV_DMA_BYTE_CNT_L 0x07
|
||||||
|
#define MOV_DMA_BYTE_CNT_H 0x08
|
||||||
|
#define DMA_MOVE0_IRQ_CLR 0x28
|
||||||
|
#define MOV_DMA_IRQ_FINAL_STATUS 0x2A
|
||||||
|
#define DMA_MOVE0_ENABLE 0x00
|
||||||
|
#define DMA_RW 0x50 //0 for dma write to device, 1 for dma read from device
|
||||||
|
#define DMA_READ 0x01
|
||||||
|
#define DMA_WRITE 0x00
|
||||||
|
#define DMA_DEVICE_MODE 0x51
|
||||||
|
#define DMA_DEVICE_SEL 0x52
|
||||||
|
|
||||||
|
//spi dma
|
||||||
|
#define MSPI_DMA_DATA_LENGTH_L 0x30
|
||||||
|
#define MSPI_DMA_DATA_LENGTH_H 0x31
|
||||||
|
#define MSPI_DMA_ENABLE 0x32
|
||||||
|
#define MSPI_DMA_RW_MODE 0x33
|
||||||
|
#define MSPI_DMA_WRITE 0x00
|
||||||
|
#define MSPI_DMA_READ 0x01
|
||||||
|
|
||||||
|
#define MSTAR_SPI_TIMEOUT_MS 30000
|
||||||
|
#define MSTAR_SPI_MODE_BITS (SPI_CPOL | SPI_CPHA /*| SPI_CS_HIGH | SPI_NO_CS | SPI_LSB_FIRST*/)
|
||||||
|
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------------------------------
|
||||||
|
// Macros
|
||||||
|
//-------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
#define MHal_CHIPTOP_REG(addr) (*(volatile U8*)((gChipBaseAddr) + (((addr) & ~1)<<1) + (addr & 1)))
|
||||||
|
#define MHal_PM_SLEEP_REG(addr) (*(volatile U8*)((gPmSleepBaseAddr) + (((addr) & ~1)<<1) + (addr & 1)))
|
||||||
|
#define MHal_SAR_GPIO_REG(addr) (*(volatile U8*)((gSarBaseAddr) + (((addr) & ~1)<<1) + (addr & 1)))
|
||||||
|
#define MHal_RIU_REG(addr) (*(volatile U8*)((gRIUBaseAddr) + (((addr) & ~1)<<1) + (addr & 1)))
|
||||||
|
#define READ_BYTE(_reg) (*(volatile u8*)(_reg))
|
||||||
|
#define READ_WORD(_reg) (*(volatile u16*)(_reg))
|
||||||
|
#define READ_LONG(_reg) (*(volatile u32*)(_reg))
|
||||||
|
#define WRITE_BYTE(_reg, _val) {(*((volatile u8*)(_reg))) = (u8)(_val); }
|
||||||
|
#define WRITE_WORD(_reg, _val) {(*((volatile u16*)(_reg))) = (u16)(_val); }
|
||||||
|
#define WRITE_LONG(_reg, _val) {(*((volatile u32*)(_reg))) = (u32)(_val); }
|
||||||
|
#define WRITE_WORD_MASK(_reg, _val, _mask) {(*((volatile u16*)(_reg))) = ((*((volatile u16*)(_reg))) & ~(_mask)) | ((u16)(_val) & (_mask)); }
|
||||||
|
#define READ_CPLD_DATA_IN() ((MHal_RIU_REG(PAD_Z80IO_IN_DATA_7_ADDR) & 0x1) << 7 | (MHal_RIU_REG(PAD_Z80IO_IN_DATA_6_ADDR) & 0x1) << 6 | (MHal_RIU_REG(PAD_Z80IO_IN_DATA_5_ADDR) & 0x1) << 5 | (MHal_RIU_REG(PAD_Z80IO_IN_DATA_4_ADDR) & 0x1) << 4 |\
|
||||||
|
(MHal_RIU_REG(PAD_Z80IO_IN_DATA_3_ADDR) & 0x1) << 3 | (MHal_RIU_REG(PAD_Z80IO_IN_DATA_2_ADDR) & 0x1) << 2 | (MHal_RIU_REG(PAD_Z80IO_IN_DATA_1_ADDR) & 0x1) << 1 | (MHal_RIU_REG(PAD_Z80IO_IN_DATA_0_ADDR) & 0x1))
|
||||||
|
#define SET_CPLD_READ_DATA() {MHal_RIU_REG(PAD_Z80IO_HIGH_BYTE_ADDR) |= 0x4;}
|
||||||
|
#define SET_CPLD_READ_STATUS() {MHal_RIU_REG(PAD_Z80IO_HIGH_BYTE_ADDR) &= ~0x4;}
|
||||||
|
#define SET_CPLD_HIGH_BYTE() {MHal_RIU_REG(PAD_Z80IO_HIGH_BYTE_ADDR) |= 0x4;}
|
||||||
|
#define CLEAR_CPLD_HIGH_BYTE() {MHal_RIU_REG(PAD_Z80IO_HIGH_BYTE_ADDR) &= ~0x4;}
|
||||||
|
#define CPLD_READY() (MHal_RIU_REG(PAD_Z80IO_READY_ADDR) & 0x1)
|
||||||
|
#define CPLD_RESET() (MHal_RIU_REG(PAD_Z80IO_RESET_ADDR) & 0x1)
|
||||||
|
#define CPLD_LAST_TSTATE() (MHal_RIU_REG(PAD_Z80IO_LTSTATE_ADDR) & 0x4)
|
||||||
|
#define SPI_SEND8(_d_) { uint32_t timeout = MAX_CHECK_CNT; \
|
||||||
|
MSPI_WRITE(MSPI_WRITE_BUF_OFFSET, (uint16_t)(_d_)); \
|
||||||
|
MSPI_WRITE(MSPI_WBF_SIZE_OFFSET, 1); \
|
||||||
|
while((MHal_RIU_REG(PAD_Z80IO_READY_ADDR) & 0x1) == 0);\
|
||||||
|
MSPI_WRITE(MSPI_CHIP_SELECT_OFFSET, MSPI_CS8_DISABLE | MSPI_CS7_DISABLE | MSPI_CS6_DISABLE | MSPI_CS5_DISABLE | MSPI_CS4_DISABLE | MSPI_CS3_DISABLE | MSPI_CS2_DISABLE | MSPI_CS1_ENABLE); \
|
||||||
|
MSPI_WRITE(MSPI_TRIGGER_OFFSET, MSPI_TRIGGER); \
|
||||||
|
while((MSPI_READ(MSPI_DONE_OFFSET) & MSPI_DONE_FLAG) == 0) { if(--timeout == 0) break; } \
|
||||||
|
MSPI_WRITE(MSPI_CHIP_SELECT_OFFSET, MSPI_CS8_DISABLE | MSPI_CS7_DISABLE | MSPI_CS6_DISABLE | MSPI_CS5_DISABLE | MSPI_CS4_DISABLE | MSPI_CS3_DISABLE | MSPI_CS2_DISABLE | MSPI_CS1_DISABLE); \
|
||||||
|
MSPI_WRITE(MSPI_DONE_CLEAR_OFFSET, MSPI_CLEAR_DONE);\
|
||||||
|
}
|
||||||
|
#define SPI_SEND16(_d_) { uint32_t timeout = MAX_CHECK_CNT; \
|
||||||
|
MSPI_WRITE(MSPI_WRITE_BUF_OFFSET, (uint16_t)(_d_)); \
|
||||||
|
MSPI_WRITE(MSPI_WBF_SIZE_OFFSET, 2); \
|
||||||
|
while((MHal_RIU_REG(PAD_Z80IO_READY_ADDR) & 0x1) == 0);\
|
||||||
|
MSPI_WRITE(MSPI_CHIP_SELECT_OFFSET, MSPI_CS8_DISABLE | MSPI_CS7_DISABLE | MSPI_CS6_DISABLE | MSPI_CS5_DISABLE | MSPI_CS4_DISABLE | MSPI_CS3_DISABLE | MSPI_CS2_DISABLE | MSPI_CS1_ENABLE); \
|
||||||
|
MSPI_WRITE(MSPI_TRIGGER_OFFSET, MSPI_TRIGGER); \
|
||||||
|
while((MSPI_READ(MSPI_DONE_OFFSET) & MSPI_DONE_FLAG) == 0) { if(--timeout == 0) break; } \
|
||||||
|
MSPI_WRITE(MSPI_CHIP_SELECT_OFFSET, MSPI_CS8_DISABLE | MSPI_CS7_DISABLE | MSPI_CS6_DISABLE | MSPI_CS5_DISABLE | MSPI_CS4_DISABLE | MSPI_CS3_DISABLE | MSPI_CS2_DISABLE | MSPI_CS1_DISABLE); \
|
||||||
|
MSPI_WRITE(MSPI_DONE_CLEAR_OFFSET, MSPI_CLEAR_DONE); \
|
||||||
|
}
|
||||||
|
#define SPI_SEND32(_d_) { uint32_t timeout = MAX_CHECK_CNT; \
|
||||||
|
MSPI_WRITE(MSPI_WRITE_BUF_OFFSET, (uint16_t)(_d_)); \
|
||||||
|
MSPI_WRITE(MSPI_WRITE_BUF_OFFSET+1, (uint16_t)((_d_) >> 16)); \
|
||||||
|
MSPI_WRITE(MSPI_WBF_SIZE_OFFSET, 4); \
|
||||||
|
while((MHal_RIU_REG(PAD_Z80IO_READY_ADDR) & 0x1) == 0);\
|
||||||
|
MSPI_WRITE(MSPI_CHIP_SELECT_OFFSET, MSPI_CS8_DISABLE | MSPI_CS7_DISABLE | MSPI_CS6_DISABLE | MSPI_CS5_DISABLE | MSPI_CS4_DISABLE | MSPI_CS3_DISABLE | MSPI_CS2_DISABLE | MSPI_CS1_ENABLE); \
|
||||||
|
MSPI_WRITE(MSPI_TRIGGER_OFFSET, MSPI_TRIGGER); \
|
||||||
|
while((MSPI_READ(MSPI_DONE_OFFSET) & MSPI_DONE_FLAG) == 0) { if(--timeout == 0) break; } \
|
||||||
|
MSPI_WRITE(MSPI_CHIP_SELECT_OFFSET, MSPI_CS8_DISABLE | MSPI_CS7_DISABLE | MSPI_CS6_DISABLE | MSPI_CS5_DISABLE | MSPI_CS4_DISABLE | MSPI_CS3_DISABLE | MSPI_CS2_DISABLE | MSPI_CS1_DISABLE); \
|
||||||
|
MSPI_WRITE(MSPI_DONE_CLEAR_OFFSET, MSPI_CLEAR_DONE); \
|
||||||
|
}
|
||||||
|
|
||||||
|
// read 2 byte
|
||||||
|
#define MSPI_READ(_reg_) READ_WORD(gMspBaseAddr + ((_reg_)<<2))
|
||||||
|
// write 2 byte
|
||||||
|
//#define MSPI_WRITE(_reg_, _val_) {pr_info("PDS: MSPI_WRITE(0x%x, 0x%x, 0x%x)\n", _reg_, _val_, gMspBaseAddr + ((_reg_)<<2)); WRITE_WORD(gMspBaseAddr + ((_reg_)<<2), (_val_)); }
|
||||||
|
#define MSPI_WRITE(_reg_, _val_) WRITE_WORD(gMspBaseAddr + ((_reg_)<<2), (_val_));
|
||||||
|
//write 2 byte mask
|
||||||
|
//#define MSPI_WRITE_MASK(_reg_, _val_, mask) {pr_info("PDS: WRITE_LONG(0x%x, 0x%x, mask=0x%x)\n", _reg_, _val_, mask); WRITE_WORD_MASK(gMspBaseAddr + ((_reg_)<<2), (_val_), (mask)); }
|
||||||
|
#define MSPI_WRITE_MASK(_reg_, _val_, mask) WRITE_WORD_MASK(gMspBaseAddr + ((_reg_)<<2), (_val_), (mask));
|
||||||
|
|
||||||
|
#define CLK_READ(_reg_) READ_WORD(gClkBaseAddr + ((_reg_)<<2))
|
||||||
|
//#define CLK_WRITE(_reg_, _val_) {pr_info("PDS: CLK_WRITE(0x%x, 0x%x)\n", _reg_, _val_); WRITE_WORD(gClkBaseAddr + ((_reg_)<<2), (_val_)); }
|
||||||
|
#define CLK_WRITE(_reg_, _val_) WRITE_WORD(gClkBaseAddr + ((_reg_)<<2), (_val_));
|
||||||
|
|
||||||
|
#define CHIPTOP_READ(_reg_) READ_WORD(gChipBaseAddr + ((_reg_)<<2))
|
||||||
|
//#define CHIPTOP_WRITE(_reg_, _val_) {pr_info("PDS: CHIPTOP_WRITE(0x%x, 0x%x)\n", _reg_, _val_); WRITE_WORD(gChipBaseAddr + ((_reg_)<<2), (_val_)); }
|
||||||
|
#define CHIPTOP_WRITE(_reg_, _val_) WRITE_WORD(gChipBaseAddr + ((_reg_)<<2), (_val_));
|
||||||
|
|
||||||
|
#define MOVDMA_READ(_reg_) READ_WORD(gMOVDMAAddr + ((_reg_)<<2))
|
||||||
|
//#define MOVDMA_WRITE(_reg_, _val_) {pr_info("PDS: MOVDMA_WRITE(0x%x, 0x%x)\n", _reg_, _val_); WRITE_WORD(gMOVDMAAddr + ((_reg_)<<2), (_val_)); }
|
||||||
|
#define MOVDMA_WRITE(_reg_, _val_) WRITE_WORD(gMOVDMAAddr + ((_reg_)<<2), (_val_));
|
||||||
|
|
||||||
|
#define _HAL_MSPI_ClearDone() MSPI_WRITE(MSPI_DONE_CLEAR_OFFSET,MSPI_CLEAR_DONE)
|
||||||
|
#define MAX_CHECK_CNT 2000
|
||||||
|
|
||||||
|
#define MSPI_READ_INDEX 0x0
|
||||||
|
#define MSPI_WRITE_INDEX 0x1
|
||||||
|
|
||||||
|
#define SPI_MIU0_BUS_BASE 0x20000000
|
||||||
|
#define SPI_MIU1_BUS_BASE 0xFFFFFFFF
|
||||||
|
|
||||||
|
|
||||||
|
// Function definitions.
|
||||||
|
//
|
||||||
|
int z80io_init(void);
|
||||||
|
uint8_t z80io_SPI_Send8(uint8_t txData, uint8_t *rxData);
|
||||||
|
uint8_t z80io_SPI_Send16(uint16_t txData, uint16_t *rxData);
|
||||||
|
uint8_t z80io_SPI_Send32(uint32_t txData, uint32_t *rxData);
|
||||||
|
#ifdef NOTNEEDED
|
||||||
|
uint8_t z80io_PRL_Send8(uint8_t txData);
|
||||||
|
uint8_t z680io_PRL_Send16(uint16_t txData);
|
||||||
|
#endif
|
||||||
|
uint8_t z80io_PRL_Read8(uint8_t dataFlag);
|
||||||
|
uint16_t z80io_PRL_Read16(void);
|
||||||
|
uint8_t z80io_SPI_Test(void);
|
||||||
|
uint8_t z80io_PRL_Test(void);
|
||||||
|
uint8_t z80io_Z80_TestMemory(void);
|
||||||
|
|
||||||
|
extern void MHal_GPIO_Init(void);
|
||||||
|
extern void MHal_GPIO_Pad_Set(uint8_t u8IndexGPIO);
|
||||||
|
extern int MHal_GPIO_PadGroupMode_Set(uint32_t u32PadMode);
|
||||||
|
extern int MHal_GPIO_PadVal_Set(uint8_t u8IndexGPIO, uint32_t u32PadMode);
|
||||||
|
extern void MHal_GPIO_Pad_Oen(uint8_t u8IndexGPIO);
|
||||||
|
extern void MHal_GPIO_Pad_Odn(uint8_t u8IndexGPIO);
|
||||||
|
extern uint8_t MHal_GPIO_Pad_Level(uint8_t u8IndexGPIO);
|
||||||
|
extern uint8_t MHal_GPIO_Pad_InOut(uint8_t u8IndexGPIO);
|
||||||
|
extern void MHal_GPIO_Pull_High(uint8_t u8IndexGPIO);
|
||||||
|
extern void MHal_GPIO_Pull_Low(uint8_t u8IndexGPIO);
|
||||||
|
extern void MHal_GPIO_Set_High(uint8_t u8IndexGPIO);
|
||||||
|
extern void MHal_GPIO_Set_Low(uint8_t u8IndexGPIO);
|
||||||
|
extern void MHal_Enable_GPIO_INT(uint8_t u8IndexGPIO);
|
||||||
|
extern int MHal_GPIO_To_Irq(uint8_t u8IndexGPIO);
|
||||||
|
extern void MHal_GPIO_Set_POLARITY(uint8_t u8IndexGPIO, uint8_t reverse);
|
||||||
|
extern void MHal_GPIO_Set_Driving(uint8_t u8IndexGPIO, uint8_t setHigh);
|
||||||
|
extern void MHal_GPIO_PAD_32K_OUT(uint8_t u8Enable);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#endif // Z80IO_H
|
||||||
541
software/FusionX/src/driver/MZ700/z80io_test.c
Normal file
@@ -0,0 +1,541 @@
|
|||||||
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Name: z80io_test.c
|
||||||
|
// Created: Oct 2022
|
||||||
|
// Author(s): Philip Smart
|
||||||
|
// Description: Z80 IO Interface Test Methods
|
||||||
|
// This file contains the methods used to test the SOM to CPLD interface and evaluate
|
||||||
|
// it's performance. Production builds wont include these methods.
|
||||||
|
// Credits:
|
||||||
|
// Copyright: (c) 2019-2022 Philip Smart <philip.smart@net2net.org>
|
||||||
|
//
|
||||||
|
// History: Oct 2022 - Initial write of the z80 kernel driver software.
|
||||||
|
//
|
||||||
|
// Notes: See Makefile to enable/disable conditional components
|
||||||
|
//
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// This source file is free software: you can redistribute it and#or modify
|
||||||
|
// it under the terms of the GNU General Public License as published
|
||||||
|
// by the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This source file is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#include <linux/module.h>
|
||||||
|
#include <linux/kernel.h>
|
||||||
|
#include <linux/semaphore.h>
|
||||||
|
#include <linux/kthread.h>
|
||||||
|
#include <linux/sched.h>
|
||||||
|
|
||||||
|
//--------------------------------------------------------
|
||||||
|
// Test Methods.
|
||||||
|
//--------------------------------------------------------
|
||||||
|
uint8_t z80io_Z80_TestMemory(void)
|
||||||
|
{
|
||||||
|
// Locals.
|
||||||
|
//
|
||||||
|
uint32_t addr;
|
||||||
|
uint32_t fullCmd;
|
||||||
|
uint8_t cmd;
|
||||||
|
struct timeval start, stop;
|
||||||
|
uint32_t iterations = 100;
|
||||||
|
uint32_t errorCount;
|
||||||
|
uint32_t idx;
|
||||||
|
long totalTime;
|
||||||
|
long bytesMSec;
|
||||||
|
uint8_t result;
|
||||||
|
spinlock_t spinLock;
|
||||||
|
unsigned long flags;
|
||||||
|
|
||||||
|
SPI_SEND8(CPLD_CMD_CLEAR_AUTO_REFRESH);
|
||||||
|
|
||||||
|
SPI_SEND32(0x00E30000 | (0x07 << 8) | CPLD_CMD_WRITEIO_ADDR);
|
||||||
|
udelay(100);
|
||||||
|
SPI_SEND32(0x00E80000 | (0x82 << 8) | CPLD_CMD_WRITEIO_ADDR);
|
||||||
|
udelay(100);
|
||||||
|
SPI_SEND32(0x00E20000 | (0x58 << 8) | CPLD_CMD_WRITEIO_ADDR);
|
||||||
|
udelay(100);
|
||||||
|
SPI_SEND32(0x00E00000 | (0xF7 << 8) | CPLD_CMD_WRITEIO_ADDR);
|
||||||
|
udelay(100);
|
||||||
|
SPI_SEND32(0x00E90000 | (0x0F << 8) | CPLD_CMD_WRITEIO_ADDR);
|
||||||
|
udelay(100);
|
||||||
|
SPI_SEND32(0x00EB0000 | (0xCF << 8) | CPLD_CMD_WRITEIO_ADDR);
|
||||||
|
udelay(100);
|
||||||
|
SPI_SEND32(0x00EB0000 | (0xFF << 8) | CPLD_CMD_WRITEIO_ADDR);
|
||||||
|
udelay(100);
|
||||||
|
pr_info("Z80 Host Test - IO.\n");
|
||||||
|
for(idx=0; idx < 1000000; idx++)
|
||||||
|
{
|
||||||
|
SPI_SEND32(0x00E80000 | (0xD3 << 8) | CPLD_CMD_WRITEIO_ADDR);
|
||||||
|
SPI_SEND32(0xD0000000 | (0x41 << 8) | CPLD_CMD_WRITE_ADDR);
|
||||||
|
SPI_SEND32(0xD0100000 | (0x41 << 8) | CPLD_CMD_WRITE_ADDR);
|
||||||
|
SPI_SEND32(0xD0200000 | (0x41 << 8) | CPLD_CMD_WRITE_ADDR);
|
||||||
|
SPI_SEND32(0xD0300000 | (0x41 << 8) | CPLD_CMD_WRITE_ADDR);
|
||||||
|
SPI_SEND32(0xD0400000 | (0x41 << 8) | CPLD_CMD_WRITE_ADDR);
|
||||||
|
SPI_SEND32(0xD0500000 | (0x41 << 8) | CPLD_CMD_WRITE_ADDR);
|
||||||
|
}
|
||||||
|
|
||||||
|
spin_lock_init(&spinLock);
|
||||||
|
pr_info("Z80 Host Test - Testing IO Write performance.\n");
|
||||||
|
do_gettimeofday(&start);
|
||||||
|
spin_lock_irqsave(&spinLock, flags);
|
||||||
|
for(idx=0; idx < iterations; idx++)
|
||||||
|
{
|
||||||
|
for(addr=0x0000; addr < 0x10000; addr++)
|
||||||
|
{
|
||||||
|
fullCmd = 0x00000000| ((uint8_t)addr) << 8 | CPLD_CMD_WRITEIO_ADDR;
|
||||||
|
SPI_SEND32(fullCmd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
spin_unlock_irqrestore(&spinLock, flags);
|
||||||
|
do_gettimeofday(&stop);
|
||||||
|
totalTime = (stop.tv_sec - start.tv_sec) * 1000000 + stop.tv_usec - start.tv_usec;
|
||||||
|
bytesMSec = (long)(1*iterations*0xC000)/((long)totalTime/1000);
|
||||||
|
pr_info("Loop mode time=%ldms, %ldBytes/sec\n", totalTime/1000, (bytesMSec*1000));
|
||||||
|
|
||||||
|
spin_lock_init(&spinLock);
|
||||||
|
pr_info("Z80 Host Test - Testing IO Read performance.\n");
|
||||||
|
do_gettimeofday(&start);
|
||||||
|
spin_lock_irqsave(&spinLock, flags);
|
||||||
|
for(idx=0; idx < iterations; idx++)
|
||||||
|
{
|
||||||
|
// Go through all the accessible IO ports and write to it.
|
||||||
|
for(addr=0x0000; addr < 0x10000; addr++)
|
||||||
|
{
|
||||||
|
fullCmd = 0x00000000 | ((uint8_t)addr) << 8 | CPLD_CMD_READIO_ADDR;
|
||||||
|
SPI_SEND32(fullCmd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
spin_unlock_irqrestore(&spinLock, flags);
|
||||||
|
do_gettimeofday(&stop);
|
||||||
|
totalTime = (stop.tv_sec - start.tv_sec) * 1000000 + stop.tv_usec - start.tv_usec;
|
||||||
|
bytesMSec = (long)(1*iterations*0xC000)/((long)totalTime/1000);
|
||||||
|
pr_info("Loop mode time=%ldms, %ldBytes/sec\n", totalTime/1000, (bytesMSec*1000));
|
||||||
|
|
||||||
|
spin_lock_init(&spinLock);
|
||||||
|
pr_info("Z80 Host Test - Testing RAM Write performance.\n");
|
||||||
|
do_gettimeofday(&start);
|
||||||
|
spin_lock_irqsave(&spinLock, flags);
|
||||||
|
for(idx=0; idx < iterations; idx++)
|
||||||
|
{
|
||||||
|
// Go through all the accessible RAM and write to it.
|
||||||
|
for(addr=0x1000; addr < 0xD000; addr++)
|
||||||
|
{
|
||||||
|
fullCmd = (addr << 16) | ((uint8_t)addr) << 8 | 0x18;
|
||||||
|
SPI_SEND32(fullCmd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
spin_unlock_irqrestore(&spinLock, flags);
|
||||||
|
do_gettimeofday(&stop);
|
||||||
|
totalTime = (stop.tv_sec - start.tv_sec) * 1000000 + stop.tv_usec - start.tv_usec;
|
||||||
|
bytesMSec = (long)(1*iterations*0xC000)/((long)totalTime/1000);
|
||||||
|
pr_info("Loop mode time=%ldms, %ldBytes/sec\n", totalTime/1000, (bytesMSec*1000));
|
||||||
|
|
||||||
|
pr_info("Z80 Host Test - Testing RAM Write performance (opt).\n");
|
||||||
|
do_gettimeofday(&start);
|
||||||
|
spin_lock_irqsave(&spinLock, flags);
|
||||||
|
for(idx=0; idx < iterations; idx++)
|
||||||
|
{
|
||||||
|
// Go through all the accessible RAM and write to it.
|
||||||
|
for(addr=0x1000; addr < 0xD000; addr++)
|
||||||
|
{
|
||||||
|
if(addr == 0x1000)
|
||||||
|
{
|
||||||
|
fullCmd = (addr << 16) | ((uint8_t)addr) << 8 | 0x18;
|
||||||
|
SPI_SEND32(fullCmd);
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
cmd = 0x19;
|
||||||
|
SPI_SEND16(((uint8_t)addr) << 8 | cmd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
spin_unlock_irqrestore(&spinLock, flags);
|
||||||
|
do_gettimeofday(&stop);
|
||||||
|
totalTime = (stop.tv_sec - start.tv_sec) * 1000000 + stop.tv_usec - start.tv_usec;
|
||||||
|
bytesMSec = (long)(1*iterations*0xC000)/((long)totalTime/1000);
|
||||||
|
pr_info("Loop mode time=%ldms, %ldBytes/sec\n", totalTime/1000, (bytesMSec*1000));
|
||||||
|
|
||||||
|
pr_info("Z80 Host Test - Testing RAM Write/Fetch performance (opt).\n");
|
||||||
|
errorCount = 0;
|
||||||
|
SET_CPLD_READ_DATA();
|
||||||
|
//MHal_RIU_REG(gpio_table[PAD_Z80IO_HIGH_BYTE ].r_out) |= gpio_table[PAD_Z80IO_HIGH_BYTE ].m_out;
|
||||||
|
do_gettimeofday(&start);
|
||||||
|
for(idx=0; idx < iterations; idx++)
|
||||||
|
{
|
||||||
|
// Go through all the accessible RAM and write to it.
|
||||||
|
for(addr=0x8000; addr < 0xD000; addr++)
|
||||||
|
{
|
||||||
|
if(addr == 0x8000)
|
||||||
|
{
|
||||||
|
fullCmd = (addr << 16) | ((uint8_t)addr) << 8 | 0x18;
|
||||||
|
SPI_SEND32(fullCmd);
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
cmd = 0x19;
|
||||||
|
SPI_SEND16(((uint8_t)addr) << 8 | cmd);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read back the same byte.
|
||||||
|
cmd = 0x10;
|
||||||
|
SPI_SEND8(cmd);
|
||||||
|
while(CPLD_READY() == 0);
|
||||||
|
|
||||||
|
result = READ_CPLD_DATA_IN();
|
||||||
|
if(result != (uint8_t)addr)
|
||||||
|
{
|
||||||
|
if(errorCount < 50) pr_info("Read byte:0x%x, Written:0x%x\n", result, (uint8_t)addr);
|
||||||
|
errorCount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
do_gettimeofday(&stop);
|
||||||
|
totalTime = (stop.tv_sec - start.tv_sec) * 1000000 + stop.tv_usec - start.tv_usec;
|
||||||
|
bytesMSec = (long)(1*iterations*0xC000)/((long)totalTime/1000);
|
||||||
|
pr_info("Loop mode time=%ldms, errorCount=%d, %ldBytes/sec\n", totalTime/1000, errorCount, (bytesMSec*1000));
|
||||||
|
|
||||||
|
pr_info("Z80 Host Test - Testing RAM Write/Read performance (opt).\n");
|
||||||
|
errorCount = 0;
|
||||||
|
SET_CPLD_READ_DATA();
|
||||||
|
//MHal_RIU_REG(gpio_table[PAD_Z80IO_HIGH_BYTE ].r_out) |= gpio_table[PAD_Z80IO_HIGH_BYTE ].m_out;
|
||||||
|
do_gettimeofday(&start);
|
||||||
|
for(idx=0; idx < iterations; idx++)
|
||||||
|
{
|
||||||
|
// Go through all the accessible RAM and write to it.
|
||||||
|
for(addr=0x8000; addr < 0xD000; addr++)
|
||||||
|
{
|
||||||
|
if(addr == 0x8000)
|
||||||
|
{
|
||||||
|
fullCmd = (addr << 16) | ((uint8_t)addr) << 8 | 0x18;
|
||||||
|
SPI_SEND32(fullCmd);
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
cmd = 0x19;
|
||||||
|
SPI_SEND16(((uint8_t)addr) << 8 | cmd);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read back the same byte.
|
||||||
|
cmd = 0x20;
|
||||||
|
SPI_SEND8(cmd);
|
||||||
|
while(CPLD_READY() == 0);
|
||||||
|
|
||||||
|
result = READ_CPLD_DATA_IN();
|
||||||
|
if(result != (uint8_t)addr)
|
||||||
|
{
|
||||||
|
if(errorCount < 50) pr_info("Read byte:0x%x, Written:0x%x\n", result, (uint8_t)addr);
|
||||||
|
errorCount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
do_gettimeofday(&stop);
|
||||||
|
totalTime = (stop.tv_sec - start.tv_sec) * 1000000 + stop.tv_usec - start.tv_usec;
|
||||||
|
bytesMSec = (long)(1*iterations*0xC000)/((long)totalTime/1000);
|
||||||
|
pr_info("Loop mode time=%ldms, errorCount=%d, %ldBytes/sec\n", totalTime/1000, errorCount, (bytesMSec*1000));
|
||||||
|
|
||||||
|
pr_info("Z80 Host Test - Testing RAM Fetch performance.\n");
|
||||||
|
SET_CPLD_READ_DATA();
|
||||||
|
do_gettimeofday(&start);
|
||||||
|
for(idx=0; idx < iterations; idx++)
|
||||||
|
{
|
||||||
|
// Go through all the accessible RAM and read from it.
|
||||||
|
for(addr=0x1000; addr < 0xD000; addr++)
|
||||||
|
{
|
||||||
|
if(addr == 0x1000)
|
||||||
|
{
|
||||||
|
fullCmd = (addr << 16) | ((uint8_t)addr) << 8 | 0x10;
|
||||||
|
SPI_SEND32(fullCmd);
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
cmd = 0x11;
|
||||||
|
SPI_SEND8(cmd);
|
||||||
|
}
|
||||||
|
while(CPLD_READY() == 0);
|
||||||
|
result = READ_CPLD_DATA_IN();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
do_gettimeofday(&stop);
|
||||||
|
totalTime = (stop.tv_sec - start.tv_sec) * 1000000 + stop.tv_usec - start.tv_usec;
|
||||||
|
bytesMSec = (long)(1*iterations*0xC000)/((long)totalTime/1000);
|
||||||
|
pr_info("Loop mode time=%ldms, %ldBytes/sec\n", totalTime/1000, (bytesMSec*1000));
|
||||||
|
|
||||||
|
pr_info("Z80 Host Test - Testing RAM Read performance (opt).\n");
|
||||||
|
SET_CPLD_READ_DATA();
|
||||||
|
do_gettimeofday(&start);
|
||||||
|
for(idx=0; idx < iterations; idx++)
|
||||||
|
{
|
||||||
|
// Go through all the accessible RAM and read from it.
|
||||||
|
for(addr=0x1000; addr < 0xD000; addr++)
|
||||||
|
{
|
||||||
|
if(addr == 0x1000)
|
||||||
|
{
|
||||||
|
fullCmd = (addr << 16) | ((uint8_t)addr) << 8 | 0x20;
|
||||||
|
SPI_SEND32(fullCmd);
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
cmd = 0x21;
|
||||||
|
SPI_SEND8(cmd);
|
||||||
|
}
|
||||||
|
while(CPLD_READY() == 0);
|
||||||
|
result = READ_CPLD_DATA_IN();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
do_gettimeofday(&stop);
|
||||||
|
totalTime = (stop.tv_sec - start.tv_sec) * 1000000 + stop.tv_usec - start.tv_usec;
|
||||||
|
bytesMSec = (long)(1*iterations*0xC000)/((long)totalTime/1000);
|
||||||
|
pr_info("Loop mode time=%ldms, %ldBytes/sec\n", totalTime/1000, (bytesMSec*1000));
|
||||||
|
|
||||||
|
// Go through all the accessible attribute VRAM and initialise it.
|
||||||
|
pr_info("Z80 Host Test - Testing VRAM Write performance.\n");
|
||||||
|
SPI_SEND32(0x00E80000 | (0xD3 << 8) | CPLD_CMD_WRITEIO_ADDR);
|
||||||
|
iterations = 256*10;
|
||||||
|
do_gettimeofday(&start);
|
||||||
|
for(addr=0xD800; addr < 0xE000; addr++)
|
||||||
|
{
|
||||||
|
//while(CPLD_READY() == 0);
|
||||||
|
if(addr == 0xD800)
|
||||||
|
{
|
||||||
|
fullCmd = (addr << 16) |(0x71 << 8) | 0x18;
|
||||||
|
SPI_SEND32(fullCmd);
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
cmd = 0x19;
|
||||||
|
SPI_SEND8(cmd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for(idx=0; idx < iterations; idx++)
|
||||||
|
{
|
||||||
|
// Go through all the accessible VRAM and write to it.
|
||||||
|
for(addr=0xD000; addr < 0xD800; addr++)
|
||||||
|
{
|
||||||
|
//while(CPLD_READY() == 0);
|
||||||
|
if(addr == 0xD000)
|
||||||
|
{
|
||||||
|
fullCmd = (addr << 16) | ((uint8_t)idx << 8) | 0x18;
|
||||||
|
SPI_SEND32(fullCmd);
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
cmd = 0x19;
|
||||||
|
SPI_SEND8(cmd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
do_gettimeofday(&stop);
|
||||||
|
totalTime = (stop.tv_sec - start.tv_sec) * 1000000 + stop.tv_usec - start.tv_usec;
|
||||||
|
bytesMSec = (long)((1*iterations*0x800)+0x800)/((long)totalTime/1000);
|
||||||
|
pr_info("Loop mode time=%ldms, %ldBytes/sec\n", totalTime/1000, (bytesMSec*1000));
|
||||||
|
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// A simple test to verify the SOM to CPLD SPI connectivity and give an estimate of its performance.
|
||||||
|
// The performance is based on the SPI setup and transmit time along with the close and received data processing.
|
||||||
|
// In real use, the driver will just send a command and generally ignore received data so increased throughput can be achieved.
|
||||||
|
//
|
||||||
|
uint8_t z80io_SPI_Test(void)
|
||||||
|
{
|
||||||
|
// Locals.
|
||||||
|
//
|
||||||
|
struct timeval start, stop;
|
||||||
|
uint32_t iterations = 10000000;
|
||||||
|
uint32_t idx;
|
||||||
|
uint8_t rxData8;
|
||||||
|
uint16_t rxData16;
|
||||||
|
uint16_t rxData16Last;
|
||||||
|
uint32_t rxData32;
|
||||||
|
uint32_t rxData32Last;
|
||||||
|
uint32_t errorCount;
|
||||||
|
long totalTime;
|
||||||
|
long bytesMSec;
|
||||||
|
|
||||||
|
// Place the CPLD into echo test mode.
|
||||||
|
z80io_SPI_Send8(0xfe, &rxData8);
|
||||||
|
|
||||||
|
// 1st. test, 8bit.
|
||||||
|
pr_info("SPI Test - Testing 8 bit performance.\n");
|
||||||
|
errorCount=0;
|
||||||
|
do_gettimeofday(&start);
|
||||||
|
for(idx=0; idx < iterations; idx++)
|
||||||
|
{
|
||||||
|
z80io_SPI_Send8((uint8_t)idx, &rxData8);
|
||||||
|
if(idx > 1 && (uint8_t)(idx-1) != rxData8)
|
||||||
|
{
|
||||||
|
if(errorCount < 20)
|
||||||
|
pr_info("0x%x: Last(0x%x) /= New(0x%x)\n",idx, (uint8_t)(idx-1), rxData8 );
|
||||||
|
errorCount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
do_gettimeofday(&stop);
|
||||||
|
totalTime = (stop.tv_sec - start.tv_sec) * 1000000 + stop.tv_usec - start.tv_usec;
|
||||||
|
bytesMSec = (long)(1*iterations)/((long)totalTime/1000);
|
||||||
|
pr_info("Loop mode errorCount: %d, time=%ldms, %ldBytes/sec\n", errorCount, totalTime/1000, (bytesMSec*1000));
|
||||||
|
|
||||||
|
// 2nd. test, 16bit.
|
||||||
|
pr_info("SPI Test - Testing 16 bit performance.\n");
|
||||||
|
errorCount=0;
|
||||||
|
do_gettimeofday(&start);
|
||||||
|
for(idx=0; idx < iterations; idx++)
|
||||||
|
{
|
||||||
|
// Byte re-ordering required as the CPLD echo's back the last 8bits received, it doesnt know if a transmission is 8/16/32bits.
|
||||||
|
z80io_SPI_Send16((uint16_t)idx, &rxData16);
|
||||||
|
if(idx > 0 && (uint16_t)(idx-1) != (uint16_t)(((rxData16&0x00ff) << 8) | ((rxData16Last & 0xff00) >> 8)))
|
||||||
|
{
|
||||||
|
if(errorCount < 20)
|
||||||
|
pr_info("0x%x: Last(0x%x) /= New(0x%x)\n",idx, (uint16_t)(idx-1), (uint16_t)(((rxData16&0x00ff) << 8) | ((rxData16Last & 0xff00) >> 8)));
|
||||||
|
errorCount++;
|
||||||
|
}
|
||||||
|
rxData16Last = rxData16;
|
||||||
|
}
|
||||||
|
do_gettimeofday(&stop);
|
||||||
|
totalTime = (stop.tv_sec - start.tv_sec) * 1000000 + stop.tv_usec - start.tv_usec;
|
||||||
|
bytesMSec = (long)(2*iterations)/((long)totalTime/1000);
|
||||||
|
pr_info("Loop mode errorCount: %d, time=%ldms, %ldBytes/sec\n", errorCount, totalTime/1000, (bytesMSec*1000));
|
||||||
|
|
||||||
|
// 3rd. test, 32bit.
|
||||||
|
pr_info("SPI Test - Testing 32 bit performance.\n");
|
||||||
|
errorCount=0;
|
||||||
|
do_gettimeofday(&start);
|
||||||
|
for(idx=0; idx < iterations; idx++)
|
||||||
|
{
|
||||||
|
z80io_SPI_Send32((uint32_t)idx, &rxData32);
|
||||||
|
if(idx > 0 && (uint32_t)(idx-1) != (uint32_t)(((rxData32&0x00ff) << 8) | ((rxData32Last & 0xff000000) >> 8) | ((rxData32Last & 0xff0000) >> 8) | ((rxData32Last & 0xff00) >> 8)))
|
||||||
|
{
|
||||||
|
if(errorCount < 20)
|
||||||
|
pr_info("0x%x: Last(0x%x) /= New(0x%x)\n",idx, (uint32_t)(idx-1), (uint32_t)(((rxData32&0x00ff) << 8) | ((rxData32Last & 0xff000000) >> 8) | ((rxData32Last & 0xff0000) >> 8) | ((rxData32Last & 0xff00) >> 8)));
|
||||||
|
errorCount++;
|
||||||
|
}
|
||||||
|
rxData32Last = rxData32;
|
||||||
|
}
|
||||||
|
do_gettimeofday(&stop);
|
||||||
|
totalTime = (stop.tv_sec - start.tv_sec) * 1000000 + stop.tv_usec - start.tv_usec;
|
||||||
|
bytesMSec = (long)(4*iterations)/((long)totalTime/1000);
|
||||||
|
pr_info("Loop mode errorCount: %d, time=%ldms, %ldBytes/sec\n", errorCount, totalTime/1000, (bytesMSec*1000));
|
||||||
|
|
||||||
|
pr_info("Press host RESET button Once to reset the CPLD.\n");
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Method to test the parallel bus, verifying integrity and assessing performance.
|
||||||
|
uint8_t z80io_PRL_Test(void)
|
||||||
|
{
|
||||||
|
// Locals.
|
||||||
|
//
|
||||||
|
struct timeval start, stop;
|
||||||
|
uint32_t iterations = 10000000;
|
||||||
|
uint32_t idx;
|
||||||
|
uint8_t rxData8;
|
||||||
|
uint16_t rxData16;
|
||||||
|
long totalTime;
|
||||||
|
long bytesMSec;
|
||||||
|
#ifdef NOTNEEDED
|
||||||
|
uint32_t errorCount;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Place the CPLD into echo test mode.
|
||||||
|
|
||||||
|
// 1st. test, 8bit RW.
|
||||||
|
#ifdef NOTNEEDED
|
||||||
|
pr_info("Parallel Test - Testing 8 bit r/w performance.\n");
|
||||||
|
errorCount=0;
|
||||||
|
do_gettimeofday(&start);
|
||||||
|
for(idx=0; idx < iterations; idx++)
|
||||||
|
{
|
||||||
|
// Write byte and readback to compare.
|
||||||
|
z80io_PRL_Send8((uint8_t)idx);
|
||||||
|
rxData8 = z80io_PRL_Read8();
|
||||||
|
if((uint8_t)idx != rxData8)
|
||||||
|
{
|
||||||
|
pr_info("0x%x: Written(0x%x) /= Read(0x%x)\n", idx, (uint8_t)(idx), rxData8);
|
||||||
|
errorCount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
do_gettimeofday(&stop);
|
||||||
|
totalTime = (stop.tv_sec - start.tv_sec) * 1000000 + stop.tv_usec - start.tv_usec;
|
||||||
|
bytesMSec = (long)(iterations)/((long)totalTime/1000);
|
||||||
|
pr_info("Loop mode errorCount: %d, time=%ldms, %ldBytes/sec\n", errorCount, totalTime/1000, (bytesMSec*1000));
|
||||||
|
|
||||||
|
// 2nd. test, 8bit Write.
|
||||||
|
pr_info("Parallel Test - Testing 8 bit write performance.\n");
|
||||||
|
do_gettimeofday(&start);
|
||||||
|
for(idx=0; idx < iterations; idx++)
|
||||||
|
{
|
||||||
|
// Write byte.
|
||||||
|
z80io_PRL_Send8((uint8_t)idx);
|
||||||
|
}
|
||||||
|
do_gettimeofday(&stop);
|
||||||
|
totalTime = (stop.tv_sec - start.tv_sec) * 1000000 + stop.tv_usec - start.tv_usec;
|
||||||
|
bytesMSec = (long)(iterations)/((long)totalTime/1000);
|
||||||
|
pr_info("Loop mode time=%ldms, %ldBytes/sec\n", totalTime/1000, (bytesMSec*1000));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// 3rd. test, 8bit Read.
|
||||||
|
pr_info("Parallel Test - Testing 8 bit read performance.\n");
|
||||||
|
do_gettimeofday(&start);
|
||||||
|
for(idx=0; idx < iterations; idx++)
|
||||||
|
{
|
||||||
|
// Read byte.
|
||||||
|
rxData8 = z80io_PRL_Read8(0);
|
||||||
|
}
|
||||||
|
do_gettimeofday(&stop);
|
||||||
|
totalTime = (stop.tv_sec - start.tv_sec) * 1000000 + stop.tv_usec - start.tv_usec;
|
||||||
|
bytesMSec = (long)(iterations)/((long)totalTime/1000);
|
||||||
|
pr_info("Loop mode time=%ldms, %ldBytes/sec\n", totalTime/1000, (bytesMSec*1000));
|
||||||
|
|
||||||
|
#ifdef NOTNEEDED
|
||||||
|
// 4th test, 16bit.
|
||||||
|
pr_info("Parallel Test - Testing 16 bit r/w performance.\n");
|
||||||
|
errorCount=0;
|
||||||
|
do_gettimeofday(&start);
|
||||||
|
for(idx=0; idx < iterations; idx++)
|
||||||
|
{
|
||||||
|
// Byte re-ordering required as the CPLD echo's back the last 8bits received, it doesnt know if a transmission is 8/16/32bits.
|
||||||
|
z80io_PRL_Send16((uint16_t)idx);
|
||||||
|
rxData16 = z80io_PRL_Read16();
|
||||||
|
if((uint16_t)idx != rxData16)
|
||||||
|
{
|
||||||
|
pr_info("0x%x: Written(0x%x) /= Read(0x%x)\n", idx, (uint16_t)(idx), rxData16);
|
||||||
|
errorCount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
do_gettimeofday(&stop);
|
||||||
|
totalTime = (stop.tv_sec - start.tv_sec) * 1000000 + stop.tv_usec - start.tv_usec;
|
||||||
|
bytesMSec = (long)(2*iterations)/((long)totalTime/1000);
|
||||||
|
pr_info("Loop mode errorCount: %d, time=%ldms, %ldBytes/sec\n", errorCount, totalTime/1000, (bytesMSec*1000));
|
||||||
|
|
||||||
|
// 5th test, 16bit Write.
|
||||||
|
pr_info("Parallel Test - Testing 16 bit write performance.\n");
|
||||||
|
do_gettimeofday(&start);
|
||||||
|
for(idx=0; idx < iterations; idx++)
|
||||||
|
{
|
||||||
|
// Write word.
|
||||||
|
z80io_PRL_Send16((uint16_t)idx);
|
||||||
|
}
|
||||||
|
do_gettimeofday(&stop);
|
||||||
|
totalTime = (stop.tv_sec - start.tv_sec) * 1000000 + stop.tv_usec - start.tv_usec;
|
||||||
|
bytesMSec = (long)(2*iterations)/((long)totalTime/1000);
|
||||||
|
pr_info("Loop mode time=%ldms, %ldBytes/sec\n", totalTime/1000, (bytesMSec*1000));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// 6th test, 16bit Read.
|
||||||
|
pr_info("Parallel Test - Testing 16 bit read performance.\n");
|
||||||
|
do_gettimeofday(&start);
|
||||||
|
for(idx=0; idx < iterations; idx++)
|
||||||
|
{
|
||||||
|
// Read word.
|
||||||
|
rxData16 = z80io_PRL_Read16();
|
||||||
|
}
|
||||||
|
do_gettimeofday(&stop);
|
||||||
|
totalTime = (stop.tv_sec - start.tv_sec) * 1000000 + stop.tv_usec - start.tv_usec;
|
||||||
|
bytesMSec = (long)(2*iterations)/((long)totalTime/1000);
|
||||||
|
pr_info("Loop mode time=%ldms, %ldBytes/sec\n", totalTime/1000, (bytesMSec*1000));
|
||||||
|
|
||||||
|
pr_info("Press host RESET button Once to reset the CPLD.\n");
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
57
software/FusionX/src/driver/MZ700/z80menu.c
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Name: z80menu.c
|
||||||
|
// Created: Oct 2022
|
||||||
|
// Author(s): Philip Smart
|
||||||
|
// Description: Z80 User Menu
|
||||||
|
// This file contains the methods used to present a menu of options to a user to aid
|
||||||
|
// in configuration and load/save of applications and data.
|
||||||
|
// Credits:
|
||||||
|
// Copyright: (c) 2019-2022 Philip Smart <philip.smart@net2net.org>
|
||||||
|
//
|
||||||
|
// History: Oct 2022 - Initial write of the z80 kernel driver software.
|
||||||
|
//
|
||||||
|
// Notes: See Makefile to enable/disable conditional components
|
||||||
|
//
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// This source file is free software: you can redistribute it and#or modify
|
||||||
|
// it under the terms of the GNU General Public License as published
|
||||||
|
// by the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This source file is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
|
||||||
|
#include <linux/module.h>
|
||||||
|
#include <linux/init.h>
|
||||||
|
#include <linux/kernel.h>
|
||||||
|
#include <linux/device.h>
|
||||||
|
#include <linux/fs.h>
|
||||||
|
#include <linux/mm.h>
|
||||||
|
#include <asm/uaccess.h>
|
||||||
|
#include <linux/slab.h>
|
||||||
|
#include <linux/string.h>
|
||||||
|
#include <linux/kthread.h>
|
||||||
|
#include <linux/sched.h>
|
||||||
|
#include <linux/delay.h>
|
||||||
|
#include <linux/time.h>
|
||||||
|
#include "z80io.h"
|
||||||
|
#include "z80menu.h"
|
||||||
|
|
||||||
|
#include <gpio_table.h>
|
||||||
|
#include <asm/io.h>
|
||||||
|
#include <infinity2m/gpio.h>
|
||||||
|
#include <infinity2m/registers.h>
|
||||||
|
|
||||||
|
void z80menu(void)
|
||||||
|
{
|
||||||
|
// Locals.
|
||||||
|
|
||||||
|
}
|
||||||
44
software/FusionX/src/driver/MZ700/z80menu.h
Executable file
@@ -0,0 +1,44 @@
|
|||||||
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Name: z80menu.h
|
||||||
|
// Created: Oct 2022
|
||||||
|
// Author(s): Philip Smart
|
||||||
|
// Description: Z80 User Interface Menu
|
||||||
|
// This file contains the declarations required to provide a menu system allowing a
|
||||||
|
// user to configure and load/save applications/data.
|
||||||
|
// Credits:
|
||||||
|
// Copyright: (c) 2019-2022 Philip Smart <philip.smart@net2net.org>
|
||||||
|
//
|
||||||
|
// History: Oct 2022 - Initial write of the z80 kernel driver software.
|
||||||
|
//
|
||||||
|
// Notes: See Makefile to enable/disable conditional components
|
||||||
|
//
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// This source file is free software: you can redistribute it and#or modify
|
||||||
|
// it under the terms of the GNU General Public License as published
|
||||||
|
// by the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This source file is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
#ifndef Z80MENU_H
|
||||||
|
#define Z80MENU_H
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Function definitions.
|
||||||
|
//
|
||||||
|
void z80menu(void);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#endif // Z80MENU_H
|
||||||
23
software/FusionX/src/driver/Makefile
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
MODEL := MZ2000
|
||||||
|
KERNEL := /srv/dvlp/Projects/tzpu/FusionX/software/linux/kernel
|
||||||
|
CROSS := arm-linux-gnueabihf-
|
||||||
|
ccflags-y += -O2 -I${src}/Z80/Zeta/API -I${src}/Z80/API -I${KERNEL}/drivers/sstar/include -I${KERNEL}/drivers/sstar/include/infinity2m -I${KERNEL}/drivers/sstar/gpio/infinity2m
|
||||||
|
CTRLINC += -IZ80/Zeta/API -IZ80/API
|
||||||
|
|
||||||
|
obj-m += z80drv.o
|
||||||
|
z80drv-objs += $(MODEL)/z80driver.o Z80.o $(MODEL)/z80io.o $(MODEL)/z80menu.o # emumz.o sharpmz.o osd.o
|
||||||
|
z80drv-objs += ../../../linux/kernel/drivers/sstar/gpio/infinity2m/gpio_table.o
|
||||||
|
z80drv-objs += ../../../linux/kernel/drivers/sstar/gpio/infinity2m/mhal_gpio.o
|
||||||
|
z80drv-objs += ../../../linux/kernel/drivers/sstar/gpio/infinity2m/mhal_pinmux.o
|
||||||
|
z80drv-objs += ../../../linux/kernel/drivers/sstar/gpio/infinity2m/padmux_tables.o
|
||||||
|
|
||||||
|
|
||||||
|
all:
|
||||||
|
@echo "Build driver for host: $(MODEL)"
|
||||||
|
@echo ""
|
||||||
|
make -C $(KERNEL) ARCH=arm CROSS_COMPILE=$(CROSS) M=$(PWD) modules
|
||||||
|
$(CROSS)gcc $(CTRLINC) $(MODEL)/z80ctrl.c -o z80ctrl
|
||||||
|
|
||||||
|
clean:
|
||||||
|
make -C $(KERNEL) M=$(PWD) clean
|
||||||
|
|
||||||
9
software/FusionX/src/driver/README.txt
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
Development Cycle
|
||||||
|
-----------------
|
||||||
|
|
||||||
|
To avoid changes for one host affecting another the driver is split into seperate hosts containing almost identical code.
|
||||||
|
The idea, after development is complete, is to merge them into a single drive which autodetects, via the CPLD, the host model
|
||||||
|
and selects the code accordingly.
|
||||||
|
|
||||||
|
Please edit Makefile and set the model prior to changing the Model source. In theory this file will be deleted once the source is
|
||||||
|
merged.
|
||||||
2636
software/FusionX/src/driver/Z80.c
Normal file
150
software/FusionX/src/spitools/Makefile
Normal file
@@ -0,0 +1,150 @@
|
|||||||
|
# Makefile
|
||||||
|
# Created by Rico Castelo <rico.castelo at gmail dot com>
|
||||||
|
# Free to Use
|
||||||
|
|
||||||
|
PRJ_ROOT_DIR := $(shell pwd)/
|
||||||
|
LINUX_HEADERS := ../../../linux/project/kbuild/4.9.84/i2m/include/uapi/linux/spi
|
||||||
|
|
||||||
|
|
||||||
|
# Target Name
|
||||||
|
TARGET_NAME := mspi_main
|
||||||
|
PROJECT_TYPE := app
|
||||||
|
|
||||||
|
#Version Number
|
||||||
|
MAJOR := 0
|
||||||
|
MINOR := 08
|
||||||
|
|
||||||
|
#Include directories
|
||||||
|
INCLUDES_SRC = -I. -I./include -I$(LINUX_HEADERS)
|
||||||
|
|
||||||
|
#Libraries
|
||||||
|
#LIBRARIES := -lboost_filesystem -lboost_thread -lboost_system -ldl -L. -lpthread
|
||||||
|
LIBRARIES := -ldl -L. -lpthread
|
||||||
|
|
||||||
|
#Add more App Object files
|
||||||
|
OBJFILES :=
|
||||||
|
|
||||||
|
#Add more Dependency files
|
||||||
|
#These files are generated automatically. This is only needed to delete them all
|
||||||
|
DEPFILES :=
|
||||||
|
|
||||||
|
# Doxygen Configuration file
|
||||||
|
DOXYGEN_CONFIG := doxyfile
|
||||||
|
|
||||||
|
# ----------------------------------------------------------------------------
|
||||||
|
# DO NOT MODIFY BELOW
|
||||||
|
# ----------------------------------------------------------------------------
|
||||||
|
#Set for Debug mode or non-debug
|
||||||
|
BUILD := rel
|
||||||
|
|
||||||
|
#Set Architecture
|
||||||
|
ARCH := arm
|
||||||
|
|
||||||
|
#Compilers
|
||||||
|
ifeq ($(ARCH),arm)
|
||||||
|
CPP := /opt/gcc-arm-eabihf/bin/arm-linux-gnueabihf-g++
|
||||||
|
CC := /opt/gcc-arm-eabihf/bin/arm-linux-gnueabihf-gcc
|
||||||
|
else
|
||||||
|
CPP := g++
|
||||||
|
CC := gcc
|
||||||
|
endif
|
||||||
|
|
||||||
|
#Set the file extension and prefix if lib
|
||||||
|
ifeq ($(PROJECT_TYPE),lib)
|
||||||
|
TARGET_PREFIX = lib
|
||||||
|
TARGET_POSTFIX = .so
|
||||||
|
CC += -shared
|
||||||
|
else
|
||||||
|
TARGET_PREFIX =
|
||||||
|
TARGET_POSTFIX =
|
||||||
|
endif
|
||||||
|
|
||||||
|
#BuildTool flags
|
||||||
|
ifeq ($(BUILD),devel)
|
||||||
|
DEBUGFLAGS_Assembler = -g
|
||||||
|
DEBUGFLAGS_C++-Compiler = -g -O0 -fno-omit-frame-pointer -pipe -Wall -DDEBUG
|
||||||
|
DEBUGFLAGS_C++-Linker = -g
|
||||||
|
DEBUGFLAGS_C-Compiler = -g -O2 -fno-omit-frame-pointer -pipe -Wall
|
||||||
|
DEBUGFLAGS_C-Linker = -g
|
||||||
|
DEBUGFLAGS_Librarian = -g
|
||||||
|
DEBUGFLAGS_Shared-Library-Linker = -g
|
||||||
|
TARGET_VER = $(TARGET_PREFIX)$(TARGET_NAME)_$(MAJOR).$(MINOR)_debug$(TARGET_POSTFIX)
|
||||||
|
TARGET = $(TARGET_PREFIX)$(TARGET_NAME)_debug$(TARGET_POSTFIX)
|
||||||
|
else
|
||||||
|
DEBUGFLAGS_Assembler =
|
||||||
|
DEBUGFLAGS_C++-Compiler = -O3 -Wall -Werror
|
||||||
|
DEBUGFLAGS_C++-Linker =
|
||||||
|
DEBUGFLAGS_C-Compiler = -O2 -fomit-frame-pointer -D__USE_STRING_INLINES -pipe -Wall
|
||||||
|
DEBUGFLAGS_C-Linker =
|
||||||
|
DEBUGFLAGS_Librarian =
|
||||||
|
DEBUGFLAGS_Shared-Library-Linker =
|
||||||
|
TARGET = $(TARGET_PREFIX)$(TARGET_NAME)_$(MAJOR).$(MINOR)$(TARGET_POSTFIX)
|
||||||
|
TARGET_VER = $(TARGET_PREFIX)$(TARGET_NAME)$(TARGET_POSTFIX)
|
||||||
|
endif
|
||||||
|
|
||||||
|
#Global Build Macros
|
||||||
|
DEFINES +=
|
||||||
|
|
||||||
|
#Global Include directories
|
||||||
|
INCLUDES_SRC += -I$(PRJ_ROOT_DIR)/include
|
||||||
|
|
||||||
|
#Global Libraries
|
||||||
|
LIBRARIES +=
|
||||||
|
|
||||||
|
#Global App Object files
|
||||||
|
OBJFILES += $(patsubst %.cpp,%.o,$(wildcard *.cpp)) $(patsubst %.cpp,%.o,$(wildcard src/*.cpp))
|
||||||
|
OBJFILES += $(patsubst %.c,%.o,$(wildcard *.c)) $(patsubst %.c,%.o,$(wildcard src/*.c))
|
||||||
|
|
||||||
|
#Global Dependency files
|
||||||
|
#These files are generated automatically. This is only needed to delete them all
|
||||||
|
DEPFILES += $(patsubst %.cpp,%.d,$(wildcard *.cpp)) $(patsubst %.cpp,%.d,$(wildcard src/*.cpp))
|
||||||
|
DEPFILES += $(patsubst %.c,%.d,$(wildcard *.c)) $(patsubst %.c,%.d,$(wildcard src/*.c))
|
||||||
|
|
||||||
|
#Compile object files
|
||||||
|
%.o: %.cpp
|
||||||
|
$(CPP) $(DEBUGFLAGS_C++-Compiler) $(INCLUDES_SRC) $(DEFINES) -c -fmessage-length=0 -Wold-style-cast -Woverloaded-virtual -o $@ $<
|
||||||
|
|
||||||
|
#Compile object files
|
||||||
|
#May need to replace $(CC) with $(GCC)
|
||||||
|
%.o: %.c
|
||||||
|
$(CC) $(DEBUGFLAGS_C-Compiler) $(INCLUDES_SRC) $(DEFINES) -c -fmessage-length=0 -o $@ $<
|
||||||
|
|
||||||
|
#Build application
|
||||||
|
#Create two version of the file so when including the library you do not have to worry about a version
|
||||||
|
all: $(OBJFILES)
|
||||||
|
$(CC) -o $(TARGET) $(OBJFILES) $(LIBRARIES)
|
||||||
|
$(CC) -o $(TARGET_VER) $(OBJFILES) $(LIBRARIES)
|
||||||
|
|
||||||
|
#Clean files
|
||||||
|
clean:
|
||||||
|
rm -f $(OBJFILES) rm -f $(DEPFILES) rm -f $(TARGET) rm -rf $(TARGET_VER)
|
||||||
|
|
||||||
|
#Make Doxygen files
|
||||||
|
doxygen:
|
||||||
|
cd docs && \
|
||||||
|
doxygen $(DOXYGEN_CONFIG)
|
||||||
|
|
||||||
|
#Clean Doxygen files
|
||||||
|
clean_doxygen:
|
||||||
|
rm -rf docs/html
|
||||||
|
rm -rf docs/latex
|
||||||
|
|
||||||
|
#Help option
|
||||||
|
help:
|
||||||
|
@echo
|
||||||
|
@echo " make [target] [OPTIONS]"
|
||||||
|
@echo
|
||||||
|
@echo " Targets:"
|
||||||
|
@echo " all Builds the app. This is the default target."
|
||||||
|
@echo " clean Clean all the objects, apps and dependencies."
|
||||||
|
@echo " help Prints this message."
|
||||||
|
@echo " doxygen Create doxygen files"
|
||||||
|
@echo " doxygen_clean Clean doxygen files"
|
||||||
|
@echo " Options:"
|
||||||
|
@echo " BUILD=rel Build a release build (default)"
|
||||||
|
@echo " BUILD=devel Build a debug build"
|
||||||
|
@echo " "
|
||||||
|
@echo " ARCH=arm Build an ARM build (default)"
|
||||||
|
@echo " ARCH=x86 Build an X86 build"
|
||||||
|
@echo " "
|
||||||
|
@echo
|
||||||
BIN
software/FusionX/src/spitools/mspi_main
Executable file
1152
software/FusionX/src/spitools/mspi_main.c
Normal file
6
software/FusionX/start_FusionX.sh
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
ROOTDIR=/apps/FusionX
|
||||||
|
|
||||||
|
cd ${ROOTDIR}
|
||||||
|
#nohup ${ROOTDIR}/bin/FusionX &
|
||||||
39
software/WebServer/Makefile
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
#
|
||||||
|
# Copyright (c) 2013 No Face Press, LLC
|
||||||
|
# License http://opensource.org/licenses/mit-license.php MIT License
|
||||||
|
#
|
||||||
|
|
||||||
|
#This makefile is used to test the other Makefiles
|
||||||
|
|
||||||
|
|
||||||
|
PROG = WebServer
|
||||||
|
SRC = WebServer.cpp
|
||||||
|
|
||||||
|
TOP = ../../../../civetweb
|
||||||
|
CIVETWEB_LIB = libcivetweb.a
|
||||||
|
|
||||||
|
CFLAGS = -I$(TOP)/include $(COPT)
|
||||||
|
LIBS = -lpthread
|
||||||
|
|
||||||
|
include $(TOP)/resources/Makefile.in-os
|
||||||
|
|
||||||
|
ifeq ($(TARGET_OS),LINUX)
|
||||||
|
LIBS += -ldl -lrt
|
||||||
|
endif
|
||||||
|
ifdef WITH_ZLIB
|
||||||
|
LIBS += -lz
|
||||||
|
endif
|
||||||
|
|
||||||
|
all: $(PROG)
|
||||||
|
|
||||||
|
$(PROG): $(CIVETWEB_LIB) $(SRC)
|
||||||
|
$(CXX) -o $@ $(CFLAGS) $(LDFLAGS) $(SRC) $(CIVETWEB_LIB) $(LIBS)
|
||||||
|
|
||||||
|
$(CIVETWEB_LIB):
|
||||||
|
$(MAKE) -C $(TOP) clean lib WITH_CPP=1
|
||||||
|
cp $(TOP)/$(CIVETWEB_LIB) .
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -f $(CIVETWEB_LIB) $(PROG)
|
||||||
|
|
||||||
|
.PHONY: all clean
|
||||||
446
software/WebServer/WebServer.cpp
Normal file
@@ -0,0 +1,446 @@
|
|||||||
|
/* Copyright (c) 2013-2018 the Civetweb developers
|
||||||
|
* Copyright (c) 2013 No Face Press, LLC
|
||||||
|
* License http://opensource.org/licenses/mit-license.php MIT License
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Simple example program on how to use Embedded C++ interface.
|
||||||
|
|
||||||
|
#include "CivetServer.h"
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
#include <windows.h>
|
||||||
|
#else
|
||||||
|
#include <unistd.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define DOCUMENT_ROOT "webfs/"
|
||||||
|
#define PORT "80"
|
||||||
|
#define EXAMPLE_URI "/example"
|
||||||
|
#define EXIT_URI "/exit"
|
||||||
|
|
||||||
|
|
||||||
|
/* Exit flag for main loop */
|
||||||
|
volatile bool exitNow = false;
|
||||||
|
|
||||||
|
|
||||||
|
class ExampleHandler : public CivetHandler
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
bool
|
||||||
|
handleGet(CivetServer *server, struct mg_connection *conn)
|
||||||
|
{
|
||||||
|
mg_printf(conn,
|
||||||
|
"HTTP/1.1 200 OK\r\nContent-Type: "
|
||||||
|
"text/html\r\nConnection: close\r\n\r\n");
|
||||||
|
mg_printf(conn, "<html><body>\r\n");
|
||||||
|
mg_printf(conn,
|
||||||
|
"<h2>This is an example text from a C++ handler</h2>\r\n");
|
||||||
|
mg_printf(conn,
|
||||||
|
"<p>To see a page from the A handler <a "
|
||||||
|
"href=\"a\">click here</a></p>\r\n");
|
||||||
|
mg_printf(conn,
|
||||||
|
"<form action=\"a\" method=\"get\">"
|
||||||
|
"To see a page from the A handler with a parameter "
|
||||||
|
"<input type=\"submit\" value=\"click here\" "
|
||||||
|
"name=\"param\" \\> (GET)</form>\r\n");
|
||||||
|
mg_printf(conn,
|
||||||
|
"<form action=\"a\" method=\"post\">"
|
||||||
|
"To see a page from the A handler with a parameter "
|
||||||
|
"<input type=\"submit\" value=\"click here\" "
|
||||||
|
"name=\"param\" \\> (POST)</form>\r\n");
|
||||||
|
mg_printf(conn,
|
||||||
|
"<p>To see a page from the A/B handler <a "
|
||||||
|
"href=\"a/b\">click here</a></p>\r\n");
|
||||||
|
mg_printf(conn,
|
||||||
|
"<p>To see a page from the *.foo handler <a "
|
||||||
|
"href=\"xy.foo\">click here</a></p>\r\n");
|
||||||
|
mg_printf(conn,
|
||||||
|
"<p>To see a page from the WebSocket handler <a "
|
||||||
|
"href=\"ws\">click here</a></p>\r\n");
|
||||||
|
mg_printf(conn,
|
||||||
|
"<p>To exit <a href=\"%s\">click here</a></p>\r\n",
|
||||||
|
EXIT_URI);
|
||||||
|
mg_printf(conn, "</body></html>\r\n");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class ExitHandler : public CivetHandler
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
bool
|
||||||
|
handleGet(CivetServer *server, struct mg_connection *conn)
|
||||||
|
{
|
||||||
|
mg_printf(conn,
|
||||||
|
"HTTP/1.1 200 OK\r\nContent-Type: "
|
||||||
|
"text/plain\r\nConnection: close\r\n\r\n");
|
||||||
|
mg_printf(conn, "Bye!\n");
|
||||||
|
exitNow = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class AHandler : public CivetHandler
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
bool
|
||||||
|
handleAll(const char *method,
|
||||||
|
CivetServer *server,
|
||||||
|
struct mg_connection *conn)
|
||||||
|
{
|
||||||
|
std::string s = "";
|
||||||
|
mg_printf(conn,
|
||||||
|
"HTTP/1.1 200 OK\r\nContent-Type: "
|
||||||
|
"text/html\r\nConnection: close\r\n\r\n");
|
||||||
|
mg_printf(conn, "<html><body>");
|
||||||
|
mg_printf(conn, "<h2>This is the A handler for \"%s\" !</h2>", method);
|
||||||
|
if (CivetServer::getParam(conn, "param", s)) {
|
||||||
|
mg_printf(conn, "<p>param set to %s</p>", s.c_str());
|
||||||
|
} else {
|
||||||
|
mg_printf(conn, "<p>param not set</p>");
|
||||||
|
}
|
||||||
|
mg_printf(conn, "</body></html>\n");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
bool
|
||||||
|
handleGet(CivetServer *server, struct mg_connection *conn)
|
||||||
|
{
|
||||||
|
return handleAll("GET", server, conn);
|
||||||
|
}
|
||||||
|
bool
|
||||||
|
handlePost(CivetServer *server, struct mg_connection *conn)
|
||||||
|
{
|
||||||
|
return handleAll("POST", server, conn);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class ABHandler : public CivetHandler
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
bool
|
||||||
|
handleGet(CivetServer *server, struct mg_connection *conn)
|
||||||
|
{
|
||||||
|
mg_printf(conn,
|
||||||
|
"HTTP/1.1 200 OK\r\nContent-Type: "
|
||||||
|
"text/html\r\nConnection: close\r\n\r\n");
|
||||||
|
mg_printf(conn, "<html><body>");
|
||||||
|
mg_printf(conn, "<h2>This is the AB handler!!!</h2>");
|
||||||
|
mg_printf(conn, "</body></html>\n");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class FooHandler : public CivetHandler
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
bool
|
||||||
|
handleGet(CivetServer *server, struct mg_connection *conn)
|
||||||
|
{
|
||||||
|
/* Handler may access the request info using mg_get_request_info */
|
||||||
|
const struct mg_request_info *req_info = mg_get_request_info(conn);
|
||||||
|
|
||||||
|
mg_printf(conn,
|
||||||
|
"HTTP/1.1 200 OK\r\nContent-Type: "
|
||||||
|
"text/html\r\nConnection: close\r\n\r\n");
|
||||||
|
|
||||||
|
mg_printf(conn, "<html><body>\n");
|
||||||
|
mg_printf(conn, "<h2>This is the Foo GET handler!!!</h2>\n");
|
||||||
|
mg_printf(conn,
|
||||||
|
"<p>The request was:<br><pre>%s %s HTTP/%s</pre></p>\n",
|
||||||
|
req_info->request_method,
|
||||||
|
req_info->request_uri,
|
||||||
|
req_info->http_version);
|
||||||
|
mg_printf(conn, "</body></html>\n");
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
bool
|
||||||
|
handlePost(CivetServer *server, struct mg_connection *conn)
|
||||||
|
{
|
||||||
|
/* Handler may access the request info using mg_get_request_info */
|
||||||
|
const struct mg_request_info *req_info = mg_get_request_info(conn);
|
||||||
|
long long rlen, wlen;
|
||||||
|
long long nlen = 0;
|
||||||
|
long long tlen = req_info->content_length;
|
||||||
|
char buf[1024];
|
||||||
|
|
||||||
|
mg_printf(conn,
|
||||||
|
"HTTP/1.1 200 OK\r\nContent-Type: "
|
||||||
|
"text/html\r\nConnection: close\r\n\r\n");
|
||||||
|
|
||||||
|
mg_printf(conn, "<html><body>\n");
|
||||||
|
mg_printf(conn, "<h2>This is the Foo POST handler!!!</h2>\n");
|
||||||
|
mg_printf(conn,
|
||||||
|
"<p>The request was:<br><pre>%s %s HTTP/%s</pre></p>\n",
|
||||||
|
req_info->request_method,
|
||||||
|
req_info->request_uri,
|
||||||
|
req_info->http_version);
|
||||||
|
mg_printf(conn, "<p>Content Length: %li</p>\n", (long)tlen);
|
||||||
|
mg_printf(conn, "<pre>\n");
|
||||||
|
|
||||||
|
while (nlen < tlen) {
|
||||||
|
rlen = tlen - nlen;
|
||||||
|
if (rlen > sizeof(buf)) {
|
||||||
|
rlen = sizeof(buf);
|
||||||
|
}
|
||||||
|
rlen = mg_read(conn, buf, (size_t)rlen);
|
||||||
|
if (rlen <= 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
wlen = mg_write(conn, buf, (size_t)rlen);
|
||||||
|
if (wlen != rlen) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
nlen += wlen;
|
||||||
|
}
|
||||||
|
|
||||||
|
mg_printf(conn, "\n</pre>\n");
|
||||||
|
mg_printf(conn, "</body></html>\n");
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define fopen_recursive fopen
|
||||||
|
|
||||||
|
bool
|
||||||
|
handlePut(CivetServer *server, struct mg_connection *conn)
|
||||||
|
{
|
||||||
|
/* Handler may access the request info using mg_get_request_info */
|
||||||
|
const struct mg_request_info *req_info = mg_get_request_info(conn);
|
||||||
|
long long rlen, wlen;
|
||||||
|
long long nlen = 0;
|
||||||
|
long long tlen = req_info->content_length;
|
||||||
|
FILE * f;
|
||||||
|
char buf[1024];
|
||||||
|
int fail = 0;
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
_snprintf(buf, sizeof(buf), "D:\\somewhere\\%s\\%s", req_info->remote_user, req_info->local_uri);
|
||||||
|
buf[sizeof(buf)-1] = 0;
|
||||||
|
if (strlen(buf)>255) {
|
||||||
|
/* Windows will not work with path > 260 (MAX_PATH), unless we use
|
||||||
|
* the unicode API. However, this is just an example code: A real
|
||||||
|
* code will probably never store anything to D:\\somewhere and
|
||||||
|
* must be adapted to the specific needs anyhow. */
|
||||||
|
fail = 1;
|
||||||
|
f = NULL;
|
||||||
|
} else {
|
||||||
|
f = fopen_recursive(buf, "wb");
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
snprintf(buf, sizeof(buf), "~/somewhere/%s/%s", req_info->remote_user, req_info->local_uri);
|
||||||
|
buf[sizeof(buf)-1] = 0;
|
||||||
|
if (strlen(buf)>1020) {
|
||||||
|
/* The string is too long and probably truncated. Make sure an
|
||||||
|
* UTF-8 string is never truncated between the UTF-8 code bytes.
|
||||||
|
* This example code must be adapted to the specific needs. */
|
||||||
|
fail = 1;
|
||||||
|
f = NULL;
|
||||||
|
} else {
|
||||||
|
f = fopen_recursive(buf, "w");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (!f) {
|
||||||
|
fail = 1;
|
||||||
|
} else {
|
||||||
|
while (nlen < tlen) {
|
||||||
|
rlen = tlen - nlen;
|
||||||
|
if (rlen > sizeof(buf)) {
|
||||||
|
rlen = sizeof(buf);
|
||||||
|
}
|
||||||
|
rlen = mg_read(conn, buf, (size_t)rlen);
|
||||||
|
if (rlen <= 0) {
|
||||||
|
fail = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
wlen = fwrite(buf, 1, (size_t)rlen, f);
|
||||||
|
if (wlen != rlen) {
|
||||||
|
fail = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
nlen += wlen;
|
||||||
|
}
|
||||||
|
fclose(f);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fail) {
|
||||||
|
mg_printf(conn,
|
||||||
|
"HTTP/1.1 409 Conflict\r\n"
|
||||||
|
"Content-Type: text/plain\r\n"
|
||||||
|
"Connection: close\r\n\r\n");
|
||||||
|
} else {
|
||||||
|
mg_printf(conn,
|
||||||
|
"HTTP/1.1 201 Created\r\n"
|
||||||
|
"Content-Type: text/plain\r\n"
|
||||||
|
"Connection: close\r\n\r\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class WsStartHandler : public CivetHandler
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
bool
|
||||||
|
handleGet(CivetServer *server, struct mg_connection *conn)
|
||||||
|
{
|
||||||
|
|
||||||
|
mg_printf(conn,
|
||||||
|
"HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nConnection: "
|
||||||
|
"close\r\n\r\n");
|
||||||
|
|
||||||
|
mg_printf(conn, "<!DOCTYPE html>\n");
|
||||||
|
mg_printf(conn, "<html>\n<head>\n");
|
||||||
|
mg_printf(conn, "<meta charset=\"UTF-8\">\n");
|
||||||
|
mg_printf(conn, "<title>Embedded websocket example</title>\n");
|
||||||
|
|
||||||
|
#ifdef USE_WEBSOCKET
|
||||||
|
/* mg_printf(conn, "<script type=\"text/javascript\"><![CDATA[\n"); ...
|
||||||
|
* xhtml style */
|
||||||
|
mg_printf(conn, "<script>\n");
|
||||||
|
mg_printf(
|
||||||
|
conn,
|
||||||
|
"var i=0\n"
|
||||||
|
"function load() {\n"
|
||||||
|
" var wsproto = (location.protocol === 'https:') ? 'wss:' : 'ws:';\n"
|
||||||
|
" connection = new WebSocket(wsproto + '//' + window.location.host + "
|
||||||
|
"'/websocket');\n"
|
||||||
|
" websock_text_field = "
|
||||||
|
"document.getElementById('websock_text_field');\n"
|
||||||
|
" connection.onmessage = function (e) {\n"
|
||||||
|
" websock_text_field.innerHTML=e.data;\n"
|
||||||
|
" i=i+1;"
|
||||||
|
" connection.send(i);\n"
|
||||||
|
" }\n"
|
||||||
|
" connection.onerror = function (error) {\n"
|
||||||
|
" alert('WebSocket error');\n"
|
||||||
|
" connection.close();\n"
|
||||||
|
" }\n"
|
||||||
|
"}\n");
|
||||||
|
/* mg_printf(conn, "]]></script>\n"); ... xhtml style */
|
||||||
|
mg_printf(conn, "</script>\n");
|
||||||
|
mg_printf(conn, "</head>\n<body onload=\"load()\">\n");
|
||||||
|
mg_printf(
|
||||||
|
conn,
|
||||||
|
"<div id='websock_text_field'>No websocket connection yet</div>\n");
|
||||||
|
#else
|
||||||
|
mg_printf(conn, "</head>\n<body>\n");
|
||||||
|
mg_printf(conn, "Example not compiled with USE_WEBSOCKET\n");
|
||||||
|
#endif
|
||||||
|
mg_printf(conn, "</body>\n</html>\n");
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef USE_WEBSOCKET
|
||||||
|
class WebSocketHandler : public CivetWebSocketHandler {
|
||||||
|
|
||||||
|
virtual bool handleConnection(CivetServer *server,
|
||||||
|
const struct mg_connection *conn) {
|
||||||
|
printf("WS connected\n");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void handleReadyState(CivetServer *server,
|
||||||
|
struct mg_connection *conn) {
|
||||||
|
printf("WS ready\n");
|
||||||
|
|
||||||
|
const char *text = "Hello from the websocket ready handler";
|
||||||
|
mg_websocket_write(conn, MG_WEBSOCKET_OPCODE_TEXT, text, strlen(text));
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool handleData(CivetServer *server,
|
||||||
|
struct mg_connection *conn,
|
||||||
|
int bits,
|
||||||
|
char *data,
|
||||||
|
size_t data_len) {
|
||||||
|
printf("WS got %lu bytes: ", (long unsigned)data_len);
|
||||||
|
fwrite(data, 1, data_len, stdout);
|
||||||
|
printf("\n");
|
||||||
|
|
||||||
|
mg_websocket_write(conn, MG_WEBSOCKET_OPCODE_TEXT, data, data_len);
|
||||||
|
return (data_len<4);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void handleClose(CivetServer *server,
|
||||||
|
const struct mg_connection *conn) {
|
||||||
|
printf("WS closed\n");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
mg_init_library(0);
|
||||||
|
|
||||||
|
const char *options[] = {
|
||||||
|
"document_root", DOCUMENT_ROOT, "listening_ports", PORT, 0};
|
||||||
|
|
||||||
|
std::vector<std::string> cpp_options;
|
||||||
|
for (int i=0; i<(sizeof(options)/sizeof(options[0])-1); i++) {
|
||||||
|
cpp_options.push_back(options[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// CivetServer server(options); // <-- C style start
|
||||||
|
CivetServer server(cpp_options); // <-- C++ style start
|
||||||
|
|
||||||
|
ExampleHandler h_ex;
|
||||||
|
server.addHandler(EXAMPLE_URI, h_ex);
|
||||||
|
|
||||||
|
ExitHandler h_exit;
|
||||||
|
server.addHandler(EXIT_URI, h_exit);
|
||||||
|
|
||||||
|
AHandler h_a;
|
||||||
|
server.addHandler("/a", h_a);
|
||||||
|
|
||||||
|
ABHandler h_ab;
|
||||||
|
server.addHandler("/a/b", h_ab);
|
||||||
|
|
||||||
|
WsStartHandler h_ws;
|
||||||
|
server.addHandler("/ws", h_ws);
|
||||||
|
|
||||||
|
#ifdef NO_FILES
|
||||||
|
/* This handler will handle "everything else", including
|
||||||
|
* requests to files. If this handler is installed,
|
||||||
|
* NO_FILES should be set. */
|
||||||
|
FooHandler h_foo;
|
||||||
|
server.addHandler("", h_foo);
|
||||||
|
|
||||||
|
printf("See a page from the \"all\" handler at http://localhost:%s/\n", PORT);
|
||||||
|
#else
|
||||||
|
FooHandler h_foo;
|
||||||
|
server.addHandler("**.foo", h_foo);
|
||||||
|
printf("Browse files at http://localhost:%s/\n", PORT);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef USE_WEBSOCKET
|
||||||
|
WebSocketHandler h_websocket;
|
||||||
|
server.addWebSocketHandler("/websocket", h_websocket);
|
||||||
|
printf("Run websocket example at http://localhost:%s/ws\n", PORT);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
printf("Run example at http://localhost:%s%s\n", PORT, EXAMPLE_URI);
|
||||||
|
printf("Exit at http://localhost:%s%s\n", PORT, EXIT_URI);
|
||||||
|
|
||||||
|
while (!exitNow) {
|
||||||
|
#ifdef _WIN32
|
||||||
|
Sleep(1000);
|
||||||
|
#else
|
||||||
|
sleep(1);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("Bye!\n");
|
||||||
|
mg_exit_library();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
63
software/WebServer/build_webfs.sh
Executable file
@@ -0,0 +1,63 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
SRCDIR=`pwd`/webserver
|
||||||
|
WEBFSDIR=`pwd`/webfs
|
||||||
|
echo "Building into:$WEBFSDIR from $SRCDIR..."
|
||||||
|
|
||||||
|
mkdir -p ${WEBFSDIR}/css
|
||||||
|
mkdir -p ${WEBFSDIR}/js
|
||||||
|
mkdir -p ${WEBFSDIR}/font-awesome
|
||||||
|
mkdir -p ${WEBFSDIR}/font-awesome/css
|
||||||
|
mkdir -p ${WEBFSDIR}/font-awesome/fonts
|
||||||
|
mkdir -p ${WEBFSDIR}/images
|
||||||
|
|
||||||
|
(cd ${SRCDIR}/;
|
||||||
|
cp favicon.ico ${WEBFSDIR}/
|
||||||
|
cp version.txt ${WEBFSDIR}/
|
||||||
|
cp index.html ${WEBFSDIR}/
|
||||||
|
cp keymap.html ${WEBFSDIR}/keymap.html
|
||||||
|
cp mouse.html ${WEBFSDIR}/mouse.html
|
||||||
|
cp ota.html ${WEBFSDIR}/ota.html
|
||||||
|
cp wifimanager.html ${WEBFSDIR}/wifimanager.html
|
||||||
|
|
||||||
|
|
||||||
|
(cd ${SRCDIR}/css;
|
||||||
|
cp bootstrap.min.css.gz ${WEBFSDIR}/css/
|
||||||
|
gzip -c jquery.edittable.min.css > ${WEBFSDIR}/css/jquery.edittable.min.css.gz
|
||||||
|
gzip -c sb-admin.css > ${WEBFSDIR}/css/sb-admin.css.gz
|
||||||
|
gzip -c sharpkey.css > ${WEBFSDIR}/css/sharpkey.css.gz
|
||||||
|
gzip -c style.css > ${WEBFSDIR}/css/style.css.gz
|
||||||
|
gzip -c styles.css > ${WEBFSDIR}/css/styles.css.gz
|
||||||
|
)
|
||||||
|
|
||||||
|
(cd ${SRCDIR}/font-awesome
|
||||||
|
)
|
||||||
|
|
||||||
|
(cd ${SRCDIR}/font-awesome/css
|
||||||
|
#cp font-awesome.min.css.gz ${WEBFSDIR}/font-awesome/css/
|
||||||
|
gzip -c font-awesome.css > ${WEBFSDIR}/font-awesome/css/font-awesome.min.css.gz
|
||||||
|
)
|
||||||
|
|
||||||
|
(cd ${SRCDIR}/font-awesome/fonts
|
||||||
|
gzip -c fontawesome-webfont.woff > ${WEBFSDIR}/font-awesome/fonts/fontawesome-webfont.woff.gz
|
||||||
|
#cp fontawesome-webfont.ttf.gz ${WEBFSDIR}/font-awesome/fonts/
|
||||||
|
#cp fontawesome-webfont.woff.gz ${WEBFSDIR}/font-awesome/fonts/
|
||||||
|
)
|
||||||
|
|
||||||
|
(cd ${SRCDIR}/images;
|
||||||
|
)
|
||||||
|
|
||||||
|
(cd ${SRCDIR}/js;
|
||||||
|
cp 140medley.min.js ${WEBFSDIR}/js/
|
||||||
|
cp bootstrap.min.js.gz ${WEBFSDIR}/js/
|
||||||
|
gzip -c index.js > ${WEBFSDIR}/js/index.js.gz
|
||||||
|
gzip -c jquery.edittable.js > ${WEBFSDIR}/js/jquery.edittable.js.gz
|
||||||
|
gzip -c jquery.edittable.min.js > ${WEBFSDIR}/js/jquery.edittable.min.j.gz
|
||||||
|
cp jquery.min.js.gz ${WEBFSDIR}/js/
|
||||||
|
gzip -c keymap.js > ${WEBFSDIR}/js/keymap.js.gz
|
||||||
|
gzip -c mouse.js > ${WEBFSDIR}/js/mouse.js.gz
|
||||||
|
gzip -c ota.js > ${WEBFSDIR}/js/ota.js.gz
|
||||||
|
gzip -c wifimanager.js > ${WEBFSDIR}/js/wifimanager.js.gz
|
||||||
|
)
|
||||||
|
|
||||||
|
)
|
||||||
86
software/WebServer/conf/civetweb.conf
Normal file
@@ -0,0 +1,86 @@
|
|||||||
|
# Instructions to run (on Linux) to reproduce test results:
|
||||||
|
#
|
||||||
|
# 1) copy civetweb executable here (examples/https directory)
|
||||||
|
# 2) sudo ./civetweb
|
||||||
|
#
|
||||||
|
# Instructions to adapt to your own server:
|
||||||
|
#
|
||||||
|
# 1) generate your own server cert
|
||||||
|
# 2) generate at least one backup server cert
|
||||||
|
# in case you want a self signed cert, you can use the script
|
||||||
|
# in resources/cert for both steps
|
||||||
|
# 3) copy the content of the *.pin files into the Public-Key-Pins
|
||||||
|
# header config (the base64 encoded certificate hash)
|
||||||
|
# 4) set the document root, and all other required http server settings
|
||||||
|
# 5) Run the tests from the three websites below. They will tell you
|
||||||
|
# also what clients are compatible with your settings. The settings
|
||||||
|
# here are very strict and lock out most older clients/browsers.
|
||||||
|
# You will find some hints for fine tuning there as well.
|
||||||
|
# 6) If you know all your clients, and give them client certificates in
|
||||||
|
# advance, you can significantly improve security by setting
|
||||||
|
# "ssl_verify_peer" to "yes" and specifying a client cert (directory)
|
||||||
|
# using "ssl_ca_file/path". This will lock out all clients without a
|
||||||
|
# proper certificate. Don't use it for your public home page, but
|
||||||
|
# consider it for your private remote access server.
|
||||||
|
# 7) run civetweb, like above - or better create your own start script
|
||||||
|
# You are welcome to share your thoughts and experience on GitHub
|
||||||
|
# (see README.md in CivetWeb main directory).
|
||||||
|
|
||||||
|
# Don't run as super user, switch back to a regular user
|
||||||
|
run_as_user user
|
||||||
|
|
||||||
|
# The standard HTTP port 80 should redirect to the standard HTTPS port 443
|
||||||
|
listening_ports 80r,443s
|
||||||
|
|
||||||
|
# Don't forget to set the document root and domain
|
||||||
|
#document_root tdb
|
||||||
|
#authentication_domain mydomain.com
|
||||||
|
|
||||||
|
# Set the a certificate
|
||||||
|
ssl_certificate ../../resources/cert/server.pem
|
||||||
|
|
||||||
|
# Require a client cert for your private server (see above)
|
||||||
|
#ssl_verify_peer yes
|
||||||
|
#ssl_ca_file ../../resources/cert/client.pem
|
||||||
|
|
||||||
|
# Enforce TLS1.2 and some strong cipher(s)
|
||||||
|
ssl_protocol_version 4
|
||||||
|
ssl_cipher_list ECDH+AESGCM+AES256:!aNULL:!MD5:!DSS
|
||||||
|
|
||||||
|
# Tell all browsers to access this site only as HTTPS for the next 180 days
|
||||||
|
strict_transport_security_max_age 15552000
|
||||||
|
|
||||||
|
# Set some HTTP security header, see https://securityheaders.io
|
||||||
|
additional_header Content-Security-Policy: script-src 'self'
|
||||||
|
additional_header X-Frame-Options: SAMEORIGIN
|
||||||
|
additional_header X-Xss-Protection: 1; mode=block
|
||||||
|
additional_header X-Content-Type-Options: nosniff
|
||||||
|
additional_header Referrer-Policy: same-origin
|
||||||
|
additional_header Public-Key-Pins: pin-sha256="uz1UTAPen+xb+UoQqkVlEx4H653LbMjfRJcZx5OrjbI="; pin-sha256="pf3px1MBPmlTGAPoiHWqaSJ9L9Z+DKfwgsU7LfLnmsk="; max-age=7776000
|
||||||
|
#additional_header Expect-CT: max-age=86400,report-uri="https://mydomain.com/report"
|
||||||
|
|
||||||
|
|
||||||
|
# Ratings from 2017-09-03 (tests performed later may require more
|
||||||
|
# strict security settings)
|
||||||
|
#
|
||||||
|
# Headers rated A+ from https://securityheaders.io/
|
||||||
|
#
|
||||||
|
# SSL rated B from https://www.htbridge.com/ssl when using a self signed
|
||||||
|
# certificate, but no other weaknesses for modern browsers.
|
||||||
|
# Site remarks some older TLS versions and some weaker ciphers are not
|
||||||
|
# supported (but that's accessibility, not security).
|
||||||
|
#
|
||||||
|
# HTTPS rated A+ from https://www.htbridge.com/websec/ when using a self
|
||||||
|
# signed certificate, generated with make_certs.sh in resources/cert/
|
||||||
|
# and adding the server.pin and server_bkup.pin content into the
|
||||||
|
# Public-Key-Pins header above.
|
||||||
|
#
|
||||||
|
# A rating of "T / If trust issues are ignored: A" (ignoring self-signed cert)
|
||||||
|
# from https://www.ssllabs.com/ssltest/, https://www.qualys.com/forms/freescan/
|
||||||
|
# (Note: this test is runs with reverse DNS name, while all others use the
|
||||||
|
# IP address).
|
||||||
|
#
|
||||||
|
# Note: This settings are very strict and prevent some older but still common
|
||||||
|
# versions of major browsers to access this site. The test web sites will give
|
||||||
|
# you an overview. Test, before you use this settings.
|
||||||
|
|
||||||
14
software/WebServer/conf/server.crt
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIICHDCCAYUCFGkCyCGW5oP6L+eDHT4wZi1NQGb7MA0GCSqGSIb3DQEBCwUAME0x
|
||||||
|
CzAJBgNVBAYTAkdCMRMwEQYDVQQIDApTb21lLVN0YXRlMRcwFQYDVQQKDA5lbmdp
|
||||||
|
bmVlcnNAd29yazEQMA4GA1UEAwwHZWF3LmFwcDAeFw0yMjA5MTUxMzUxNTRaFw0z
|
||||||
|
MjA5MTIxMzUxNTRaME0xCzAJBgNVBAYTAkdCMRMwEQYDVQQIDApTb21lLVN0YXRl
|
||||||
|
MRcwFQYDVQQKDA5lbmdpbmVlcnNAd29yazEQMA4GA1UEAwwHZWF3LmFwcDCBnzAN
|
||||||
|
BgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA6WvBDkVGMa5fYEke2jM3ydnA+SJD+PO/
|
||||||
|
nDP68uIWrzqmu4lMeEt5iw5EvcKJePVzbP567z2MLrxyQZEvF3QArWxnlZVKgzMm
|
||||||
|
vE+WdOq+TBgehWr/si/RnDQhnq/pSF7K89k0ZwzqEiETDeQw64SBtVwZEl+gB2VJ
|
||||||
|
70p4atfS4xECAwEAATANBgkqhkiG9w0BAQsFAAOBgQDDzPd3zQ4UHyvSMBBjgWlq
|
||||||
|
41y9lTg7sukQqSSULHGqsLsZ8DSXtXyzqMV0EDy+k0Hns8+gwqStpr/GKxHLOgo5
|
||||||
|
EjfB/IJwFKxzFkboDwoLPbPib6REw1o0DT8io7sBIZwawua47UF/gLtvSYNBOlfj
|
||||||
|
OV0444A20JaDYutEpn9weg==
|
||||||
|
-----END CERTIFICATE-----
|
||||||
11
software/WebServer/conf/server.csr
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
-----BEGIN CERTIFICATE REQUEST-----
|
||||||
|
MIIBjDCB9gIBADBNMQswCQYDVQQGEwJHQjETMBEGA1UECAwKU29tZS1TdGF0ZTEX
|
||||||
|
MBUGA1UECgwOZW5naW5lZXJzQHdvcmsxEDAOBgNVBAMMB2Vhdy5hcHAwgZ8wDQYJ
|
||||||
|
KoZIhvcNAQEBBQADgY0AMIGJAoGBAOlrwQ5FRjGuX2BJHtozN8nZwPkiQ/jzv5wz
|
||||||
|
+vLiFq86pruJTHhLeYsORL3CiXj1c2z+eu89jC68ckGRLxd0AK1sZ5WVSoMzJrxP
|
||||||
|
lnTqvkwYHoVq/7Iv0Zw0IZ6v6UheyvPZNGcM6hIhEw3kMOuEgbVcGRJfoAdlSe9K
|
||||||
|
eGrX0uMRAgMBAAGgADANBgkqhkiG9w0BAQsFAAOBgQCVJ44RrkgQMAKKQKYbHAwW
|
||||||
|
6T8sYQhDk9ko0daxFdDan9HifohZMHGfNYB5kpZRevV6zQFyP5npApK5S5akpL/G
|
||||||
|
hmdi2G3qJKuX2LgKTC7cUk8qgTlhgihNElZZHZlmPG4TG2BJlfEJMOnXZNInoUkO
|
||||||
|
q6/Yq0vAWzUaMKOmS8t4zg==
|
||||||
|
-----END CERTIFICATE REQUEST-----
|
||||||
15
software/WebServer/conf/server.key
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
-----BEGIN RSA PRIVATE KEY-----
|
||||||
|
MIICXgIBAAKBgQDpa8EORUYxrl9gSR7aMzfJ2cD5IkP487+cM/ry4havOqa7iUx4
|
||||||
|
S3mLDkS9wol49XNs/nrvPYwuvHJBkS8XdACtbGeVlUqDMya8T5Z06r5MGB6Fav+y
|
||||||
|
L9GcNCGer+lIXsrz2TRnDOoSIRMN5DDrhIG1XBkSX6AHZUnvSnhq19LjEQIDAQAB
|
||||||
|
AoGAQ+vE62AhAsfYnO3p+lg4/ZVNX7Em0kQrF0rQ1OgQ7cBFUACtrbtYjKwEOKto
|
||||||
|
0Teq9KZAI2lnZxoSrR2P9GUe5MmHR9CrXiTczmRM7uND7t/ardW3gT0RbjaCr9oH
|
||||||
|
Exp4YKFKv24LMdcgkVe8JwJOZhB8VvnB0WQMDyFYsy8hAjkCQQD3CNCQR65MOEjy
|
||||||
|
vE3G+WRLtOWvzuNzAN9FMFNj5pH5oz6skDts7Yvj0DWyb5FHlBwpItNs9rJd2UyC
|
||||||
|
UQWaxhZXAkEA8eR09UnxOV7LaShmchoX/otuKeVMATdcyjOonM/fiHfBSZefW6YS
|
||||||
|
675lEGqRfGfjXpXQQBvMbQq67TUAISbg1wJBANU7/Jut5BvSsdUlCZXpC9P1kBXT
|
||||||
|
Za2NYSwd7L1c90Ae0yitTz5VRd0dilw9xY+dnzk64Hk78PblbQ9H1Kimt/0CQQCC
|
||||||
|
CAuPaGZSLtEuAFfB8qD/ZribsPWAmeA5mjeDxIMneyjehLFXtRjqvXjasE7xD2+8
|
||||||
|
gtBmBguIeoItzZX6PEoVAkEApwW7FNmNwUYuklu7WtS1HXOKvQzp+BZrDZAdnIPY
|
||||||
|
xEeTiJDvBsxDLBptzLS8I0elHE/7zHtQSr8mDqQifiT2Rw==
|
||||||
|
-----END RSA PRIVATE KEY-----
|
||||||
18
software/WebServer/conf/server.key.orig
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
-----BEGIN RSA PRIVATE KEY-----
|
||||||
|
Proc-Type: 4,ENCRYPTED
|
||||||
|
DEK-Info: DES-EDE3-CBC,B353E67B85AB5B84
|
||||||
|
|
||||||
|
oD/257rCCOkKvU5nqMdJjbcdILvGb+JTBtBy4Hzk8eoiq2idENQE86W34faYG+ho
|
||||||
|
wMosr5J+80hkrQI9ct+s5xb8/GTVFJPG3ek1aghL0ToDyNUmdWGqAK/+VbNptcLE
|
||||||
|
j5HNDttaKkDIqiiiIPDUWEJsIzOXU9NZF86bOsORU4q83lZk56sAhdvkgfRlBmso
|
||||||
|
BClwG/ABVxPc4vR+9N3Vbu9fWHEkRedqVoWju7vDLFoNPIO418lk0fzdgrVri6ah
|
||||||
|
+nOsSpjZxjjkDc5rJhqBreK1EaR1+Y2DzJ3r6944bPuwjwHXbhEzQz8y/xsjAsYl
|
||||||
|
bF+zrSaQN0ncyj4XjvNaAc0WXx0CEHEpC0OKwA4+zUYIC9utlVkt1CzGCN9FJYrk
|
||||||
|
8JtDfhaok4zlVBCowTpdkjhc6FXXicxIiaenSTOu9WzHjx1/TgRWt+SAERr7zCD0
|
||||||
|
no0pV3mA3ObUCg1HCcda9qQ9J+z6crXE7hep7m2T161ebg1h8N9gkdMjtnzvV+AA
|
||||||
|
U6Xxq4fqafG/Jjj8+2YZZZZ/osOBPU4D6FVr+XoqW7rqEGvOT6lhO1AVwZG/Wgbx
|
||||||
|
eimOniQfdjAwtMdjSbfS8EqawUhZfJ3QlV8rDbrhTJIwcWpVJEI20V1bvRf/DQwj
|
||||||
|
js2paPPs01xKROL6H5oegn4BMV66OTD0km/cqu52MONLnsGDdQJJAGmmftguxRh1
|
||||||
|
+jFO2iNeJ91jLfUObFyun5qOWi2I6lwkHtGG6M34h+14tniOA6C8NmbxXBhXDPa/
|
||||||
|
UHyJFGDQJnnRgZTPxsnXly1Vc7/I23/MVkIXNp/w4jX7FM4CP8jVaw==
|
||||||
|
-----END RSA PRIVATE KEY-----
|
||||||
14
software/WebServer/conf/server.pem
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIICHDCCAYUCFGkCyCGW5oP6L+eDHT4wZi1NQGb7MA0GCSqGSIb3DQEBCwUAME0x
|
||||||
|
CzAJBgNVBAYTAkdCMRMwEQYDVQQIDApTb21lLVN0YXRlMRcwFQYDVQQKDA5lbmdp
|
||||||
|
bmVlcnNAd29yazEQMA4GA1UEAwwHZWF3LmFwcDAeFw0yMjA5MTUxMzUxNTRaFw0z
|
||||||
|
MjA5MTIxMzUxNTRaME0xCzAJBgNVBAYTAkdCMRMwEQYDVQQIDApTb21lLVN0YXRl
|
||||||
|
MRcwFQYDVQQKDA5lbmdpbmVlcnNAd29yazEQMA4GA1UEAwwHZWF3LmFwcDCBnzAN
|
||||||
|
BgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA6WvBDkVGMa5fYEke2jM3ydnA+SJD+PO/
|
||||||
|
nDP68uIWrzqmu4lMeEt5iw5EvcKJePVzbP567z2MLrxyQZEvF3QArWxnlZVKgzMm
|
||||||
|
vE+WdOq+TBgehWr/si/RnDQhnq/pSF7K89k0ZwzqEiETDeQw64SBtVwZEl+gB2VJ
|
||||||
|
70p4atfS4xECAwEAATANBgkqhkiG9w0BAQsFAAOBgQDDzPd3zQ4UHyvSMBBjgWlq
|
||||||
|
41y9lTg7sukQqSSULHGqsLsZ8DSXtXyzqMV0EDy+k0Hns8+gwqStpr/GKxHLOgo5
|
||||||
|
EjfB/IJwFKxzFkboDwoLPbPib6REw1o0DT8io7sBIZwawua47UF/gLtvSYNBOlfj
|
||||||
|
OV0444A20JaDYutEpn9weg==
|
||||||
|
-----END CERTIFICATE-----
|
||||||
BIN
software/WebServer/libcivetweb.a
Normal file
6
software/WebServer/start_WebServer.sh
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
ROOTDIR=/apps/WebServer
|
||||||
|
|
||||||
|
cd ${ROOTDIR}
|
||||||
|
nohup ${ROOTDIR}/WebServer &
|
||||||
BIN
software/WebServer/webserver/css/bootstrap.min.css.gz
Normal file
18
software/WebServer/webserver/css/jquery.edittable.min.css
vendored
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
table.inputtable{width:100%;border:1px solid #ddd;border-collapse:collapse;border-spacing:0;-moz-box-shadow:0 1px 3px rgba(0,0,0,.075);-webkit-box-shadow:0 1px 3px rgba(0,0,0,.075);box-shadow:0 1px 3px rgba(0,0,0,.075);margin:15px 0}
|
||||||
|
table.inputtable a.icon-button{background-color:#ccc;display:inline-block;width:18px;height:18px;text-decoration:none;color:#fff;font-weight:800;line-height:16px;text-align:center;font-size:14px;-moz-border-radius:1px;-webkit-border-radius:1px;border-radius:1px;-moz-box-shadow:0 0 1px rgba(0,0,0,0.2);-webkit-box-shadow:0 0 1px rgba(0,0,0,0.2);box-shadow:0 0 1px rgba(0,0,0,0.2)}
|
||||||
|
table.inputtable a.icon-button.addcol,table.inputtable a.icon-button.addrow{background-color:#81b71a}
|
||||||
|
table.inputtable a.icon-button.delcol,table.inputtable a.icon-button.delrow{background-color:#db4a39}
|
||||||
|
table.inputtable a.icon-button.disabled{background-color:#eee}
|
||||||
|
table.inputtable td:last-child,table.inputtable th:last-child{width:54px;border:1px solid #eee;border-right:thick;}
|
||||||
|
table.inputtable td,table.inputtable th{border:1px solid #eee;text-align:center;height:40px;vertical-align:middle;font-size:14px}
|
||||||
|
table.inputtable th{background-color:#f1f1f1;border-top:none;border-bottom:2px solid #ddd;border-color:#ddd}
|
||||||
|
table.inputtable td input[type=text]{border:0;width:90%;height:100%;text-align:center;padding:0 5%}
|
||||||
|
table.inputtable tr td input:focus{background-color:#fafafa}
|
||||||
|
table.inputtable.wh tbody tr:nth-child(1),table.inputtable.wh tbody tr:nth-child(1) input{background-color:#fdfdfd;font-weight:800}
|
||||||
|
table.inputtable th:first-child,table.inputtable td:first-child{border-left:none}
|
||||||
|
table.inputtable tr:last-child td{border-bottom:none}
|
||||||
|
@media only screen and max-width 480px {
|
||||||
|
table.inputtable td,table.inputtable th{min-width:40px;height:80px}
|
||||||
|
table.inputtable a.icon-button{width:40px;height:40px;font-size:18px;min-width:40px;line-height:40px;margin:3px 0}
|
||||||
|
table.inputtable td input{height:80px}
|
||||||
|
}
|
||||||
159
software/WebServer/webserver/css/sb-admin.css
Normal file
@@ -0,0 +1,159 @@
|
|||||||
|
/*
|
||||||
|
Author: Start Bootstrap - http://startbootstrap.com
|
||||||
|
'SB Admin' HTML Template by Start Bootstrap
|
||||||
|
|
||||||
|
All Start Bootstrap themes are licensed under Apache 2.0.
|
||||||
|
For more info and more free Bootstrap 3 HTML themes, visit http://startbootstrap.com!
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* ATTN: This is mobile first CSS - to update 786px and up screen width use the media query near the bottom of the document! */
|
||||||
|
|
||||||
|
/* Global Styles */
|
||||||
|
|
||||||
|
body {
|
||||||
|
margin-top: 50px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#wrapper {
|
||||||
|
padding-left: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#page-wrapper {
|
||||||
|
width: 100%;
|
||||||
|
padding: 5px 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Nav Messages */
|
||||||
|
|
||||||
|
.messages-dropdown .dropdown-menu .message-preview .avatar,
|
||||||
|
.messages-dropdown .dropdown-menu .message-preview .name,
|
||||||
|
.messages-dropdown .dropdown-menu .message-preview .message,
|
||||||
|
.messages-dropdown .dropdown-menu .message-preview .time {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.messages-dropdown .dropdown-menu .message-preview .avatar {
|
||||||
|
float: left;
|
||||||
|
margin-right: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.messages-dropdown .dropdown-menu .message-preview .name {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.messages-dropdown .dropdown-menu .message-preview .message {
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.messages-dropdown .dropdown-menu .message-preview .time {
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Nav Announcements */
|
||||||
|
|
||||||
|
.announcement-heading {
|
||||||
|
font-size: 50px;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.announcement-text {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Table Headers */
|
||||||
|
|
||||||
|
table.tablesorter thead {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
table.tablesorter thead tr th:hover {
|
||||||
|
background-color: #f5f5f5;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Flot Chart Containers */
|
||||||
|
|
||||||
|
.flot-chart {
|
||||||
|
display: block;
|
||||||
|
height: 400px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.flot-chart-content {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Edit Below to Customize Widths > 768px */
|
||||||
|
@media (min-width:768px) {
|
||||||
|
|
||||||
|
/* Wrappers */
|
||||||
|
|
||||||
|
#wrapper {
|
||||||
|
padding-left: 225px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#page-wrapper {
|
||||||
|
padding: 15px 25px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Side Nav */
|
||||||
|
|
||||||
|
.side-nav {
|
||||||
|
margin-left: -225px;
|
||||||
|
left: 225px;
|
||||||
|
width: 225px;
|
||||||
|
position: fixed;
|
||||||
|
top: 50px;
|
||||||
|
height: 100%;
|
||||||
|
border-radius: 0;
|
||||||
|
border: none;
|
||||||
|
background-color: #222222;
|
||||||
|
overflow-y: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Bootstrap Default Overrides - Customized Dropdowns for the Side Nav */
|
||||||
|
|
||||||
|
.side-nav>li.dropdown>ul.dropdown-menu {
|
||||||
|
position: relative;
|
||||||
|
min-width: 225px;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
border: none;
|
||||||
|
border-radius: 0;
|
||||||
|
background-color: transparent;
|
||||||
|
box-shadow: none;
|
||||||
|
-webkit-box-shadow: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.side-nav>li.dropdown>ul.dropdown-menu>li>a {
|
||||||
|
color: #999999;
|
||||||
|
padding: 15px 15px 15px 25px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.side-nav>li.dropdown>ul.dropdown-menu>li>a:hover,
|
||||||
|
.side-nav>li.dropdown>ul.dropdown-menu>li>a.active,
|
||||||
|
.side-nav>li.dropdown>ul.dropdown-menu>li>a:focus {
|
||||||
|
color: #fff;
|
||||||
|
background-color: #080808;
|
||||||
|
}
|
||||||
|
|
||||||
|
.side-nav>li>a {
|
||||||
|
width: 225px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.navbar-inverse .navbar-nav>li>a:hover,
|
||||||
|
.navbar-inverse .navbar-nav>li>a:focus {
|
||||||
|
background-color: #080808;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Nav Messages */
|
||||||
|
|
||||||
|
.messages-dropdown .dropdown-menu {
|
||||||
|
min-width: 300px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.messages-dropdown .dropdown-menu li a {
|
||||||
|
white-space: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||