Building PDP-11 Memory
I was recently sent a post about building PDP-11 memory written by Peter Schranz. I wanted to have a go at building it. So far, it doesn't work, but I think I know why (and will test eventually).
The files provided on Peter's website are in Eagle format, which I don't have (and have never used). The first thing I tried was to open the PCB in KiCAD, which helpfully offered to convert it. The conversion worked well and I was able to produce the gerber files which I sent off to JLCPCB. I think it was about £10 for five boards, not too bad given they have a card edge connector and are larger than most other boards I make.
In the meantime, I tried to figure out what components I would need. There are a bunch of tantlum caps (SMCC footprint) which I've not fitted yet. The other capacitors (and one resistor) were all 0805 footprint. Since I had those passives already in 0603, I just used those. The sizes are close enough that they work fine. There were a number of components which I still needed though:
- CY62167GN - SRAM
- ECS-100AX-200 - 20MHz Oscillator package
- DC005 - QBUS driver chips, these were £10 each off eBay
- 74HCT573D - TTL latch
- 74S38D - I decided to use 74HC00D instead, which I already had
- ATF1504AS - The CPLD
Everything other than the driver chips were ordered off DigiKey and arrived very quickly! Exciting!
I laser cut a solder stencil at the hackspace out of 100 micron mylar, applied the paste, placed the components and popped onto the hot plate. I had a couple of small shorts on the SRAM chips - these have a pin pitch of 0.5mm, but I was able to clean them up with some flux and a soldering iron.
The next part was more tricky. This thing has a CPLD - I've heard of them but barely knew what they were, how to "compile" the program or how to flash it. After a bit of DuckDuckGoing "how to program ATF150 cpld" I learnt that I needed to use WinCupl from the Microchip website. They don't have a Linux version, but apparently it runs ok under Wine. Not 64 bit wine though… I had to setup a new Wine 32 bit prefix, which seemed to run the program ok.
WINEARCH=win32 WINEPREFIX=~/.wine32 wine ~/.wine32/drive_c/Wincupl/WinCupl/Wincupl.exe
I pasted in the program off Peter's website and selected the menu button to build the program, which produced a JED file! Right… what do I do with this? Some more searching later, I found afterburner which is apparently able to program CPLD chips using an Arduino, but I think it needs a custom shield which the CPLD can be installed in. It was already soldered to the board!
Anyway, after messing about with the Arduino for a bit, I gave up and remembered I had a Glasgow Interface Explorer. I was a bit confused about how all of this works, and could see that there were a couple of applets available for programming CPLD, but not the ATF150x. However, while searching earlier I had read something about SVF files, and conveniently the Glasgow has an applet for that. I also remember seeing in the afterburner repo that there was a script for converting JED files into SVF files. So, I ran that, and it made the SVF file which I then handed over to the glasgow.
(venv) [aaron@zerocool jtag]$ python3 ./fuseconv.py -d ATF1504AS qbus.jed qbus.svf
(venv) [aaron@zerocool git]$ glasgow run jtag-svf --pin-tck 0 --pin-tms 1 --pin-tdi 2 --pin-tdo 3 -V 5 afterburner/utils/jtag/qbus.svf
I: g.device.hardware: device already has bitstream ID d7e2b292d71c1323925868e1ca0d6f1d
I: g.cli: running handler for applet 'jtag-svf'
I: g.applet.interface.jtag_svf: port(s) A, B voltage set to 5.0 V
That's a partial lie, because the first time I ran it there was an error, but running it again seemed to work? I wasn't sure, so I asked in #glasgow. Catherine / whitequark was incredibly helpful and explained that it will have worked. They explained that the programmer just does what the SVF file instructs it to do, which includes instructions to verify each block of the CPLD. Amazing!
So… I sort of hesitantly decided to install the card in my PDP-11. I turned on the power and had hoped to be greeted with the output of the boot ROM, but it didn't do anything. I turned off the machine, installed the original memory and tried again, and that worked. Hmmm, so the card does not work.
I think the issue (and knew this might be an issue) is that I have an MXV11-BF card. This is a "multifunction" card and provides 128K of RAM, serial lines and boot ROMs. The starting address for this memory is 0. The starting address for the CPLD memory card is also 0. That is likely to cause problems.
I don't think enough address lines are passed to the CPLD in order to filter the address range with resolution of 128K. There is a (semi-)reversible modification which can be made to the MXV11 card though, and that is to disable the build in RAM. This is explained in micronote 19, but I will paste the details verbatim in case that ever goes offline.
PROCEDURE (see figure below)
1. The etch cut can be achieved two ways.
Cut and bend up pin 13 of chip E17.
OR
On side 2 of module (the non-component side), cut etch
which connects E17 pin 13 to E26 pin 2.
2. Add wire between E17 pin 13 and E17 pin 14 (+5 Volts).
3. The on-board RAM is now disabled.
MXV11-BF (M7195)
| |
| |
| |
| Pin 1 |
| | |
| | Pin 14 |
| | | |
| | | |
| | | |
| +-+ V V +-+ |
| Pin 1 ---> +-+ | | +-+ +-+ | | +-+ +-+ |
| | | | | | | | | | | | | | | |
| E26 -----> | | | | | | | | | | | | | | |
| | | | | | | | | | | | | | | |
| +-+ | | +-+ +-+ | | | | | | |
| +-+ ^ +-+ | | | | |
| | +-+ +-+ |
+-+ +-+ | |
| +---+ | | +-+
| | | E17 |
| | | |
+--------------------+ +--------------------+
So, I will try that soon.
<2025-01-03 Fri 20:01> I tried the modification to the MXV11-BF (to disable the on-board memory). It did not improve the situation, so I think I'll need to get a logic analyser out and try to track what's happening and why the boot might be failing. Couple of pics of the mod done and undone, PDP-11 works again with mod undone.
<2025-01-04 Sat 00:09> Hmm I was looking at photos wondering what the issue could be. Well, one issue is that I installed 74HC4049D (hex inverter) backwards. Glad that didn't blow anything up. The card no longer prevents the machine from booting if there is memory at address 0, but it doesn't boot with the memory disconnected (i.e. with the mod above undone to the MXV11-BF). So, maybe some progress. Glad I found that before starting more serious debugging.
<2025-01-04 Sat 14:28> I think in order to debug this I'd be better off with a working ODT, so I can poke memory and watch with a logic analyser. That means I need the first 128KB of RAM for the MXV11 card to be enabled. So, I need to figure out how to mask off those addresses from the DIY card.
The CUPL currently has this, which enables / disables the appropriate RAM chip depending on whether we're looking at the first or second 2MB chunk of RAM.
CE0 = RSYNC & !BS7 & !A21;
CE1 = RSYNC & !BS7 & A21;
So we want to also mask off A20, A19, A18 and A17, which leaves only the addresses above 128K. So we need:
CE0 = RSYNC & !BS7 & !A21 & !A20 & !A19 & !A18 & !A17;
CE1 = RSYNC & !BS7 & A21 & !A20 & !A19 & !A18 & !A17;
but 20, 19, 18 and 17 aren't mapped to the CPLD! Bodge wire time.
and some code changes:
[aaron@zerocool ~]$ diff -U2 memory4m.cupl qbus.cupl
--- memory4m.cupl 2025-01-04 15:33:19.674027734 +0000
+++ qbus.cpld 2025-01-04 16:06:04.358666830 +0000
@@ -18,4 +18,7 @@
PIN 22 = DAL21;
PIN 20 = DAL20;
+PIN 43 = DAL19;
+PIN 44 = DAL18;
+PIN 6 = DAL17;
PIN 37 = CLK;
@@ -45,4 +48,7 @@
PINNODE = A0;
+PINNODE = A17;
+PINNODE = A18;
+PINNODE = A19;
PINNODE = A20;
PINNODE = A21;
@@ -51,7 +57,7 @@
PINNODE = RDOUT0, RDOUT1, RDOUT2;
+[BS7, A21, A20, A19, A18, A17, A4, A3, A2, A1, A0].le = !RSYNC;
+[BS7, A21, A20, A19, A18, A17, A4, A3, A2, A1, A0].l = [RBS7, DAL21, DAL20, DAL19, DAL18, DAL17, DAL4, DAL3, DAL2, DAL1, DAL0];
-[BS7, A21, A20, A4, A3, A2, A1, A0].le = !RSYNC;
-[BS7, A21, A20, A4, A3, A2, A1, A0].l = [RBS7, DAL21, DAL20, DAL4, DAL3, DAL2, DAL1, DAL0];
[RDIN2..0].ck = CLK;
@@ -72,7 +78,7 @@
REC = !RDIN & !RDIN2;
-CE0 = RSYNC & !BS7 & !A21;
+CE0 = RSYNC & !BS7 & !A21 & !A20 & !A19 & !A18 & !A17;
-CE1 = RSYNC & !BS7 & A21;
+CE1 = RSYNC & !BS7 & A21 & !A20 & !A19 & !A18 & !A17;
and then reprogram:
(venv) [aaron@zerocool jtag(master)]$ glasgow run jtag-pinout -V5 --port A --pins-jtag 0,1,2,3,4
I: g.device.hardware: generating bitstream ID 7e00c7a10c8deb4044e176ce83aa9976
I: g.cli: running handler for applet 'jtag-pinout'
I: g.applet.interface.jtag_pinout: port(s) A voltage set to 5.0 V
I: g.applet.interface.jtag_pinout: detecting pull resistors
I: g.applet.interface.jtag_pinout: detecting TCK, TMS, and TDO
I: g.applet.interface.jtag_pinout: shifted 10 out of IR with TCK=A0 TMS=A2 TDO=A1
I: g.applet.interface.jtag_pinout: detecting TDI
I: g.applet.interface.jtag_pinout: shifted 10-bit IR with TCK=A0 TMS=A2 TDI=A3 TDO=A1
I: g.applet.interface.jtag_pinout: detecting TRST#
I: g.applet.interface.jtag_pinout: JTAG interface without reset detected
I: g.applet.interface.jtag_pinout: use `jtag-probe -V 5.0 --port A --pin-tck 0 --pin-tms 2 --pin-tdi 3 --pin-tdo 1` as arguments
(venv) [aaron@zerocool jtag(master)]$ glasgow run jtag-svf -V 5.0 --port A --pin-tck 0 --pin-tms 2 --pin-tdi 3 --pin-tdo 1 qbus.svf
I: g.device.hardware: generating bitstream ID e6ca4185e11d74d0705347bb94685351
I: g.cli: running handler for applet 'jtag-svf'
I: g.applet.interface.jtag_svf: port(s) A voltage set to 5.0 V
I absolutely love that I can just let the Glasgow figure out the jtag pin mapping.
Right, that's all for now. I'll test later.
Related posts:






Wanting to leave a comment?
Comments and feedback are welcome by email (aaron@nospam-aaronsplace.co.uk).