© 2001-2017 HT-Lab
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 v2 or v3
All trademarks mentioned on this web page are trademarks of their respective owners.
Free 8088 FPGA IP Core
Introduction date: June 8, 1978
Clock speeds: 5 MHz (0.33 MIPS)
8 MHz (0.66 MIPS)
10 MHz (0.75 MIPS)
Number of transistors: 29,000 (3 microns)
Bus width: 16 bits
Addressable memory: 1 Megabyte
Typical use: Portable computing
Ten times the performance of the 8080
Download Source Files
Download CPU86 IP source files (version 0.82, 549KB, zipped)
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 the zipfile:
Contains the different conversion programs (Windows, DOS).
CPU86 Synthesizable VHDL Source files.
Implementation example for the Enterpoint Drigmorn1 board, ISE 12.1 project file is included.
Modelsim Simulation batch file.
VHDL source code for the Opencores 16750 compatible UART.
ROM, MON88 and some example asm source files.
Contains VHDL testbench files for CPU86+UART+256Byte ROM (see top_rtl dir).
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, ISIM also works fine
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).
Simulating using 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:
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 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
# 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
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
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.