The DCJ11 developed by DEC together with Harris implements a PDP‑11 CPU with many features found on the PDP‑11/70 on a ceramic substrate with two dies. Documentation about the DCJ11 can be found in…
The DCJ11 developed by DEC together with Harris implements a PDP‑11 CPU with many features found on the PDP‑11/70 on a ceramic substrate with two dies. Documentation about the DCJ11 can be found in the PDF EK-DCJ11-UG-PRE_J11ug_Oct83.pdf available as scan on ‘bitsavers.org’ and in the Semiconductor Databook Volume 1 from ‘digital’, on the same web site. When I refer to chapter numbers they are taken from the EK-DCJ11-UG-PRE_J11ug_Oct83.pdf
When you think of 16-bit processors or microprocessors of the time the DCJ11 was released in 1983 then this would have been a great microprocessor to build your own computer. A minimal setup with DCJ11 just requires a serial interface with the registers as described in chapters 5.3.1.1/2/3/4.
Receive Data Flag Bit 7 of RCSR
Receive Data Buffer Low Byte of RBUF
Transmit Buffer Empty Flag Bit 7 of XCSR
Transmit Data Buffer Low Byte of XBUF
The DCJ11 comes with a simple monitor included in the microcode, called ODT. Although it supports only a few commands it has everthing required to interact with the CPU and peek and poke into your system, start and continue code you have previously entered manually. Such minimal systems are known as PDP‑11/Hack.
One of the first PDP‑11/Hack seen is from Brent Hilpert and the description of his PDP‑11 on a breadbaord is still available at http://madrona.ca/e/pdp11hack/index.html. It dates from May 2014.
His system has been the inspiration for my DCJ11 based projects, including my fully functional PDP‑11 described on my web site.
Other DCJ11 hacks are also available and intentions of building more hacks have been expressed in various forums.
There exists also more complex systems built by PDP‑11 enthusiasts, built much earlier than the DCJ11 hacks from Brent and Len, but unfortunately not much information is available and generally they are not documented so you cannot reproduce them.
The DCJ11 has a built-in crystal oscillator. There are two generations of DCJ11, one supporting clock speeds up to 15MHz and another supporting clock speeds up to 18MHz. All samples I have run with clock speeds up to 22MHz. I can imagine that some specs for propagation delay and setup time are critical and using high-speed logic as glue logic allows to push the clock further to its limits.
There is some confusion about the speed of a DCJ11. This is because a minimal CPU cycle requires 4 clock cycles. In most cases you read about either 3.75MHz or 4.5MHz and are referred to as the CPU speed. And indeed for the DCJ11 this refers to the maximum rate for CPU cycles with a DCJ11 having a 15Mhz or 18MHz clock crystal as the shortest CPU cycle requires four clock cycles.
The DCJ11 has two types of CPU cycles. A short, non-stretched, CPU cycle, which takes 4 clocks and is used in case of a cache hit for memory reads or in case the CPU is performing internal operations which is called a non-IO cycle. These are the only non-stretched CPU cycle. These cycles can be stretched by either a cache MISS or a DMA Request. All other CPU cycles are stretched CPU cycles and take at least 8 clocks.
The clocks in a CPU cycle are named T0, T1, T2, T3, T4, T5, T6, T7. Non-stretched cycles only have clock cycles T0, T1, T2, T3. Stretched cycles require CONT to be asserted to finish. If CONT is not asserted non-stretched cycles will repeat the clock cycles T4 in pairs, so you can have 1,3,5,.. T4 clock cycles in a stretched CPU cycle.
The clock cycles T0, T1, T2 and T3 are sometimes referred to as the non-stretched part of a cycle and the other clock cycles are referred to as the stretched part of a cycle.
The DCJ11 has various types of CPU cycles. Which cycle the DCJ11 performs is shown via the AIO code. AIO stands for Address/Input/Output.
AIO3 AIO2 AIO1 AIO0 Description
1 1 1 1 NON-I/O (NIO) cycle
1 1 1 0 GP (General Purpose) read
1 1 0 1 Interrupt acknowledge, vector read
1 1 0 0 Instruction-stream request read
1 0 1 1 Read/Modify/Write - no bus lock
1 0 1 0 Read/Modify/Write - bus lock
1 0 0 1 Data-stream read
1 0 0 0 Instruction-stream demand read
0 1 0 x GP word write
0 0 1 x Bus byte write
0 0 0 x Bus word write
Some confusion exists for AIO0 when AIO3 is low. These are all write cycles and in the preliminary documentation AIO0 is supposed to be high during write cycles but in the Semiconductor Handbook AIO0 is marked as don’t care and should be ignored. I think it is save to just ignore AIO0. I have done many LA captures and I have never seen a write code with AIO0 being low.
Bus cycles also provide the signals BS0 and BS1 to indicate the bank which is selected
BS1 BS0 Description
1 1 Internal Register
1 0 External I/O device register
0 1 System Register
0 0 Memory
Bank Select signals are only meaningful for bus access CPU cycles, these
are the AIO codes 1100
, 10xx
and 00xx
.
In a minimal system you can use the bank select to select either the serial interface or the memory. No further address decoding is required for external I/O when there is no other device than the serial interface and you can use the code for memory access to generate a memory select signal if you do not need to detect non-existing memory. If you have some sort of address decoding for the external device registers you need to make sure that your console is selected when the DCJ11 uses the addresses 17756x (octal) to access the four registers, else you will not be able to use ODT. Note that the external registers use addresses 160000 and above. In a PDP-11 these addresses were considered to be the IO Page with all device registers. Still IO is just memory mapped and you can use the normal instructions to access device registers. The only restriction is that sometimes device registers are not byte writable, e.g. the registers of the RL01/02 disk controller, the RLV11/12, can only be written as a word. The bank select code for external registers is never used for lower addresses. Therefore it is sufficient to decode only addresses A0..12 if you have multiple IO devices.
Note that both, the AIO and BS, are multiplexed data signals and as such must be demultiplexed using ALE as the clock to latch the primary values of these signals. After the falling edge of ALE these signals have a different meaning, but so far I have not used them or analyzed them. More information is available in the datasheet.
The DCJ11 uses a multiplexed address/data bus, first DAL0..21 show the memory, register, IO address or GP code and then DAL0..15 are used as data bus.
Note that the DCJ11 is a 16-bit processor and uses 16-bit addresses. Address lines DAL16..21 are only used when the memory management unit is activated and programmed. And of course ODT also sets address lines DAL16..21 when you use an address between 00160000 and 17760000.
This very important signal indicates that the address and other multiplexed signals are valid and must be latched. Hence the name ‘Address Latch Enable’.
The following signals must be latched using this signal
DAL0..21 AIO0..3 BS0..1
After ALE those signals have other than their primary function.
ALE occurs in every CPU cycle and divides the cycle into two portions. During the first part, when ALE is de-asserted (note ALE is an inverted signal, therefore the electrical level is high when ALE is de-asserted) the DCJ11 will prepare the above mentioned signals and they are valid tDALD ns after the falling edge of the last clock of the previous CPU cycle (falling edge of T3 or T7). ALE is asserted with the falling edge of T0.
This signal can be latched using ALE and reflects the status of bit 5 of MMR3 (Memory Management Register #3) and signals if I/O map is active. I/O map is a feature of the Unibus which allows devices to access all 4Mbyte of memory using some sort of address translation using the Unibus Address Translation Registers, also known as Unibus Map Registers. This was required as the Unibus only has 18 address lines and DMA on Unibus could only address 128kW. Of course you can ignore this signal if you have no Unibus.
In the second part of the CPU cycle MAP will indicate if a DMA request has been honored. In this case non-stretched cycles will turn into stretched cycle, that is why it is important to assert CONT after the DMA took place else the cycle will never end.
This signal is asserted whenever the DCJ11 executes a stretched cycle. It can be interpreted as the requirement to assert CONT to finish a CPU cycle. Note that a stretched CPU cycle only ends if CONT is asserted and you can stretch a cycle for as long as you want. In other words, the DCJ11 will wait forever and continue the current cycle as long as CONT is not asserted.
The QBUS or Unibus time-out is something external logic needs to implement to make sure that a cycle is terminated in case no device or memory responds with BRPLY on a bus request. This time-out value is not something the DCJ11 knows of.
This signal may be used to latch data, i.e. to gate write enable signals for the memory or IO registers.
Also if a cycle needs to be aborted you should only do so when this signal is asserted.
SCTL is asserted during clock cycle that follows the first T4 clock cycle.
Strobe is asserted for every CPU cycle one clock period after ALE and is de-asserted when the CPU cycle ends. This signal can be used to reset external state machines, e.g. the state machines used to grant DMA requests or the state machine that requests the interrupt vector from the bus.
This signal is asserted when the DCJ11 is not driving data on the DAL lines. This signal can be used to enable buffers that send data over the DAL lines. The signal is de-asserted when the DCJ11 is driving the data or address lines.
During the non-stretched part of the CPU cycle BUFCTL is asserted with the falling edge of T2 and is de-asserted with the leading edge of T4. And in the stretched part of the CPU cycle BUFCTL is again asserted with the leading edge of T5 and is de-asserted again with the leading edge of T0 of the following CPU cycle.
The DCJ11 has the following input signals, most of them are not needed for a minimal setup and are therefore tied to either GND or VCC using a small resistor.
Data Valid. This input signals to the DCJ11 that data on the data lines DAL0..15 is valid and can be latched to the internal buffer. The purpose of DV is to inform the DCJ11 that data in a stretched CPU cycle is now ready and can be latched. DV is only evaluated when both BUFCTL and SCTL are asserted. Non-stretched read cycles do not require DV to be asserted as the DCJ11 always latches the data at the end of the non-stretched part of a CPU cycle.
At first it seems strange, that you have to actively inform the DCJ11 that data is valid during the stretched portion of a CPU cycle. However you must keep in mind, that the system design might require to extend the CPU cycle beyond the moment data is valid. One reason is that you want to add a DMA cycle to a memory read cycle.
Four interrupt request signals are provided to cause an asynchronous external interrupt. Each interrupt is associated with a processor level. If the processor level is equal or higher than the level of the associated interrupt the interrupt is not executed. Else the interrupt is executed, which means the DCJ11 starts an IACK CPU cycle during which the requesting device is supposed to provide an interrupt vector. The vector address is used as the absolute address in kernel mode to fetch the address and processor status of the next instructions. During the IACK cycle the DCJ11 first drives DAL0..3 with the corresponding interrupt that is being acknowledged and DAL4..21 set low. Then a vector address is expected and if required DV needs to be asserted to latch the vector address during the stretched portion of the CPU cycle.
The IACK cycle is a normal stretched cycle and hence needs as well CONT to be finished. If necessary ABORT can be asserted to indicate that the device failed to present a vector address.
Any stretched cycle needs CONT to be asserted in order to finish the CPU cycle. The DCJ11 will wait forever if not asserted. Typically this is associated with the bus reply signal on the bus. The DCJ11 will start to sample CONT with each falling edge of a T4 clock cycle.
During the stretched part of a CPU cycle the DCJ11 samples this signal and if asserted the cycle is aborted and and a trap through address 250 or 4 is taken. This signal is an open collector output of the DCJ11 which might be driven during the non-stretched part of the CPU cycle, therefore it is important to make sure that this signal is only externally driven during the stretched part of the CPU cycle and is never asserted during non-IO CPU cycles. It is save to say that ABORT must only be asserted when SCTL is asserted.
Memory read cycles per default are non-stretched CPU cycles. In most cases this will not provide enough time to read memory from the QBUS or Unibus. Only cache hits are assumed to be fast enough to leave read cycles non-stretched. Hence in systems MISS is typically asserted when the requested address is not cached.
The KDJ-11E CPU had an interesting feature as the on-board memory was implemented as fast RAM. They have no cache memory as the fast RAM was fast enough to provide the data within the time of a non-stretched read cycle. However in case only 2Mbyte of on-board memory MISS has to be asserted when an address was trying to read beyond the on-board memory in order to be able to assert ABORT and indicate a non-existant memory address to the DCJ11.
When PARITY is asserted during a read cycle the DCJ11 will execute a parity error interrupt cycle when CONT is asserted. For parity errors in cache memory you also will have to assert MISS as this signal is only sampled during the stretched portion of a CPU cycle.
This signal causes a non-maskable trap through address 24. a GPREAD with write code 140 is executed by the DCJ11 to assert the power fail.
This signal causes a non-maskable trap through address 244. This signal typically comes from the floating point accelerator, e.g. FPJ11, and informas the CPU that some floating point exception has occurred during processing a floating point instruction. This is necessary as floating point instructions are executed asychronuously by the FPA.
This signal causes a level 6 interrupt through address 100. As part of the interrupt acknowledge cycle a GPWRITE with write code 100 is executed by the DCJ11.
Typically EVENT
is implemented as a latch that is asserted whenever BEVENT
is
asserted. As this bus signal is just a square signal with the line frequency the
GPWRITE typically resets the latch to avoid continuous interrupts during the time
the bus signal is asserted.
This input signals the DCJ11 that a device wants to perform a DMA and will cause non-stretched cycles to be stretched and MAP will indicate in the second portion of the CPU cycle that a DMA request is pending. DMR is supposed to be cleared during the DMA cycle. The DMA itself is not handled by the DCJ11 and must be orchestrated by external logic. The DCJ11 only extends non-stretched cycles, e.g. cache hits or NIO cycles, into stretched CPU cycles to allow DMA to take place as soon as possible. Note that typically you should implement DMA only during DCJ11 read cycles as the DCJ11 will not release the data lines during a write cycle and therefore you would need to add buffers between the DCJ11 and the data path for DMA.
These signals are associated with testing and disable the DCJ11 functions and are used for board-level testing.
This signal is the reset input for the DCJ11 and forces teh system through a power-up procedure. This signal must be asserted for at least 25 clock cycles. The DCJ11 will then execute the initialization microroutine as described in chapter 8.3. of the first document mentioned.
The HALT
signal when asserted forces the DCJ11 into console mode, i.e. initiates
console ODT. This is the highest priority non-maskable interrupt.
The DCJ11 has an built-in crystal oscillator which only requires an external crystal a bias resistor of approx. 1MΩ and two load capacitors of approx. 68pF. The pins are named XTALI and XTALO. Two clock output signals are provided by the DJC11. CLK is only used for diagnostic. CLK2 has as well the same clock rate as the oscillator and is CLK2 is typically used as the system clock for external logic.
Although the DCJ11 has many signals and options, only very few are required for the DCJ11 to operate. The following inputs
HALT, IRQ0, IRQ1, IRQ2, IRQ3, MISS and CONT
can just be tied to GND and the signals
PWRF, FPE, EVENT, PARITY, DMR, DV
can be tied to VCC.
The ABORT signal should be left unconnected as it is an open drain signal that is internally tied to VCC.
With this configuration all bus cycles will be stretched and 8 clock cycles long. The access time for peripheral and memory needs to be less than approx 5 clock cycles. Which is approx 275ns. Typical SRAM has an access time of less than 120ns, CDP6402 has an access time of less than 150ns and the DC319 has an access time of less than 250ns. We should be on the safe side for all these devices.
The critical part are write cycles, as in a minimal system you would use SCTL to gate the write enable signal of memory or IO. If you connect CONT to GND a write pulse of only one clock cycle will be the result, which is too short for a CDP6402 and also outside the specifications of a DC319. One trick is to connect CONT to SCTL. As CONT is sampled using the falling edge of T4 and SCTL is asserted during T5, connecting CONT to SCTL will add at least two clock cycles to the CPU cycle during which SCTL will be as well asserted. In this case a write pulse that uses SCTL will last for 3 clock cycles, or approx 166ns when the DCJ11 is operated using a 18MHz crystal.
Connecting CONT to SCTL will of course slow down the system. If you are using fast SRAM as memory with an access time 70ns or less you can connect MISS to VCC, which lets the DCJ11 think every memory read cycle is a cache hit and hence memory read cycles are non-stretched.
Most latches, like the 74HCT574 edge triggered latch, require a positive clock. As you need to latch the signals for AIO, BS and DAL with ALE you need to connect the clock inputs of the latches via an inverter to this signal. You need to latch at least AIO, BS, and some memory address signals. This will result in at least two 8-bit latches which will provide you with a DCJ11 system with 512W of memory. If you add another 8-bit latch you can support up to 128kW of memory using two standard 128kbyte SRAM devices in a DIP-32 package as the minimal system presented here. You need to use edge triggered latches as ALE is only asserted for a short period.
As next you need to decode the AIO and BS signals. There is no need for an address decoder. Decoding the bank select is all a hack requires.
Bus Select code ‘b'00 can be used to generate the chip enable for the memory, and code ‘b'10 to generate the chip enable of the UART. AIO codes ‘b'1100 and ‘b'10xx can be used to generate output enable and AIO codes ‘b'00xx for write enable. To support byte writes we need to create two write enables. One that is asserted for word writes and lower byte writes and another for word writes and upper byte writes. The lower byte write signal can also be used as the write enable of the UART.
It is very important to provide the correct power-up configuration during the initialization. You should at least provide the correct information for bits 0, 1, 2, 3 and 8 during the two GPREAD with code 000 and 002. When you have no floating point accellerator you can just decode the GPREAD cycle to provide the power up configuration bits for all GPREAD cycles, this is AIO code ‘b'1110.