My very first exploration of the 68000 family of processors involved designing a 68020 based computer consisting of 64KB of 16 bit wide EEPROM, 2MB of 32 bit wide SRAM and a quad UART. This board was called the MINI020, and in the end I did not get the PCB made up. I was not particularly happy with the PCB design, but mostly I was displeased with skipping over the earlier 68K family members. As it happened I also made a couple of errors on the schematic so the board wouldn’t have worked anyway.
But now I’ve made up two 68000-based computers, it is time to look again at the 68020. The features offered by this updated 68020 board has pretty much followed the outline given in the previous post:
- 68020 rated at 25MHz
- 68882 FPU coprocesor rated the same
- 1MB of 16 bit flash provided by 2 x SST39SF040 (PDF) in PLCC32
- A 32 bit 72 pin SIMM slot
- A SC16C654 (PDF) quad UART
- 2 RS232 ports on RJ45
- Keyboard on RJ11 allowing me to use the keyboard built for the MAXI000
- TTL debug header
- RTC using the DS1307Z (PDF) on an I2C bus
- Temperature sensor IC TCN75A (PDF) on I2C
- Board current and voltage sensor IC INA226 (PDF) on I2C
- PS/2 port for mouse and keyboard
- IDE interface
- 4 expansion slots
- Each with an isolated I2C bus
- 16 bit data, 24 bit address processor busses
- Interrupt, upper and lower decoded chip selects, wait and bus error signals
- Some kind of auto configuration
A single EPF10K20 (PDF) FPGA provides glue, and other logic:
- DRAM controller for the SIMM slot
- I2C controller for the onboard and expansion cards
- PS/2 controller
- Interrupt routing
- The usual buzzer and LED control
Some compromises have been made relative to the plans discussed in my previous blog post:
- There is no alternative bus master. There’s just not enough pins on an EPF10K20 in QFP144, and I didn’t want to make this a multi-FPGA board.
- The expansion connectors have 16 bits of data and 24 bits of address, and are only intended for peripherals, that is a controller on a card cannot become a bus master.
But on the up side I have included a 68882 maths coprocessor, which wasn’t originallyplanned. This should be interesting to play with.
I have switched the serial bussed peripherals to I2C from SPI. For example the RTC is on an I2C bus driven from the EPF10K20. I did this for two reasons.
Firstly to save pins on the FPGA. It would be useful to be able to have serial peripherals on expansion cards, for the retrieval of expansion card peripheral parameters so cards can be automatically detected. But using SPI requires one pin at the FPGA for the slave select pin per expansion slot, in addition to the clock and two data pins. In contrast with I2C the clock and single data pins can be shared across all devices. This saves 5 FPGA pins.
Secondly I’d like the challenge of implementing an I2C master in VHDL. I’ve not played with I2C in a few years and it would be an interesting learning experience. I can easily work on this with the MAXI000 board, a small piece of breadboard, and a peripheral IC like a real time clock.
The board’s name, suggested by Steve Moody, is MIDI020: it’s too big to be classed as a MINI, but lacks the features, especially multi-master, to be classed a MAXI. It should hopefully be the perfect jumping of point to a MAXI030.
Now onto a discussion of the schematic. Unlike previous projects, multiple schematic sheets have been used to keep the schematic neater.
The FPGA is attached to only 8 bits of the MPU databus due to the number of pins available. In general the FPGA is only accessed by the processor to do things like buzz the buzzer, or configure interrupt routing, so a wide bus is not required. The databus will also be used to operate the PS/2 and I2C controllers.
The address bits attached, from the 32 presented by the processor, are as follows:
- 0 to 7: these 8 bits will be used to select a local register, allowing 256 byte-wide registers to be defined, which is more then enough.
- 16 to 19: these are used to decode the operation it is in when it is running a CPU space bus cycle, which is used by both interrupt acknowledge cycles and coprocessor cycles (the FPGA selects the coprocessor in a similar way to any other device, but the FC 0 to 2 and A 16 to 19 are needed). Also to be used for peripheral IC decoding on the main board.
- 24 to 31: this is the top level. 32 bits of address allows the memory map to be very inefficient if we want to be and expansion slots will each get a 16MB slot. The bottom half (2GB) will be reserved for the SIMM slot with the top 16MB being reserved for the flash. Onboard devices, like the QUART and the FPGA itself will use a single slot, with A 16 to 19 being used to decode the actual device.
The system memory map, looking at the top byte, will therefore be as follows:
0x00 to 07f: SIMM slot
0x80: expansion slot 0
0x81: expansion slot 1
0x82: expansion slot 2
0x83: expansion slot 3
0x84: onboard peripherals
There is also a push button attached to an FPGA pin. The intention of this button is to assert an NMI condition, but in theory the button could be used for other things.
The rest of the FPGA connections are pretty self explanatory and break down into processor connections, memory and peripheral chip selects, expansion slot control, interrupt lines, SIMM control, the PS/2 port and the I2C bus.
The system clock is generated by a 50MHz can, which is the fastest clock I’ve used so far. The processor will be run at half this clock rate. This will allow me to experiment with running the DRAM controller state machine at 50MHz, which may or may not be too fast for the SIMM to handle.
As there is only one FPGA in this board it doesn’t really need a name, but where one is required in the names of signals I’ve called it Core.
Next up is the QUART, of which there is next to nothing to say about. Except that thanks to the dynamic bus sizing present on the 68020 the byte wide address of a register on the QUART can be addressed at consecutive bytes instead of at odd or even addresses as per the 68000.
I did actually consider using an alternative UART just to play with something new, but as I still have a couple of unused SC16C654 I decided to stick with this IC. Probably the next board will use another part for its UART functionality.
The MPU then. This sheet includes the FPU as well, the connections between them being relatively straight forward and essentially identical to a peripheral IC. It’s attached to the full 32 bits of databus, 4 bits of the address bus, the standard asynchronous bus control lines, a chip select and a hardwired size selector which is used to instruct the coprocessor that the databus connection to the MPU is 32 bits wide, since it is, somewhat strangely, possible to use the 68882 in both 8 and 16 bit wide 68000-family systems. The final FPU specific pin is labelled /SENSE and is used to let the processor know that an FPU is installed in the system. The pin is merely wired to ground inside the part so a low value at the socket pin indicates the presence of an FPU, whilst a high (the pin is pulled up) indicates the absence. This state can be read back via a register presented by the FPGA. The purpose of this is so floating point functions could be implemented as a 68000 library when an FPU isn’t available. Its not really necessary in a one off board like MIDI020 but as I had a spare FPGA pin I thought I might as well add it.
Note that unlike the 68000 (PDF), /HALT does not need to be asserted at power on.
Most of the 68020 control pins are attached to the FPGA. This includes pins that are not essential, in this application, to the operation of the processor. The purpose of this is experimentation.
The three pins related to bus mastering are not connected to the FPGA as this is not, unfortunately, a multi-master board (unlike MAXI000). Lastly the pin to inhibit the instruction cache present in the 68020 is attached to a jumper.
The IDE interface is essentially unchanged relative to the MAXI000.
The main differences in the SIMM schematic relate to the fact the memory is now 32 bits wide, with 4 74HC245 (PDF) octal bus transceivers being needed. Also each of the 12 address pins on the slot is connected to a MUX output. The seemingly random numbering of the address pins on the MUXes facilitates board routing. The largest SIMM I have to hand is a 32MB part, and it will be interesting to see if it can all be accessed using this wiring.
The wiring on the flashes is entirely unexciting. Note that the flashes will only be 16 bits wide, which means that even if they can operate without wait states (it’s not known at present if that is the case, but it seems very unlikely with a 25MHz processor) they will not operate as fast as they would if they presented 32 bits of data per access.
The main board contains four I2C peripherals:
- RTC using the DS1307Z (PDF): This RTC IC is one I used back in 2013 when I first played with I2C. The square wave output is fed back to the FPGA. It uses address 0x68.
- Temperature sensor IC TCN75A (PDF): This is a simple board temperature sensor presenting on address 0x4f. It is possible to configure a threshold temperature, above which an alarm signal is generated, which is fed back to the FPGA.
- Current and voltage sensor IC INA226 (PDF): On address 0x45 this is a sensor that should be able to return the current used by the board. A sense resistor is employed, and by measuring the voltage across it is is possible to calculate the current passing through it, which is the total current on the 5V supply line.
- A PCA9544 (PDF) 4 channel bus interface: This is on address 0x70 and presents the four expansion cards’ own I2C bus to the main board bus. In essence the master address is used to select which channel (expansion) card should be routed through via a register. Note that the interrupt capabilities of this part are not utilised. This is useful for propagating alarm signals etc. This was mostly because this part was added after the board was fully routed.
The main board contains pullups for the local I2C bus, but cards themselves must include their own pullups. This was to both to save space on the main board and because it seemed more logical.
The expansion connectors is where things get, perhaps, the most interesting relative to my previous projects.
There are many ways to design an expansion bus for a 68000-basd system. There is at least one standard 68000-derived bus available, the VMEBus. Instead of using an existing system, the approach I’ve taken is that it should be possible to make a simple single peripheral card without adding extra glue logic. An alternative approach, which VMEBus roughly follows, is that the bus merely provides the raw processor signals and address decoding and other glue functions must be done on the card. This allows a great deal of flexibility at the added cost of glue logic on each and every expansion card.
Four slots will be provided. DIN 41612 connectors will be used. After attempting to route PCI (and PCIe) connectors I concluded that the connectors are not really suitable for boards with only two signal layers. The DIN 41612 is available with either two or three rows of 32 100 mil spaced pins. For this board two rows is sufficient.
The signals provided by the connector are as follows:
- Power (5V) and ground
- D0 to D15: 16 bits of databus
- A0 to A23: 24 bits of address bus, allowing a 16MB memory space
- /UCS and /LCS: upper and lower chip selects for this card. These will be generated by the FPGA for the card’s address, gated with the upper and lower data strobes as determined internally by the A0, A1, SIZ0 and SIZ1 pins
- /AS and /DS: if /UCS and /LCS do not gate these signals when address decoding it can be done on the card. Probably not required by a card but included for diagnostics
- /READ and /WRITE: as well as the processor’s R/\W
- MASTERCLK and MPUCLK: Master clock and the processor clock
- /RESET: system reset
- /INT: asserted by the card to generate an interrupt, the FPGA has a pin per card to determine which card generated the interrupt.
- /BERR: asserted by the card to generate a bus error. One FPGA pin is used with a simple external logic gate to combine them.
- /WAIT: used by the card to generate wait states.
- SCK and SDA: the per card I2C bus. The main board uses a 4 channel I2C bus interface which is attached to each expansion card, giving it a private I2C bus.
- /IACK: Interrupt acknowledge cycle in progress. This is used by some 68000-friendly peripheral ICs to emit an interrupt vector number. Glue logic on the card will e required to decode the interrupt number.
One idea I’m exploring is to make the card integration with the system dynamic in that the address decoding and interrupt routing required is published on an I2C EEPROM and then configured by the processor writing into FPGA registers. The ROM could contain a card type field, a data width field (so the FPGA knows what /DSACKx value to assert) as well as whether an interrupt level is required. The processor would configure the base address for the card from a list of free slots. The idea of this is to allow the system to operate with cards removed without changing the FPGA design and to allow cards to be moved between slots freely. Probing would be accomplished by looking for the configuration ROM on each card at a fixed I2C address on each of the 4 I2C channels used by expansion cards.
Next the expansion buffers. Pretty much all of the MPU and FPGA signals are buffered. In truth this is probably a good example of over-engineering. As I found out, they complicate board routing as well.
The /BERR (bus error) and /WAIT (wait state) are logically combined outside of the FPGA to save pins.
The “Other IO” sheet contains just the PS/2 connector. Nothing exciting here. As before both channels possible on a single PS/2 port are utilised allowing a keyboard and mouse to be hooked up at the same time on one connector via a splitter cable.
The power section is trivial: as usual for my projects, a 5V potting switching regulator, a SR05S05 (PDF) is used to generate the 5V line. Because I am a little worried about total power requirements (the SR05S05 is only rated for 1A) a harddisk Molex connector is also available. I may not even solder this up, it depends on the current draw observed.
This sheet also contains a link (Vin+) to the current and voltage sensor I2C peripheral pin; the 5V rail is the other side of the resistor shunt which the sensor uses to determine the power usage of the board.
After the schematic was designed, the next step was PCB routing.
This was a lengthy process, though I saved a little time by reusing some PCB trace designs from the previous MAXI000 board. I’m not 100% pleased with the result, but it is adequate:
As expected, there are a fair few instances of 3 traces running between 100mil pins. But perhaps the biggest area which needs improvement is the large open space required at the bottom of the board, where the 32 bit bus runs to the SIMM connector. But as this is my first proper 32 bit board, I’m not going to beat myself up over it too much.
The use of buffers on the external connectors (SIMM slot, IDE header and expansion connectors) also greatly contributed to the work and space required to route the board. Future boards may limit this to only the expansion connectors.
As per the MAXI000, this is a 4 layer board using internal power planes.
The obligatory 3D view:
Steve Moody found me some models and other then the 68020 processor itself this 3D view is complete, though some models lack colour details.
I have so far completed the design of two expansion cards.
First up, a test card.
This card contains headers for attaching the logic analyser to all the expansion bus pins, as well as two 512KB 8 bit SRAMs (IS61C5128AL (PDF)). The purpose of the SRAM is to allow the MIDI020 board to be brought up without the SIMM slot being operable.
Here is the, somewhat trivial, schematic:
The board design is not very interesting, but here is the 3D render:
To reduce construction costs, the board is a 2 layer one.
The second expansion card is more interesting. It has the following functionality:
- Two 9 pin Atari-style joysticks presented via 74HC574 (PDF) 8 bit latches
- An MCP3428 (PDF) 4 input ADC on I2C allows simple X/Y analogue joysticks to be used via the same 9 pin connector
- A 25 pin Centronics printer port via a MC68230 (PDF) Parallel Interface/Timer
- 10 Mbit/s Ethernet on RJ45 via a Realtek RTL8019AS (PDF)
This is another multi-sheet schematic:
First up, the top level sheet with the expansion connector, configuration EEPROM and some glue logic. Glue logic is required to decode the peripheral selected by the processor (one of the two joysticks, the parallel port, or the Ethernet controller), and to generate the out-going interrupt signal, which can be generated either from the MC68230 or the RTL8019AS. The address decoding uses A16 and A17 to determine the peripheral IC on the card.
The joystick portion is pretty simple. As usual, 74HC574 addressable latches are used for the digital side, with the analogue side being handled by the single MCP3428 4 channel ADC. For this computer, if I ever get around to attaching an analogue joystick, I will be building my own, as I did with MAXI09. Unfortunately the joystick I build previously broke so I will have to build a new one.
The parallel port schematic is mostly derived from the published Motorola Application Note AN-854 (PDF) on this topic. A unidirectional buffer is used for the data lines only. The actual DB25 is on a header to keep the board size down.
Perhaps the most interesting component on this board is an Ethernet controller. This will be a new one for my home-built computers: a real Ethernet connection.
The RTL8019AS was a popular part in the early 90s and was included on many PC ISA network cards. Though it was aimed squarely at the PC market, it can be targeted at other platforms, including 68000-based systems and even 8 bit microcontrollers.
The schematic is derived from various sources including the part’s datasheet and some other projects. Like the IDE interface the databus is byte-swapped. The RJ45 connector itself is one with integrated magnetics and LEDs. There is also an external configuration ROM, an AT93C64 (PDF) 8 KByte SPI memory, which the Realtek part uses for its configuration data including the MAC address, etc. Because of some “traditionally” active low signals being active high, single gate inverters are used.
This is a four layer board. It was fairly easy to route, until I realised that the connectors were on the wrong side of the board, and would have faced inwards instead of towards the top edge of the MIDI020 board when the card was inserted in the expansion connector! Another couple of hours work was required to remedy that problem.
The required 3D view:
For diagnostics, I’ve added test points to the Ethernet signal lines. Hopefully I’ll be able to capture some interesting traces.
I’m yet to order these boards for manufacture; they require a final check over. In the last few days I’ve placed an order with mouser.com for the outstanding parts I need to build these 3 boards, and have collected up the parts I currently have on hand. The order also contains the parts I need to build an FPGA-based graphics card, but I wont start on the schematic and board layout for that until I’m certain the MIDI020 board is working well.
While I’m waiting for various things to arrive in the post I also plan to start work on the I2C controller. That should be an interesting project in its own right…