Home S-100 Boards History New Boards Software Boards For Sale
Forum Other Web Sites News Index    

The S-100 Bus FPGA Z80 SBC Board.
Under Construction
  FPGA_Z80_SBC_Picture
  
Introduction

The original S100 bus FPGA board has proven to be a very useful development board.  The board can be morphed into many functions.  If you are not familiar with that board it is essential you read up on that board before going any further here.  Much of what is written here assumes you are familiar with the "V1" board.  There also is an introduction to FPGAs and how to program and use them.

That "V1" board was followed up with a more generalized "V2" FPGA Prototype board which allows the user the experiment with simple FPGA circuits within the S100 bus.

We will now (again), move things up a notch and use the full power of the Cyclone IV FPGA. We will construct and program the FPGA to be a S100 Bus Z80 CPU board.  The board will act as a fully self contained S100 bus "Single Board Computer (SBC), somewhat similar to our earlier S100 bus SBC's (see here and here) -- but much more powerful.
The board contains:-

A 50MHz Z80 CPU FPGA module
An 80X40 line VGA character terminal with its own ROM character table and 4K graphics RAM
An FPGA internal two page (4K+4K) ROM containing the Z80 monitor along with diagnostics support for the IDE/CF Card.
An IBM PC PS2 keyboard input port (with input converted to standard ASCII)
A USB serial I/O port at speeds up to 38K to a PC
An SPI or I2C external connector interface
An interrupt controller for S100 bus interrupts.
Two SD Card slots  & an interface to R/W to the two cards
One IDE CF card to run our "out of the box CPM3" (exactly like out original Z80 SBC)
A Parallel printer port with Strobe/Ack etc.
An 8 bit IOBYTE input port and 8 status LEDs.
A buzzer
There is an FPGA interface to the onboard clock/calendar RTC chip with battery backup.
The board has 512K of onboard RAM that is page addressable to the Z80
There are numerous diagnostic LEDs all around the board for debugging etc.  


The Z80 CPU is completely built and programed within the FPGA.  There is no real Z80 or ROM chip on the board.!

While the board internally is quite complex,  externally it looks and behaves very simple. It will be an ideal board for somebody new getting into building an S100 bus system since with this board alone and a simple USB/FPGA programmer they can have a complete CPM3 system. Then gradually the user can inactivate various sections within the FPGA code and activate the corresponding old/new S100 boards they have in their system.   They can start off looking upon the FPGA as a black box.   In fact to get started you don't even need an S100 bus -- just hookup 8V to a jumper on the board and connect the onboard USB port to you PC system to act as a  TTY character terminal

Keeping in mind the above potential audience, I will try and over-explain some things below.  Our "hard core" audience can just skip ahead.  That said this is NOT a board for a complete electronic novice. Minimally you should have some soldering experience and knowledge of electronic circuits.  You should for example be comfortable with web sites that describe Arduino or Raspberry circuits.  You should have a basic understanding what a Field Programmable Gated Array (FPGA) is. If not, look them up on web.  In summary, these chips allow you to lay down any circuit you might come up with within the chip just like you might do by soldering hundreds of TTL/74xxx chips together as in the old days.  Its all done in software. The resulting code/pattern is then programmed into the chip.

What Is Needed
The FPGA we will use here is an Altera/Intel Cyclone IV FPGA.  This chip is currently in about the middle range of the programming capacity of FPGA's.   The actual chip uses a "Ball Grid Array" method of soldering it to a printed circuit board.  This requires very specialized equipment, so normally one purchases an "adaptor board" for these chips with the chip on it.  Besides providing "normal" pin attachments to (in our case), the main S100 board,  these adaptors contain a number of voltage regulators, Flash RAM, a programming socket  and other components these FPGAs require to operate.

As for our previous boards we will use the WaveShare "CoreEPCE10" Cyclone IV board adaptor. Its schematic can be seen here.
    
  CoreEP4C10 USB Blaster Adaptor Sockets
   
The second thing you will need is a device to program the FPGA chip itself. 
There are many FPGA programmers available. I really like the USB Blaster (V2) that Waveshare sells.  Its simple and reliable.  And importantly, works directly within Intel's Quartus V12 (see below).
The good news is; With this board you will not need to purchase a separate EEPROM burner, GAL programmer or CPLD programmer.

Somewhat unexpectedly you will need to pay particular attention to the special very tightly spaced pins on the above adaptor board.  Because there are so many FPGA output pins, its not practical to have a connector with the standard PC board 0.1" pin spacing.  The above WaveShare unit uses unusual 2 mm dual row pin connectors.  Unlike to normal 0.1" connectors these are quite rare an expensive.  If you solder these female sockets to the board the WaveShare adaptor sits quite high on the board and will prevent the next S100 bus slot from being used.  If you carefully remove the JTAG socket top border edge with a wire cutter - all around about 1/8 ", it will fit into most S100 bus motherboards without taking up two slots. Alternatively you can solder the adaptor directly to the S100 board. Of course removing the adaptor is all but impossible in this case. 

Please note the 2 mm dual row pin connectors (Digi-Key #S5750-30-ND sockets) for the WaveShare adaptor are quite tricky to fit on to the board.  I found the best way to do this (after trimming to size), is to push them half way on to the adaptor pins and then wiggle them to fit the whole unit on to the S100 board.  Figure on spending 10 minutes on this step!  Do not solder them to the board first and then try and press the adaptor down on them. They are very fragile and internally the leaves will bend if socket angles are not exactly correct.  When in place, check each pin is visible on the back of the board before soldering.  Only then solder all around.  Add as little solder to each pin as possible - the narrow pins have a tendency to wick up solder internally. 

Leonard Young recently pointed out better sockets are available from Mouser (Preci-dip 833-87-038-10-001101)  as part 437-8338703810001101 for $3.04 ea.  You’ll need a few, since 38 positions is a 2x19 strip.  To  cut to size. Clip with a wire cutter one pin past that required pins and then file down to size.

The rest of the boards components are standard -- available from Jameco, Mouser, Digi-Key etc. 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 actual IC pins. 
 

Programming the Cyclone IV FPGA
As mentioned above, in order to actually implement a circuit the FPGA must be programmed.  During board development the code is passed to a Flash RAM on our adaptor board from which the FPGA has enough intelligence to load it from there and run.   This means that if we power down the board that code is lost and the chip has to be re-programmed.  As we shall see below. when one is satisfied with the code there is a separate process to burn it into the chip so it is not lost upon power up.  This is a slower process and so is not normally done.  You can however program by both methods essentially an infinite number of times. 

There are two major languages to program FPGA's Verilog and VHDL.

Verilog was created by Prabhu Goel, Phil Moorby, Chi-Lai Huang and Douglas Warmke around 1984. Originally, Verilog was only intended to describe and allow chip hardware simulation. The automated synthesis of subsets of the language to physically realizable gates etc. was developed after the language had achieved widespread usage. Verilog stands for the words "verification" and "logic". There were many upgrades/extensions over the years. The last major version appeared in 2005.

VHDL was originally developed for the U.S Department of Defense in order to document the behavior of the ASIC chips that supplier companies were including in equipment. Because of this background much of the syntax was based on the Ada programming language. The language has undergone numerous revisions and has a variety of sub-standards associated with it that augment or extend it in many ways, the last major release being in 2008.

Usage between the two tends to be polarized. Probably because of its Ada/Pascal style VHDL seems to be more popular in Europe.  The "C'" style syntax Verilog seems to be more popular in the US. 

With both the above languages you can write programs line by line just like is C or Java etc. Alternatively you can use a newer graphic diagram approach which in the background converts your graphic diagrams into Verilog of VHDL code -- totally transparent to the user.  This approach uses  a special file called a
"Block Diagram File" (.bdf) (for Altera/Intel chips). The whole process is somewhat like writing a web site page.  You can either write the whole page yourself in HTML or use something like I'm using here (Expression Web),  to "draw" a web page in blocks, graphics etc.

Again, usage between the two approaches by people tends to be polarized.  The good news is that within IDE's you can import and export modules for both types.  You can for example see/export the Verilog code that makes up a complex
.bdf module or you can convert a Verilog module into a .bdf module.

Coming from by now, years of experience using KiCAD to lay out over 100's of S100 bus PC boards I personally found the .bdf approach of programming an FPGA very easy. Within a day or two I was up and running programming an FPGA with quite complex circuits.   This was possible because the Quartus IDE (see below), supplies libraries for things like all the common 74xx logic chips, many of the common VSLI style chips (e.g.. UARTs) etc. It contains many libraries of many extremely complex/useful modules such as CPUs.  While you can drill down for detail,  at a top level they behave as "black boxes". You just supply the wire or bus connections -- which you draw as lines.   It would take me months of learning to do the equivalent in raw Verilog code.  I will illustrate this below. 

BTW, there is one well known/subscribed source code site for FPGA's called OpenCores  where you will find an enormous list of FPGA projects/code.  There numerous other excellent FPGA code applications on the web. For example Javier Valcare's FPGA home page and fpga4fun.

Quartus Prime.
For Altera/Intel FPGA's the program of choice to program them is called Quartus Prime.  This a very large Windows based IDE interface. It is completely self contained with everything you need to write FPGA code and program the chips. Its an expensive software package. Fortunately Intel supplies a "Quartus Lite" free version for students and people like us.  Even this is way overkill for our use.  The most recent version can be downloaded from this Intel site.  The package will take ~20 minutes to install on Windows 10.  You may want to first review this video about the installing process.
 
Please keep in mind that programming an FPGA is different from the normal linear/sequential programming approach you may be used to.  On an FPGA everything is potentially happening at once.  Good FPGA programmers take years to excel and currently are in high demand.   Timing and power distributions across the chip almost become an art form.  Fortunately out needs will be far simpler.   Also there seems to be an excellent community of experienced people ready to help -- beginners.  I have found the Altera forum to be very useful and helpful.   However by far the best way to get started is to look at a few YouTube demonstrations.   

One outstanding YouTube video to get you going with Block Design File FPGA programming is this one by ClockFabrick Electronics Academy
A text summary is provided here.  If you cannot get to that YouTube video you can directly view it in the video below.
Note, click on the "full screen icon" for easy viewing. Use ESC to return.   
Also allow a few minutes for it to download.  It's a very large (50 minutes) video file.
         
 
 
  
For absolute FPGA beginners, rest assured,  you can more or less use the FPGA code examples below as "Black boxes" to get this board up and running. However you will be missing one major aspect of the board. By stepping along and understanding how the FPGA code works you will in the end have the ability to modify the board in amazing ways -- up to the point of even using a different CPU.

Before we start, a few things about our FPGA code file directory structures.   We will "build" our FPGA code in steps of increasing complexity. I have found out the hard way, that that you have to be very careful with Quartus where you place your files.  The actual Quartus "Project file" work 
Z80_FPGA.qpf  should reside in the main folder you will build your programs. In my case it happens to have a path:-

C:\intelFPGA_lite\18.0\quartus\MyFPGAPrograms\Z80_FPGA\Z80_FPGA.qpf

The above path (in yellow) is the root below which we will build all files in this project. Your path may be different but the Z80_FPGA directory must exist.
The actual
Z80_FPGA.bdf in this directory is our current "work file" which when compiled we use to program the FPGA.

You will notice in the download (see bottom of this page) , numerous
Z80_FPGA1.bdf, Z80_FPGA2.bdf , FPGA3.bdf...... files.  these are the main Z80_FPGA.bdf file of increasing complexity as we add FPGA components/modules  to our board.  The file Z80_FPGA.bdf is always the most sophisticated and current file constructed. It will get more complex over time. 

In every case as we build,  we first "Close" the current
Z80_FPGA.bdf file it within Quartus.  Note not the project file (Z80_FPGA.qpf).
We then go outside of Quartus into windows and delete (or rename) it.
We then take the next more complicated
Z80_FPGAx.bdf file (Z80_FPGAx+1.bdf) and rename it Z80_FPGA.bdf
We then go back to Quartus and open this
Z80_FPGA.bdf file and work on it.

The key thing here is Quartus does not know we switched files on it.  This way all pin designations, ROM and RAM preloaded .HEX files remained unchanged.  Plus other things.  If you start flipping files around renaming them etc., within Quartus it gets confused -- without telling you.

I cannot stress enough the trick of saving old
.bdf files, renaming them etc. along the way. This way you can easily fall back to the last good working example.  Saved my neck many times!

A few things about Quartus.

1. It constructs a number of sub-directories as it constructs its FPGA code below the Z80_FPGA. You don't  have to bother about them.

2. As Quartus compiles your code,  it seems to send out endless information in messages. Again don't bother about them unless it tells you (in red text) that there are errors at the end.


3. Be very careful when you place copies of a logic item. Sometimes when you click you can place one item exactly over another yet the item appears as only one unit. For example a NOT or a NOR gate. The compiler will insist the gate has no input when in fact there is a hidden gate under it.

4. Be careful when you join up and input or output port to a wire or bus line. Make sure they join by dragging them apart.

5. Some gates are negative true. I use names like pWR- to signify this. Quartus does not accept pWR*.

6. Be sure you assign actual pin numbers to FPGA inputs and outputs. Quartus does not tell you if they are unassigned.

7. As I said above build a circuit in stages of increasing complexity saving versions along the way.

8. Be sure the designated FPGA for a new project is a EP4CE10F17C8  FPGA for the above WebShare board.

BTW, the actual compiling and programming process takes longer than you might expect (~3minutes for the complete program).



Step By Step Building the FPGA Z80 SBC 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.
   
Solder in all the required IC sockets, resistors, resistor arrays, capacitors, jumpers, and the Pololu 5V and 3.3V (LM3940) voltage regulators.  Do not add the LED's yet. Also do not add the MicroSD Card Adaptor. 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).  Insert all jumper arrays.  Note there are two sockets for the Pololu 5V regulator. While the older ones (D24V25F5) are still available, it seems Pololu is suggesting users use the D24V22F5's (5V, 2.5 Amp) units.  

Please take care to not "slobber" solder on the sockets. They are very closely spaced on this board with vias often close to a socket pin - particularly for the FPGA adaptor sockets.  Note, RR4 Pin 1 is on the RHS.
  
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.  Solder in the buzzer SP1 with the "+" pin on the RHS. You may wish to play around with the buzzer sound volume by replacing the 100 Ohm resistor R11 with a lower one say 75 Ohms or 33 Ohms to get a louder buzzer sound later. So solder it high on the board for easy removal.

Here is a picture of the board at this stage (With the WaveShare FPGA Inserted):-
    Build0
For testing remove every S100 bus board in your system except (if you have one, the S100 Bus SMB and/or the Bus Display Board).  If you have neither of these boards you must press the reset button (
SW2) on the board itself to run the actual FPGA program (after uploading it). As we shall see below during the software build, there are two options for the Z80 monitor console IO. If you have a Propeller Console IO Board, great, use it. If not, you will need to use the onboard USB port connected to a TTY terminal on your PC for monitor IO.  The former option is much better and far easier to get going. It will be a few steps down before you have a working USP port. Except for looking with a logic probe at critical signals you will be in a sense flying blind in that case.

Lets get started, Place the board as shown above in the bus without any chips  inserted, (including the Waveshare FPGA adaptor). There are two separate voltage rails on this board 5V and 3.3V. Carefully examine the schematic and check the voltage to the individual sockets are either 5V or 3.3V.  Be sure you have 3.3V and 5V going to the appropriate pins on the Waveshare FPGA adaptor socket.   

If you are comfortable with the above, carefully insert the WaveShare Cyclone IV adaptor in its sockets.   Power on the  computer.  "Virgin" Cyclone IV Adaptor boards from WaveShare seem to have the FPGA preloaded with a program (in the EPCS16 Flash RAM) that already that pulses its 4 onboard LEDs.  Note the rate of flashing rate.

Within Quartus open the Project file Z80_FPGA.qpf (see above), then open the file Z80_FPGA0.qpf
.  (These are available at the bottom of this page). When loaded, "Compile the Design", then "Program the Device" and then hit the "Start" button.  The LED's on the Waveshare adaptor should flash differently. To confirm, kill the power and reboot the computer. The code in the FPGA is lost so the original flashing rates should reappear.   Note,  if you are using a previously programmed FPGA adaptor with code "burnt" into the FPGA the power-on flashing will probably not be present.  In fact,  Waveshare may in the future supply adaptors without the flashing code in them.   Here are some pictures:-
   
    Quartus Run 1
   
  Quartus Run 2

Very important the LED D10 "BOARD_ACTIVE" should be flashing.
This is your first connection of the FPGA adaptor to the outside world!  Do not go forward until you see this response.

1. The address line test.
We will next load a simple FPGA program to test our S100 bus address lines connection to the bus.
Within Quartus, close the current Z80_FPGA.bdf file.  Note,  not the project file (Z80_FPGA.qpf).
Then go outside of Quartus and into windows and delete (or rename) it.
Then take the next more complicated file, Z80_FPGA
1.bdf, and rename it Z80_FPGA.bdf
Then go back to Quartus and open this Z80_FPGA.bdf file and work on it.

First look it over carefully to understand what is happening. It's in essence just a 16 bit counter increasing the S100 bus address lines.
Here is a picture of part of the core module.
   

  Address Line Test 0
   
  Address Line Test 1
 
You see we also pulse the pSYNC, pSTVL, and pDBIN. This is because the S100 Bus SMB and/or the Bus Display Board do not display the actual S100 bus address lines unless they are latched into the LED displays by these signals.  Do not get too hung up on the accuracy of this circuit its just a quick and dirty emulator for Z80/S100 bus signals.
 
That said,  the address lines on the bus should be continuously changing.  If not check the signals going to (3.3V) and coming from the 74LVC245's 
U8 & U10 as well as the Address line buffers U14, U15 & U16.

2. The address Line Test Using the Z80 FPGA Core CPU.

Next we will do the exact same thing using our "real" Z80 to increase the address lines.  For the Z80,  an input of the opcode 00H on its data lines will do nothing. The CPU just goes to the next higher address. So if you ground the 8 data lines of a Z80, after a reset it will read in the 8 data lines at address 0000H. See its a nop and do the same for 0001H.  It will continue to do this all the way up to FFFFH and then roll-over to 0000H again.  This is in effect what we have in our Z80_FPGA2.bdf file.  So as before...

Within Quartus, close the current Z80_FPGA.bdf file.  Note,  not the project file (Z80_FPGA.qpf).
Then go outside of Quartus and into windows and delete (or rename) it.
Then take the next more complicated file Z80_FPGA
2.bdf, and rename it Z80_FPGA.bdf
Then go back to Quartus and open this Z80_FPGA.bdf file and work on it.

Add U9 and U11.

Again, look it over carefully to understand what is happening. It's in essence using the Z80 module as a 16 bit counter to increase the S100 bus address lines. Here is a picture of part of the core module.
   
      Address Line Test 2
    
You should see the address lines increase from 0000H after hitting the reset button SW2.
Also the increase should stop if you push the RDY or XRDY button on the SMB.
Don't get too hung up on how the S100 bus signals are generated. It's a "kludge" to fool the SMB or Bus Display board to latch the address lines.


3. The ROM test with Z80 Core CPU.
First add
U4, U12, U17, U13,

We will now add some intelligence to the Z80. We will hook to its data in lines a ROM module programmed within the FPGA. 

Within Quartus, close the current Z80_FPGA.bdf file.  Note,  not the project file (Z80_FPGA.qpf).
Then go outside of Quartus and into windows and delete (or rename) it.
Then take the next more complicated
Z80_FPGA3.bdf file and rename it Z80_FPGA.bdf
Then go back to Quartus and open this
Z80_FPGA.bdf file and work on it.

Look it over carefully to understand what is happening.

The actual ROM module is obtained from one of the Quartus IP libraries.

The Z80 will start off as before reading in 0's on its data in lines until the address
F000H is reached. At this time the ROM's
OE* "pin" is activated and the Z80 starts reading the ROM at address
F000H.  The ROM has the following simple code:-

START: LD     A,33H
       OUT    01H,A
       JP     START


in actual bytes this would be:-
3E,33H,D3,01,
C3,00,F0

This will output continuously 3's on the Console IO port. 
If you are using the USB port only and a PC connection,  sorry, you will only see
pin 17 of U8 pulse with a logic probe.

Its important to appreciate that while the code runs at
F000H within the Z80's address space the actual code must start at 0H within the ROM.  Quartus expects an "Intel" HEX file format for ROM code. Simple code like the above can actually be entered by hand using most ROM programmers software.  You can for example download the software for a Wellon VP299 (or later) Programmer from here:-

http://www.weilei.com/dow.asp

and install it. You do not need hardware to run it.

Here is a picture of the two relevant steps to make a "
PORT_TEST.HEX" file for use with Quartus.  The file is actually supplied below,  but you need to know how to make Quartus .HEX compatible files.  The
PORT_TEST.HEX file must reside in the FPGA ROM starting at the ROM's 0H location.
  
   ROM1
   
  ROM1a
 
It's very important you select the Intel File format and the buffer address starts at 0H

Next we need to insert an actual FPGA ROM.  Modules like this are supplied in the Quartus IP library. 
In our application we will use a simple 8 bit, 8K ROM.  Way overkill here,  but we will use most of it later.
We will position the ROM in the
Z80_FPGA.brd file to start at F000H. We need to load the above .HEX file into this ROM within Quartus.
 
Generally the ROM .HEX files will not be made/stored in the Quartus sub-folders. You need to point Quartus to them.  
The good news is that once you define the .HEX file path and name, Quartus will always find it for subsequent FPGA builds.  You don't have to reload them each time into the ROM module. 
  
To insert the actual
HEX code into a ROM follow the pictures below.
 
    ROM2   ROM2a
   
Let's look at our FPGA code "hardware"
ROM_Boot_Circuit
 
The FPGA coded 74682 goes low when the Z80 reaches address F000H.
This triggers the Flip-flop (FF)
JMP_ENABLE low so the address lines are no longer grounded.  It also enables the FPGA ROM and the tri-state buffer from its data lines so the ROM now supplies data to the Z80.  From it code to continuously send 3's to the Propeller Console Data out port is sent.  You should see something like this on your console.
     
     Output 3s
   
Note it takes about 1 second for the '3's to start to appear because we are using a very slow CPU clock at this stage.
You must get this FPGA program working before going any further.
If you don't have a Propeller Console IO board be sure you see
U4 pin 19 is low and U8 pin 17 is pulsing with a logic probe.


4. Adding the Z80 to S100 Bus Interface
The above step simply used the raw write signals from the Z80 module. We need to very carefully modify them so that they generate the corresponding signals of the S100 bus as specified in the IEEE-696 specifications.  Only then can we be sure the board will work with other S100 bus boards.

The FPGA circuit we use to do this is a direct copy of that on our
Z80 SBC  (and the original Z80 board).  These boards are very reliable the latter now being over 10 years old.  Unfortunately the actual circuit is a little complex. It's actually a close copy of the Intersystem's Z80 board from which Mark Garetz came  -- one of the IEEE-696 authors.  Most users can look upon the circuit as a "black box".  Z80 signals go in, S100 bus signals come out.

Before we look at the actual FPGA code we need a few more FPGA support chips.  Add  U7  (for S100 bus data in).
 
Within Quartus, close the current Z80_FPGA.bdf file.  Note,  not the project file (Z80_FPGA.qpf).
Then go outside of Quartus and into windows and delete (or rename) it.
Then take the next more complicated Z80_FPGA4.bdf file and rename it Z80_FPGA.bdf
Then go back to Quartus and open this Z80_FPGA.bdf file and work on it.

Again, look it over carefully to understand what is happening.  In essence its a repeat of the previous version except now we send out "proper" S100 bus signals.

Here is a picture of the main Z80->S100 bus conversion module.
  
     S100 Converter Module
    
You should see the exact same 3's output on your Propeller Console IO board.  Or for USB port users, pulses on
U8 pin 17.


5. Adding RAM to the Z80_FPGA Board.
Next we will check Input from a port is working.  Add U7.
We will modify the above  "PORT_TEST.HEX file to the following:-

ROM has the following simple code:-

START: LD     A,33H      ;Display '3'
START2:OUT    (01H),A
       IN     A,(01H)    ;Get a keyboard character
       JP     START2


in actual bytes this would be:-
3E,33H,D3,01,DB,01,C3,02,F0

We will call this
PORT_TEST2.HEX.  Load it into the FPGA ROM exactly as described above. Compile and run the Z80_FPGA.bdf file.
Press a keyboard character. You should see it displayed on the Console.  Again USB port users should look for pulses on U8 pin 17.

You must get this program working before going further.



6. Adding RAM to the Z80_FPGA Board.
Next we need to add RAM access to our Z80 module.  This is where things get a little tricky.  First you will notice that the Z80 FPGA module as written, has a separate 8 bit data in and a separate 8 bit data out bus.  This makes things very convenient to interface with the S100 bus which also has separate in and out data lines.   We will however be using a "real' RAM chip on this board (
AS6C4008, 512X8 SRAM chip).  Like all such RAM chips,  the data lines are bidirectional.  We need to accommodate this within our FPGA for Z80 RAM access.   We do this with the following FPGA circuit. We handle each of the 8 RAM data bits with the following circuit.
    
  RAM Interface
 
Eight of the dual tri-state buffers are used with the FPGA pins that directly interface the RAM chip (U5).  Note the RAM chip itself has a VCC of 3.3 Volts. (This chip will work at 5 or 3.3 Volts).  The OE* and WR* signals from the FPGA are also 3.3 volts.  Most important the address lines are 3.3V coming directly from the FPGA.  This as we will see later allows us to run a very fast clock for the Z80 module itself

A second complication is that data to the Z80 may come from circuits on the Z80_FPGA board itself or from the S100 bus.  Again we must accommodate this within the FPGA.  Since the Z80 has separate in and out data lines this simplifies things.  For data out its simple, the data can go to both locations (s100 bus or the FPGA "circuits" on the board),  the Z80 control and status lines within the FPGA define which are relevant.

For data in however we must control which 8 bits actually reach the Z80.  We use the following circuit:-
   
    Data In Circuit
   
Basically we will assume any Z80 data input comes from the S100 buss unless told otherwise. In the above,  for now, ANY Z80 input from an I/O port..
As we developed our FPGA circuits below we will add exceptions to this by supplying negative signals to the 8 input AND gate.  (Remember HIGHs activate the tri-state buffers)..

Within Quartus, close the current Z80_FPGA.bdf file.  Note,   not the project file ((Z80_FPGA.qpff)..
Then go outside of Quartus and into windows and delete (or rename) it..
Then take the next more complicated Z80_FPGAA6.bdf file and rename it Z80_FPGA.bdff
Then go back to Quartus and open this Z80_FPGA.bdf file and work on it..

To test our new addition we need to change the code in the FPGA ROM to
RAM_TEST.HEX file derived from RAM_TEST.Z80
The core of the RAM_TEST.Z80  file is:-

COLD: LD HL,RAM_BASE                 ;We will check we can store and change a byte at RAM location E000H

RAM_TST:
     LD    A,'@'                     ;For quick hardware diagnostic test
     OUT   (S100_CONSOL_OUT),A       ;Force a "@" on the CRT if ROM access is active
     LD    (HL),'?'                  ;Default 3FH
     LD     B,0FH                    ;Count 16 times

PROP_CI1:
     IN     A,(S100_CONSOL_STATUS)   ;Get a character
     AND    02H
     JR     Z,PROP_CI1               ;Wait until something there
     IN     A,(S100_CONSOL_IN)
     AND    7FH
     LD     (HL),A                   ;Store in RAM

PROP_CSTS1:
     IN     A,(S100_CONSOL_STATUS)
     AND    04H
     JP     Z,PROP_CSTS1             ;Z if not ready
     LD     A,(HL)                   ;Get stared value from RAM
     OUT    (S100_CONSOL_OUT),A
     DJNZ   PROP_CSTS1               ;Do 16 times

This time it's a little too much to do by hand.  Its supplied below,  but you should know how it is done/assembled by opening up the RAM_TEST.Z80 in its own folder and generating a hex file RAM_TEST.HEX with your favorite Z80 Assembler. See here. Again as described above, while the actual code resides in the Z80's address space at F000H it must reside in the ROM at 0H.  

Repeat the process described above.   Do not save the file with the same name, I use RAM_TEST_FPGA_ROM.HEX.  Then go to Quartus and program the FPGA ROM with the RAM_TEST_FPGA_ROM.HEX
file -- again as described above.

Then compile, load, and run the Z80FPGA.bdf file.

You should see that the value is not stored  in RAM and will give you a display like this:-
  
    RAM Test1
 
As you can see above we are saving a byte in RAM and then reading it back from RAM and sending it to the console.
Again unfortunately if you only have a USB port console you are still flying blind just seeing
U8 pin 17 pulse.

At this point you are well on your way to having a working board. You have a Z80 CPU, ROM and RAM and IO/Pore addressing. 
You can if you like at this stage load the boards main monitor
SBC-MON2_4+4K.HEX, supplied below.  It will sign on like this:-
  
    Monitor Signon
  
Please note that at this stage not all of the menu options will work (A,D,E,F,G,J,K,M,Q,R,S,T,V,Z).
Here is a picture of the board at this stage:-
  
    Build 1


7. Adding the IOBYTE, Wait States & RAM Bank Selection to the Z80_FPGA Board.

We will now add the ability to direct where Console IO data will come from and be sent to.   We do what we have always done with our S100 bus CPUs, we utilize a few bits on a read/write port that are utilized by the Z80 ROM based monitor to decide where console I/O originates.  This is an age old approach first used in S100 bus systems in the TDL SMB and its Zapple monitor.

On this board in its current final form (see below), there are 4 different I/O possibilities for a Console for the Z80 Monitor (and CPM).
1.  The Propeller Console IO board.
2.  A USB port connected to a PC and a TTY character terminal.
3.  For both of the above,  the keyboard can instead come from a PS2 keyboard connected to the boards PS2 socket P20 or P22
4.  For all 3 of the above,  the Console output can instead go to a VGA display connected to the boards VGA socket J1 or P21


The decision in the Z80 monitor is based on the lower 4 bits of the 8 bit IOBYTE port. Defined as follows.
 
xxxxxx11 All console IO goes via the Propeller Console I/O board.  
xxxxxx10  All console IO goes via the USB port/PC TTY terminal
xxxxxx0x  Input for the console (above) is  overridden and always comes from the PS2 keyboard.
xxxxx0xx  Output for the console (above) is overridden and always goes to the onboard VGA display.

So for example if the IOBYTE port is absent/ non-functioning (11111111),  all Console IO will be via the Propeller Console I/O board.  
If the
IOBYTE port is xxxxx00x the PS2 Keyboard and VGA display would be the Console.

First add  and set the dip switch SW3 to all open.  Add U3.


Within Quartus, close the current Z80_FPGA.bdf file.  Note,  not the project file (Z80_FPGA.qpf).
Then go outside of Quartus and into windows and delete (or rename) it.
Then take the next more complicated Z80_FPGA
7.bdf file and rename it Z80_FPGA.bdf
Then go back to Quartus and open this Z80_FPGA.bdf file and work on it.

On this board we assign port
36H as the IOBYTE port.  This BTW is the same port we use on the Z80  SBC Board
However the meaning of the bits is different.

Here is a picture of the relevant FPGA circuit.
   
  IOBYTE Circuit
  
Most of this circuit we will not use quite yet.  We only want to read the value of the 8 dip switches (SW1) addressed at port 36H.
Close one or more of the upper IOBYTE switches and reset to board.  They should display correctly on the monitor Signon.

Next Display/Fill RAM at 0-100H
Output to port
36H 01H.
Again display RAM at 0-100H. It should be different. Also LED D17 (High RAM) should light up.
Output to port
36H, 00H.
The original RAM values should re-appear.

Note while the current configuration allows only two 32K pages for banked CPM (see below). The circuit can easily be modified/enlarged for more.

>>>>>>>>>>>>>>>>>>>>>>>>>..

8. Adding the USB Port to the Z80_FPGA Board.
We will now add a USB Port for Console I/O to the board.

the ability to direct where Console IO data will come from and be sent to.   We do what we have always done with our S100 bus CPUs, we utilize a few bits on a



We will also add the USB port interface for our long suffering users that do not have the Propeller Console IO Board. Here is the core circuit for the USB interface.
  
      USB port Module
    
This is an example of how powerful and useful these FPGA .bdf modules are.  Incorporating a USB port from scratch on an S100 board would be quite an undertaking in terms of hardware.  Granted you could use one of the many USB port adaptors, but here we do everything with just a few FPGA pins.

We have one further thing to do. Because data from the IOBYTE port and USB port will be coming into the board via these modules and not the S100 bus,  as explained above we must send the data to the Z80 in data bus directly. We prevent the S100 bus tri-state buffers from becoming active using this circuit.
   
     Data In Circuit 2

We will also update the ROM again. We will write a small Z80 program to read the IOBYTE port and display its value on BOTH the Propeller and USB consoles.  It is called
IOBYTE.Z80.  Its supplied below,  but you should know how it is done/assembled by opening up the IOBYTE.Z80 in its own folder and generating a hex file IOBYTE.HEX. Again as described above, while the actual code resides in the Z80's address space at F000H it must reside in the ROM at 0H.  How to do this is described above.  Then compile, load, and run the Z80FPGA.bdf file.

By flipping the dip switches at
SW1 you should see the correct bit pattern displayed.  It's essential this test works correctly before going further.
Here is a typical display on the USB port Console.

    

9. Adding Wait States and Z80 Monitor.
Up until now we have been running the Z80 with a 4Mhz clock.  We will now add a simple wait state circuit to allow the Z80 to run faster in different hardware situations.  The circuit we will use it similar to that of our
Z80 CPU board.
Here is the core circuit.
    
      Wait States
  
We will now again change the onboard ROM code. We will use the Z80 monitor specially written for this board called Z80_MON2.Z80. This is a fairly sophisticated menu driven monitor. However not all menu options will work at this stage.

There is one "complication" with this monitor. It’s almost 8K in size when assembled. Rather than set its origin to E000H and up to FFFFH we will use a trick we did previously for the Z80 CPU board MASTER.Z80 monitor, will write it in two "pages" of 4K each. The monitor will reside at F000H-FFFFH and flip its two 4K pages on the fly - as need. We set the "LOW" or "HIGH" 4K page by flipping the ROM's A16 address line using the following circuit.
    
    ROM_A16

This way we get two 8K of code into 4K -- leaving more room for CPM.  As we shall see later, the Quartus FPGA library can be programmed for a 16K ROM so this trick can be used extensively to get more ROM code into this 4K space --- The ROM Address lines A16, A17 & A18 are programmable within the FPGA.

The only tricky part is programming the FPGA ROM or rather generating a .HEX file for the FPGA ROM.  If you are not familiar with the above "page" concept you should first read this page.

Different PROM Burners probably have different ways of doing this. Here is the process for a  Wellon VP-290 (or VP299) with 28C64's EEPROMS. Again remember, you do not need the Wellon hardware to run their software.

Assemble and make two .HEX files, Z80_MONA.HEX and Z80_MONB.HEX from Z80_MONA.Z80 and Z80_MONB_Z80  (available at the bottom of this page).  Use the Wellon programming program to combine these files into a single .HEX file for the FPGA ROM. Here is a step by step account

 

Load the file Z80_MONA.HEX with the following settings:

For File Mode use "Normal" and Clear Buffer Options = Enable
Leave the "To Buffer Address (HEX) as 0000
Set the "File Address(Hex) as F000 and the
For "Auto Format Detect" use Intel
Leave the File size (for a 28C64) to 2000

Load the file Z80MONB.HEX with the following settings:

For File Mode use "Normal" and Clear Buffer Options = Disable
Set the "To Buffer Address (HEX) as 1000
Set the "File Address(Hex) as F000
For "Auto Format Detect" use Intel
Set the File size (for a 28C64) to 1000

Save the file as Z80_SBC_4K+4K.HEX with the following settings:


For Intel HEX Mode
Set the "To Buffer Address (HEX) as 1000
Set the "File Address(Hex) as F000
For "Auto Format Detect" use Intel
Set the File size (for a 28C64) to 2000

Be sure you set the last 2000. The program default is 1 byte!
Note where the final
Z80_SBC_4K+4K.HEX file is stored.

Within Quartus, close the current Z80_FPGA.bdf file.  Note,  not the project file (Z80_FPGA.qpf).
Then go outside of Quartus and into windows and delete (or rename) it.
Then take the next more complicated Z80_FPGA
7.bdf file and rename it Z80_FPGA.bdf
Then go back to Quartus and open this Z80_FPGA.bdf file and examine it.

Program the FPGA ROM with the above Z80_SBC_4K+4K
.HEX file as described above.
Then compile, load, and run the Z80FPGA.bdf file.

If the IOBYTE switches are set to
xxxxx111B the following output should appear on the Propeller Console IO Screen.
  
    
   
If the IOBYTER switches are set to
xxxxx110B the same output should appear on the USB port PC TTY terminal.
You can try the Z80 monitor A,D,M,S,T and Z commands immediately.

While now is not the time to optimize the Z80 CPU clock speed, the next few upgrade steps will use a 25mHz CLK rather then the 4 MHz we have been using up to now.


9. Adding the IDE-CF Card Interface and running CPM (Unbanked).
If you are not familiar with our IDE-CF card interface please read
this section first. Also look at how CPM was configured and brought up on the Z80_SBC S100 board.  If you happen to have an unbanked version of CPM configured for the Propeller Console IO already on a CF card and used with the Z80_SBC board you can use it directly here. If you are using a USB port PC TTY terminal you must modify the CPM BIOS first or load a CF-card with CPM System files supplied below.  Carefully see here for information as to how to do this.

Add the IDE-CF card hardware:-  Ux,ux,ux and the IDE-CF card adaptor.  Here is a close-up picture.
   
   
      
  
Within Quartus, close the current Z80_FPGA.bdf file.  Note,  not the project file (Z80_FPGA.qpf).
Then go outside of Quartus and into windows and delete (or rename) it.
Then take the next more complicated Z80_FPGA
8.bdf file and rename it Z80_FPGA.bdf
Then go back to Quartus and open this Z80_FPGA.bdf file and examine it.

Here is the core IDE-CF Card interface within the FPGA. 
  
    IDE Interface
   
You will note that this time the actual 82C55A interface is a "real" physical chip rather than one programmed within the FPGA, see the
Z80_FPGA schematic.  The latter could easily be done but the requirement of a 5 volt interface (and so 74lVC245 level shifters),  and  40 I /O pins would chew up too much board  real estate and FPGA pins.

Program the FPGA ROM with the above Z80_SBC_4K+4K .HEX file as described above.
Then compile, load, and run the Z80FPGA.bdf file.

Be sure you have the CF Card jumpers as shown above. Insert a CF Card with CPM -- an unbanked version.  Bring up the Z80 Monitor and select the IDE Menu
I command. The is way more than is normally needed here but just to be sure see you can read a few CF card sectors with the S command. The go for the Jackpot and hit the P command to boot CPM. Here is what you should see:-
   
     
  
If you don't,  try and use the IDE Menu commands to try and figure out what is the problem.



10.  Adding the PS2 Keyboard and VGA Video Interface.
If you are not familiar with our IDE-CF















-------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Under Construction
   
NOT VALID TEXT


Burning FPGA Code to Flash RAM
Up until now whenever we programmed our FPGA via  the JTAG socket the data is lost whenever the power is turned off.   While fine for code development etc. it is not desirable for a final board configuration.  Like most FPGA applications the "final" code is saved in Flash RAM and immediately loaded by the FPGA each time upon power-up.  This is a standard and common characteristic of most FPGA's. Some older models in fact had a ROM onboard.    Our Cyclone IV Adaptor board has 16MB of Flash RAM on board for this purpose -- way more than we are ever going to need!

The tricky part is programming this Flash RAM.  I found the Intel documentation poor and confusing.  Here is a summary of the process: 
Within Quartus you need to "convert" your normal JTAG FPGA .sof programming file to a special file .jic to program the Serial Flash RAM chip on the Weveshare board.

Within Quartus, click on the File Menu and select "Convert Programming files". The dialog box below will popup.
From the dropdown box on the "Programming File Type"  select a .jic file type.
This is the file format that is required to program the onboard serial Flash RAM.
For the Options/Boot info select EPCS16. Leave Active Serial as is.
You can name the .jic output file anything you like. I usually just leave it output_file.jic.
Note it will be in the Quartus generated "output_files" folder within your work directory.

Next click on Flash loader within the lower "Input Files to Convert", then click on the highlighted "Add Device" button.
You will get a popup dialog box as shown below.
Select Cyclone IV  and EP4CE10.  Note Quartus takes some time to allow you to actually select these options -- seems to be doing things in the background!
Next click on "SOF Data" and "Add File".  You should see your "normal" FPGA program .sof file in your "output_files" folder within your work directory.
Finally click the "Generate" button.
You should get a popup dialog saying "Generated output_files/output_file.jic successfully.
Note the name and location of the converted file. Then close that dialog box.  See the pictures below.
                
    Programming 1     Programming 2
 
Programming 3 Programming 4
   
Programming 5
  
Next we need to actually flash the Waveshare boards RAM chip.
Click on the normal "Program Device (Open Programmer)" you normally use. If its not already open,  give it time to come up as a dialog box.
Make sure your board has power.  To be safe click the Auto Detect button. your normal xxx.sof file should display with the device set as EP4CE10F17.

First delete the above line xxx.sof  |  EP4CE10F17 etc.
Click on Add File and select the xxx.jic file (in your file_output directory) you generated above.
Click on the Program/Configure little square character.
The Start button should highlight.
Click on this and you will flash the RAM chip.  Follow the Progress bar until it is done.
You can power off and re-power your computer.
Your FPGA board should (after reset), start with whatever FPGA code is within the chip.
 
Programming 8
 
Note when you close the above dialog box, normally you do NOT save the changes.
Typically you want the chip to be quickly reprogrammable.

Bugs

There appears to be a few variations of the 74LVC245 20 pin DIP level Shifters chips with "A", "AN" etc after the 245.   As best I can tell so long as they are 20 pin DIPs they are all OK. I use Mouser chips # 595-SN74LVC245AN.   The WaveShare Cyclone IV adaptor can be obtained directly from WaveshareThe WaveShare unit uses unusual 2mm dual row pin connectors. Unlike to normal 0.1" connectors these are quite rare an expensive (Digi-Key #S5750-30-ND). You need to carefully cut them to size, carefully cutting off the extra pins with a wire cutter.  The USB serial Adaptor is from Sparkfun F1231x.  The Micro SD Card adaptor is from AdaFruit.

Please note the Digi-Key #S5750-30-ND sockets for the WaveShare adaptor are quite tricky to fit on to the board.  I found the best way to do it is (after trimming to size), push them half way on to the adaptor pins and then wiggle them to fit the whole unit on to the S100 board.  Figure on spending 10 minutes on this step!  Do not solder them to the board first and then try and press the adaptor down on them. They are very fragile and internally the leaves will bend if socket angles are not exactly correct.  When in place, check each pin is visible on the back of the board before soldering.  Only then solder all around.  Add as little solder to each pin as possible - the narrow pins have a tendency to wick up solder internally. 

Leonard Young recently pointed out better sockets are available from Mouser (Preci-dip 833-87-038-10-001101)  as part 437-8338703810001101 for $3.04 ea.  You’ll need a few,  since 38 positions is a 2x19 strip.

To remove the adaptor,  leaver each corner up a little going round and round. The first time its quite difficult to get the adaptor out. It gets easier with time.


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 S100Computers Forum, a "group purchases" is now open. Contact and join the group if you would like to be involved in this project.  Please see here for more information.
 
Please note the final verson of this board (V2.1a) differs very slightly in the placement of some of the components shown on this page. 

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.

PORT_TEST.HEX
PORT_TEST2.HEX         
SBC-MON2_4+4K.HEX
                                    



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

This page was last modified on 07/18/2019