S100 Computers

Home S-100 Boards History New Boards Software Boards For Sale
Forum Other Web Sites News Index    
An S-100 80386 CPU Board.
Production 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 unknown layout.
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 mode.

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 Z80, 6502, 8088, 8086, 80286 and 68000 CPU S-100 boards,  I felt the time was now right to tackle an 80386 S100 board.

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

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 three phases:-
   1   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.
  2 Build a ribbon cable connected S100 daughter RAM board utilizing very high capacity static RAM chips  (16M chips).
  3 Build the same type of board utilizing very high capacity DRAM SIMMS  (1GB 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
The picture 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.

80386 Prototype #1

The top connector pins to hook up the daughter board cable is not yet implemented.   The original 80386 schematic for this board can be seen here.  Before discussing the board in detail it might be useful to review the 80386 pins in detail.

Address Lines
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 downloaded here.

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:-
  Address Lines A0+A1
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:-
  Upper PROM Address
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, t
his also conveniently gets around the 16 MB address space limitation of the S-100 bus.  

Data Lines
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 8086 & 80286 boards). It has proven to be a reliable circuit. Here is the circuit used on this 80386 board:-
  Data Lines
It turns out that it is important that U78 is a 74LS244 (and not a faster 74F244) however.

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:-
  Control Signals
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 have not 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. 
  Delayed pWR
  Write Signals

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.
A 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 here.

 Prototype 3
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 fit everything. 

A 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 here.
  Prototype V4
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 here.  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.

 Final 80386 Prototype
Address Pipelining
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 fine.

RAM Boards.
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 boards. See 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 ints.

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:-
  Clock Schematic   Clock Table
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:-
  New Clock Picture

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

  V7 Prototype Picture
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:-
  RAM Test Picture

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 Slave Controller
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.
If so, 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).
  Master Schematic

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 utilized.
  Slave Schematic
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 8088, 8086, 80286 & 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/O port.

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.
  Slave+Slave Schematic
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 Disk Controller-->80386-->z80.

Step By Step Building the 80386 CPU Board.
  Production 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 to high.
Here is a picture of the board at this stage:-
  Production Step 1
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 (vertical).
Add 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 on.
Add U87 and U2. Jumper K1 1-2, P2 5-6 and p11 9-10 for an initial test wait states configuration.
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. 
Here is a picture of the board at this stage:-
  Production Step 2
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 up.

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 8086 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 (+/- ZFDC 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!

Board Debugging.
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:-

B0 33
E6 01
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 console/Port1.

If this does not work, you can backup one further step and place in RAM at FFFF0H the code

B0 33
E6 01
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 in RAM.
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 500H:-

31 C0
8E D8
BB 01 06
B8 34 12
89 07

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 this process:-
  Dual pWRs

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

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 sections see here and here.

Dave Fry has been reported that under certain software conditions (notably monitor menu option ‘N’),  a 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 The 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’)”.   Thanks Dave.

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

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 multi-step process. 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 80386 Monitor 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 potentially useful.

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  Google 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 directly.

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 here.  Let us look at some of the key changes on this board.  If you are not familiar with GAL's please review this GAL write-up first.
  GAL based 80386 Board
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.
  Old S100 Sel Circuit
  GAL S100 Sel Circuit

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
                + /LMIO
                + /SLAVE_ACTIVE

S100_SEL     =    /A24 * /A25 * /A26 * /A27 * /A28 * /A29 * /A30 * /A31 * SLAVE_ACTIVE * LMIO
                + /LMIO
                + /SLAVE_ACTIVE

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.

  A0-A1 Circuit

Again there is nothing particularly special here, but again it  illustrates how one GAL chip can replace multiple 74LSxx chips.  The simple PALASM code is:-

mA1  = mBE0@ * mBE1@

mA0   =  mBE0@ * /mBE1@ * /mBE2@
       + mBE0@ * /mBE1@ *  mBE2@
       + mBE0@ *  mBE1@ *  mBE2@


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.
  Status Signals

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                   ;80386_DATA_RD@
         + LMIO * /LDC * /LWR                   ;80386_CODE_RD@

/ssM1@ = /LMIO * /LDC * /LWR                    ;80386_INTA@
        + LMIO * /LDC * /LWR                    ;80386_CODE_RD@

/ppWR@ =   LMIO * LDC * LWR                     ;80386_DATA_WR@
        + /LMIO * LDC * LWR                     ;80386_IO_OUT@

ppDBIN = /LMIO *  LDC * /LWR                    ;80386_IO_IN@
        + LMIO *  LDC * /LWR                    ;80386_DATA_RD@
        + LMIO * /LDC * /LWR                    ;80386_CODE_RD@

ssWO =    /LMIO *  LDC *  LWR                   ;80386_IO_OUT@
        +  LMIO *  LDC *  LWR                   ;80386_DATA_WR@
        + /LMIO * /LDC * /LWR                   ;80386_INTA@

/MDATAWR@ =  LMIO *  LDC *  LWR                 ;S100 MWRT

/IOOUT@   = /LMIO *  LDC *  LWR                 ;S100 SOUT

/IOIN@    = /LMIO *  LDC * /LWR                 ;S100 SINP

/INTA@    = /LMIO * /LDC * /LWR                 ;S100 INTA

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.
  Clock Summary Diagram
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 PALASM code:-

OSC2_OUT := /OSC2                                                ;Proceed to divide the clock signal down
                                                                 ;36 MHz input, 18MHz output 
OSC4_OUT := /OSC4 * OSC2_OUT                                     ;8 MHz
           + OSC4 * /OSC2_OUT

OSC8_OUT := /OSC8 * OSC4_OUT * OSC2_OUT                          ;4.5MHz
           + OSC8 * /OSC4_OUT
           + OSC8 * /OSC2_OUT

OSC16_OUT := /OSC16 * OSC8_OUT * OSC4_OUT * OSC2_OUT             ;2.25MHz
            + OSC16 * /OSC8_OUT
            + OSC16 * /OSC4_OUT
            + OSC16 * /OSC2_OUT

OSC32_OUT := /OSC32 * OSC16 * OSC8_OUT * OSC4_OUT * OSC2_OUT     1.13 MHz
            + 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 incorporated here.
  Port Summary Diagram
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

Under Construction

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
here.   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.  See here for an introduction to PCLDs.

Here is a picture of the prototype board:-

You can see the one large CPLD in the center of the board.

Here is a schematic of the ATM 1508 CPLD circuit for this CPLD based 80386 board:-
  CPLD Circuit
As you can see most of the input signals to several GAL's are now concentrated into a single 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. Activate the board.
The current software assumes this 80386 board will act as an S100 bus slave.
Later if needed, it can be modified/jumpered as being a bus master.
In hardware one of the TMA lines (Jumper P13) goes low to start the master/slave transfer process.
Sequentially XFER1 & XFERII are then activated (and the S100 bus PHI then originates from this board).

Pinnode = [reg2..0];                            /* Need 3 D type Flip Flops */

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 */
                                                /* Note we inactivate U55 for RAM > 16M in protected mode */
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 */

2.  The Clock Generator/Divider Circuit
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 = 64MHz */
CD0.t = 'b'1;                                  /* 32 MHz */
CD1.t = CD0;                                   /* 16 MHz */
CD2.t = CD0 & CD1;                             /* 8 MHz */
CD3.t = CD0 & CD1 & CD2;                       /* 4 MHz */

[CD3..0].ckmux = MASTER_CLK;

CLK2 = (CD1 & !LS100_SEL)                      /* CPU Clock, for S100 bus access (16 MHz) */
     # (CD0 & LS100_SEL);                      /* CPU Clock, for > 16MB PM Access (32 MHz!) */

CLK = (CD2 & !LS100_SEL)                       /* S100 bus Clock, for S100 bus access (8 MHz) */
    # (CD2 & LS100_SEL);                       /* S100 bus Clock, for > 16MB PM Access (8 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 works 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 wit the above you might want to start with a 60MHz oscillator,

3. Activated and latch the LS100_SEL* signal.
The CPU will be talking to two completely separate RAM circuits. For RAM below 16MB it will address RAM on the S100 bus. ANY ram above this address space will be assumed to be on the extended bus using the overhead connectors. ALL I/O and Ints will also be on the S100 bus.  The relevant signal that defines which bus the CPU is talking two is the S100_SEL signal. If it is low the S100 bus is being addressed. If it is high the overhead bus is being addressed.  The extra complication is that when addressing the overhead bus the CPU's clock (CLK2) is doubled -- because that bus can handle a much faster speed.

Pinnode = S100_SEL;                               
Pinnode = SLAVE_ACTIVE;                          /* SLAVE_ACTIVE HIGH if 80386 has control of the bus, see below */

!S100_SEL = ((!A24 & !A25 & !A26 & !A27 & !A28 & !A29 & !A30 & !A31 & SLAVE_ACTIVE & LMIO) /* > 16M */
# (!LMIO & SLAVE_ACTIVE));                       /* I/O or INTA's) */

LS100_SEL.d = S100_SEL;                          /* Need to latch/change the LS100_SEL signal ONLY on a CLK2 transition */
LS100_SEL.ck = CLK2;                             /* This is necessary to avoid clock switching in the middle of a cycle */

4. Synthesize the Address lines A0 & A1 & sXTRQ* from the CPU BE3*... BE0*
This is fairly straightforward. We also need to generate the S100 bus signal sXTRQ for 16 bit access:-

mA1 = mBE0 & mBE1;                               /* Note these signals are latched by U75 before appearing on the S100 bus */

mA0    = (mBE0 & !mBE1 & !mBE2)
        #(mBE0 & !mBE1 & mBE2)
        #(mBE0 & mBE1 & mBE2);

msXTRQ  = (mBE1 & mBE3)
         # mA0;

5. Synthesize the S100 Bus Control and Status signals
This is the heart of the board. We need to carefully reformulate the main 80386 control signals to their S100 bus counterparts.
After much trial and  error this is what i ended up with:-

!IO_OUT    = !LMIO & LDC & LWR & ADS;                 /* I/O Write */

!IO_IN     = !LMIO & LDC & !LWR & ADS;                /* I/O read */

!MEM_WR    = LMIO & LDC & LWR & ADS & !LS100_SEL;     /* RAM Write (data) for S100 bus only */

!MEM_RD    = ((LMIO & !LDC & !LWR & ADS & !LS100_SEL) /* RAM code read for S100 bus only */
           # (LMIO & LDC & !LWR & ADS & !LS100_SEL)); /* RAM data read for S100 bus only */

!INTA      = !LMIO & !LDC & !LWR & ADS;

!HALT      = LMIO & !LDC & LWR & ADS;

!ssM1      = ((LMIO & !LDC & !LWR)                    /* RAM code read for S100 bus only */
           # (!INTA)); /* INTA */

ssWO       = (!IO_OUT /* I/O Write */
            # !MEM_WR /* RAM Write */
            # !INTA); /* INTA (ALL) */

!dpWR      = ((!IO_OUT & !Delay2)                      /* Delayed I/O Write (ALL) */
           # (!MEM_WR & !Delay2));                     /* Delayed RAM Write (S100 Bus only) */

ppDBIN     = ((!MEM_RD & INTA)                         /* RAM read (S100 Bus only) */
           # (!IO_IN & INTA));                         /* I/O read (ALL) */

!EXT_RAM_RD = ((LMIO & !LDC & !LWR & ADS)              /* RAM code read for overhead bus */
            # (LMIO & LDC & !LWR & ADS));              /* RAM data read for overhead bus */

!EXT_RAM_WR = LMIO & LDC & LWR & ADS;                  /* RAM Write (data) to overhead bus */

All this is based on the data sheets Intel and AMD supplied that describes the levels of the critical M/IO, D/C and R/W control lines send out by the CPU.   See here for more details. Note these lines going into the CPLD are first latched via U177 (a 74LS75). 

In the first version of this board I sent these three lines over the top of the board (via the ribbon cable connector) to the 32 bit RAM boards.  These boards would decode the signals to generate the corresponding RAM read and write signals.   I find it is more reliable to do the decoding on this board and just send the RAM read or write signals directly.    The two signals EXT_RAM_RD and EXT_RAM_WR are these signals.  There are jumpers (K103 7 K106)  to utilize the "old" signals if you wish to utilize the earlier RAM boards.  All newer extended RAM boards (see below) however will utilize these two signals only.

6.  Generate CPU Ready* signal.
If READY is HIGH then the CPU will add wait states until it is LOW again.  The clock going to the wait state generator circuit (U102 & U103) is CLK2, so each jumper setting is 1/2 an actual  S100 bus cycle wait state. That said, even at 8MHz the S100 bus the board requires 1 and a 1/2 wait states for RAM and I/O access.   Note in protected mode when access the overhead RAM boards these wait states are not inserted.  Those boards have their own wait state generator which returns the "DB_WAIT" signal to request a wait state.  With a 16MHz CLK signal only 1/2 a wait state is required with our current overhead RAM boards. 

READY     =     ((!S100_WAIT & !LS100_SEL)                                                  /* XRDY or RDY low, then S100_READY goes HIGH */
                 #    (!CPU_WAIT & !LS100_SEL)                                                    /* RAM_WAIT, IO_WAIT or INTA_WAIT then CPU_WAIT is LOW*/
                 #    (!DB_WAIT & LS100_SEL));

S100_WAIT is generated by the two S100 bus wait request signals XRDY* and RDY*. 
CPU_WAIT  is generate on this board to slow down the CPU for RAM and I/O access.
Here is a picture of the optimum jumpers I obtained. (yours may be different).

7. Generate buffer control signals for 8/16 bit CPU transfers to S100 bus data lines using the  IEEE-696 protocol
One nice thing about using a CPLD is there is now ample room to lay down detailed equations so we can convert the 8 or 16 bit data signals to/from the 80386 and redirect them to the appropriate 8 or 16 bit S100 bus data lines.  If you are not familiar with the unique way the S100 bus handles 8 and 16 bit data please see here first.
Here are the relevant equations:-

!U104_OE  = ((!MEM_RD & !msXTRQ & !LS100_SEL)                /* U104, HIGH 16 Bit MEM CPU READ (DI0-7) */
          # (!MEM_WR & !msXTRQ & !LS100_SEL)                 /* HIGH 16 Bit MEM CPU WRITE (DI0-7) */
          # (!IO_IN & !msXTRQ & !LS100_SEL)                  /* HIGH 16 Bit I/O CPU READ (DI0-7) */
          # (!IO_OUT & !msXTRQ & !LS100_SEL)                 /* HIGH 16 Bit I/O CPU WRITE (DI0-7) */
          # (!MEM_RD & msXTRQ & mA0 & !LS100_SEL)            /* HIGH 8 bit MEM CPU READ (DI0-7) */
          # (!IO_IN & msXTRQ & mA0 & !LS100_SEL));           /* HIGH 8 bit I/O CPU READ (DI0-7) */

!U112_OE  = ((!MEM_RD & !msXTRQ & !LS100_SEL)                /* U112, LOW 16 Bit MEM CPU READ (DO0-7)*/
          # (!MEM_WR & !msXTRQ & !LS100_SEL)                 /* LOW 16 Bit MEM CPU WRITE (DI0-7) */
          # (!IO_IN & !msXTRQ & !LS100_SEL)                  /* LOW 16 Bit I/O CPU READ (DI0-7) */
          # (!IO_OUT & !msXTRQ & !LS100_SEL)                 /* LOW 16 Bit I/O CPU WRITE (DI0-7) */
          # (!MEM_WR & msXTRQ & !mA0 & !LS100_SEL)           /* LOW 8 bit MEM CPU READ (DO0-7) */
          # (!IO_OUT & msXTRQ & !mA0 & !LS100_SEL));         /* LOW 8 bit I/O CPU READ (DO0-7) */

!U106_OE  = ((!MEM_RD & msXTRQ & !mA0 & !LS100_SEL)          /* U106 LOW 8 bit MEM CPU READ (DI0-7) */
          # (!IO_IN & msXTRQ & !mA0 & !LS100_SEL)            /* LOW 8 bit I/O CPU READ (DI0-7) */
          # !INTA & !LS100_SEL);                             /* INTA vectors are always on 80386 LOW data bits 0-7 */

!U105_OE = ((!MEM_WR & msXTRQ & mA0 & !LS100_SEL)            /* U105, HIGH 8 bit MEM CPU WRITE ((DO0-7) */
         # (!IO_OUT & msXTRQ & mA0 & !LS100_SEL));           /* HIGH 8 bit I/O CPU READ */

No longer are we shifting 8 bits to/from the Data In/Out S100 bus lines as we had to do with out 8086, and 80286 CPU boards. This makes for a much more reliable approach.

8. Generate the S100 Bus pSYNC and pSTVAL signals  
Finally we need a few housekeeping signals. We will generate the S100 bus signal pSTVAL (Low) = ADS (CPU Low), Synchronized against it with the falling ADS* signal.
We will generate the S100 bus signal pSync (High) = /ADS (CPU Low), (pSYNC is inverse of pSTVAL on this board).

ppSTVAL.ckmux =  CLK;
ppSTVAL.d     =  ADS;                    /* ADS Active LOW so in STVAL */
ppSync        = !ppSTVAL;                /* pSYNC is active high */

All the above code can be quickly and easily generated utilizing the Atmel "WinCupl" Windows IDE interface.  You can read more about this interface here.

I still retained one 22V10 GAL to handle the master/slave switching circuit described above.  However now the GAL code was further condensed so as not even need a 74LS74 flip-flop.
Here is the PALASM code:-

;---------------------------------- PIN Declarations ---------------
PIN 1 PULSE_IN ;CLK pin, input from pin 23 (PULSE_OUT)
PIN 2 A0                 ;Note these are actual S100 bus address lines (outside the 80386)
PIN 3 A1
PIN 4 A2
PIN 5 A3
PIN 6 A4
PIN 7 A5
PIN 8 A6
PIN 9 A7
PIN 10 A8
PIN 11 A9
Pin 12 GND

Pin 13 A10
Pin 14 A11
Pin 15 A12
Pin 16 A13
Pin 17 A14
Pin 18 A15
Pin 19 pDBIN              ;S100 bus port write
Pin 20 sINP               ;S100 bus status Port IN line
Pin 21 /RESET             ;Active LOW reset pulse from S100 bus
Pin 22 TMAXPU             ;Toggle bit to TMA 1-4 (inversed)
Pin 23 PULSE_OUT          ;Pulse to clock pin 1 input

;----------------------------------- Boolean Equation Segment ------


/PULSE_OUT =   A0 * /A1 * A2 * A3 * /A4 * A5 * A6 * A7              ;Port EDH = 1110 1101
            * /A8 * /A9 * /A10 * /A11 * /A12 * /A13 * /A14 * /A15
            * sINP * pDBIN
            + RESET * TMAXPU                                        ;Clock LOW if HIGH with reset

TMAXPU    := /TMAXPU * /RESET                                       ;Toggle
           + RESET

Here is the relevant circuit:-  

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.

The Intel 80386 Hardware Reference Manual

MOST CURRENT 80386 CPU  BOARD LAYOUT   (V3 FINAL-3, 10/16/2014)
Most current KiCAD files for this board  (S100 80386 V3-001 (1).zip   11/5/2014)


(V2  FINAL  8/18/2013)
MOST CURRENT 32 MB MEZZ BOARD SCHEMATIC    (V06   Final   8/18/2013)
MOST CURRENT 32 MB MEZZ BOARD LAYOUT     (V06   Final  8/18/2013)

MOST CURRENT CPLD BASE (V29) 80386 CPU BOARD KICAD FILES     (V29,Final  10/2/2015)

Other pages describing my S-100 hardware and software.
Please click here to continue...

This page was last modified on 10/03/2015