This website describes my project, PDP2011 – a re-creation of the well known series of PDP-11 computer systems in VHDL. Everything that is needed to run a complete PDP-11 system is included; you can run a complete Unibus PDP-11 system with console, disks and other peripherals on a simple low cost FPGA development board. The original V5-V7 versions of Unix, BSD 2.11, and the original DEC operating systems for the PDP-11 work. (*)
- The CPU model is configurable, from the smallest 11/10 up to J-11 systems. Model-specific exceptions are implemented to the point that many of the original XXDP MAINDEC test programs run without error, and the original model detection code embedded in several operating systems in most cases correctly identifies the configured model.
- The memory management unit is automatically included if the CPU model can support it, does 18- or 22 bit translation and supports separate instruction and data spaces, as well as kernel, supervisor and user mode. For the 11/45 and 11/70, the 3-bit ACF is implemented including memory management traps and A- and W-bits; all other models have the later, simpler version of memory management based on a 2-bit ACF. The special maintenance mode is also implemented – this makes it possible to run the original XXDP test programs to verify that the MMU works correctly. For the 22-bit processor models the Unibus map is included in the memory management unit.
- Model-specific optional instructions, like SPL, MARK, MxPx, MxPS, MFPT, CSM etc. are present according to the CPU model.
- J-11, 11/45 and 11/70 have the dual general purpose register set.
- The EIS instructions: MUL, DIV, ASH, ASHC, and XOR are available if the CPU model supports them.
- The floating point processor is complete, and is included by default with the CPU models that it could optionally be installed in. It can be disabled too, for instance to save FPGA resources.
- RK11 and RL11 disk controllers work and use SD cards to store the disk data on. Up to 8 RK05 or 4 RL02 disks can be emulated on a single SD card.
- If the RK or RL disks are too small, then there is the option to configure a RH70 (for 11/70) or RH11 controller with a single RP04, RM05, or RP06 disk. The disk data for the RM or RP disk is also stored on a SD card.
- A KW11L line clock is present; by default it is configured at 60Hz, but 50Hz and 400Hz are also possible.
- Up to four serial lines for console and terminals can be configured.
- A DEUNA/DELUA compatible core is available; the DEUNA core is a front end for a ENC424J600 ethernet chip, which does most of the ‘real’ ethernet work. Digilent’s PMODNIC100 contains the ENC424J600 chip, and can be easily connected to FPGA boards.
- If the FPGA board includes ps2 and vga ports, a simple terminal can be added to the FPGA core so you don’t need a pc with hyperterm or minicom to run a PDP-11. The CPU that runs the software for the terminal is of course also a PDP-11.
- Everything is verified in hardware, on both Altera and Xilinx boards. The VHDL is not vendor specific, so it should be possible to make it work on any FPGA that is large enough with only minor changes in the top level VHDL to map the board resources like connectors, blinkenlights and memories to the core. Several top level VHDL files and tool chain project definitions are available for popular development boards from Terasic and Digilent.
Type Address Vector Description - 17 777 776 - PSW - Program status word - 17 777 774 - Stack limit register - 17 777 772 - PIRQ - Software IRQ register - 17 777 766 - CER - CPU Error Register - 17 777 640 - MMU User mode PAR - 17 777 600 - MMU User mode PDR - 17 777 576 - MMU SR2 - 17 777 574 - MMU SR1 - 17 777 572 - MMU SR0 - 17 777 570 - Console switch and display register KL11 17 777 560 60/64/4 KL11 Console serial line KW11L 17 777 546 100/6 KW-11L Line clock - default 60Hz RK11 17 777 400 220/5 RK11 RK05 Disk controller RH11/70 17 776 700 254/5 RH11/RH70 Mass bus controller - RP/RM disk KL11 17 776 500 300/304/4 KL11 optional 2nd serial line KL11 17 776 510 310/314/4 KL11 optional 3rd serial line KL11 17 776 520 320/324/4 KL11 optional 4th serial line XU 17 774 510 120/5 DEUNA controller RL11 17 774 400 160/5 RL11 RL02 disk controller M9312 17 773 000 - M9312-style bootrom - 17 772 516 - MMU SR3 - 17 772 340 - MMU Kernel mode PAR - 17 772 300 - MMU Kernel mode PDR - 17 772 240 - MMU Supervisor mode PAR - 17 772 200 - MMU Supervisor mode PDR - 17 770 200 - Unibus map registers
The RL controller is a bit more special, in that the RL has 256-byte sectors, while the SD card standard only allows for 512-byte sectors. This mismatch is solved in that the controller only reads or writes the first half of each SD card sector, and leaves the rest blank. This means that ‘real’ RL disk images must be converted to the 256-byte payload,256-byte blank SD card format. I’ve written a trivially simple C program to do that; it is called sdfmt. It takes two parameters: -i (which may occur multiple times) names the input image file; -o names the output image file, that is to be copied to an SD card.
Writing the original disk images, or new disk images created by SIMH, to SD cards is a bit tricky. On Linux, you typically do this with the dd command, and make a plain one to one copy of the disk image to SD card, for instance using a USB card reader/writer. Many laptops also come with a SD card slot built in. The tricky bit is however to find out the device name of the SD card slot, and be *very* sure that you have the right one. Look in your mounted disk table; any device you see here you should *not* use on the dd command. Then connect the card, look in the syslog to see which device was just connected, make sure that it has not been taken by an automounter (if so, just unmount it) and make very sure you’re not confused by something else. If you make a mistake here, you *will* lose data; the dd command will just overwrite anything that is on the device that you tell it to, even if that is a partition table. You may very well mess up your entire primary hard disk and lose all data on it.
For Linux systems, something like
dd if=unix_v5_rk.dsk of=/dev/sdc
will create a Unix V5 disk image on a SD card, *if your card reader is mapped to /dev/sdc*. Again, *please* be sure you know what you’re doing, because you can really lose your data with a very simple mistake in this command.
sdfmt -i unix_v7_rl.dsk -o v7.rl dd if=v7.rl of=/dev/sdc
will create an RL02-formatted image of V7 unix. Again, please be sure that the dd command refers to the right device.
I don’t ever use anything else but Linux for this kind of work, so I don’t know how to create images with Mac OS or Windows.
The current serial link controller is KL11-like; it is the most basic serial controller that was typically used to connect the console to. The baud rate is by default set to 9600, 8 bits, no parity; the baud rate can be defined in the VHDL, but is not software selectable. Usually, the most significant bit of all output bytes is forced to 0 by the hardware – so actually only 7-bit characters are sent out.The same VHDL is used for both the primary port (the one at address 17777560) as well as additional ports that can be configured in the top level source. The primary port is usually connected to the most obvious DB9 port on the FPGA board – if one is available.
- RT-11 V5.3 crashes during the boot from the original RL02 distribution images. When the files are copied over to an RK05 image, the boot is ok however.
- A more extensive boot rom implementation, that runs more elaborate diagnostics and hardware identification at initial boot, and allows for a dialog that lets the operator choose from which device to boot.
- A somewhat more VT100 like terminal – mainly, this can be done by improving the assembler code for the terminal somewhat.
- An improved SD card interface for the disk controllers, where the card communication is decoupled from the memory interface. This would make it possible to release the CPU during the card communication – so the systems would appear to be more responsive. It would also solve one of the major differences between this core and real hardware – PDP11 were known for their fast response to interrupts. This core however can remain unresponsive to any interrupt as long as a disk controller remains bus master. Which translates to the maximum time that the connected SD card is busy processing a command.
- An improved SD card controller, that allows for SDHC cards, maybe also for SDXC cards, and implements error checking on all card types. The card initialization should allow for slower cards to be correctly initialized.
- A JTAG interface to look into the CPU’s registers and control variables while it is running, single-stepping or halting the cpu, instruction history, etc… Also probably a lot of work.
With a few small exceptions, the source files are structured along the major components in a complete system – the CPU and MMU are described each in one source file, as are all the peripherals. All of these are connected in a large source called Unibus. The Unibus component in turn is instantiated in a top level source that deals with the specific stuff needed to make the VHDL fit to an FPGA board – like, driving the memory and the ‘real’ peripherals. One special item to mention is the M9312-style boot rom, which has a tiny bit of code that will bootstrap the system from the first available disk controller.
The CPU is by far the most complex source; it contains the main state machine for the CPU, and also for the FPU and the optional instructions. The main task for the state machine besides sequencing through the instruction ‘microsteps’ is to drive the bus signals; reading from and writing to memory. The three separate ALU’s for the regular instructions, the EIS instructions, and for the FPU are also in the CPU source.
The memory management unit is in comparison fairly simple; it contains a large number of control registers, and a few rather complex adders that generate several versions of the physical access. Also in the memory management unit is the black magic of the Unibus map, and the tricks it requires to connect peripherals onto a bus that is somewhat separate from the ‘real’ memory bus, but still the same if mapped through the Unibus map.
All three disk controllers basically follow the same model; they have a state machine for interfacing the SD card, and a set of control registers that will cause the state machine to start to work when the correct bits are read or written. The differences are mainly in the control registers, in the sector size (256 for RL, 512 for the others), and in the disk track and cylinder to sd card sector calculation.
In- and excluding specific parts of the CPU, MMU, or even entire peripherals to implement the different functions of the different PDP11 system models is done by regular signals and if-then-else statements – the compilers and optimizers do an excellent job of turning this into efficient core; there seems to be very little overhead as a result of this coding style. I’ve not really tried to write very resource efficient core either. The VHDL coding style is simple – maybe even naive, and probably violating a lot of coding best practices. In my own defence, I should probably say that this is the first design I’ve worked on that is more complex than pushing buttons to turn leds on and off.
The sources and other files are organized in a fairly flat directory. The main VHDL sources, Macro-11 sources for the bootstraps, test programs and terminal are in the top level directory. The tools – Richard Krehbiel’s Macro-11 etc – are in a subdirectory.
Every board that I use is defined in a subdirectory; these subdirectories contain the top level VHDL source for that board, and also any board-specific VHDL if required. See the page titled ‘Files’ for a more detailed explanation of what each file is.
The goal that I set has been to get the VHDL to work, and as correct as possible – not to get the maximum speed out of it; any speed ‘correct for the period’ is really good enough. Having said that, I’m obviously very happy and proud that the CPU is in most cases considerably faster than the original models. It could have been a lot faster still, if I had not made a major mistake in the design of the memory interface very early in development; some of the memory access runs at half cycle – which I thought at the time was a smart trick to make it go faster, but I realize now that I actually did the opposite. To remove this mistake would mean almost a complete redesign though, and I’m not going to.
Walter’s w11 is a lot faster though. When compared to this table, where w11 reaches 160-168 Hanoi’s per second, pdp2011 reaches about 38 with the CPU running at 10 Mhz, which is not the maximum speed I’ve ever been able to get, but a decent baseline that is stable on most boards. I’ve not yet been able to compile the Dhrystone test yet, so the numbers for that cannot be compared. Still, looking at the Hanoi number for 11/53+, pdp2011 is about three times as fast as that.
The copyrights to the VHDL described on this site are held by me. Basically, you can run the core for personal use, but you cannot use it commercially. See the licence description in the source files for more information.
Other PDP-11 projects
- POP11, created by Yoshihiro Iida at the Tokai University of Japan; it is a PDP-11/40 that runs Unix V6. It’s implemented in SFL, a language that is used to generate Verilog. There appear to be no recent developments, but it was probably the first working PDP-11 in a FPGA capable of running Unix.
- Brad Parker‘s Verilog PDP-11, a 11/34 that is verified to be correct by running it in simulation alongside SIMH.
- Walter Müller‘s w11, which currently is an 11/70 in VHDL, including a real cache implementation and capable of impressive speed.
- And of course SIMH, the brilliant simulator by Bob Supnik that is a reference for all things PDP-11 and a lot more.
Several people I’ve never even talked to or emailed with have still contributed to this project. I owe a big thankyou to Al Kossow for running bitsavers.org, with it’s enormous amount of documentation and software. Without access to this information, the project would not have been possible at all. But I also would like to thank to some slightly less famous people, like John Kent, and Tim Boscke whose work taught me the first basics of how to make a CPU work; and Bill Buzbee for inspiring me to start working on my own blinkenlights project.