Initial repo build

This commit is contained in:
Philip Smart
2022-12-01 09:35:39 +00:00
commit 372b4debad
130 changed files with 78685 additions and 0 deletions

816
.gitignore vendored Normal file
View 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/

View 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"

View 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

View 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
#**************************************************************

View 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;

View 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;

View 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;

View 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"

View 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

View 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
#**************************************************************

View 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;

View 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;

View 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;

View 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"

View 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

View 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
#**************************************************************

View 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;

View 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;

View 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
View 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>
--------------------------------------------------------------------------------------------------------

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

674
license.txt Normal file
View 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>.

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 353 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 489 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 179 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 227 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 112 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 128 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 129 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 145 KiB

BIN
software/FusionX/bin/mspi_main Executable file

Binary file not shown.

BIN
software/FusionX/bin/z80ctrl Executable file

Binary file not shown.

14
software/FusionX/etc/cpuset.sh Executable file
View 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
View 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

View 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
View 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

Binary file not shown.

View 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)

View 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 */

View 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);
}

File diff suppressed because it is too large Load Diff

View 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

View 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

View 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

View 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);
}

View 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.
}

View 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

View 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 */

View 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);
}

File diff suppressed because it is too large Load Diff

View 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

View 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

View 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

View 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);
}

View 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.
}

View 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

View 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

View 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.

File diff suppressed because it is too large Load Diff

View 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

Binary file not shown.

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,6 @@
#!/bin/sh
ROOTDIR=/apps/FusionX
cd ${ROOTDIR}
#nohup ${ROOTDIR}/bin/FusionX &

View 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

View 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;
}

View 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
)
)

View 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.

View 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-----

View 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-----

View 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-----

View 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-----

View 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-----

Binary file not shown.

View File

@@ -0,0 +1,6 @@
#!/bin/sh
ROOTDIR=/apps/WebServer
cd ${ROOTDIR}
nohup ${ROOTDIR}/WebServer &

Binary file not shown.

View 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}
}

View 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;
}
}

Some files were not shown because too many files have changed in this diff Show More