There is an updated page with a lot of more information about ZX97 here:
See http://www.user.dccnet.com/wrigter/ for the latest update.
Hello Sinclair Fans, here is a ZX81 project worthy of your attention: the ZX97!
In this project we will design and build an enhanced, low power discrete logic version of the ZX81. The design presented here is not yet fully tested and is therefore open to participation, suggestions, comments, criticism. I will describe the ZX97 first, followed by any suggested improvements in 1 or 2 more articles.
I don't intend to take a purist approach and reverse engineer the ULA "verbatim" but I would rather improve on the original design by adding functionality without compromising compatability or simplicity. The final design should be a truly enhanced ZX81 and yet use fewer chips than the ZX80.
This ZX97 idea has solicited several design proposals using complex "ULA replacement" parts in order to reduce chip count. But replacing the Sinclair ULA with another custom chip or several smaller complex chips (PALs) would do little to help shed light on the ZX81 "blackbox". I propose an accessable low level design to help focus discussion on the logic itself rather than how the chips work.
You may wish to compare the circuit of the ZX97 with the ZX80 and ZX81 schematics available at NVG. The ZX81 schematic is relatively easy to understand, at least functionally. But the ZX80 schematic! I went through the execise of redrawing it in functional blocks before I could unravel the logic and most of the timing.
I propose the following functional description and I invite everyone to propose added features and improvements to the original ZX81. (1K RAM, membrane keyboard, tape loading good enough for you? I don't think so!)
The ZX97 design goals include:
Compatability with 64K stock ZX81 BASIC and machine code
software and all varieties of high resolution software
including those that require special hardware (static
RAM, modified 16K, etc).
Most ZX81 software uses ZX81 ROM routines and the default
ZX97 operating system should therefore be a minimally
modified ZX81 ROM.
OS extensions including Hires Basic commands can be added
using a new ROM address space (i.e. bank switching) and a
few simple hooks in the existing ROM. (also see F.)
A flexible character pattern generator: instead of only
one set of 64 characters patterns and their inverse, we
add additional sets of UDGs (user definable characters).
The stock ZX97 of course needs to have 64K memory to meet
the basic design objective of (expanded) ZX81
compatability. But a single 128K SRAM is the simplest way
to achieve this. By the same token, alternate OS and
utility programs in firmware could use a 128Kbyte EPROM.
This way we buy a lot of extra power using the same
number of chips at little extra cost.
Needless to say the RAM is battery backed up and must be
selectively write protected!
256K Memory management: now that we talked ourselves into
using 128K RAM and EPROM chips we use a few I/O lines to
do the bank switching
A flexible memory mapping circuit allows SHADOW RAM to be
used instead of EPROM,
for example, in the 0-8K area for experimenting with OS
software.
ZX81 compatability dictates the ZX97 0-8K ROM is
virtually identical to the ZX81 ROM.
However OS extensions need to hook into the existing
operating system.
I propose a new set of keywords which use a new
"X" cursor mode in addition to the existing
"K" , "L" and "F" cursor
modes.
Like the "F" mode, the "X" mode uses
SHIFT ENTER but is followed by an additional ENTER to
chang the cursor to "X" and then a single
keystroke selects any of up to 38 new keywords.
Serial and parallel I/O enables connecting and
comunicating with other computers or printers.
I propose emulating an existing commercial product to
take advantage of existing software support.
Well without further delay here is the first part of the ZX97 design
The ZX81 discrete logic is straight forward and it's not surprising that it bears a strong resemblance to the ZX80 circuit. The circuit is described in functional blocks as shown in FIG 1. The circuit details are shown in the schematic FIG 2. The critical video timing is shown in timing diagram FIG 3.
This circuit generates the 6.5MHz video clock, the 3.25MHz CPU clock and the 15.75KHz horizontal clock. The 6.5 MHz crystal clock is divided by 2 with a 74HC74 to generate the CPU clock and the 74HC393 dual 4 bit counter together with the 74HC11 divides the CPU clock further by 207 to generate the 15.75 KHz horizontal frequency. The 74HC08 generates 4.6 us wide SYNC/NMI pulses which are gated by the SYNC and NMI latches before routing to the video/sync mixer and the CPU NMI input.
Two SR latches are used to control the flow of NMI pulses to the CPU and SYNC pulses to the VIDEO/SYNC MIXER. The NMI latch is set with OUT FE which gates the NMI pulses to the CPU and is reset with OUT FD.
The action of the SYNC latch is a little confusing in that it doesn't actually turn off the SYNC pulses but rather switches between normal HSYNC pulses and inverted HSYNC pulses which is a VSYNC pulse. The SYNC latch is set with IN FE which inverts the HSYNC pulses and is used to generate the vertical SYNC pulse. Any OUT command will reset the latch to terminate the VSYNC and enable the normal HSYNC pulses.
To maintain compatability with the ZX81 I/O port assignment, the same incomplete I/O address decoding is used and no attempt made to refine the address range. This is important because some programs access the ZX81 ports at more than one address. A few 74HC32 provide the necesary logic to access the NMI and SYNC latches.
The ZX97 keyboard uses 8255 port B for input by decoding the
inverted A0 and A7 lines.
Note that the 8255 defaults to 3 input ports on reset and no
further initialization is required until you want to use port C
(I/O address 7F) for output. Port A (I/O address FF) is dedicated
for use as a high speed interface to a PC printer port.
The control port is located at I/O address 7E and control word 93 sets up ports A and B as inputs and port C as output.In accordance with 8255 internal port decoding, Port C output bits can be accessed at two different locations: Port C output byte is written to I/O address 7F but in addition Port C may be reset or set individually at I/O address 7E with control byte values 00 to 0F. Even values 02 to 0E reset bits 0 to 7 respectively and odd values 01 to 0F set bits 0 to 7. The format of the control word is as follows:
| Port C must be initialized as an output with OUT 7E,93 Bit set/reset is controlled with OUT 7E,00 to OUT 7E,0F |
D7 D6 D5 D4 D3 D2 D1 D0
\_________/ \_____/ \_/
| | |
always 0 bit # 1=on
select 0=off
|
Memory decoding is performed with a 74HC251 which maps the
EPROM at adress 0-8K and 40K-64K.
The RAM is mapped 8K-40K but the RAM segment 32-40K may be mapped
over the 0-8K area to allow installation of modified BASIC or
other operating systems by setting 8255 port C bit 7.
Note that the 0-8K EPROM segment is then remapped to 32-40K. Furthermore the 0-8K RAM is write protected and the VIDEO pattern data continues to be supplied from the EPROM pattern table unless the I register is changed. This allows the 1E00 to 1FFF area of the shadow RAM to be used for 512 byte of program code. Future enhancements include decoding and control of a 256K bank switch.
In this revision, both devices are 32K byte CMOS devices.
The RAM is battery backed up and write protected in the 0-8K
segment to avoid corrupting the shadow RAM operating system from
spurious writes especially because Sinclair BASIC performs some
dummy writes to locations 0000-0004.
The sinclair text mode is supported with the pattern table in location 1E00-1FFF.
User Defined Graphics (UDG) RAM pattern tables are also
supported.
UDGs are accessed by changing the I register to point to the new
pattern table in RAM or EPROM.
Only 3 bits of the 8 bit 74HC590 are used as a modulo 8 ROW
counter which increments every horizontal line and during RFSH
time it addresses the 8 rows of patterns for each character.
The ROW counter is reset with the VSYNC signal. The CHR$ latch is loaded with each DFILE character code and during RFSH it is used to address the corresponding pattern table entries. The I register is intialized to address the Sinclair pattern table at base address of 1E00 during RFSH time.
In order to support True High Resolution graphics (i.e. WRX16) , bit 6 of the 8255 port C is used to disable the ROW counter and CHR$ latch outputs during RFSH. Pseudo Hires is supported without any changes although, given the ZX97 hardware, UDG's and True Hires would appear the more logical choices.
The Sinclair keyboard scanning method uses A8-15 to scan keyboard rows and 5 bits of the 8255 Port A to sense column data. Two other bits are used to sense the 50/60 Hz option, and tape in.
The video shift register is loaded with the video pattern data from RAM or EPROM and the pixels are clocked out at 6.5 MHz. If bit 7 of the CHR$ code is a 1 then the video serial bits are inverted using an XOR gate. The video is combined (mixed) with the SYNC signal to produce a composite video signal suitable for connecting to a video monitor or RF modulator.
This bit of logic controls the timing of the video hardware. It decodes valid (displayable) DFILE characters then loads the character code into the CHR$ LATCH, forces the CPU to execute a NOP, and finally loads the pattern data into the video shift register. The timing diagram 3 shows the video process in detail.
____
| 6.5|--->------------------------------------------------------+
| | _____ ________ _____ _____ _____ __|__
|XTAL| | CPU | | MEMORY | | RAM | |EPROM| | ROW | |VIDEO|
|TIME| | MREQ|-->| DECODE |-->| A0-2|->| A0-2|<--| CTR | | S/R |
|BASE| | | |________| | | | | |-----| | U14 |
| | | ADR|->-+----[2K]--->|A3-8 |->|A3-8 |<--| CHR | | SOUT|---+
| 3.2|--->|CLK | |----------->|A9-14|->|A9-14| |LATCH| | | |
| | | DATA|<--|-+--[2K]--->|D0-7 |->|D0-7 |-->|D0-7 |->|_S/L_| |
| | | | | | __ | | | | |___Q7|->---|----+ |
| | | IORQ|_ | +-<-|NOP| |_____| |_ _| __|__ | | |
| | +->|NMI | | | |___|<------------------<-|VIDEO|-----+ | |
| | | |_____| | |__________ |LOGIC| _____ | |
| | | _____ | ________ | _____ _____ |_____| |VIDEO|<+ |
| | +--| NMI | |_| I/O | | |KEYBD| | 8255| _____ |INVRT| |
|15.7|--->|/SYNC|<--| DECODER| +>|LOGIC|->| I/O | |VIDEO|<-|_____|<--+
|____| |LATCH| |________| |_____| |_____| |/SYNC|
| | | |MIXER|--> COMPOSITE
|_____|----------------------------|----->|_____| VIDEO OUT
|__________
FIG 1 - ZX97 BLOCK DIAGRAM `----> to PC LPT
|
|||||
CRYSTAL TIME BASE VIDEO SHIFT REGISTER SYNC/VIDEO MIXER
______
6.5 MHz D0`---|D0 U14| __ 74HC86 +5V
__|-|___ D1`---|D1 S0|--|U21\__ ______
| |-| | D2`---|D2 | +|__ / | | |
| | D3`---|D3 | | [1K] [1K] | C
|-[10M]--| 74HC74 D4`---|D4 | | | | |/
| [2K] ____ D5`---|D5 | | +-----+--| Q1
|__|\____|_____|CL Q|-- D6`---|D6 | | | B |\
|/ | U15| D7`---|D7 | |___ | | E
U17 _|D /Q|_ S/L---|S/L | | | _V_ |
74HC05 | |____| | |______| | | |1N914 [220]
__|________| 74HC165 | [2K] | |___
| | | | VIDEO OUTPUT
| ______ D7`` 0V |_______
| |U13 R|________________________________ |
3.2MHz ____|___|CLK R|___| __ | |
| Q1|------------------------| \ | |
| Q2|------------------------| U12>--+ |
| | __ +--|__ / |
| Q3|-------------| \ | |
| Q4|--+----------| U12>--+ |
| CLK|__| +--|__ / |
| Q5| | |
| Q6| __ | |
| Q7|--|U10\___|________________ |
| Q8|--|__ / HSYNC | |
|______| | |
74HC393 | |
| |
| |
I/O DECODER SYNC/NMI | |
LATCHES | |
__ 74HC32 (OR) __ TO KEYBD | |
A0 --)U11\__ __ | BUFFER | |
RD --)__ / `--)11 \__| __ | |
+--)__ / `---)U11\__ __ | |
| IN FE +-)__ / `--|U8 \-_ | |
| (VSYNC) | +-|__ / | | |
| | | | | |
IORQ -------+ | |________|__ | __ |
| | ________| | +--|U21\__|
| __ | | __ |---|--|__ / COMPOSITE
+--)U11\__ | +-|U8 \_____| | 74HC86 SYNC
WR ------------)__ / +-|-----------|__ / VSYNC |
OUT FF | | | __
(HSYNC) | |__________________ +--)U9 \__ NMI
| __ | +------)__ / |
+--)U6 \__ __ | | 74HC32 |
A0 -------------------|--)__ / `---|U8 \__| | |
| OUT FE +-|__ / | | |
| (NMI ON) | | | |
| |________|__| |
| ________| | |
| __ | __ | |
+--)U6 \__ +-|U8 \_____| |
A1 ----------------------)__ / `---|__ / NMI |
OUT FD 74HC00 |
(NMI OFF) |
VIDEO DECODER LOGIC |
|
__ 74HC32 |
D6'---)U9 \___|\_ __ |
M1 ---)__ / |/ `-|U10\____________________________________|__|\_____
__ +---|__ / | VALID DFILE CHR$=NOP | |/ |
A14---|U12\ | 74HC08 | | 74HC04 |
A15---| >---+ | | |
HALT--|__ / 74HC11 | _______________| |
_____________________| | |
| __ | ________ |
MREQ----|-----------------| \ |_______|NMI CPU | |
3.2MHz--|-----------------| U7 >----> S/L | __ | | |
| +----|__ / +-)U6 \_|WAIT | |
| | 74HC10 +-)__ / | | |
| CHR$ LATCH |---[1k]---> 0V |_______|HALT | |
| ______ | ______ ______ | | |
+--|D6 Q6|--+ | RAM | |EPROM | | | |
| U4 | | U3 | | U2 | | U1 | |
D0'--------|D0 Q0|----|A3 |-----|A3 |--[1K]--|A3 | |
D1'--------|D1 Q1|----|A4 |-----|A4 |--[1K]--|A4 | |
D2'--------|D2 Q2|----|A5 |-----|A5 |--[1K]--|A5 HALT| |
D3'--------|D3 Q3|----|A6 |-----|A6 |--[1K]--|A6 A6|___ |
D4'--------|D4 Q4|----|A7 |-----|A7 |--[1K]--|A7 INT|___| |
D5'--------|D5 Q5|----|A8 |-----|A8 |--[1K]--|A8 | 3.2 |
D7'--------|D7 Q7|-d7`|A9 |-----|A9 |--------|A9 0|--> MHz |
RD --------|CP | |A10 |-----|A10 |--------|A10 M1|--> |
RFSH__ _|OE | |A11 |-----|A11 |--------|A11 MREQ|--> |
____| | |______| |A12 |-----|A12 |--------|A12 IORQ|--> |
| __ | 74HC574 |A13 |-----|A13 |--------|A13 RD|--> |
`-)U9 \_| |A14 |-----|A14 |--------|A14 WR|--> |
+-)__ / | ROW CTR | | | | --|A15 | |
|____ | ______ | | | | | RFSH|--> |
PC6___| |_|OE U5 | | | | | | | |
HSYNC _____|CP Q0|----|A0 |-----|A0 |--[1K]--|A0 | |
| Q1|----|A1 |-----|A1 |--[1K]--|A1 | |
VSYNC _____|CL Q2|----|A2 |-----|A2 |--[1K]--|A2 |74HC05 |
|______| | | | | | | ___ |
74HC590 | | | | | | | | |
D0`--|D0 |-----|D0 |--[1K]--|D0 |--|D0 |_|
D1`--|D1 |-----|D1 |--[1K]--|D1 |--|D1 |_|
D2`--|D2 |-----|D2 |--[1K]--|D2 |--|D2 |_|
D3`--|D3 |-----|D3 |--[1K]--|D3 |--|D3 |_|
D4`--|D4 |-----|D4 |--[1K]--|D4 |--|D4 |_|
D5`--|D5 |-----|D5 |--[1K]--|D5 |--|D5 |_|
D6`--|D6 |-----|D6 |--[1K]--|D6 | | | |
B1 1N34A D7`--|D7 |-----|D7 |--[1K]--|D7 |--|D7 |_|
+5 --[3V]---|<---+-----|VSS | __|OE | _____|RST | |___|
0V ---------|<---| | | |__|CE | | | | U18
+5------||-------+ __|OE | | |______| | |________|
+ 1uF |__|CE | | 27C256 | Z80B
BATTERY BACKUP | |______| | | KEYBOARD
5V | 62256 | | LOGIC
| | | | A8 -|<--|-|-|-|-|
[2K] | 5V | | A9 -|<--|-|-|-|-|
|___| | | | A10-|<--|-|-|-|-|
_____ | [2K] | | A11-|< -|-|-|-|-|
| Z |_| | | | A12-|<--|-|-|-|-|
0V _______|1 Y |_________|____| 5V | A13-|<--|-|-|-|-|
0V _______|2 | | | A14-|<--|-|-|-|-|
0V _______|3 | [10K] | A15-|<--|-|-|-|-|
| | MEMORY |_______| | | | | |
5V _______|5 | DECODER | ________ | | | | |
5V _______|6 | | | U16 | | | | | |
5V _______|7 | |___|\________|RST PA0|_| | | | |
| U20 | | |/U17 | PA1|___| | | |
A13 _______|A | + | 74HC04 | PA2|_____| | |
A14 _______|B 4|___________ 1uF === | PA3|_______| |
A15 _______|C | | | | PA4|_________|
___|E 0|_______ | 0V PC6 _____|PC6 PA5|___ 0V
| |_____| | | | | PA6|___ 0V
|_____ 74HC251 | | [10K]| PA7|___ EAR
__ | | | | | |
MREQ--|U10\___| 74HC04 | | 0V | PB0|---< D0
RFSH--|__ / _______/|__|___|_____________________|PC7 PB1|---< D1
74HC08 | __ \| | | | PB2|---< D2
+---)U9 \___| [10K]| PB3|---< D3
RD ---------------)__ / | | PB4|---< D4
74HC32 0V | PB5|---< D5
| PB6|---< D6
A7 ____|\________|B PB7|---< D7
U17|/ | PC0|---> STB
74HC04 | PC1|---> ALF
A0 ____|\________|A PC2|---> ACK
U17|/ | PC3|--->
74HC04 | PC4|--->
| PC5|--->
|________| LPT1
FIG 2 - ZX97 SCHEMATIC DIAGRAM
|
|||||
| U1 | Z80 | U2 | ROM | U3 | RAM |
| U4 | HC574 | U5 | HC590 | U6 | HC32 |
| U7 | HC10 | U8 | HC00 | U9 | HC32 |
| U10 | HC08 | U11 | HC32 | U12 | HC11 |
| U13 | U14 | HC165 | U15 | HC74 | |
| U16 | 82C55? | U17 | HC04 | U18 | HC05 |
| U19 | U20 | HC251 | U21 | HC86 | |
The Sinclair ZX97 character display hardware shown in FIG 3 is required to generate a standard screen of 24 lines of 32 characters.
The character display starts when the last blank line at the top of the screen has occurred and and the video routine jumps to the DFILE echo above 32K.
The STATE LOGIC takes control when any opcode is executed above 32K (A15 high and M1 low) with data bit 6 equal to zero. The video data is loaded in these simplified steps:
Read loads the character code into the 74HC574 register.
The STATE LOGIC turns on the 74HC05 and forces the data lines low.
The CPU interprets the byte as a NOP.
The refresh signal provides OE for the 74HC574 and the
74HC590 ROW
COUNTER and together with the I register generates the
pattern table
address and the
The pattern byte is loaded into the video shift register.
Keith's note: the HC574, HC590, and the resistors in A0-A8
replace the 74LS157 chips of the original design.
Also, I don't think the 7405 is easy to get in LS or HC logic. It
may be better to use an 8-bit buffer to pull D0-7 low. I wonder
why they didn't do that originally? Perhaps using LS05 chips left
them a useful spare inverter?
One could say that the DFILE is literally executed with NOPs
substituted for each character code.
Each NOP executes in 4 CPU clock cycles at 3.25 MHz or 8 pixels
at 6.5MHz from the ULA video shift register.
<--------CHARACTER 1-----------><--------CHARACTER 2----------->
T STATE <--T1--><--T2--><--T3--><--T4--><--T1--><--T2--><--T3--><--T4--><
(ref) ___ 1___2 3___ ___ 5___ 1___2 3___ ___ 5_
CPU CLOCK | |___| |___| |___| |___| |___| |___| |___| |___|
_ _______________ _______________ _______________ _______________ _
A0-A15 _X_____PC________X___I+CHR+CTR___X______PC_______X___I+CHR+CTR___X_
________ NOP _______________ ________ NOP _______________
DATA >---|__CHR___|___|_PATTERN DATA__|--|__CHR___|___|_PATTERN DATA__|-
|
FIG 3 ZX97 CHARACTER DISPLAY TIMING |
| Character 1 | Character 2 | |||||||||||||||||
| CPU CLOCK: | H | L | H | L | H | L | H | L | H | L | H | L | H | L | H | L | ||
| T STATE: | T1 | T2 | T3 | T4 | T1 | T2 | T3 | T4 | ||||||||||
| /M1: | L | H | L | H | ||||||||||||||
| /MREQ: | H | L | H | L | H | L | H | |||||||||||
| /RD: | H | L | H | L | H | |||||||||||||
| /REFRESH: | H | L | H | L | ||||||||||||||
| ROM A15-9: ROM A8-3: ROM A2-1: | PC | I CHR1 CTR | PC | I CHR2 CTR | ||||||||||||||
| char_latch: | ... | CHR1 | CHR2 | |||||||||||||||
| DATA: | CHR | NOP | PATTERN DATA | CHR | NOP | PATTERN DATA | ||||||||||||
The detailed sequence of operations for each character byte is shown in FIG 1 and described as follows:
Each character code (CHR$) byte in DFILE is addressed by the CPU PC, on the rising edge T2 data is loaded from DFILE into the 74HC574 : bits 0-5 and 7 into 7 bits.
On the falling edge of T2, the NOP circuit forces all CPU data lines to zero.
On the rising edge of T3 the low data lines are interpreted by the CPU as a NOP instruction.
During T3/4, the CPU executes the Refresh cycle and ROM address lines are generated with I register on A9-A15, the CHR$ latch on A3-A8, and the ROW counter on address lines A0-A2.
On the rising edge of T1, pattern data from the EPROM is loaded into video shift register and 8 video pixels are shifted out at 6.5MHz
If bit 7 of the CHR$ latch equals 1, then the serial video data is inverted.
The CPU increments the program counter and fetches the next character code.
This repeats until a HALT is fetched.
HALT opcode bit 6 = 1 and is therefore executed (no NOP)
The SYNC timebase generates a HSYNC pulse independend of the CPU timing and the ROW counter is incremented
The halted CPU continues to execute NOPs, incrementing register R and samples the INT input on the rising edge of each T4.
When A6, which is hardwired to INT, goes low during
refresh time,
(bit 6 of the R reg = 0), the Z80 executes the INT
routine (below 32K)
CPU returns from INT and resumes "execution" of DFILE CHR$ codes.
The process repeats 192 times and then INT routine
returns to the main video routine,
turns on the NMI latch and switches back to the
application code.