>moria.de >SC/MP: CPU card for the NDR Klein Computer

SC/MP: CPU card for the NDR Klein computer

Introduction

A new SC/MP system in the 21st century is really late, but I always wanted one for personal reasons. Finally! The >NDR Klein computer is a great modular system and the perfect environment to bring up older CPUs with a minimal amount of work. There is still an active group of enthusiasts that manufactures PCBs and develops new hardware and software for it.

Since hardware is nothing without software, let's have a look at the most popular SC/MP system ever: The Elektor SC/MP microcomputer. While the small MK14 single board computer, a clone of the National Semiconductor development kit with calculator keypad and seven segment display, was popular as well, it was quite limited. The Elektor system grew in a rather cluttered way to a full system with serial console and BASIC.

Its beginning was the RAMIO board (classic front panel working as DMA busmaster, RAM and GPIO with LEDs) together with a freely wired breakout board for the CPU. The address map was:

0000-00ffRAM
0100-01ff8 bit LED (incompletely decoded)
0200-02ff8 bit input switch (incompletely decoded)

The later system using euro cards did not use either and contained the cards CPU (CPU, driver, RAM, ROM), interrupt/multiplexer (interrupt encoder, RAM, ROM), HEXIO (7 segment LEDs with discrete controller and hex keypad) as well as additional RAM cards. Two serial interfaces for a terminal and a cassette interface were directly connected to the CPU. With time there was a switch from SC/MP to SC/MP II, which is software compatible, but not entirely pin compatible. It needs twice as many clock cycles for a micro cycle, but could run at four times the clock speed.

The interrupt/multiplexer card needs 16 ports and was incompletely decoded, but the software never used it. Its most use was to also contain some RAM and ROM.

HEXIO needs a port for the keyboard (read) and 8 ports for the LEDs (write). Both were incompletely decoded, but software never made use of that and always used the lowest addresses, so the hardware could also decode them completely. HEXIO has a discrete display controller, relieving the CPU from having to multiplex LEDs, and also decodes the keypad, leaving only debouncing to the CPU. It was used with the monitor program Elbug.

NIBL was a tiny BASIC interpreter from the manufacturer National Semiconductor, which was released to run at address 0. The Elektor system already used that for Elbug, so Elektor modified NIBL to run at address 1000 hex and called that NIBL-E. The BASIC interpreter only used the serial console interface and no further IO.

That yields the final address map of the modular system:

0000-05ffElbug ROM
0600-06ffInterrupt Encoder / Multiplexer (unused)
0700-07ffHEXIO (0700-0707 display, 0708 keyboard)
0800-0bffunused
0c00-0fffRAM (Elbug uses 0fc9-0fff)
1000-1fffNIBL-E ROM
2000-????RAM

After the Elektor article series in 1980 the system was maintained further in the German book "SC/MP Microcomputer Handbuch", which replaced the serial console with a CRT card and a parallel ASCII keyboard interface along with a bunch other cards. I did not find any system of that kind at the web, probably because other CPUs pushed out the SC/MP from the market.

Reconstructing the Elektor system would be much work, but building a compatible system with just a single CPU card for the modular NDR Klein computer (NKC) is rather simple.

The CPUSCMP board

This CPU board is built around the SC/MP II CPU in a way that allows to run old software. Since the NKC bus origins in the Z80 world, it features separate memory and IO address spaces. By using a comparator for the upper address byte, the IO devices can be mapped to either run NIBL or Elbug/NIBL-E. The few programs for the RAMIO can be modified using a different address for the existing NKC board IOE.

Clock

The Elektor system used a crystal with RC combination connected to the CPU. The SC/MP II ran at 2 MHz for the original CPU card and at 4 MHz for the later one, because the memory used originally did not allow more. For compatibility, being able to switch between both speeds is desirable.

The CPU can also be clocked externally using XIN. The clock is symmetrically with a phase of at least 120 ns, although the data sheet shows an asymmetric clock. By dividing the clock, a jumper allows to select between full and half speed.

Reset

The Elektor system used a power on reset on the CPU board, but could be reset from the bus as well, which was used for a reset button on the HEXIO board. The NKC always drives the reset signal on the bus from the CPU board, which has power on reset and its own reset button as well as a jumper for an external button. The TLC7705 implements all that in a reliable fashion.

As described in the datasheet, the SC/MP takes quite some time to get out of reset:

Multiplexing of data and address bus

While /NADS is active, the CPU puts the address bits A12–A15 on D0-D3, which need to be latched at the falling edge until the rising edge. One way is an inverter and a half 74 573 latch.

An easier way is a 74 395 loadable shift register, which does not need an inverter and takes less space, because it is only 4 bit wide. Its primary function as shift register is not used.

Bus cycle

The IO access signal /IORQ is used through an address area of 256 bytes, which means the addresses must be decoded before /NRDS and /NWDS. That is done using the signal ADDRVALID, which signals a valid address on the bus. It begins with the rising edge of /NBREQ to enable the comparator that selects between memory and IO access.

The generated signals /NKC_IORQ and /NKC_MREQ are active before /NKC_RD and /NKC_WR, like for the CPU68008 board, which also uses memory mapped IO, but different to the CPUZ80 which creates both signals synchronously.

The bus cycle can be extended using /NKC_WAIT connected to /NHOLD (untested).

DMA

Besides fast io transfers, DMA is a convenient way to access the memory in a new system that has no firmware yet. Back then, front panels were popular. Today an Arduino is way more convenient.

The SC/MP offers bus arbitration for symmetric multi processing: /NBREQ is the bus request signal (open collector) and /NENIN with /NENOUT is the priority daisy chain. Changes to the daisy chain are always accepted immediatly and a running bus cycle is aborted and restarted later. A DMA controller acts as bus master like CPUs do. That is quite advanced, but typical peripheral controllers are not built for aborted bus cycles, so is made sure that started bus cycles are always finished before accepting a bus request using /NKC_BUSRQ by waiting until the address bus is no longer used. The bus release is then signaled using /NKC_BUSAK. There is no DMA daisy chain on the NKC.

Bus request when idle:

The bus request right before /NADS shows the CPU does not abort the cycle immediatly at this point, as described in the data sheet, but still fast enough:

Slightly earlier, it does abort the cycle immediatly, though:

Once the cycle begins, the bus is granted after the cycle finishes:

HALT

The SC/MP HALT instruction has an uncommon meaning: It only sets a buit in the status register, which is output during multiplexing the upper address bits. If it is desired to halt the CPU, external hardware has to accomplish that by disabling CONT. That forbids to handle interrupts without further hardware. Apart from that, any other semantics could be implemented using hardware, kind of like a CPU extension. Since the semantic is not portable, HALT is rarely, if ever used by existing software and the CPUSCMP board does not use it.

UARTs

Starting with the very first development kit from National Semiconductor, all systems implemented a half duplex software UART using FLAG-0/SENSE-B, which was used as console. FLAG-0 is inverted to allow a simple discrete level shifter on the NS kit and all subsequent systems followed that convention. Due to the CPU clock of 2 or 4 MHz, timing constants had to be changed for both CPU speed and baud rate. Originally 110 baud were used with 8N2.

A second half duplex software UART is implemented using SIN/SOUT.

Both UARTs use a MAX232 level shifter (ACPE for use with 100 nF) and the edge connectors have the same pinout as the SER serial interface of the NKC.

Speaker interface

The Elektor system had a transistor connected to FLAG-1, which drove a speaker. The fanout of the SC/MP is really low, which requires a Darlington transistor. The problem of that interface is that the speaker is only driven in one direction, which distorts the sound in addition to square wave signals. A push-pull with a third transistor in front avoids that, but good operating points need even more parts. In the end using a LM386 is much easier.

The input voltage is ±0.4 V using a voltage divider made for the SC/MP fanout.

The resistor of 50 kOhm in the LM386 in combination with 330 nF is a high pass with a border frequency of 9.6 Hz:

$$f_G = 1 / { 2 · π · R · C }$$

For possibly using PWM/PDM, a LC low pass with 68 µH and 1 µF limits the output to about 20 kHz with less loss than a RC combination:

$$f_G = 20 \text"kHz"$$ $$R_l = 8 \text"Ohm"$$ $$L = R_l / { 2 · π · f_G }$$ $$C = 1 / { ( 2 · π · f_G )^2 · L }$$

LED at FLAG-2

A LED can be helpful in debugging. Due to the low fanout a transistor is required to drive the LED.

The BC547 has hFE of 200 at IC, which allows to drive up to 20 mA IC using 0.1 mA IB. 0.1 mA already load the port output to VCC - 1 V. The base voltage for saturation is 0.7 V. The base series resistor is:

$${ 5.0 \text"V" - 1.0 \text"V" - 0.7 \text"V" } / 0.1 mA = 33 \text"kOhm"$$

The cut off voltage is 0.660 V, which is met by the SC/MP using 0.4 V. The LED current is limited with 1.5 kOhm, because a few mA suffice for being bright enough.

Interrupts

The interrupt is implemented using SENSE-A, but no software ever made use of it.

Schematics

>Kicad schematics and PCB

Architecture details of the SC/MP

The SC/MP has a classic architecture for its time: The memory is divided into pages of 4 KB. Although there is a 16 bit PC, only 12 bit are incremented. Besides the PC there are 3 more 16 bit wide pointer (address) registers.

There is no dedicated stack pointer, but there is an auto increment address mode for the pointer registers. Subroutine calls are done using branch-and-link by loading a pointer register and exchanging it with the PC. Nested calls need to save the pointer register with the return address. Local variables are addressed either PC-relative or through a pointer register, which points to either static working space or a stack frame.

The PC is incremented before fetching the opcode, not after decoding the instruction, which means execution starts at address 0. That's why diagnosis programs have a NOP as place holder at address 0 and branch targets are one address before the actual address.

BOM

I manufactured the PCB at JLCPCB using the provided Gerber files. It works, but the silk screen could be more helpful, because I did not export the part values. J4 and J5 are not in the order you may expect (console is right, not left).

>Gerber files
16x 100 nF ceramic 2.5 mm pitch
1x 330 nF ceramic 2.5 mm pitch
1x 1 uF/10 V electrolytic 3.5 mm pitch radial
1x 22 uF/10 V electrolytic 3.5 mm pitch radial
1x 200 uF/10 V electrolytic 3.5 mm pitch radial
1x LED green 3 mm
1x pin header angled 50p 2.54 mm pitch (Reichelt SL 1X36W 2,54)
1x pin header 2x8p straight 2.54 mm pitch
2x pin header 1x2p angled 2.54 mm pitch
2x pin header 1x5p angled 2.54 mm pitch
1x pin header 1x3p straight 2.54 mm pitch
1x 68 uH inductor radial 5.00 mm pitch
1x BC547 TO92
1x 82k axial 1/4 W
1x 5.6k axial 1/4 W
1x 33k axial 1/4 W
1x 1.5k axial 1/4 W
1x 22k axial 1/4 W
2x 10k array sip9 (Reichelt SIL 9-8 10K)
1x button 6 mm pitch
1x DIP40 socket
5x DIP20 socket
2x DIP16 socket
3x DIP14 socket
2x DIP8 socket
4x 74LS245 DIP
1x 74LS04 / 74HCT04 DIP
1x 74LS00 / 74HCT00 DIP
1x 74LS688 / 74HCT688 DIP
1x 74LS395 / 74HCT395 DIP
1x 74LS74 / 74HCT74 DIP
1x LM386 DIP
1x INS8060
1x MAX232 ACPE DIP
1x TL7705A DIP
1x 4 MHz crystal oscillator DIP14