5

I would like to assign a Z80 PIO chip to my homebrew Z80 "computer". Unfortunately, what I've recently noticed in the datasheet, chip version which I actually have: Z0842006PSC can handle max. 6 MHz only, while my CPU works with 16 MHz crystal (chip itself can handle up to 20 MHz). Does it really mean I have to reduce Z80 clock also to 6 MHz?

After quick research I can see that PIOs can generally run with slower frequencies than Z80s - most common versions are 4 or 6 MHz (I couldn't find anything faster than 10 MHz), while Z80 in majority are 20 MHz versions. I don't understand why such disproportion, like using PIO in the architecture often impose CPU speed reduction.

I don't want to limit the clock so drastically, maybe is there some workaround? I know there are chips e.g. MOS6522 but I don't believe they would fit better :)

2
  • 2
    The Z80 K(iller)IO Z84C90 can run at up to 12.5MHz clock speed. With a bit of good will and luck, it might even run at your 16MHz rate
    – tofro
    Jun 26, 2021 at 12:15
  • You can get 10MHz Z80 PIO parts, and they seem to run fine an awful lot faster. Above that you could just switch from the Zilog parts to something better - many of the 82C55 or 16C255X type chips will run happily at that speed and let you get more PIO lines and serial on a single chip.
    – Alan Cox
    Jul 7, 2021 at 12:43

2 Answers 2

10

The Z80 PIO is much more of an I/O co-processor than a classic I/O peripheral chip. For this reason, it needs to be connected to the system clock of the Z80 main CPU.

The PIO listens to various control bus signals like /RD /IOREQ /M1 and /RD and derives the intended or currently executed actions of the CPU from them (It does scan the data bus during the CPU instruction fetch for RETI opcodes, for example, to detect when the CPU is done with its interrupt handling to be able to release a daisy-chain trigger).

For this reason, it needs to run at the same clock speed as the CPU. Introducing wait states when accessing the PIO doesn't help, as the PIO must "understand" the bus even when it's not directly accessed.

So, in the specific case of a Z80 PIO, the peripheral needs to run at the same clock as the CPU. You could use the Z80 KIO ("Killer"-I/O) chip Z84C90, which is basically a conglomerate of all Z80 I/O chips (SIO, PIO, CTC) and is/was available for frequencies up to 12MHz (and could possibly be slightly over-clocked), or use more "classic" I/O chips like the 8255 or Z85xx peripheral family that are not so closely tied to the CPU's clock.

The daisy-chaining of interrupts was an innovative method the Z80 introduced to enable its I/O devices to hardware-prioritize their interrupts between each other without requiring a specific interrupt controller chip (like, for example, the 8080 needed) and did only work with the dedicated Z80 peripheral chips.

13
  • 1
    The Z80 had some good design decisions and some bad ones. The use of the RETI instruction as an interrupt acknowledge strikes me as one of the goofiest unless the intention was to make the use of non-Z80-family peripherals less convenient. Determining when a RETI is executed in the instruction stream may not be all that expensive, but it does represent a fair bit of needless complexity.
    – supercat
    Jun 26, 2021 at 15:16
  • @supercat Actually, I see no other (easy) way to detect when the CPU is done handling the previous interrupt (other than adding a pin to the Z80, which always was a problem) when using daisy-chained interrupts. The interrupt chain is actually a nice way to hardware-prioritize interrupts saving a lot of otherwise necessary hardware.
    – tofro
    Jun 26, 2021 at 21:07
  • BTW: RETI is not used as an interrupt acknowledge (that's INTACK). RETI is used to detect the CPU has handled the previous interrupt and the handled device can activate the next device in the daisy chain to trigger its interrupt.
    – tofro
    Jun 26, 2021 at 21:14
  • 1
    @lvd once your daisy chain got longer than like 3 devices, you'd better be expecting latency problems, that's true. But when you have that many devices to prioritize, it's probably better to go for an interrupt controller anyways (and use non-Z80 devices).
    – tofro
    Jun 27, 2021 at 9:42
  • 2
    @supercat The interrupt acknowledge cycle starts with (/IOREQ && /M1), when the device is asked to put its vector (or RST) onto the data bus. There's no more "cycle" going on from this point. The CPU runs the ISR, typically one per device (to avoid polling). To be able to know when the next-lower priority device can be allowed to interrupt the CPU, the currently handled device needs to see the RETI (but that's no longe part of the INTACK cycle). With daisy-chained interrupts, you need to live with much less devices than 8 (the run-time of the daisy chain allows not more than 3 or 4 devices.
    – tofro
    Jun 27, 2021 at 19:32
1

[...] Z80 PIO chip [...] can handle max. 6 MHz only, while my CPU works with 16 MHz crystal (chip itself can handle up to 20 MHz). Does it really mean I have to reduce Z80 clk also to 6 MHz?

No. You just have to make sure that the CPU control and data signals are valid within the PIO timing when accessing the PIO. The usual way to do this is inserting wait cycles.

Wait states are known by most CPU, meant to accommodate slower peripherals, memory or I/O. They are a hardware protocol to synchronize operations the fastest possible way without any software overhead.

Zilogs INTERFACING Z80 CPUS TO THE Z8500 PERIPHERAL FAMILY application note describes this in great detail. Here especially the section of interfacing a Z80H (8MHz) with Z8500 (4MHz) or Z8500A (6 MHz) peripherals starting on p6-10.

I don't want to limit the clock so drastically

So don't. Simply clock the PIO appropriate and have the CPU wait a bit when accessing the PIO. Next to any combination can be used, but the following may come rather easy:

   CPU Clock   PIO clock  Divider Wait states

1) 12 MHz      6 MHz      2       2
2) 16 MHz      2 MHz      8       8
3) 16 MHz      4 MHz      4       4
4) 16 MHz      6.4 MHz    2.5     3  *
5) 18 MHz      6 MHz      3       3 

(#4 might need a higher (32 MHz) base clock)

Of course any other combination can be created. I would recommend case #2 or #3. Keep in mind, the slow down is only for that specific I/O cycle the PIO gets accessed. Otherwise the system runs at full speed, giving the best of both worlds.

I know there are chips e.g. MOS6522 but I don't believe they would fit better :)

They fit well, but may run into similar issues.

2
  • 4
    I'm not sure that the Z85xx document is fully applicable to the Z80 PIO - The PIO is much more closely interworking with the Z80 CPU than "normal" I/O devices from other families - it scans the data bus for RETI opcodes, for example, to find the end of an interrupt acknowledge cycle, something it couldn't do when not running on the same clock (one of the reasons why it needs to connect to /M1 as well, which is pretty unsual for an I/O device).
    – tofro
    Jun 26, 2021 at 11:29
  • Please note that I'm reffering to Z0842 chip, like @tofro mentioned. As I can see in the document about Z85, which you provided, it doesn't require CLK signal - seems it is driven rather by CE pin. Z084 has CLK pin and I'm afraid it cannot take >6Mhz. If I wanted to use wait states, I would have to connect PIOs CLK pin rather to Z80s IORQ pin and not to crystal clock - the question is whether it will work. Or maybe divide PIOs clk signal e.q. x4
    – RaspbJan
    Jun 26, 2021 at 12:14

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .