Wouldn't is work something more like a 'Key['#'] Down' and 'Key['#'] Up' ? So each key being pressed down transmits a activate signal. And only when the key is released would it send a de-activate for that key?
This way, your Z80 will see any number of keys being pressed on and off simultaneously, or one after another, or held down for any amount of time?
Well, that's the way PS/2 keyboards work, yes. The interface module I'm using dumbs that down a bit so it only sends 'key down' (or 'make') codes and doesn't send on the 'break' codes. It would involve some work on the host side to buffer 'make' codes and respond to the running program with a list of keys that are pressed at that instant, for little benefit currently. That's something I can work on later as and when the need arises.
Well in the Z80, for normal keyboard operation, we are talking code as simple as when a 'make' is received, set that as a single strike and do nothing else, ignoring everything until ANY 'break' is received. Natural exception would be flags for combo keys like 'shift' and 'ctrl' and 'alt'. Only special apps like games would need direct access to 1 stage earlier. We are talking something like 8-12 assembly commands, not counting a lookup table if you need to translate to ascii.
Or, in fact, maybe something like a lookup jump table, where whenever a 'make' is set, the jump would fill in the ascii or shift/ctrl/alf flags and a 'break' would clear the normal keys. This strategy may waste a good 64 to 128, or 256 additional bytes of program space, but, it would be stupid quick and difficult to mess up.
Or, you can partially hold the flags and decode the basic ascii in verilog, and have 2 keyboard bytes to read. 1 for base bottom ascii code, the second byte for shift/ctrl/alt status and 'make' / 'break' being set, plus maybe an interrupt enable.