5

My understanding of how interrupts (and more specifically, interrupt daisy-chaining) works in the Z80 is limited, to say the least, so if I get anything wrong please correct me.

Anyway, let's say I have two PIO chips to control two different peripherals (let's say, a character LCD display, and some switches, but I'm sure that's not very relevant). I've connected the IEO pin of one PIO to the CPU's INT pin, and it's IEI pin to the other PIO's IEO. I then connected that PIO's IEI pin to a 5 V rail. I got this information from this image: (but instead of the three different peripheral chips they use, I just have two PIO chips.)

Daisy chaining Z80 peripherals

[from here]

Anyway, my understanding is that this kind of configuration means that if the second PIO (the one directly connected to the 5 V rail) pulls its IEO pin low, the other PIO will not be able to send an interrupt. Correct?

My issue is this: How would I cause a PIO chip's IEO pin to go low? And how can I actually send an interrupt from one of these peripherals? My initial thought would be that I'd just pull the CPU's INT pin low, but that doesn't make sense the more I think about it.

(On a side note, any idea what the INTACK pin is on that diagram?)

  • Your diagram is incorrect. The IEO does not connect to the IRQ. Each compatible device has an IRQ line which are wired together with a pullup resistor to the CPU irq input. The IEI-IEO chain starts with the highest priority device having IEI = +5V and the IEO chained through IEI of the next lower priority device. The devices determine which one has both a pending interrupt and a IEI input enabled. There is no INTACK signal on the Z-80. Compliant devices recognize this as the combination of the M1 and IORQ signals. All of this is covered in Z-80 user docs. – Peter Camilleri Apr 20 at 19:16
10

You might want to consult the chapter for 'Interrupt Response' of the CPU manual (Chapter 8 on p.55 of the 1976 issue) and 'Interrupt Servicing' from the PIO manual (Chapter 6 on p.15 of the 1977 issue).

In general the Z80 supports 3 different interrupt modes:

  • Mode 0 - like 8080, here the interrupting device must place an instruction on the bus - usually done by a 8259 interrupt controller.

  • Mode 1 - All interrupts will jump to 38h (restart) and execute from there. Much like NMI

  • Mode 2 - Peripherals put an interrupt service number on the bus during interrupt response, the CPU uses for an indirect call thru a table of pointers in a 256 byte page pointed to by the I register.

The picture inserted hints that you intend to use Z80s Mode 2. To make it work:

  • Write some service routine for your interrupt, ending in an RETI
  • Disable interrupts
  • Setup a vector table in a memory page (256 byte boundary)
  • Pick any vector number you like (lets say 3)
  • Put the address of your service routing to that vector (xx06/xx07)
  • Put the vector number into the PIO channels vector register (control word with 2^0 set)
  • Set the Interrupt control word (x7) for the port to define which bits and under which configuration will trigger an interrupt. For example 97h FFh sent to Port A will make all inputs issue interrupts as soon as they go high.
  • Set interrupt Mode 2 of the CPU
  • Enable interrupts
  • Enjoy whatever happens :))

A Z80 in Mode 2 is perfectly suited for an interrupt driven system.

How would I cause a PIO chip's IEO pin to go low?

Err ... by waiting for an interrupt to occur, then servicing it?

(Maybe I do not really understand what part of information is missing).

  • Okay, thanks! That cleared a lot of things up for me. I don't know if I'm being stupid, but one thing I don't understand is exactly how I would create an interrupt from the PIO -- I mean, how can I interrupt the CPU when a button is pressed, for example? – Jacob Garby Mar 30 at 0:25
  • @Jacob, do you mean, how do you configure the PIO to generate an interrupt? If I'm reading this correctly, you use the interrupt control word. If the PIO is in input mode then it looks like all you have to do is set the interrupt enable bit and every byte of data that arrives will generate an interrupt. – Harry Johnston Mar 30 at 6:49
  • @JacobGarbyIt's the above interrupt control word(s) of 97h FFh. First byte defined the workings. abcd0111 means interrupt control word, where a enables interrupt (1=enable); b defines if all or any port bit have to be set/reset (0=any); c if tested for set or reset (0=set) and d tells that a mask for the bits follows. A mask of FFh lets thus the interrupt fire if any of the port lines goes high. For a button it may be more appropriate to take one pin, pull it via a resistor high and ahave the button pull it low. Words to make only pin 2^0 sensitive would be 93h 01h – Raffzahn Mar 30 at 7:53
  • The one thing I would add to this answer is to fill in all the vector table entries with the address of a sensible interrupt routine, even if it does nothing. – JeremyP May 8 at 9:14
2

The short answer is that Z80 do NOT determine itself which peripheral sends an interrupt. In Zilog's framework, all compatible peripherals determine among themselves who's emitting the interrupt to the CPU this time. Or more specifically, who is sending IM2 vector on the bus during the time Z80 acknowledges the interrupt.

This kind of controlling prioritization of interrupts allows one building Z80 system not to use additional dedicated interrupt controller, as i8080 system designer had to do. However, the drawbacks are:

  • extra pins every Z80-world compatible peripheral has to have.
  • extra intelligence every such a peripheral has to have: particularly, they have to understand specific Z80 command (that is, RETI), whose the only purpose is to say to the peripherals the interrupt routine ends; otherwise RETI is fully equivalent to RET.
  • probably the very long interrupt chains could have timing problems.
  • The docs for the Z-80 PIO included a section on reducing IEI-IEO propagation timing using AND gates. – Peter Camilleri Apr 20 at 19:11
2

Just to clarify a couple of points, using information from the Z80 Family Program Interrupt Structure.


Firstly, the Z80 has three types of interrupts:

  1. Bus request (/BUSRQ)
  2. Nonmaskable (/NMI)
  3. Maskable (/INT)

It is the latter, maskable, that Raffzahn refers to in his answer, when he states that there are three modes: 0, 1, and 2.


Secondly, the article, Z80® Family Interrupt Structure by Michael Moore, to which you link and obtained your diagram is very misleading indeed. Whilst the first IEI line is indeed tied to 5 V, the IEO line of the last peripheral, does not go to the INT pin at all, it is just left "hanging":

Interrupt priority chain

FWIW, the ripple reduction look-ahead logic schematic is this:

Ripple reduction look-ahead logic

Again, as the diagram shows, the first IEI is tied to 5 V, and the POUT goes to the next stage, or nowhere, if there is no subsequent stage.


Thirdly, the bizarre INTACK line shown in the article's diagram appears to be an over simplification of the /IORQ and /M1 lines. From page 15 of the Z80 Family Program Interrupt Structure, Interrupt nesting:

Interrupt acknowledgment

The PIO requests interrupt service by setting its /HELP logic and pulling the /INT and its IEO line low. Assuming interrupts have been enabled, the Z80-CPU finishes the current instruction and responds with an interrupt acknowledge (/M1 and /IORQ low).

1

Have added this here as additional info to answers above (too big for comment)...

The IEI / IEO are part of a daisy chain to determine interrupt priority. The signals are generated by the peripheral chips themselves. In the diagram in the question the DART has the highest priority, the PIO next and the CTC the lowest. A chip will not generate an interrupt if its IEI pin is low. As soon as a chip generates an interrupt it will lower its IEO pin to prevent lower priority chips interrupting. The interrupting chips monitor the M1 line and the data bus to detect the RETI instruction (could make for convoluted hardware as peripheral chips had to monitor data bus during CPU M1/read cycles). Nested interrupt was handled as follows; assume the PIO above has generated an interrupt. If the DART now interrupts the PIOS's IEI line goes low and its interrupt service routine is interrupted by the DART. The DART now waits for the RETI (the PIO ignores the next RETI as its IEI is low). As soon as the RETI for the DART service routine is detected the DART will let its IEO line to go high. The PIO's service routine resumes and when the next RETI appears it is done (all this applies to mode 2 interrupt handling). Very sophisticated for the time.

The diagram in the question is completely wrong in one respect. The IEO of the CTC would just not be connected. All of the Z80 chips would connect to the /INT of the CPU. I have no idea what INTACK is.

In the previous answer Ivd also correctly notes that there could be timing issues with long peripheral chip chains. An approach to this was to AND outputs together. For example a product I worked on had four such chips on individual boards and we could have up to sixteen boards in a system. The four IEOs on each individual board were ANDed together to drive the bus IEO signal for that slot. On the backplane the IEO of a slot was wired to the IEI of the next slot.

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.