An S-100 80386 CPU Board.
I am only
aware of one commercial S-100 80386 CPU board. It was advertised by Macrotech in 1998.
Few (if any) of these boards were ever produced because the company folded
at about that time. I have no further information about it. No
schematic was ever published, worse the board had almost a dozen PALS of
This was unfortunate because the 80386 for a number of years represented the
apex of microprocessor development for Intel and indeed for microprocessors
in general. It is still to this day a very popular CPU in stand alone
powerful dedicated systems. The 80386 is a true 32 bit CPU with 4GB
RAM addressing capability and tremendous protected and paging mode power.
Yet at the same time upon a hardware reset it starts off in an 8086 like
I have for a long time dreamed of having my own 80386 S-100 computer where I
had complete knowledge and control of all the hardware and could bring up not
only MSDOS, windows but Linux or my own software starting with my own EPROM
BIOS. Spurred on by our success with
68000 CPU S-100 boards, I felt the time was now right to tackle an 80386 S100
Shoehorning a powerful chip like the 80386 into the S100 bus has a number of
unique challenges. First, many of the CPU status and control signals of
the earlier Intel CPU's now have quite different timing parameters (or are simply
absent). These will have to be synthesized to work with standard S-100 IEEE
like boards. Second the sheer number of address and data lines
required to interface the chip taxes the real estate available on an S-100
CPU board. However the biggest challenge is the fact that the 4GB of
RAM that the CPU can address can be up to 32 bits wide. The S-100
bus itself is only an 8 or 16 bit wide data bus. Fortunately the 80386 has a
special pin (BS16*,C14) that will force the CPU to talk to the data bus only in 16
bit wide data bits at a time. 32 bits of data is sent/received sequentially
as two back to back 16 bit packages. A further limitation is the fact
the S100 bus has only 24 address lines limiting its RAM capacity to 16 MB.
While decent for early DOS like programs, is far below the capacity of the
To cut a long story short, I decided to utilize the S-100 bus for "low"
RAM addressing with 16 bit capability but to have a 32 bit data and address
bus ribbon cable at the top of the board connecting the CPU to one or more
"daughter" boards. These boards would sit in S-100 bus slots for power
and a few other signals but would communicate directly (and only) with the 89386
pins. All 80386 I/O and interrupt signals go through the S-100 bus to
the other S100 boards as does 80386 RAM/PROM access to (a switch
configurable) amount or low RAM. All other 80386 RAM access is via the
special "over the top" ribbon cable bus to one or more daughter boards.
One nice thing about the AMD 80386 CPU's is the fact that the clock speed
can be varied (all the way from 0 to their max rate). This BTW is not
the case for the Intel chips. The second trick I use is to
have a different CPU clock speed if the S-100 bus is being utilized
(currently 12 MHz) and a much faster clock speed for the daughter RAM
board(s). These we will run at the maximum CPU clock speed, 33MHz
currently. Since the 80386 will spend most of its time in high RAM it
will be able to run code very fast.
Finally because Gigabytes or DRAM these days are so common and cheap, and
far exceed the capacity of static RAM chips, it makes sense to stock the
daughter board with common DRAM SIMMS and use a dedicated DRAM refresh
controller to maintain them.
All this sounds simple and great in theory. Putting it into practice is
another thing. I decided to tackle this program in
Build and debug Master/Slave S-100 80386 CPU board such that it is completely
self-contained and can run MS-DOS in the system on the S-100 bus.
Build a ribbon cable connected S100 daughter RAM board utilizing very high
capacity static RAM chips (16M chips).
Build the same type of board utilizing very high capacity DRAM SIMMS
The first two stages are now complete (see below). I have not yet
tackled making a DRAM board for this CPU board. I will do so when we
get the equivalent board done since they will use the same interface.
The First S-100 Bus 80386 Prototype Board
below shows our first prototype board. Extra chips ware added to the board
to allow considerable experimentation to get the board to work in the
S100 bus along with the many other boards available.
The top connector pins to hook up the daughter board cable is not yet
implemented. The original 80386 schematic for this board can be
here. Before discussing the board in detail it might be useful to
review the 80386 pins in detail.
The address lines of the 80386 (all 32 of them) are fairly standard there are just more of
them. Unlike the later 80486, they have limited drive capacity and
except for small dedicated systems need drivers. Since we will be
driving potentially up to 20 other cards in the S100 bus and one or more
daughter RAM boards, we will clearly need 74LS244's or 74F244's.
Because the 80386 can address bytes (8 bits), words (16 bits), or double
words (32 bits) there is no address line A0 and A1. Instead there are 4
"Bank Enable", lines BE0*-BE3* that select byte word or double word
memory access. I'm assuming that you understand this concept if you
are reading about a CPU of this complexity. If not there are countless
descriptions/illustrations on the web. While on this topic, if you
will be interested in later building a board like this you should get one of
Barry Brey's "The Intel Microprocessors" books. There are many editions,
the later the better. I have the 7th edition.
Another essential reference is the Intel 80386 hardware manual. It can be
As in the case of the earlier 8086 and 80286 CPUs (which had only one "BHE"
line (and A0)) , we will need to generate address lines A0 and A1 for the
S-100 bus. Intel suggested the following circuit:-
We have two other requirements. We will need circuitry to determine if
the 80386 is addressing RAM due for S-100 bus access or daughter board
access. We use our well tried 74LS682
circuit to determine if the current address is above a certain value (set
with a switch). If it is the 80386 essentially ignores this board and the
S-100 bus RAM and communicates directly with the daughter board .
Normally the trigger point would be at the 1 M or 16 M boundary (FFFFFH or
FFFFFFH). This correspond to the top of an 8086 address space or the limit
of the S-100 bus itself.
Here is a schematic for this circuit:-
The all important S100_SEL signal directs all access traffic on the board.
It also adjusts the CPUs clock speed. It's very important this signal
is clean and fast.
The second "complication" we have on the address lines is something we first
utilized on the 80286 board. The 80386 always starts at
FFFFFFF0H upon reset. This is at the
very top of the CPU's 4 GB memory address space. In contrast, the
8086 starts at 0FFFF0H (at the top of its 1 MB address space). It's
usually convenient to write one BIOS/Monitor for both CPU's. We play a
trick on the 80386 in that whenever its top 12 address lines are all high
(only at the top 64K of the 4GB address space), these 12 address lines in
hardware show up as all low on the S-100 bus. Thereby an 8086 BIOS/monitor
ROM can be utilized. A two line to one line converter (U95,U7 &
U8, 74LS157s) are used to accomplish this in the following circuit:-
With K11 jumpered 2-3, when pin 1 of each 74LS157 is low (Address lines A20
-A31 are all high to U6) the "a" inputs (GND) are passed through to the "Z'
outputs. When pin 1 is high the normal 80386 lines are passed through
to the "Z' outputs. BTW, this also conveniently gets around the
16 MB address space limitation
of the S-100 bus.
This is where things start to
get complicated. Data to/from the 80386 can be up to 32 bits wide. However
it can also be 16 or 8 bits wide and unlike the 68000, can start on
any 8 bit
memory boundary. Address lines are numbered A2 - A32 with
special lines (called BHE0, BHE1, BHE2 & BHE3) to select 8, 16 or 32 bit
access to RAM. This is like the BHE/A0 lines of the 8086 for high and low bytes
of a 16 bit access except this time there are 4 possibilities. Now the
challenge here is to convert these signals into an S100 SXREQ* signal and
generate A0, and A1 and deliver the data to the appropriate RAM location.
The circuit described above generates these signals.
Again these lines need to be clean and fast. The good news is they are not needed
for the RAM daughter board. That board can talk to the 80386 directly.
The actual circuit we use to deliver the 8 or 16 bit data to the S100 bus
is, the by now, well worked out (see the
80286 boards). It has
proven to be a reliable circuit. Here is the circuit used on this 80386
It turns out that it is important that U78 is a 74LS244 (and not a faster
The Control Signals
The control signals of the 80386 are quite different from the earlier Intel CPU's.
While intrinsically far simpler, we have to emulate those of the S-100 bus.
The trick is to utilize ADS* as the start signal for each bus cycle.
We latch the CPU M/IO, R/W, C/D signals with a 74LS75 with ADS and
then decode them with a 74LS138. Each of the output pins of the 74LS138
contains a single control signal. These are combined to generate the
appropriate S-100 signals. The following circuit does the job:-
The only difficulty with the above circuit for the S-100 Bus is that the pWR* signal comes
up too early and stays too long. On some S-100 bus RAM cards the address lines
yet "settled" or it hangs around after the RAM memory select
address is valid. After trying a number of things I found the most
reliable way to correct this problem was to synthesize our own pWR*
signal one clock cycle later and end it before the address lines changed
with the following circuit.
This turned out to be very reliable and is largely clock speed independent. Allowing
for a 24MHz 80386 CLK2 clock and a 12 MHz S-100 master clock.
Much to my relief the interrupt INTA signal worked reliably without any
modifications using an 8259A Interrupt controller on our
MS-DOS Support board.
The board modified to conform to the above circuitry has proven itself quite
reliable using five I/O wait states for both RAM and I/O and INTA cycles on
the S-100 bus at the above speeds. I hope minimally to be able to run
the future DRAM daughter board(s) at these speeds with no wait states.
Second 80386 CPU Board
Learning form the first above prototype board we made a second prototype
board. Here is a picture of this board. The schematic can be seen
Many of the jumpers
present on the first board were removed. They were there to "try out"
various circuit arrangements but are now no longer needed. The basic core
control circuits still remain as shown above. As I experimented with the
board it was quite clear that the key signal still remains the pWR* on the
S-100 bus. I tried delaying, speeding up and extending the signal but in
every case the circuit shown above seemed to work best. This is
frustrating because I still feel the signal is too short, bring the board
down to this lowest common denominator.
Nevertheless the board works very reliable in a 10 slot S100 system with a
clock (CLK2) of 24MHz and a bus clock of 12MHz. In my larger 21
slot system I can not get it to this speed. It is however 100% reliable with
a 20MHz clock. (The next lowest oscillator I currently have. I have ordered
22MHz oscillators). In both case only one Memory and I/O wait
state was needed.
One reason for the second prototype board was to see if we could fit
connections to the daughter board connector. It's crowded but we could
Third 80386 CPU Board
Learning form the first and second above prototype boards we made a third prototype
board. Here is a picture of that board.
The schematic can be seen
This board worked fine with up to 16 MB of RAM in the S-100 bus with a
32 MHz CPU clock input (3 I/O & PROM wait states).
However when I connected
up the static RAM daughter board via the top connectors/ribbon cable, there
were problems switching the clock speed from 8 to 32 MHz when one started
accessing the static RAM on the daughter board. See
8MB Static RAM Board and
32MB Static RAM Board for more information about these boards.
The Final Pre-Production Run 80386 CPU Board
The problem of switching the CPU clock frequency when accessing the
daughter RAM boards was fixed by adding a circuit to make sure "runt" CPU clock cycles did not occur
when the CPU clock frequency was changed.
Learning form the above three prototype boards (and two prototype RAM
boards), we made a fourth prototype
board. Below is a picture of that board. The schematic can be seen
The board fine tunes and corrects some minor errors in the previous boards.
It now looks like a remarkable simple and clear interface to the S-100 bus.
Simpler in fact than our previous 8086 or 80286 boards. The 80386 does not
require a separate bus controller of clock generator for example. Also
the control signals are consistent and simple.
Note in all cases I have used the AMD 80386 CPU chips. I chose these
because the clock in the AMD can actually be reduced to 0 and restarted. The
ability to change the clock frequency "on the fly" is important here because
the clock speed for RAM and I/O access to the S-100 bus is dynamically
halved to that of the RAM on the daughter board. The original Intel
CPU had a minimum clock frequency requirement. I have not tested the
ability to change its frequencies in mid stream. AMD CPU's are common so
this should not be a problem.
I have not really checked this board out with a wide range of old S-100 bus
RAM boards. As best I can tell it should run with any IEEE-696 that
has 16 bit R/W capability. It works fine for example with the
Godbout 128K static RAM and
BG Computers 256K Static RAM boards. It will not work with 8 bit
only RAM boards and I doubt with older S-100 bus DRAM boards. I really
recommend the board be run with our fast
4MB Static RAM board.
With the 80386, the timing of the address lines and status outputs can be
controlled so the outputs become valid before the end of the previous bus
cycle. This technique allows bus cycles to be overlapped and is called "Pipelining".
Address pipelining increases bus throughput without decreasing allowable
memory (or I/O) access times. Pipelining is controlled by the
status of the CPU NA pin. High = pipelining off, Low = pipelining on
(Jumper K2 on this board). Because pipelining is turned off for 16 bit
data access/conversions it will be ignored for S-100 bus access.
However for our extended memory boards it can be utilized and makes a real
difference. BTW, I find it best to turn off pipelining if you are
testing memory boards in an extender card connected to the CPU board in the
bus with two 8" ribbon cables. For the normal 1" connectors it is
In order to really utilized the full power of this CPU you need more memory.
This is a work in progress. Currently we now have two prototype Static RAM
8MB Static RAM and
32MB Static RAM for a full description of the 80386 daughter RAM boards to use
with the above CPU board. Later I hope to build a very high
capacity DRAM board. To run this board with MSDOS and our
MSDOS-Support Board its
essential that U6 on that board be a 74F244, otherwise you will get false
Using a Cyrix 80486 CPU.
The 80486DLC was Cyrix's first serious entry into the mainstream X86 market,
and made possible many people's first taste of 486 performance.
It was introduced in 1992 and was 100% pin compatible with the Intel/AMD
80386. The 486DLC can be described as a 386DX with the 486 instruction
set and 1 KB of on-board L1 cache. It does not have a math coprocessor
however. I managed to obtain off eBay a 33MH version and popped
it on the board. I found that the board could not attain the
32MHz of the AMD 80386-40 chip but worked fine at 27MHz (the next lowest
oscillator I happen to have). Interestingly however even at 27MHz
it ran MSDOS software about 10% faster than the 80386 chip at 32MHz.
I later switched to a 40MHz rated Cyrix chip. Whit this chip I could achieve
a 40 MHz Oscillator/speed.
Here is a picture of the board with the 80486DLC chip:-
Changing the CPU Clock Circuit.
It became quite clear that the clock circuit is critical to
obtain a reliable board at high speeds. Unfortunately setting an input
clock frequency for an 80386 is complicated. First the 80386 requires its
"CLK2" input signal to the CPU be exactly 2X the speed the basic bus clock
signal. Almost no slew/delay between the two clocks can be
tolerated. Both of these signals (typically used in extended
RAM/Protected mode), are several times the maximum frequency the S-100 bus
can tolerate. The latter typically being 10-12MHz. Now it would be
nice if we could have a separate clock/oscillator for the S-100 bus Phi
signal, so when the 80386 uses the S-100 bus it switches over its CLK2
signal to that clock. The problem with such an arrangement is
that because the clocks are not synchronized, "runt" clock signals can occur
depending on the time clock switching takes place. I spent
quite a bit of time utilizing circuits that allowed clock switching without
shortened/runt cycles. I could not get one that acted reliably.
In the end I decided to work from a single board clock signal and divide it
down as needed. This places some restrictions on what frequencies are
optimal. In particular you have to determine if you want an optimum speed
for S-100 access or extended RAM/Protected Mode access. Again, after
trying a number of circuits I decided on the 74HCT93 chip. This chip
contains a divide by 2 and 8 series of FF's. It is somewhat flexible
and also is pin compatible wit a few other signal divider chips. Note the
74HCTxx choice, the 74LSxx chips are quoted for speeds only up to
30MHz, the 74HTC93 can get to at least 50Mhz. (I could not find 74S, 74F or
even 74ALS varieties of this chip). A single chip with jumpers contains the
circuit nicely. See here:-
I tested this arrangement using a "dead bug" upside down chip patch to make
sure the circuit was reliable. It was, I could get to
using a 40MHz oscillator with both the 80386 and Cyrix 80486 CPU's.
Here is a picture of the modified board:-
The Final (V6) 80386 Prototype Board
The above clock circuit seemed to be reliable so a final prototype board was
built with this circuit. Here is a picture of that board:-
The board works reliably in my 21 slot S100 Bus system with a 36 MHz
Oscillator. This corresponds to a 9MHz S100 Phi clock and is
probably the maximum speed one can expect on a large bus like this.
For this speed, for reliable operation, (MSDOS etc.), I use four S100
bus RAM wait states and one S100 bus I/O wait states (jumpers P2 and
p11). I suspect the MSDOS board ROMs are the bottleneck -- I have not yet
played around with jumpers on that board yet.
For optimum reliability I always place the MSDOS Support and S100 Bus RAM
boards each side of the 80386/daughter RAM board.
Remember for RAM above 16MB the overhead bus (daughter RAM board) runs at the full
36 MHz (and in pipeline mode). The 80386 monitor has a command a simple
test routine (the "Y" command), that continuously reads the
SMB IOBYTE port and
outputs the corresponding ASCII character on the console (the Propeller
driven Console IO
board). This is the acid test for this hardware because the 80386
is continuously switching between S100 bus 8/16 bit access and the overhead
32 bit wide RAM access in pipeline mode. The former at 9MHz and the latter
at 36MHz, the routine is in a RAM location above the S100 buses 16M range.
There are a number of other tests within the current version of the 80386
monitor (V1.46). In particular the "J" command tests RAM (in
particular RAM above the 16MB range) extensively to make sure values do not
change over time or with writes to other locations. This test takes
time "hours" for a 32MB board and is best run overnight.
Here is a picture with the test in progress:-
Here is a short video demonstrating this double level master, slave, slave process
using the prototype version of this board:-
Running the 80386 Board in a
Multiprocessor S-100 Environment.
This S-100 80386 board (like our
80286 board) can be configured for the S-100 bus is a number of
different configurations of increasing complexity.
Let me first caution you that some of the above configurations are somewhat
complex. Not only in terms of hardware but also in terms of software.
Particularly if the system is utilizing interrupts. I would recommend the
"slave of a slave" configuration below only to seasoned individuals.
The 80386 CPU is the Bus Master Calling a
Up until now we have been using this board as an S-100 bus slave. Typically a Z80 CPU would control the bus until this board is activate by inputting from port EDH
(or with our V2 SMB
outputting to port EEH). We will now convert the board to a true bus master where it initializes on power on/reset. It's simple, just a few jumpers need to be changed.
First remove the current bus master (typically a Z80 board).
We then need to implement the boards Reset, Slave Reset and Power On Clear circuits IF these signals are not generated elsewhere on the S-100 bus.
add jumpers JP4, JP5 and JP6 and jumper K1 2-3.
Jumper JP17, JP19, JP20 & JP 21
Jumper K9 2-3 & 3-5
Jumper K10 2-3 & 3-5
Jumper K3 1-2
Jumper P57 1-3
(Bottom row horz.)
Jumper K9 2-4 and K10 2-4.
Insert the board in the bus. Power on, and/or hit the reset button, the monitor should come right up.
It is important to understand how the IEEE-696 protocol handles multiple
CPU's (or DMA controllers) on the S-100 bus. In a system with
one bus master and a second (slave) controller the slave device can request
access to the bus by lowering its S-100 HOLD* line (pin 74).
In this situation after a reset and prior to this request, the slave
controller is not visible on the bus. Its address, data, status and control
lines are all tri-stated (inactive). When the master CPU is ready to
release the bus, (and only then), it will return back an acknowledge that it
will do so by raising the S-100 HLDA line (pin 26). Then timed by the
bus master clock Phi signal (pin 24), the master controller will go through
two S-100 special clock cycles XFERI and XFREII. In the XFERI
phase, the master controller disables its address, status and data lines. At
the same time the slave activates its control
lines. For a brief moment (one Phi clock cycle), both the master and
slave controllers are driving the S-100 bus control lines (pSync, pWR*,
pDBIN an pSTVAL*). That is why BTW, on CPU boards these lines have a
10 ohm resistor to the bus so as not to overload the bus drivers.
Next, for the XFERII phase, the master controller releases its control lines
and the slave activates its address, status and data lines. This whole
process happens very fast. However it is a very ordered process with no
lines left temporally hanging in the process.
When the slave controller is done, it hands controller back to the bus
master in exactly a reverse of the above process.
Here is the relevant section of our 80386 board that carries out the above
process (The 80386 is assumed to be the bus master in this case).
The HOLD* is lowered by the external requesting slave controller. This
is clocked high into the 80386 via U98A, pin 6 and U71.
When the 80386 is ready, it returns HOLDA high
into U63B pin 3. This is returned to the S-100 bus via U79D (pHLDA*) low.
U63B pin 4 is clocked out of U97B pin 8 (high), which goes to the board
XFERII line (K10, pin 4), raising it, (thereby inactivating the 80386
address+data+status lines). This same signal is clocked into U97A pin
2, and its output goes to the board XFERI line (K9 pin1). This
inactivates the 80386 control lines (to U55).
On the corresponding slave controller (not shown here), during the XFERI
phase its S-100 control lines are activated.
During XFERII its remaining address+data+status lines are activated.
What is a bit confusing is the XFERI & XFERII terminology for the master and
slave is the same, but the order of the address+data+status lines and
control lines activation/inactivation is different. At a mid-point in
the process however both boards are briefly driving the S-100 control lines.
This way no unexpected "glitches" occur.
Another CPU is the Bus Master Calling
our 80386 Slave Controller
This is the normal case for this board. Typically one boots up the S100
system with a Z80 CPU board.
That board is designated the bus master.
For the case where another board is controlling the bus after reset, and our
80386 (as a slave) requests temporary control of the bus the process is different and the board circuit below is
We activate the slave board by lowering any one of the four S-100 DMA lines
(DMA0*, DMA1*, DMA2* or DMA3*). The board actually has an S100 I/O
port (EDH or DDH) that also allows you to do this directly simply by
inputting from this port. In any event the input to pin 1 of
U50A goes low. This is clocked by U53A which lowers the S-100
HOLD* bus line (pin 74). This signals to the bus master (usually a
Z80) that it wants control of the bus. At the same time via
jumper K9-3, the XFERI line is lowered, activating the boards control lines
to U55. As described above meanwhile, the bus master is inactivating
its adderss+data+status lines. One clock cycle later, via
U53B the 80386 boards own adderss+data+status lines are activated. One clock
cycle later via U57A and U59A the reset line to the 80386 CPU is released
allowing the CPU to control the bus.
Note that while we call the second CPU above the slave or temporary
controller, there is nothing temporary or short time about it. Once transfer
is given to the slave controller (the 80386 in our case) it has control of
the bus as long as it wants. All day if necessary!
Transfer is given back to the bus master by inputting again from the same
port reversing exactly the sequence of events described above.
While probably not needed, in theory the S-100 bus could have up to 15
possible slave controllers, indeed more, if onboard port activations are
used. Thinking ahead with long term multi-board layout plans I have
decided that I will always assign DMA0* to the
80386 family of CPU boards (using one
in the bus at a time). Likewise I have assigned the DMA1* line
for the 68000, 68010
and any future Motorola CPU's. This leaves the DMA2* and DMA3*. This
in the future, in combinations, would allow up to four other slave
controllers on the bus. I will be doing a DMA controller board
in the future that will utilize these lines. Note however that because
our boards also have an "activation" ports on board there is no limit to
number of slave controllers in the bus. For example while our
6502 CPU slave board
could be activated by lowering DMA2*, it can also be activated via its own
I should point out the IEEE-696 specification actually goes further than
this. It allows the 1+15 Controllers to on the fly, prioritize
which one has the bus at any one time by giving each board a priority number
(4 bits, via a switch). See page 258 of the Sol Libes and Mark Garetz
book Interfacing to the S100 Bus for example. The problem
with this approach is the software overhead becomes very complex. Minimally
you would have to have a general circuit to read the status of the DMA lines
as well as a number of processor specific routines to handle randomly
striking interrupts etc.
With the approach I have here things are somewhat less complicated because
the port calling program always knows the status of the CPU/DMA controller
it is working with.
Another CPU is the Bus Master Calling
our 80386 Slave Controller which calls a further slave/DMA board
An extension of the above case where
our slave 80386 board (already in control) has a request from another
controller for (temporary) control of the bus.
There are two ways to handle such a situation. In the IEEE-696 mode you
would give the new controller a higher DMA priority number, this would
inactivate our 80386 board, the new controller would do its thing, release
the bus and the 80386 would reboot as described above. Doable for sure, the
only thing is on our boards the CPU's come on starting from a reset state.
With software flags etc. this could be overcome. I decided
an easier way is to use two of the S-100 unused lines NDEF1 (pin 21) and
NDEF3 (pin 66) and a type of secondary set of HOLD* and HLDA lines. This
is what was used for our
80286 CPU board. The same arrangement can be used here.
We will utilize the following circuitry on our 80386 board.
In this situation the 80386 is in active slave mode, so HOLD* is low and
pHLDA is high (see above). Now when another controller wants to
be in charge (typically a DMA controller for a video board or disk
controller) it will pull NDEF1 low. This signal is clocked through
U98A, eventually raising the HOLD signal pin of the CPU (K13,3).
When the 80386 is ready, it will raise
its HOLDA pin and the input pin 3 of U63B. The acknowledge is sent
back to the requesting DMA controller via a raised NDEF3 S-100 line.
Meanwhile U63B pin 4 is clocked out of U97B pin 8 (high), which goes to the board
XFERII line (K10, pin 4), raising it, (thereby inactivating the 80386
address+data+status lines). This same signal is clocked into U97A pin
2, and its output goes to the board XFERI line (K9 pin1). This inactivates
the 80386 control lines (U55). You will note this sequence of events
is exactly the same as for when the 80386 is a bus master,
however instead NDEF1 and NDEF3 lines are used.
Again remember the new DMA controller can remain as long as it likes on the
bus. When done it hands control back to the 80386 which in turn later
can hand control back to the S-100 bus master.
A typical configuration might be:- Z80-->80386-->DMA
Step By Step Building the
80386 CPU Board.
The build instructions are fairly simple for this board but because it is a
complex board building it should not be rushed.
As always, first examine the bare board carefully for scratches or damaged traces, use a magnifying glass if need be. A broken trace is almost impossible to detect by eye on a completed board.
I find it useful to carefully slide a file at 45 degrees along the edges (front
& back, sides) of the S100 connectors for easier insertion into the bus. Carefully, just
one or two strokes.
Next solder in all the required IC sockets, resistors, resistor arrays, capacitors, jumpers, and the voltage regulator. Do not add the LED's yet. Be sure you put the resistor arrays in with the correct orientation of pin 1. Check their values before soldering (they are difficult to remove). Remember if you already have 1K pull-up resistors for the S-100 bus vector interrupt lines and DMA lines in your system (for example on your Z80 CPU board), you really don't need the resistors on this board (RR2 & RR3). You can insert single row sockets such as Jameco #78624 in case you want to add pull-up resistors in another system. Be sure and insert the
CPU socket correctly with the notch at the bottom left-hand corner.
The TO-3 5V regulator heat sink must not touch the traces under it. Use either a mica TO-3 insulator or two small nut washers to separate it from the board itself.
For prototype boards I generally use "double swipe" IC sockets. For a critical board like this I prefer to use "Machine Tooled" IC sockets. However they are more expensive and you have to be particularly careful not to bend the IC pins. The two clock oscillators should have their own special sockets (e.g. Jameco #133006). I in fact solder the 2MHz oscillator directly to the board since it will never be changed. If not add it to the 2MHz socket.
Next insert all 5 LED's. Before soldering them in place ground the appropriate pin on the U66 socket to make sure it lights up. I use
a blue LED for 80386 active, D7. Yellow for Halt D5. Red S100 bus select D7, and
green for wait states D2 & D1.
Check the voltage to sockets on the board is above 5V by placing the board in your S-100 system using an extender board. With no load you will typically get 5.00V (+/- 0.25V). BTW, your system should boot and run correctly with its Z80 master CPU board. If not, you have a serious solder bridge somewhere on the board. Before you do anything else with a magnifying glass go over every socket on the board and examine for a proper solder joint. I like to "reheat" each joint just to be on the safe side. The silk screen/varnish on these boards us quite thick. It's easy not to have a good solder joint for the ground pins. Double check. Extra time here will save you hours later, (been there done that! ).
We will now build the board up in functional steps. Avoid the temptation of adding everything at once and popping it into your S-100 box. Step by step is faster in the end -- trust me. We will set the board up configured as an S-100 bus slave. Inputting port 0EDH (in my system, a Z80 monitor "W" or "O" command), will switch in this 80386 CPU board and switch out the Z80.
We will first add jumpers and IC's for this function. While on jumpers, please note every time when we talk about jumpers, position 1 is the square pad of the jumper. In order to minimize board trace lengths, its actual position/orientation on the board will differ from jumper to jumper. Sometimes they are top to bottom or left to right, other times the exact opposite. An incorrect jumper can be a real pain in debugging a non-working board. Check with the
board schematic each time, to be sure . Make sure you correctly identify pin 2 in each case.
First we will install the onboard I/O port circuit that can be used to
activate the board. (This board alternatively however later can be activated
by our SMB)
Jumper P67 1-2 & 3-4. Add U52, U58, U90, U91 and U49.
Use the Z80 Monitor to activate the board (the "W" command).
This P67 configuration assumes we are using port 0EDH. Inputting data on
this port with the bus Z80 CPU board will cause pin 1 of P36 to go from high to low. Resetting the computer will bring it back high again.
Jumper p36 1-2. Add U50, U53, U57, U59,
U63, Jumper K12 1-2, Add JP11 & JP12.
Activate the board. U59 pin 3 should go from low
Here is a picture of the board at this stage:-
Next we will install the HOLD/HLDA handshaking Circuit
Install (initially), a 20MHz Oscillator. Note the Jumper K5 is very close to
the oscillator. You should bend it's pins slightly to make sure the case
does not touch the K5 pins.
Jumper P8 2-4
U18, U66 and U14 and U15 (the 74HCT93). Add U5 and jumper K3 2-3
and P4 1-2. Jumper K9 2-3 and 5-6. Jumper K10 4-5 and 2-3. Note pin 1
on both jumpers are positioned differently. Activate, The blue LED should
come on and pin 1 of U66 should go low.
Add JP7, U55, U56 and JP8. Activate, again the blue LED should come
Add U87 and U2. Jumper K1 1-2, P2 5-6 and p11 9-10 for an initial test wait
Add U79, U19, U11 and U72. Jumper P7 1-2 (horizontal) and JP15.
Activate, again this time both the red and blue LEDs should light up.
is a picture of the board at this stage:-
Next we will add the address line circuitry.
Add U95, U7, U8, U75,U74, U73 and U9. Jumper K11 3-4 for now, we will set
the address translation circuitry free later.
Add U1 and U67. Activate the board. The above two LED's should light
Next we will add the data lines circuitry.
Add U12, U71, U81 and U4 (a 74F04). Jumper K13 1-2 and K4 2-3 (its located
near U71). Activate the board. The above two LED's should again light up.
With the board inactivated it is critical to see pins 19 of U76, U77 & U78
high. When activated pins 19 of U76 and 77 should go low. Do not go
further if this is not the case, something is wrong.
If OK, add U76, U77 & U78.
Completing the board additions.
Add jumpers JP13 and JP14.
Add U6, U7, U98, U97, U10 and U13.
Jumper P20 1-2 (vertical), K2 1-2 (its above the 80386 chip).
Re-jumper K11 2-3.
Add 8 jumpers for all pins on P16 to P18. This configures Protect Mode RAM
to begin above 16MB.
Run one final board activation test and confirm both LED's light up.
Next carefully insert the 80386 CPU in it's socket. Remember pin 1 is
the bottom LHS corner. All IC's should now be on the board.
Activate the board. If you are using the monitor described below on our
MSDOS support board, or in
our RAM+ROM board the
monitor should sign on. It's a wonderful first time experience.
Makes all your hard work worthwhile. The above 80386 will also sign on
if you are using our
monitor, but of course will not have the Protect Mode options.
With either monitor you should be able to boot MSDOS using our
IDE Board (+/-
If you have difficulties with getting a signon there are a few simple tests.
Fill both ROMS with F4's (the HALT opcode) and see when you transfer control
over to the 80386 that the bus is halted (SMB
HALT light comes on).
If that's OK at FFF0H in the ROM's place code to output a character on your
console. Look at the 8086 monitor code at FFFF0H. If you don't
get this to work set a hardware breakpoint at FFFF0H and single step the
CPU. Alternatively connect pin 1 of P36 to XRDY, activate the board, switch
the stop button, remove the jumper and single step the CPU. Look at the
address and status lines for hints of the problem. If you
still have problems contact me, I will accept your finished board and
try and determine the problem.
If all of the above works fine then it's time to optimize the board for your
system. Somewhat to my surprise I find the board works best at high speeds
with a 74LS244 in U55 (instead of the 74F244 listed in the schematic).
I normally run the board at with a 36MHz oscillator, two RAM wait states and
five I/O wait states in my 21 slot S100 bus system which has currently about
12 other boards in it. This yields a rock solid system and is
putting out an S100 Phi clock signal at 8MHz. In a smaller 10 slot system I
use for testing, this same board runs fine with a 40MHz Oscillator.
Your mileage may vary. Interestingly the speed limitation
is not I/O or RAM access, as I go up in speed I get a false interrupt
(vector 7FH) every now and then. This could probably be programmed to be
ignored in the monitor but I don't like an unstable system.
Remember the monitor traps every interrupt the CPU gets both in RM and PM
mode. Of course in PM the CPU runs at the full 40MHz with no wait
states and in pipeline mode. We just need the software!
One debugging trick the is useful with boards like this is trapping the
address lines and data lines immediately after control is transferred from
the Z80 to this board in slave mode. If we force the 80386 into
an extended not ready state (ready*, CPU pin G13, high) the CPU will
lock up it's address lines at 0FFFF0H and the data bus should be
showing EA0CH (the first word of our 80386 Monitor at this reset address).
There are many ways to do this.
Bend out pin 1 of IC1A, remove jumper JP17. Jumper U18 pin 6 to
IC1A pin 1. Jumper IC1A pin 2 to U19 pin 4. Then when the
80386-reset lines goes low (releasing the CPU), it will immediately put a
continuous wait state on the S100 bus allowing the above information to
appear on our SMB.
You should for example see the S100 bus sXTRQ* low. You can then flip
on the stop switch on the SMB, remove the above jumper and single step the
CPU looking at all address, data and control lines to quickly identify
a problem. The above patch is to make sure the S100 RDY* line is
driver low with an OC gate.
Another way to checkout the board is to write a small program in RAM.
If you are using the
S100Computers Z80 board and
Master.Z80 , the
monitor the "O" command will place a far jump in RAM at FFFF0H
IF RAM is present at that
location. The far jump code will force the 8086/80286/80386 to RAM at
500H IF there is no ROM at
the top 1MB. For example if you are using our
4MB RAM board. This
allows you to test simple programs and the CPU board. For example if you place
in RAM at 500H the following bytes with your Z80:-
EB FA 00
Pressing the "O" command with no ROM/MSDOS support board present will have
the 80386 jump to 500H and continuously output the number "3" on your
If this does not work, you can backup one further step and place in RAM at
FFFF0H the code
EB FA 00
Using the Master.Z80 monitor commands:-
S 3FF0, B0, 33, ...
Then hit the reset button. This will leave the code in the at FFFF0H
Then be sure to use the "W" monitor command (not the "W") command to switch
CPU's. (The latter would overwrite the code you wrote). You
should see continuous "3333333.." on your Console display (assuming its port
is 01H). Not both of the above tests assume you do not have ROM in
the top 1MB RAM area. The MSDOS Support board for example is removed.
Lets take a more complex example. Lets continuously write 1234H in RAM at
601H. With your Z80 monitor place the following code in RAM at
BB 01 06
B8 34 12
The 80386 will continuously write the 1234H word in RAM at 601H.
However because the address starts on an odd byte. It will do so by first
writing 34H byte at address 601H, increase the address by 1 (602H) and then
fill the even byte with 34H. You can use a logic probe to see
What is interesting to note is that the 80386 continuously keeps the pWR* signal low
as it switches from the 601H to 602H address. You will note that our
"Modified pWR*" signal sends out two distinct pWR* signals to the S100 bus.
Also note the S100 pWR* signals have returned high way before the S100 address lines
Simple codes like these make debugging the hardware much easier.
Daughter 80386 RAM Boards
I have describe the configurations for the two daughter boards in their own
been reported that under certain software conditions (notably monitor menu
false trigger of U91A can occur due to a ‘Race’ situation around U90, U58A,
U52A & U52C, this results in the 80386 board handing back bus control to the
Z80 Master CPU card.
Testing has shown that changing U52 for a 74F00 and U55 for a 74LS244
reduces this false trigger situation but does not completely eliminate it.
most effective solution has proven to be a 47pf ceramic capacitor soldered
between pin 7 & 8 of U90, this suppresses the spurious pulse at U90 pin 8
that causes the false trigger of U91A without affecting a legitimate bus
transfer request (menu option ‘Z’)”
S100 Bus Master/Slaves.
Please note this board is
normally set to act as an IEEE-696 bus slave. It should work with our
Z80 CPU board
described on this site. It is important to remember however that this 80386
CPU board is counting on the fact that when the bus master to relinquishes
control of the bus to a slave device, the bus master inactivates
all of its address, data, status and control
lines while the slave has control of the bus. The S100 bus signals ADSB*,
DDSB*, SDSB* and CDSB* are expected to all go low as specified by the
IEEE-696 protocol. Some older S100 bus Z80 boards driven boards may
not do this.
This board can configured as a stand alone bus master. However you have to
configure it as described above to lower the S100 bus signals ADSB*, DDSB*,
SDSB* and CDSB* once control is transferred to the slave.
A Production S-100 Board.
Realizing that a number of people might want to utilize a
board like this together with a group of
people on the
Groups N8VEM-S100 forum, "group purchases" are made from time to time.
Join and contact the group if you would like to be involved in this project.
An 80386 ROM MONITOR
To really enjoy working with the 80386 you need to be able to utilize the 32
bit capability of the chip. First you need a ROM based monitor. To get
started with this I modified extensively the software for our old "8086 Monitor" to
accommodate the 32 bit registers of the 80386. Again it was a
First, simply utilizing the memory addressing and 32 bit registers of the
80386 in real mode. Then adding code to switch the CPU into its protected
mode. This is a fairly complex and specialized process. It
requires considerable time and reading. See
for a complete description of this process. From there you can download of the 80386 ROM based monitor
for the above board. With this monitor in protected mode you can
display all the CPU's registers, single step, check interrupts (soft, and in
hardware) and examine RAM anywhere in its 4GB address space etc.
Note the 80386 CPU board can be configured as either a bus master or bus
slave. In the former case it comes up immediately after power on/reset
as the bus controlling CPU. As a bus slave it lays dormant until
activated by (typically) a Z80 CPU. For the real hardware die hard's
there is even circuitry on the CPU card to allow one to use bus DMA in slave
mode (U97,U98, K13 etc.). This is not an IEEE-696 specification but
Realizing that a number of people might want to utilize a board like this
together with Andrew Lynch at N8VEM (see
here), and a group of
people on the
Groups N8VEM-S100 forum, "group purchases" are made from time to time.
Join and contact the group if you would like to be involved in this project.
When the final production boards arrive. I will provide basic step by step
assembly and testing construction notes for the board as I have done for
other boards. I
would like to point out however that this is a complex board. If you have
not built some of our other CPU boards I would recommend you first start
with our 8088 board.
There will be little hand holding at this stage, that said, if somebody has
assembled their board correctly and has exhausted all the obvious errors, I will
offer to check their board out for them, time permitting if they contact me
A GAL Based Prototype Version of
this 80386 Board.
The above board now seems to function correctly and has gone out to a number
of users. The next step is to create an equivalent 80486 CPU
board. This will require the swapping of a number of discrete 74LSxx chips
with a few GAL's, not only to get everything to fit on one S100 board, but
to take advantage of some of the extra properties the 80486 possesses.
We will for example be able to fit a single onboard EEPROM on the board.
There are added complexities in the way the 80486 address the data bus over
the 80386. This would require a large number of 74LSxx chips.
In order to ease the transition in going from a 80386 to 80486 board
utilizing a GAL interface, I decided to convert the above 80386
board into a GAL driven version first. Not only did this simplify the
design, but it allowed for a faster and more robust CPU board. I
should point out however that this board is just a transition prototype, the
above 74LSxx board works perfectly fine. The complete schematic for
this GAL based 80386 board can be found
Let us look at some of the key changes on this board. If you are not
familiar with GAL's please review this
This is a simple GAL to replace the 74LS682 (U13 etc.) circuit that
monitors all signals going to the S100 bus and the 386 Overhead Bus in PM.
Any RAM address utilized above the 16MB of the S100 bus's RAM space will
raise S100_SEL* and lower S100_SEL -- when the 80386 has control of the bus.
There is nothing particularly special here, but it does illustrate how 1 GAL chip
can replace multiple 74LSxx chips. K1 would normally be jumpered 1-2. The
2-3 configuration is used only in the slave of a slave configuration (see
above). The simple PALASM code is:-
/S100_SEL@ = /A24 * /A25
* /A26 * /A27 * /A28 * /A29 * /A30 * /A31 * SLAVE_ACTIVE * LMIO
S100_SEL = /A24 * /A25 * /A26 * /A27 *
/A28 * /A29 * /A30 * /A31 * SLAVE_ACTIVE * LMIO
This is also a simple GAL. It replaces the 74LSxx chips
required to convert the 80386 mBE0-3 signals to the S100 bus address lines A0,
A1 and sXTRQ*. There is one slight extra. Because GAL3 (see below),
does not have enough pin outputs we will also generate the S100 bus HALT status
signal with this GAL.
Again there is nothing particularly special here, but again it illustrates
how one GAL chip can replace multiple 74LSxx chips. The simple PALASM code
mA1 = mBE0@ * mBE1@
mA0 = mBE0@ * /mBE1@ * /mBE2@
+ mBE0@ * /mBE1@ * mBE2@
+ mBE0@ * mBE1@ * mBE2@
/HALT = LWR * /LDC * LMIO
BHE = mBE1@ * mBE3@
msXTRQ@ = BHE + mA0
This is a more complicated GAL. It replaces the 74LS138 chips
required to convert the latched 80386 control signals W/R*, D/C* and M/IO* to
the appropriate S100 bus status and control line signals. Here are the
relevant 74LSxx and GAL circuits.
Here is the corresponding PALASM code:-
/READY@ = /RAM_WAIT * LMIO * S100_SEL ;HIGH if not ready
+ /IO_WAIT * /LMIO * S100_SEL
+ /INTA_WAIT * /LMIO * /LDC
* /LWR * S100_SEL
+ /RDY * S100_SEL
+ /XRDY * S100_SEL
+ /DB_WAIT * /S100_SEL
/MEM_RD@ = LMIO * LDC * /LWR
+ LMIO * /LDC * /LWR
/ssM1@ = /LMIO * /LDC * /LWR
+ LMIO * /LDC * /LWR
/ppWR@ = LMIO * LDC * LWR
+ /LMIO * LDC * LWR
ppDBIN = /LMIO * LDC * /LWR
+ LMIO * LDC * /LWR
+ LMIO * /LDC * /LWR
ssWO = /LMIO * LDC * LWR
+ LMIO * LDC * LWR
+ /LMIO * /LDC * /LWR
/MDATAWR@ = LMIO * LDC * LWR
/IOOUT@ = /LMIO * LDC * LWR
/IOIN@ = /LMIO * LDC * /LWR
/INTA@ = /LMIO * /LDC * /LWR
This GAL is a fairly complex GAL that amongst other things generates
the basic clock signals for the CPU and S100 bus. As explained above we
need different 6 clock signals, 3 each, depending on if the CPU is addressing
the bus or RAM on the overhead 32 bit bus. Please read the above clock
discussions before reading about this GAL. Here is the relevant circuits
of the original 74LSxx based approach and the new GAL based approach.
In this case we utilize the fact that 22V10 GALs can act as D type flip-flops.
The ":=" in the PALSAM equations designate them as such. Pin 1 of these
GALs is the default clock signal. We sequentially divide the incoming clock
signals by two to obtain the relevant bus and CPU clocks. Here is the
OSC2_OUT := /OSC2 ;Proceed to divide the clock signal down
;36 MHz input, 18MHz output
OSC4_OUT := /OSC4 * OSC2_OUT
+ OSC4 * /OSC2_OUT
OSC8_OUT := /OSC8 * OSC4_OUT * OSC2_OUT
+ OSC8 * /OSC4_OUT
+ OSC8 * /OSC2_OUT
OSC16_OUT := /OSC16 * OSC8_OUT * OSC4_OUT * OSC2_OUT
+ OSC16 * /OSC8_OUT
+ OSC16 * /OSC4_OUT
+ OSC16 * /OSC2_OUT
OSC32_OUT := /OSC32 * OSC16 * OSC8_OUT * OSC4_OUT * OSC2_OUT
+ OSC32 * /OSC16_OUT * /CLK
+ OSC32 * /OSC8_OUT * /CLK
+ OSC32 * /OSC4_OUT * /CLK
+ OSC32 * /OSC2_OUT * /CLK
CLK_80486 = OSC * LS100 ;(CLK2) CPU High speed for PM RAM access
+ OSC4_OUT * /LS100 ;(CLK2) CPU Low speed for S100 bus access
CLK_S100 = OSC4_OUT * LS100 ;(CLK) S100
bus High speed for PM RAM access (not active)
+ OSC8_OUT * /LS100 ;(CLK) S100
bus Low speed (8 MHz) for S100 bus access
RES1_OUT := SLAVE_RESET ;Delay CPU reset high to low level two clock cycles
/RESET_80486 := RES1
/pWR@ = /RAW_pWR@ * /pWR_Delay ;Shorten length of CPU pWR* pulse
This is a simple GAL. Its sole purpose is to decode the address lines
so an output (or input) to/from I/O port EDH will activate the 80386 board mode
in slave mode. The recommended way to activate this board is to utilize
the four S100 bus DMA lines on our
SMB, but to test the circuit for this option on our future 80486 board it is
Here is the simple PALASM code:-
/TMAXPU = A0 * /A1 * A2 * A3 *
/A4 * A5 * A6 * A7
;EDH = 1110 1101
* /A8 * /A9 * /A10
* /A11 * /A12 * /A13 * /A14 * /A15
* sINP * pDBIN
;Activate board with Z80 monitor QIED command
A CPLD Based Prototype Version of
this 80386 Board.
The above GAL based version board went through a number (5)
of further prototype boards which I will skip over, but FYI the schematic of the
last one can be found
During the course of this process it became clear that the number of required
22V10 GALs was going to be significant, ending up between 6 to 8. One reason for
this was that the same input signals had to be fed in over and over to the
different GALs. This not only was inefficient but increased the number of
traces on the board.
It became apparent that a single "Complex Programmable Logic Device" CPLD could
do the job on many GAL's. CPLDs were essentially the next evolutionary
logic chips after GALs.
They can be viewed as just bigger GAL's.
introduction to PCLDs.
Here is a picture of a prototype board:-
Here is a schematic of the ATM 1508 CPLD circuit of the CPLD based 80386 board:-
As you can see most of the input signals to several GAL's are now concentrated
into one 68 pin chip. In fact beside the CPU and data and address line
buffers there are few other chips on the board. There would be even less
if we did not want to have control over the wait state circuits for the RAM, I/O
and INTA R/W signals with external jumpers. As with the above original "74LSxx"
based board, we need to delay the CPU driven S100 bus pWR* signal. This
time however rather than hard code it with a 74LS175 chip (see above), we will
do it in in software with the CPLD. Let us step through the
various functions/code this CPLD supplies.
1. The Clock
We will divide a 32-80MHz Oscillator down to obtain the CPU and S100 bus clocks.
CLK2 is the CPU clock, it is always 2X the bus clock.
Remember CLK becomes PHI on S100 bus via U47. It is a different
speed when Z80 is bus master, So PHI is not the same as CLK.
Pinnode = [CD3..0];
Pinnode = LS100_SEL;
/* MASTER_CLK = 80MHz */
CD0.t = 'b'1;
/* 40 MHz */
CD1.t = CD0;
/* 20 MHz */
CD2.t = CD0 & CD1;
/* 10 MHz */
CD3.t = CD0 & CD1 & CD2;
/* 5 MHz */
[CD3..0].ckmux = MASTER_CLK;
CLK2 = (CD1 & !LS100_SEL)
/* CPU Clock, for S100 bus access (20 MHz) */
# (CD0 & LS100_SEL);
/* CPU Clock, for > 16MB PM Access (40 MHz!) */
CLK = (CD2 & !LS100_SEL)
/* S100 bus Clock, for S100 bus access (10 MHz) */
# (CD2 & LS100_SEL);
/* S100 bus Clock, for > 16MB PM Access (10 MHz) */
LS100_SEL.d = S100_SEL;
/* Need to change clock speeds below ONLY on a CLK2 transition */
LS100_SEL.ck = CLK2;
/* This is necessary to avoid runt clock cycles */
In the above we setup three toggle flip flops. We divide the input
oscillator by two each time. Remembering the CLK2 is twice the speed
of CLK (PHI). For S100 bus access we will run CLK2 and CLK/PHI at 20
& 10MHz. In Protected mode (> 16MB RAM) we run CLK2 at 40MHz.
(CLK is not used with our daughter RAM boards). The only fly in the
ointment is when we switch clock speeds. We have to be careful not
to generate runt clock cycles. In the 74LXxx board we used 74LS74 chip
(clocked by CLK2) to do this (see above). The last two lines
in the above code accomplish the same thing here. Note, the upper speed
limit of these ATF 1508's is about 150MHz, so we could later add more flip flops
and get more speed options. Not all S100 systems may be able to work ate
10MHz, so even with the above you might want to start with a 60MHz oscillator,
2. Transfer control from the master z80 CPU to the slave 80386 CPU
Next we need to activate the board. The software below assumes this 80386 board
will act as an S100 bus slave. Later we can modified it to be a bus
In hardware one of the TMA lines (Jumper P13) goes low to start the master/slave
transfer process. This can be done via our
SMB (I, II or III) or by
directly inputting from I/O port 0EDH using code in the boards single onboard
GAL (U9). That port BTW is completely programmable within the GAL. See the
bottom of this page for the actual GAL code.
As in the original 74LSxx based board, we need to sequentially active
XFERI & XFERII (and the S100 bus PHI signal that originates from this board).
Here is the relevant code section for the CPLD:-
Pinnode = [reg2..0];
/* Need 3 D type Flip Flops */
Pinnode = SLAVE_ACTIVE;
/* SLAVE_ACTIVE HIGH if 80386 has control of the bus */
reg0.d = TMAx;
/* TMAx goes low-> high */
reg0.ckmux = !PHI;
reg0.ar = !MASTER_RESET;
/* Return to high on reset */
!HOLD = reg0;
/* Lower S100 bus HOLD line */
!XFERI = reg0 & pHLDA; /* Activate the S100 bus Control lines, when HLDA comes back */
reg1.d = reg0;
reg1.ck = pHLDA;
/* S100 bus grants bus by raising pHLDA line */
reg1.ar = !reg0;
SLAVE_ACTIVE = reg1;
/* HIGH when transfer comes to 80386 Board */
!XFERII = reg1;
/* LOW to activate S100 bus Status, Data & Address lines */
reg2.d = reg1;
reg2.ckmux = !PHI;
reg2.ar = !reg1;
!RESET_80386 = reg2;
/* Activate the CPU, lower it's reset pin */
Again we use three flip-flops to do the transfer/handshaking.
3. Synthesize the Address
lines A0 & A1 & sXTRQ* from the CPU BE3*... BE0*
The 80386 assumes a 32 bit memory system by default. We need to synthesize
the address lines A0 and A1 for our 8 and 16 bit RAM boards on the S100 bus.
Fortunately it's easy to do:-
mA1 = mBE0 & mBE1;
/* Note these signals are latched by U75 */
mA0 = (mBE0 & !mBE1 & !mBE2)
#(mBE0 & !mBE1 & mBE2)
#(mBE0 & mBE1 & mBE2);
msXTRQ = (mBE1 & mBE3)
/* Note 16 bit Request if these, otherwise 16 bit request */
4. Synthesize the S100 Bus control and status
is the most critical part of the CPLD code. Here we convert the three CPU
signals M/IO*, D/C* and W/R* to the equivalent S100 bus signals. I
have used a 74LS75 (U117) to latch these signals because the RAM_WAIT* wait
signal requires a latched inverted form of M/IO* input to U113. This can
be picked up from the inverted signal of the flip-flop. All of these
signals could in fact be generated within the CPLD but it's nice to have access
to the raw signals for debugging etc. Besides the is plenty of room on
!IO_OUT = !LMIO & LDC & LWR & ADS;
/* I/O Write */
!IO_IN = !LMIO & LDC & !LWR & ADS;
/* I/O read */
!MEM_WR = LMIO & LDC & LWR & ADS & !S100_SEL;
/* RAM Write (data) for S100 bus only */
!MEM_RD = ((LMIO & !LDC & !LWR & ADS & !S100_SEL)
/* RAM code read for S100 bus only */
# (LMIO & LDC & !LWR & ADS &
/* RAM data read for S100 bus only */
!INTA = !LMIO & !LDC & !LWR & ADS;
!HALT = LMIO & !LDC & LWR & ADS;
!ssM1 = ((LMIO & !LDC & !LWR & !S100_SEL)
/* RAM code read for S100 bus only */
# (!INTA)); /* INTA */
ssWO = (!IO_OUT
/* I/O Write */
/* RAM Write */
/* INTA */
!dpWR = ((!IO_OUT & !Delay2)
/* Delayed I/O Write */
# (!MEM_WR & !Delay2));
/* delayed RAM Write */
ppDBIN = ((!MEM_RD & INTA)
/* RAM code read RAM data read */
# (!IO_IN & INTA));
/* I/O read */
The S100 bus signal that gives all the trouble on the S100 bus is the pWR*
signal. As we described above we need to delay the appearance of this
signal (and provide two back to back pWR* signals when the CPU writes a word to
an uneven address -- as two 8 bit bytes). The jumper array P101,
"Delay2" now allows us to fine tune the timing of this signal with the CPU clock
speed. Currently all the other S100 bus signals are straightforward.
However jumper array inputs "Delay1" and "INTA-WAIT" are available for later
experimentation if needed.
the S100_SEL* signal
This signal will be LOW when S100 Bus RAM is active (<16MB) and for all CPU I/O.
We simply check the address lines are below 16M and the board is active.
!S100_SEL = (!A24 & !A25
& !A26 & !A27 & !A28 & !A29 & !A30 & !A31 & SLAVE_ACTIVE & LMIO)
# (!LMIO & SLAVE_ACTIVE);
6. Generate CPU Ready signal.
The 80386 CPU requires READY to be LOW if no wait states are required.
Wait state requests can come from a number of different sources.
First, from "normal" S100 bus boards or the front panel. Next is this
board itself. We need to factor in the fact that this board may require
more wait stares for S100 bus RAM or I/O addressing that say a Z80 -- when for
example it is run with a bus PHI of say 10MHz. So we will add extra
wait states for RAM and I/O S100 bus addressing when the 80386 has control of the
bus. These are set with jumpers P2 and P11.
None of the above wait states are active when the CPU is addressing RAM (in
extended mode) above 16MB using our daughter RAM board(s). In fact
2 & 4MB static RAM chips no wait states are required. Nevertheless for
future DRAM boards, the DB_WAIT signal is monitored. Finally for
debugging I have a jumper to force the CPU into an immediate continuous wait
state after reset to allow one to single step the CPU upon booting up the
monitor. This signal is called FORCE_WAIT, jumper K104. This is
invaluable when first getting the board to work. Here is the code:-
Pinnode = S100_READY;
Pinnode = DRAM_READY;
S100_READY = ((!S100_WAIT & !S100_SEL)
/* XRDY or RDY low, then S100_READY goes HIGH */
# (!CPU_WAIT &
/* RAM_WAIT, IO_WAIT or INTA_WAIT then CPU_WAIT is LOW*/
DRAM_READY = (!DB_WAIT & S100_SEL);
/* Does the DRAM board require a wait state, LOW if so */
READY = ((S100_READY & SLAVE_ACTIVE)
/* If either HIGH then put CPU in wait state */
# (DRAM_READY & SLAVE_ACTIVE));
7. Generate buffer control signals for 8/16 bit
CPU transfers to S100 bus data lines using IEEE-696 protocol
This part of the circuit differs from all our previous 16 bit CPU boards.
Because we now have the capacity in coding the CPLD, we will directly control
the data flow through four 74LS645 buffers for 8 and 16 bit read and write data
flows. No longer will we shift 8 bits from low to high S100 bus data lines
and vice versa. This makes for faster noise free data.
The 74LS645's are just better 74LS245's. Here is the code:-
!U104_OE = ((!MEM_RD & !msXTRQ)
/* U104, HIGH 16 Bit MEM CPU READ (DI0-7) */
# (!MEM_WR & !msXTRQ)
/* HIGH 16 Bit MEM CPU WRITE (DI0-7) */
# (!IO_IN & !msXTRQ)
/* HIGH 16 Bit I/O CPU READ (DI0-7) */
# (!IO_OUT & !msXTRQ)
/* HIGH 16 Bit I/O CPU WRITE (DI0-7) */
# (!MEM_RD & msXTRQ & mA0)
/* HIGH 8 bit MEM CPU READ (DI0-7) */
# (!IO_IN & msXTRQ & mA0));
/* HIGH 8 bit I/O CPU READ (DI0-7) */
!U112_OE = ((!MEM_RD & !msXTRQ)
/* U112, LOW 16 Bit MEM CPU READ (DO0-7)*/
# (!MEM_WR & !msXTRQ)
/* LOW 16 Bit MEM CPU WRITE (DI0-7) */
# (!IO_IN & !msXTRQ)
/* LOW 16 Bit I/O CPU READ (DI0-7) */
# (!IO_OUT & !msXTRQ)
/* LOW 16 Bit I/O CPU WRITE (DI0-7) */
# (!MEM_WR & msXTRQ & !mA0)
/* LOW 8 bit MEM CPU READ (DO0-7) */
# (!IO_OUT & msXTRQ & !mA0));
/* LOW 8 bit I/O CPU READ (DO0-7) */
!U106_OE = ((!MEM_RD & msXTRQ & !mA0)
/* U106 LOW 8 bit MEM CPU READ (DI0-7) */
# (!IO_IN & msXTRQ & !mA0)
/* LOW 8 bit I/O CPU READ (DI0-7) */
/* INTA vectors are always on 80386 LOW data bits 0-7 */
!U105_OE = ((!MEM_WR & msXTRQ & mA0)
/* U105, HIGH 8 bit MEM CPU WRITE ((DO0-7) */
# (!IO_OUT & msXTRQ & mA0));
/* HIGH 8 bit I/O CPU READ */
BTW, I was able to simplify the onboard port switching circuit to a single
GAL. This avoids the need for our
SMB to switch CPU's, though that way is recommended. Here is the
relevant circuit. It really illustrates the usefulness of GAL's. The
equivalent circuit would require a number of 74LSxx chips.
The PALASM code is available below.
The above CPLD based 80386 board appears to work fine with a 10MHz PHI clock
(80Mhz Oscillator) on a properly terminated S100 bus. Some
minor changes were made/added for another (hopefully) final prototype. The
schematics etc. below are for that board. Please stay tuned.
The links below will contain the most recent schematic of this board.
Note, it may change over time and some IC part or pin numbers may not correlate
exactly with the text in the article above.
80386 Hardware Reference Manual
CURRENT 80386 CPU BOARD SCHEMATIC
(V3 FINAL-3 , 10/16/2014)
CURRENT 80386 CPU BOARD LAYOUT
Most current KiCAD files for this board
(S100 80386 V3-001 (1).zip
CURRENT 80386 V2 - CPLD BASED CPU BOARD SCHEMATIC
CURRENT 80386 V2 - CPLD BASES CPU BOARD LAYOUT
Most current 80386 V2 - CPLD
BASED KiCAD files for this board
80386 V2 - CPLD files for this board
GAL0_80386 file for this board
Other pages describing my S-100
hardware and software.
This page was last modified