8088 FPGA IP Core
Last Updated: 25-June-2014
Die shot 8086
Introduction date: June 8, 1978
Modelsim 6.0a & debug.exe
On this page you will find an FPGA IP Core implementation of an 8088 processor. The CPU86 core is binary/instruction compatible with an iAPX8088 processor and can be implemented in any modern FPGA. The core is however not cycle or timing accurate. The CPU86 is ideally suited for a small embedded 8088 legacy system.
The CPU86 comes with a simple testbench instantiating the processor core together with a 256 byte ROM model, a 256Kbyte SRAM model and a 16750 UART from opencores.org. The SRAM model is pre-loaded with the MON88 debugger and the ROM contains a simple "Jump to MON88 after reset" program. The testbench monitors the UART and copies any newline terminated strings to the Modelsim transcript window, it also contains a simple function to transmit command strings back to the debugger.
The CPU86 source code is licensed under the GNU General Public License.
Download Source Files
- Download CPU86 IP source files (version 0.83, 581KB, zipped)
Version 0.83 : Added ghdl script created by Lubomir Rintel, fixed package file.
Version 0.82 : RCR REG,CL with CF set not always produced the right results, fixed.
Version 0.81 : Fixed CALL [REG] instruction, under certain circumstances the segment register was not set to use CS.
Version 0.80 : Minor update, changed ISE to version 11.1, it now simulates under ISIM.
Version 0.79 : All source code released under GNU, fixed DAS/AAA/AAS instructions, 26 June 2008.
Version 0.75 : Transferred some bug fixes from the HTL8088 to the CPU86. Amongst the bug fixes are the Divide by Zero interrupt fix, LES SI,[SI+n] fix and AAM/AAD instruction fix.
Version 0.70 : Fixed trace interrupt (broken in ver 0.68). Split design into individual files so that it can be synthesized with XST. Changed UART to opencores one. Replaced vendor memory models. Simplified simulation.
Version 0.69 : Fixed INTR logic and SHL instruction.
Version 0.68 : Fixed INTA vector read, version 0.67 always read 0 during the second INTA cycle.
Version 0.67 : Synthesisable version Released on the web 22 December 2005
Version 0.10 : Simulation model only, 02 October 2004
Directory structure in zipfile:
|CPU86\bin||Contains the different conversion programs (Windows, DOS).|
|CPU86\cpu86_rtl||CPU86 Synthesizable VHDL Source files.|
|CPU86\drigmorn1||Implementation example for the Enterpoint Drigmorn1 board, ISE 12.1 project file is included.|
|CPU86\Modelsim||Modelsim Simulation batch file.|
|CPU86\Opencores||VHDL source code for the Opencores 16750 compatible UART.|
|CPU86\Software||ROM, MON88 and some example asm source files.|
|CPU86\testbench||Contains VHDL testbench files for CPU86+UART+256Byte ROM (see top_rtl dir).|
|CPU86\top_rtl||Contains simple top level example file used for Simulation only.|
- Modelsim 6.5a SE, Note: PE, OEM and older versions of Modelsim can also be used
- Eric Isaacson free A86 assembler (Optional)
- MON88 Debug Monitor (source and hexfile included in the zipfile)
- Precision RTL Synthesis (Synplify, XST and QNS can also be used).
Simulation using Modelsim
- Download the zipfile and unzip to a suitable directory (keep the directory structure)
- Open a DOSBox or Cygwin Shell and navigate to the CPU86/Modelsim directory
- Make sure that the Modelsim win32/win32pe directory is in your search path, then execute run.bat
Modelsim will be invoked in the command line mode (vsim -c), the output should look something like this:
# RD UART : MON88 8088/8086 Monitor ver 0.12
# RD UART : Copyright WWW.HT-LAB.COM 2005-2008
# RD UART : All rights reserved.
# RD UART :
# RD UART :Cmd>R
# RD UART : AX=0000 BX=0001 CX=0002 DX=0003 SP=0100 BP=0005 SI=0006 DI=0007
# RD UART : DS=0380 ES=0380 SS=0380 CS=0380 IP=0100 ODIT-SZAPC=0000-00100
# RD UART : 0380:0100 0000 ADD [BX+SI], AL
# RD UART :Cmd>DM 0100-0124
# RD UART : 0380:0100 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
# RD UART : 0380:0110 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
# RD UART : 0380:0120 00 00 00 00 ....
Note: if you compile the files manually then make sure you suppress all warnings from the Synopsys and IEEE Numeric packages (see CPU86/Modelsim/tb.tcl for the Modelsim commands). If you don't do this then the UART messages will be lost in the large number of UXWZ warning messages.
# ** Warning: There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, the result will be 'X'(es).
# Time: 802475 ns Iteration: 7 Instance: /top_tb/fpga/cpu/cpubiu/shift
Note: If you are using Linux then check that all filenames have the right case. You might also want to run the dos2unix command on all the vhdl and bat files (removes the DOS CR character). You can execute the same batch file by making it executable (chmod +x run.bat).
Simulation using Xilinx ISIM
As of ISE11.1 you can now simulate the design using ISIM. Navigate to the Drigmorn1 directory and open the Drigmorn1.ise project file. Next run ISIM on the cpu86_top_tb file. Change the radix of the udbus[7:0] signal to ASCII, this signal is the output of the UART monitor and will contain the mon88 output string. Run the simulation for say 100 ms and you should get an output similar to the screenshot shown below:
Simulation using the Free GHDL simulator
Lubomir Rintel created a script which enables the CPU86 to be simulated by the free GHDL VHDL simulator. See the ghdl directory in the zip file for more information.
The CPU86 core can be synthesized using any modern synthesis tool such as Mentor's Precision, XST, QNS and Synplify (note : the last one has not been verified but I will be surprised if it can't handle the code).
The table below shows a push button implementation for both synthesis and P&R of the standalone core for the 3 major FPGA vendors. The values given are just a rough indication of the required area and performance so your YMMV. Mentor Graphic's Precision RTL 2007a.8 was used for synthesis and the respective vendor tools for P&R.
|Vendor||FPGA Type||Area||Fmax (constr)||P&R|
|Actel||ProASIC3 A3P600-2||10989 Tiles (79%)||24.3MHz(33)||Designer 8.1-SP2|
|Iglo AGL600V2||10182 Tiles (73%)||12MHz (14)|
|Axcelerator AX1000-2||7697 cells (42%)||35MHz (40)|
|Altera||CycloneIII EP3C10-6||4482 LE (43%)||66MHz (66)||Quartus 7.2+SP1|
|StratixIII EP3SE50-2||2935 LUTS (8%),896 Regs (2%)||108.7 MHz (120)|
|Xilinx||Spartan3E 3S500-5||2301 Slices (49%)||43MHz (50)||ISE 9.2i+SP4|
|Virtex5 5VLX30-3||1126 SliceR (5%), 3124 SliceL (16%)||93.8MHz (100)|
- Altera Nios Development kit, Cyclone1 edition.
- Enterpoint Drigmorn1 FPGA Development Board.
- Actel ProASIC+ demo board.
- Antti Lukats ported the design to the Hydra-XC FPGA prototype board (link seems dead).
The CPU86 Model is supplied with a simple testbench. The testbench monitors what the CPU is writing to the UART and displays the received string onto the transcript window. The testbench also writes a few commands to the UART after some initial delay (see tester_behaviour.vhd).
# RD UART : AX=0000 BX=0000 CX=0000 DX=0000 SI=0000 DI=0000 FX=0000 ----------------
# WR UART : FM 0000,0020 A5
The 1Mbyte 8086 memory map is filled in 2 places, the top 256 bytes contains a simple ROM model (instance U11 in cpu86_top_struct.vhd). This ROM is created by the create_rom.bat batch file located in the Software/Bootloader directory. This batch file assembles the jump0400.asm file using A86 followed by converting it to a VHDL case statement (using CPU86/bin/bin2case.exe). The jump0400.asm file does nothing else but to jump to address 0000:0400 after reset. The 0000:0400 address is just above the 8086 interrupt vector table and is the start address of the MON88 debugger.
The MON88 debugger is created by the mon88.bat batch file located in the CPU86/Software/Mon88 directory. This batch file assembles the monitor followed by converting it (using bin/bin2mem.exe) to a format suitable for Andre Klindworth's SRAM model (write result to loadfname.dat). This memory model is instantiated in the testbench and filled with the loadfname.dat file during simulation.
When the testbench issues a reset the processor jumps to FFFF:0000 (CS:IP) and then jumps to 0000:0400 which start the mon88 monitor. The testbench waits for the monitor's command prompt (Cmd>) and then issues the Display Register command (R), followed by a Dump Memory (DM 0000-0020) command.
write_to_uart('R'); -- Issue the command R (dump Registers)
write(L,string'("WR UART : R"));
wait for 47 ms; -- wait for > prompt before issuing the next command
You can easily change or extend the commands issued.
The CPU86 is binary compatible with the 8088/8086 which means that most software available for the 8086 should run without any issues on the CPU86. There are a number of software differences between the CPU86 and Intel's iAPX88. The first one is that the CPU86 has a 9 byte prefetch queue instead of 4 bytes on the iAPX88. This means that CPU Identification routines, which rely on the length of the prefetch queue, will not be able to detect if an 8088 or 8086 is present. The second difference is the number of clock cycles per instruction. Software routines that count the number of clockcycles to implement a software delay will not be accurate (consider bad coding style anyway). The LOCK and WAIT prefixes are not supported (ignore, executed as NOP's).
There is a vast amount of software available for the 8088/8086 including high-level compilers, linkers, debuggers, operating systems, application software etc, most of which can be downloaded for free.
Building a System
To build a usable system you obviously need more than just the processor. For a minimum embedded system you would need:
- An Interrupt Controller. Interrupts are an essential part of any system. The 8088 is normally paired with an 8259A Programmable Interrupt Controller. Although this device is as old as the 8088 due to legacy issues you will still find it on any modern PC. Note that you can not simply connect an device IRQ to the 8088 INTR input without additional glue logic. The reason for this is that an 8088 expects an interrupt vector to be pushed onto the databus during the second Interrupt ACKnowledge cycle.
- A Timer unit. Any embedded application even the simplest one needs timers to generate periodic interrupts (e.g. OS task switching, time keeping functions, DRAM refresh etc). The obvious choice is an 8254/8253 Programmable Timer.
- Parallel I/O Port. For any Parallel I/O operations an 8255 Programmable Peripheral Interface (PPI) can be used. This is a versatile device that can be configure in simple I/O, strobed I/O or fully bi-directional I/O.
A collection of questions I have received so far:
- Has the core been used in any commercial products
Yes, the core has been used as a small embedded controller by a US company but for any commercial work we would recommend the HTL80186.
- Can you supply the core with an 82xx peripheral core
Yes, contact HT-Lab for more info.
- Can you modify the core to do X,Y,Z
Yes, contracting is available, however, this will not be handled by HT-Lab.
- Is a Linux/DOS port available for the Core?
Not that I am aware off, however there should be no reason why it wouldn't work.
- Can you compile the model for Aldec?
Yes, the core is generic VHDL.
- Can I use C/C++?
Yes, there are several compilers available such as the OpenWatcom, Turbo-C and many others. I am using an old DOS copy of Microsoft's CL version5 compiler but I am in the process of converting the libraries to the free Open Watcom compiler.
- I am getting an Obsolete library format error message when I run sim.bat.
# ** Fatal: (vsim-3381) Obsolete library format for design unit. (See design unit listed above.)
# Time: 0 ns Iteration: 0 Instance: /top_tb/fpga File: UNKNOWN Line: 284
You are using a later version of Modelsim than was used to compile the CPU library. You can correct this by using the refresh option:
vcom -refresh -work CPU
For any other questions or feedback please use the feedback form.
- Antti Lucas partial 8086 core in verilog (link seems dead)
- Commercial 80186 core from CAST
- 8086 Instruction set
- Why learning Assembly Language is still a good idea
- 80x86 Programming page
- Brian Brown's embedded code software page (good if you want to use a C-Compiler)
- Some C-code to implement a printf function
- The FreeDOS home page
- Software only 8086 PC emulator for X
- LIBC reference page
- Webster assembler tools
- Debug tutorial by Frank Golden (broken link, does anybody know the new URL?)
- Paul Hsieh's excellent x86 Assembly Language Page
- DJGPP 16-bits toolset
- SimTel's Assembly Language Utilities
- Commercial 8086 development system
- Document describing the assembling process
- History of Intel Processors
- x86 Interrupt list
- 8088 Article by Benj Edwards
- x86 BIOS Information
- John Fine's home page (x86 newsgroup moderator?)
- ELKS Embedded Linux (runs on an 8086, if only I had the time :-)
- Borland C for ELKS
- Jack Klein's x86 page
- Serial Port Info
- CC86 and A86 source files