The Project: Book by Robert Grossblatt (ISBN 0830631712) - in My Opinion, This Second Book Is Better Because
The Project: Book by Robert Grossblatt (ISBN 0830631712) - in My Opinion, This Second Book Is Better Because
The Project: Book by Robert Grossblatt (ISBN 0830631712) - in My Opinion, This Second Book Is Better Because
This project aims to develop an Intel 8088 based single board computer (SBC) and to add various
different peripherals to it.
The project started out when someone was selling some 8088 processors on eBay, and so just out of
interest, I bought them and then started to search online to see what I could do with them. From these
searches, I found out a book called Build your own Computer based on the 8088 by Walter Fuller
(ISBN 0827370695). This book got me started, but I also found another book: The 8088 Project
Book by Robert Grossblatt (ISBN 0830631712). In my opinion, this second book is better because
the author explains a lot more about what's going on whereas the first book was meant as a lab
supplement for a college course, and so doesn't go in depth. Regardless, they're both good books
and probably worth purchasing if you plan on doing this project yourself.
When I set out to make this SBC the aim I had in mind was to build a basic SBC but have the
functionality to expand it by plugging other boards into it. Why would I want to build something using
an old 8088 instead of using some shiny new microcontrollers? Well, I've found that designing and
building a microprocessor system is quite different from building a microcontroller based circuit. This
is because with a microprocessor you have complete access to the chip's address, data and control
lines and you add the system's RAM, ROM and I/O yourself, meaning you have complete control on
the specifications of your system, whereas with a microcontroller, you're pretty much limited to what
you've bought. Also, it's fun!
General outline
The very basic microprocessor circuit is going to consist of the following: clock, processor, ROM,
RAM and the ability to read and write from I/O and so that's what I aimed for first.
First thing's first – the clock.
Clock circuit
All microprocessors need a clock source in order to run and for the 8088 (and related processors),
this is provided by the 8284 clock chip. This chip supplies the 8088 with a compatible clock signal (the
8088 needs its clock to have a 33% duty cycle) and also supplies it with 2 of it's control lines –
RESET and READY. The RESET signal does what it says on the tin and resets the 8088. This line
can also be used by other peripherals on the computer so that they reset when the 8088 resets. The
READY line is useful if you have some slow I/O interfacing to the processor. If your I/O needs to
some extra time to deal with the processor's request, it can take the READY line low. The processor
will the wait for READY to go high again before resuming. Instead of connecting your peripheral to the
8088's READY line directly, the 8284 provides 2 READY lines for your I/O (RDY1 and RDY2) which
are synchronised the the system clock, and so you'd connect your I/O READY signal to one of them.
Pins AEN1, AEN2 and ASYNC control the operation of RDY1 and RDY2. However, since the 8088's
peripheral chips are designed to work with it, they don't need READY signals, so AEN1 and AEN2 are
tied low and ASYNC is left floating.
The 8284 can take its clock source from either a crystal, or an oscillator, and you tell it which one via
the F/C pin. If using an oscillator, the output of the oscillator is connected to EFI and F/C is tied high.
If you're using crystal (like me), then the crystal is connected across X1 and X2 and F/C is tied low.
The oscillator is divided by 3 and given a 33% duty cycle and then output on CLK. Because the 8088
I have runs at 5MHz, I have used a 15MHz crystal.
[email protected]
The 8284 also provides a clock for peripheral devices on PCLK. This clock is at half the frequency of
CLK and has a 50% duty cycle. The 8284 also provides a buffered output of the full oscillator
frequency on the OSC pin.
The RES pin is an active low signal. Bringing this pin low tells the 8284 to output a reset signal. I've
used a simple resistor and capacitor circuit to hold the system in reset for a short while after you
switch on the power, to give time for the power supply and anything else in the circuit to stabilise.
When the power is first switched on, the capacitor is discharged and so RES = 0V and the system is
held in reset until the capacitor charges up and then the system is allowed to run. In my circuit, I've
used a 10k resistor and 4.7uF capacitor, giving a power-on-reset time of 47us. The button then allows
you to reset the system at any time.
The circuit diagram is shown below:
[email protected]
Testing the clock circuit
Testing the 8284 circuit is straightforward. With no chip and the power on, first check that the reset
circuit works as expected. When the power is turned on, the output of the reset circuit should rise to
5V then stay there. Pressing the reset button should bring it down to 0V and when the button is
released, the output should go back to 5V.
Once that's done, plug in the chip and apply power then take a scope and check out the output pins.
The RESET line should normally be low until the button is pressed. It should then remain high until
the button is released, where it goes back low. The following photo shows my scope output of the
RESET and RES lines (NOTE: I'm using 10x probes which is why the scope says 0.5V/div – 10*0.5=5
and so in actual fact it's 5V/div)
Next check the PCLK and CLK outputs. The CLK output should be a 5MHz square wave with 33%
duty cycle, and the PCLK output should be a 2.5MHz square wave with a 50% duty cycle. The
following photo shows my scope output of CLK and PCLK:
[email protected]
That wraps it up for the 8284 – the CLK, RESET and READY lines will be connected to the 8088 in
the next step.
There's nothing much to test here, apart from checking your wiring and making sure the correct
voltage levels and signals are present on the pins connected.
Memory
As mentioned previously, one of the things which makes microprocessors so flexible is that you have
complete control over how much memory you add and how it's mapped. You can have as little or as
much as you want (within limit of course) and arrange it how you see fit. Memory in the 8088 circuit
will contain code, data, the stack and the 8088's interrupt table. The memory is compromised of ROM
and RAM. We need the RAM because we need space to store data and code which we can change
while the processor is running. ROM is necessary because when the 8088 starts up, it has to have
something to run, and so this is preprogrammed into ROM.
The 8088 has 20 address lines, which means it can address a whopping 1MB (!) of memory from
00000 to FFFFF. When the 8088 first powers up, it starts executing code from address FFFF0. This
means there are 16 bytes of space to place our boot code. This is rather small, so what usually
happens is that at FFFF0, we tell the 8088 to jump to somewhere lower down in memory where we've
got a bit more breathing room.
[email protected]
Because we'll be using two memory chips, we need some way to disable one chip and enable the
other. We can't have them both working at the same time – imagine what'd happen if the 8088 came
to read from memory and both RAM and ROM dumped their outputs at the same time! Choosing
which chip to enable is called address decoding. The memory configuration I've used is the same as
the one described in Fuller's book. This method is much simpler than the one used by Grossblatt
because only a single NOT gate is needed to decode the address.
This configuration places 32K of RAM at the bottom of the address space (00000 – 07FFF) and 32K
of ROM directly above it (08000 – 0FFFF).
As we can see from this table, the only difference between a ROM address and a RAM address is
address bit 15 – it's 1 when it's ROM and 0 when it's RAM. This makes decoding very simple,
because A15 can be connected directly to the RAM's CS pin and connected to the ROM's CS pin via
one NOT gate.
The RAM and ROM chips themselves are relatively simple to work with. Both have a set of address
and data lines which will connect to the address and data buses respectively. Both chips have a CS
and RD pin. The CS pin is an active low signal. If CS is high, the chip is disabled and its outputs are
tristated. When CS is low, the chip is enabled. RD is also an active low signal. If RD is taken low, the
chip places the data present at the address specified. The RAM has an extra control pin which the
8088 will use: WR. As you can probably guess, this is an active low signal and used when you want
to write a byte to RAM.
[email protected]
You'll find that the 8088 doesn't have separate address and data pins. In fact, the 8 data pins are
multiplexed with the lower 8 address pins, and so there needs to be a way to separate the data from
the address and indeed there is. When the 8088 places the address on the pins, it takes ALE high.
We can use ALE to trigger a latch, which will then output the address and hold it there until a new
address is present. A good candidate for this is the 74373 Octal latch. In this circuit the address bus is
15 bits wide, so we need 2 octal latches, and one of the inputs will be left unused.
Just as we can latch the address bus, the 8088 provides us with 2 output to tell us it wants to read or
write data. These are DEN and DT/R. DEN is an active low signal indicating that the 8088 wants to
manipulate data and DT/R tells us what it wants to do with the data. If DT/R is high, the 8088 is
writing data and if it's low, it's reading data. A good chip to use for this case is the 74245 octal bus
transceiver.
We can connect DEN to the chip's E pin and the DT/R pin can go straight to the transceiver's DIR pin.
Now, when the 8088 want to read data, it places a low on DEN which enabled the 245 and also on
DT/R, so data goes from B to A. If it's writing data, DEN goes low again and DT/R goes high so data
goes from A to B. It would therefore make sense for us to connect the A side to the 8088 and the B
side to the rest of the circuit. The circuit diagram of the address latches and data transceiver is shown
below.
The OC pins for the 373's are tied low so that they're outputs are always enabled.
[email protected]
The last bit of decoding to do is the 8088's control lines. There are three we need to deal with: IO/M,
RD and WR. IO/M tells us if the 8088 is talking to I/O or memory. If it's a high then it's I/O and if it's
low it's memory. RD and WR are active low outputs which tell us if the 8088 want so read or write
data. Basically, we want to decode these to get IORD, IOWR, MEMRD and MEMWR. These should
all be active low signals, because all the peripheral and memory chips need and active low signal to
enable them.
IO/M RD WR
0 0 1 MEMRD
0 1 0 MEMWR
1 0 1 IORD
1 1 0 IOWR
In this circuit, the 74138 1-of-8 decoder is used. With RD connected to A, WR to B and IO/M to C, we
get the following outputs from the 138:
MEMRD O2
MEMWR O1
IORD O6
IOWR O5
MEMRD and MEMWR will be connected to the RAM and ROM RD and WR pins, respectively and
likewise, IORD and IOWR will be connected to the RD and WR pins on I/O devices.
The following circuit diagram shows the 8088 with all its control lines decoded and everything ready
and waiting for the memory:
[email protected]
Testing
As with before, there isn't really an amazing amount to test ere, apart from checking wiring and
voltage levels. There is one test we can now do though. Now that we've got the 8088 all wired up, we
power it up and scope the output of ALE. Pulses present on the ALE pin indicate that the 8088 has
successfully powered up and is trying to read the code stored in address FFFF0. If you can see those
on the scope, then that's a good sign. The real testing comes when we've installed the memory and
written some test code.
[email protected]
Now that all that looks like it's
working, it's time to add ROM and
RAM. For RAM, I have used a
Winbond W24257A RAM chip,
which is a 32Kx8. From ROM, I
decided to use an Atmel AT28C256
32Kx8 EEPROM chip because I
figured it'd be quicker to modify my
programs, because unlike a UV
Erasable EPROM, I don't need to
wait 15 minutes to erase the chip
every time I want to modify my
program.
For both chips, the address and
data lines connect to the
corresponding pins on the address
and data latches. The MEMR
signal goes to the chips' OE pins
and the MEMW goes to the RAM's WE, because the ROM is read only. Finally, the ROM's CS pin is
connected to the output of the inverter in the above circuit diagram, while the RAM's CS pin connects
to the input of that inverter (i.e. Directly to A15). Below is the circuit diagram of the setup.
[email protected]
[email protected]
Writing software for the computer
The SBC is now at the stage where we can write software for it to test out it's functionality. Because
the processor is an Intel 8088, there are a lot of resources on the web that describe x86 assembly
language. Robert Grossblatt's book, The 8088 Project Book, which I recommended at the start has
a chapter dedicated to 8088 assembly and is a good start. I also found 8086/8088/80286 Assembly
Language by Leo J Scanlon (0132469197) on eBay and it has been a good reference.
In order to write software for the SBC, we're going to need an x86 assembler that is capable of simply
assembling the code and giving us a raw binary file. In Walter Fuller's book, he suggests Borland's
Turbo assembler, TASM, and as I have a copy, I decided to use that. Now TASM is really old and in
fact, I don't think Borland support it anymore, so I've uploaded my copy of TASM and TLINK so
anyone interested in the project can write their own software.
The first piece of software I wrote for the 8088 was a RAM testing program. The program ran through
each cell in RAM, wrote a unique value to it and then went back and read it again to check all was
working.