I'm looking for a way (apart from manually wiring up Fig.15 of The Z80 Family Program Interrupt Structure) to daisy chain "non-Z80-family" devices in an IM2 Z80 system i'm designing.

So far i've come across the "one PIO (using a bit mask) / CTC (using a trigger input) / CIO (not sure how, haven't looked too much at that chip yet, but afaik it's just a PIO/CTC combined) port per device" approach, which, frankly, sounds rather wasteful (in pcb real estate, power, money and code overhead, especially since i'm making a modular system with multiple daughter boards, so each one would need one of those chips).

I've also found US4860200A, but couldn't find any indication that ever was an actual Tektronix product.

I've tried (and failed) to wire up the circuit in GAL22V10, and want to avoid full on CPLD/FPGA/microcontroller solutions.

Essentially what i need is an IC with data bus, IEI, IEO, INT on one side and "HELP", "INTACK" on the other, and implements the logic linked to above. Address decoding and outputting the IM2 interrupt vector i can do myself easily with a binary comparator and a tristateable buffer (or more likely the combination of those in a GAL because i have a bunch of them and they save space&power)

Does anyone know any such thing I might've missed in my research?

for the record, i've asked this on reddit too, where you can see a naive and extremely wrong attempt at the GAL implementation, but we didn't come to any results there, the most helpful reply there was showing me how to do interrupts in IM0 with polling the devices to see which has data, which i already knew

  • I'm not really sure what the setup is. at one point you're asking about non-z80 peripherals, but then about PIO, CTC. What is it? Next, that circuit of fig.15 should fit fine in an ATF750. But more important, there is no need that non Z80 peripheral follow the whole protocol, as release can be as well done under software control. – Raffzahn Oct 29 '20 at 22:03
  • @Raffzahn "at one point you're asking about non-z80 peripherals, but then about PIO, CTC." no, i'm asking about non-z80 peripherals and mentioning the possibility of abusing PIO/CTC to trigger interrupts for them (with loads of overhead). "But more important, there is no need that non Z80 peripheral follow the whole protocol,as release can be as well done under software control." what exactly do you mean by that? i'm under the impression that with IM2 i need interrupt priority, because e.g. multiple devices trying to assert their vector sounds like a bad idea (short circuit on the data bus). – nonchip Oct 30 '20 at 7:18
  • @Raffzahn and since i'm using also z80 peripherals, i'd rather adher to the standard made by the inventors of the cpu and half the peripherals i'm planning to use, than try to reinvent the wheel? e.g. "release can be done under software control" sounds like you mean ignoring the RETI thing and replacing it with e.g. a real OUT to the device, but in that case the "RETI ripple" would not work for those devices in the chain that are z80 family? – nonchip Oct 30 '20 at 7:19
  • @Raffzahn also note you mentioned the ATF750, as far as i can tell that thing needs wincupl (which doesn't run on my machine) instead of e.g. GALasm for the earlier devices, and i frankly have no idea how they want one to flash that thing (which for the 22v10 i can easily do with a TL866II, but i can't even find the overpriced proprietary thing i assume atmel wanted to sell people for that). any more info as to how to do that, or how exactly you'd implement that (i've done a bit more experimenting with 22v10 code for that circuit, the main issue is the flipflops) – nonchip Oct 30 '20 at 7:48
  • 1
    "and that's not because of my code but because the chip i've tried just doesn't have enough gates" -- this is probably the most important omission from the question. – lvd Oct 30 '20 at 15:54

My opinion is that I wouldn't rely too much on Z80 daisy-chained interrupts. It was actually invented to "dissolve" the need for the dedicated interrupt controller IC among the ordinary peripheral chips. Besides that only useful feature, everything else is disadvantage:

  1. The need for extra logic inside chips, i.e. decoding RETI instruction and maintaining IEI/IEO chain
  2. The need for extra pins dedicated to that interrupt stuff, that is, instead of single /INT output, now ICs have IEI, IEO and /M1 pins. This is probably the most stringent objection given the only standard DIP cases were available at the time.

A funny thing that the Z80 CPU itself knows little of that daisy chaining. IM2 mode could be made useful without any Z80 peripherals. Another (though little) its 'knowledge' is RETI instruction that Z80 executes exactly the same way as RET, except for two opcodes instead of one.

If I need to have a vectored prioritized interrupt system on Z80, I'd consider the following ideas:

  1. Do not use vectored prioritized system at all
  2. Use another IC from 80ies, that is 8259 interrupt controller, along with IM0 mode in Z80
  3. When some kind of programmable logic is made voluntarily available, I'd build my own minimal prioritized interrupt controller. It is as simple as having to priority encode interrupt requests to directly form an interrupt vector (for IM2 mode) or RST n opcode (for IM0 mode).

P.S.: Consider using MAX CPLDs (that is, EPM7032, 7064 and 7128, or EPM3032, 3064, 3128). They are available in PLCC cases (so that you can use PLCC sockets for them), quite powerful in comparison with GALs/PALs, 5v tolerant (only applicable to EPM30xx, as EPM70xx are already 5v-only devices) and considerably easier to program as vhld/verilog languages are higher level ones.

  • so this is what one calls the A/B problem... your answer to "how to do that" is "i don't like to do that, and here's an explanation on the things you already know"? plus i'm afraid "that only useful feature" is wat makes or breaks a modular, interrupt driven computer (unless you want to set up polling/IM0/1 handlers for every possible setup). also as i already said, i did consider and decide against cplds/fpgas. because they're a) quite overkill, b) hard to program unless you get vendor specific proprietary software (and often hardware), and c) i personally find GALasm way easier than VHDL. – nonchip Oct 30 '20 at 15:05
  • Another (though little) its 'knowledge' is RETI instruction that Z80 executes exactly the same way as RET, except for two opcodes instead of one. Are you sure about this? To my knowledge IRET restores the internal ei/di flipflop iff1 from its backup copy iff2 which RET does not touch ... meaning using RET will screw up your next maskable interrupt unless you EI before RET which could screw things up if used in nonmaskable ISR and pose also stack overflow thread in case the ISR is firing continuously – Spektre Mar 21 at 7:13
  • 1
    @Spektre First, there is no IRET insn in Z80, only RET, RETI and RETN. Then, you're speaking about RETN, which restores interrupt enableness from iff2 at the NMI return. In contrary, RET and RETI are fully equivalent, except for the number of M1 cycles. – lvd Mar 22 at 7:46
  • @lvd IRET was a typo (last few years I mix order of letter often not sure why but mostly only 2 consequent letter swap and it gets worse with time :( IRET is 3 places away weird) ... I have to investigate this closer do you have some relevant source about this? Or do you have some binary / test that would fail on using RETI instead of RETN. I would repair the behavior in my emulator as currently my RETI is using the iff? and still passing ZEXALL 100% however iffs are most likely not incorporated to the test CRCs. but I need to know for sure before changing something that works – Spektre Mar 22 at 7:53
  • 1
    @lvd looks like this link from OP confirms it thx for commenting me ... I guess all the ISRs has EI before RETI so is works even with my current implementation... Why is that all the good docs pops out only years after I need them .... – Spektre Mar 22 at 8:05

This answer is an attempt at a “middle of the road” solution: not as flexible as a fully decoded IM2 system with 128 interrupt vectors, but certainly practical enough not to require programmable logic.

Routing the IEI/O chain through modules in a general purpose system is not the best idea due to timing constraints and the general Z80-specificity - it’s not quite necessary.

So, if you can do with 7 prioritized interrupt vectors then it can be done differently - still using IM2. The trick is to use a one-of-7 priority encoding for interrupt vector number, eg. 0x00 highest priority then 0x02, 0x06, 0x0E, 0x1E, 0x3E, 0x7E, 0xFE lowest priority. Data bus would have pull ups - they can be gated by VECRQ described below, if you want to decrease general bus loading a bit. Prioritized requester uses an open-collector driver to place their interrupt vector (from jumpers etc) on the data bus in response to a vector request. The wire-or of concurrent vectors automatically provides the highest priority vector to the CPU, should multiple interrupts be pending.

This allows the use of Z80-native peripherals without the chain as well: all they would need is two bus access buffers: open-collector gated by VECRQ | CS & !RD, and open-emitter gated by CS & !RD only.

So let’s see what the logic requirements would be: each non-Z80 peripheral needs an additional 8-bit open-collector driver, input set to the encoded interrupt priority, with its OE:=VECRQ & DEVINT, where VECRQ:=M1 & !IOREQ driven by the motherboard.

Interrupt acknowledgment would be quite peripheral-specific. Some peripherals don’t need it - the handling of the device’s state may clear the interrupt active flag, or it can be cleared via a config register. But if you really need one, then physical INTACK can be generated using any GPIO mechanism or even just a plain 8-bit address comparator gated by !IORQ, and can be pulsed by the interrupt handler, or set by the interrupt handler and cleared on next M1 - just one F/F for that.

Using IRET snooping for acknowledgments takes a bit more logic: the motherboard would provide IACK:=M1 & D[7:0]=IRET. The device then would need two things: 1) comparator that compares D[7:0] with its interrupt vector, with the output, say INTEQ, latched by falling VECRQ. This lets the device know that it won the priority contest. 2) Device INTACK := INTEQ & IACK from motherboard, this would synchronously reset the INTEQ latch as well.

Since interrupt handling highly depends on peripheral type, it makes sense to put the device-specific part of it on the side of the device rather than on the motherboard, and only provide VECRQ and IACK as somewhat general-purpose signals from the motherboard.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.