Interrupt Priority Decoder
Posted: Thu Nov 11, 2021 5:24 pm
BillO on Fri 23 Jul 2021 wrote:
A 74HCT148 and a 74AC245 might make a decent interrupt priority encoder that would work on a 6502 bus.
I worked out for myself that it would be a good idea to pre-scale the priority encoder such JMP (VECTAB,X) uses even X. Dr Jefyll recommends the same although I did not work out Dr Jefyll's trick of using a larger pre-scale and using the priority encoder as the bottom byte of the vector address itself. That saves quite a few bus cycles but requires additional circuitry to handle the remainder of the vector - and all of the unrelated vectors.
74x148 has a "no selection" output and this is best wired on bit 4 such that nine even values may be produced. (0-16, not 0-14.) This leads to an 18 byte jump table where the last entry is for spurious interrupts or safe exit after all interrupt sources are serviced. It would be preferable if the spurious vector occupied jump table entry zero but this arrangement is sufficient.
I have yet to mention the annoying edge case. An interrupt may occur at any time. In particular, it may occur when the memory location of the priority encoder is read. In the worst case, the three or four signal lines from the priority encoder may be sampled in an inconsistent state. This occurs when the priority encoder transitions at the worst possible moment. At best, this will cause the wrong interrupt service routine to be executed. If the interrupt service routine is not written correctly, erroneous data may be queued - or worse. Furthermore, when the source of IRQ is not cleared, a second pass will be taken through the IRQ vector. This adversely affects the maximum frequency of periodic interrupts and may incur data loss.
In my attempt to resolve this situation, I sketched increasingly complicated circuits. After six chips, I thought that I might have the wrong approach. Indeed, a 74x573 *before* the 74x148 (and tied with the 74x245's output) is sufficient. This ensures that all *inputs* to the 74x148 settle during the read cycle for the priority encoding and guarantees that the multiple signal lines are in a consistent state when the data bus is sampled at the end of the cycle.
The 74x573 should itself be preceded with a network of eight pull-up resistors. Unless you plan to share priority encoded interrupts, this has the advantage that open collector variants of 6522 are immaterial and both variants may be mixed or substituted within one design. Unless there is a particularly clever way of scaling priority encoders, it remains possible to make a tree of interrupt sources with 8-16 fan-out at each branch.
Curious cases remain. A low priority device may interrupt. By the time the priority encoding is read, a higher priority device also wishes to interrupt. In this case, the last device to interrupt is serviced first. IRQs are typically executed sequentially. However, execution order may be significantly jumbled. This may lead to race conditions, priority inversion or resource exhaustion. The easiest way to avoid this is to aggregate or partition system interfaces.
As an example, a system with four UARTs should not place all input interrupts above all output interrupts. A continuous stream of input may exceed available buffers while output is starved. It is preferable to give priority to outputs or aggregate UART interrupt signals into a subordinate priority encoder which only aids the UART interrupt service routine.
Anyhow, four components are required: pull-up resistor network, transparent latch, priority encoder, tri-state buffer. I don't recall anyone getting the edge case correct with discrete logic. This would lead to experimental designs which mostly work but become increasingly unstable as interrupt sources are added. This is rather a shame because the very small number of registers in a 6502 contributes to its exceptionally good interrupt response time and it would be particularly suited to eight or more interrupt sources.