Apart from being one of the most obnoxious people I ever met, my professor for digital circuit design at university told us some things that stay in the back of the mind. 👨🏻🎓
One of those things was that, in a digital design, you should always make signals that are asynchronous to the system clock synchronously. Usually this applies to signals like pushbuttons or from other devices that are separate.
In case of the Apple II peripheral bus there are both synchronous and asynchronous signals. Unfortunately, this is not really clear in the simplified bus timing diagram that appeared for example in the II+ manual.
7M, Q3, Phi0 and Phi1 are really synchronous as they are devided from the 14MHz main clock. In my CPLD design for the AppleIISd card I used 7M as clock, because it is the fastest clock that is available on all slots.
The three select signals, /DEV_SEL, /IO_SEL and /IO_STB are related to Phi0/1 but are slightly late due to propagation delays in the logic that generates them.
The address bus, the data bus and R/W could be described as asynchronous, because they are only valid in a defined interval: address and R/W are valid at some time during Phi0 high and data is valid at some time during Phi0 low. The times vary between the different Apple II types. All three signals are supposed to be valid for at least 10ns after one of the select signals goes high again.
Enough theoretical talk: what does that mean for my CPLD design? As mentioned in the beginning, every asynchronous signal has to be clocked in to be synchronous to the system clock. One could argue that all signals come from the same computer, but the CPLD sees that different. The address bus and R/W are valid when one of the select signals becomes low. When writing to the peripheral, the only time one can be certain that data is valid is when select becomes high again and shortly before. But then it is only valid for 10ns and that is not a really long time at all.
I suppose one of my original problems was that my design listened only to the rising edge of /DEV_SEL when writing to the device. After that the R/W signal and the address was decoded and only after that the data was pulled from the bus. That might have taken longer than 10ns. It seems that reading from the bus might not have been a problem. According to Apple IIgs Tech Note #68, the device shall deactivate at the rising edge of /DEV_SEL and using a HTC type bus driver should keep data long enough on the bus for the CPU to read without colliding with video data.
Everyone who understood what I was taking about, please raise a hand 😉