Home Commercial IP FreeIP SCBuilder Forum Contact
© 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.

License Agreement

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

Tools/Software used

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 

1. Download the zipfile and unzip to a suitable directory (keep the directory structure) 2. Open a DOSBox or Cygwin Shell and navigate to the CPU86/Modelsim directory 3. 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                                       .... VSIM 2> 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).

Supplied Testbench

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")); writeline(output,L); wait for 47 ms;                     -- wait for > prompt before issuing the next command You can easily change or extend the commands issued.

Software Development

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.