• Please review our updated Terms and Rules here

Question about Z80's OUT instruction timings.

Sendraz

Member
Joined
Apr 8, 2022
Messages
24
So in the past i have built a homebrew 8 bit computer based on a DDR clone of the z80 microprocessor (U880). I'm currently writing machine code monitor with some extra features, like the (O)ut command, which reads the user input (e.g O 20 01), where the first value is the peripheral device number decoded by 74hc138 demultiplexer, and the second one is the value i want to write to that device. The subroutine of that command currently uses OUT (C), A instruction, but it doesn't work as expected. I was using it to write some data to 4x20 LCD display (HD44780) so i could see the results, and it returns nothing or garbled character (depending on selected LCD register controlled by LSB of the first argument in the command). I have also noticed that when i wrote a small program doing output with OUT (N), A instruction instead of the one using C register, it works correctly. (I couldn't even initialize the display in the boot sequence if it wasn't working at the first place).

So my question is, is there a significant timing difference between OUT using C register and OUT with immediate value? Or is this something with the fact i use a clone CPU and it has some unexpected behaviour?
 
One difference between OUT (C) and OUT (n) is what happens with the high byte of the address bus. Could that be relevant to your situation? The Z80 uses all 16 bits of BC as the address when you do OUT (C), but maybe the circuit is not decoding A8~A15 anyway.
 
Yes, the Z80 is a bit strange in this respect.

OUT (N),A outputs the I/O port value on A0..A7 and A is output to A8..A15. A is also output onto the data bus.

OUT (C),A outputs C on A0..A7 and B on A8..A15. A is output onto the data bus.

Technically (homebrew designs), only the lower 8 bits of the address bus (A0..A7) should be decoded for the I/O device.

Look at the schematics and identify which address lines are used to decode the specific ports that do not work.

There isn't a timing difference between the two forms of instructions (that I can determine from the Zilog Technical Manual).

We did come across a problem with the very early Zilog Z8002 (the 16-bit processor),. This did not work with direct ports, but did with indirect ports. This was a 'known' bug with the very first processors of this type. To my knowledge, a bug like you have described was not present within the Zilog Z80 family.

Of course, if you are using a clone Z80, all bets are now off...

Dave
 
One difference between OUT (C) and OUT (N)is what happens with the high byte of the address bus. Could that be relevant to your situation? The Z80 uses all 16 bits of BC as the address when you do OUT (C), but maybe the circuit is not decoding A8~A15 anyway.
I think that the smiley thing of the forum eats up ( N ) unless you add spaces or mark the text as "code".
 
@daver2 @bakemono I have looked at the schematics diagram again and that's exactly what was causing this! I wired the data input on the LCD to the upper address bus, relying on it, so its all clear now. I have been working on this project since 2023 and it was going through several design changes and i just forgot about that strange wiring.
Thanks!
 
OUT (N),A outputs the I/O port value on A0..A7 and A is output to A8..A15. A is also output onto the data bus.

Huh, I'd never noticed that. Does the 8080 also mirror the data output onto A8-A15? I'm scanning the old 8080 datasheet on deramp and I can't find anything saying it does.
 
>>> I'm scanning the old 8080 datasheet on deramp and I can't find anything saying it does.

I can't find anything in my old Intel data books either.

Dave
 
Huh, I'd never noticed that. Does the 8080 also mirror the data output onto A8-A15? I'm scanning the old 8080 datasheet on deramp and I can't find anything saying it does.
The 8080 does this differently. Although seemingly undocumented in Intel's datasheets, during an input/output port cycle the 8080 mirrors the port address on A0-A7 to A8-A15. Vintage S100 bus designs (notably, the Altair front panel) took advantage of this feature.
 
Last edited:
Aside from the noted information above, the only difference is that OUT(N),A is 11 cycles and OUT(C),r is 12 cycles.

Otherwise the I/O cycle should be the same... If I had to guess, perhaps the value of C is changing or being corrupted by the code during the transfer? Especially if you have some kind of loop?

Other possibilities are the B register, but generally the upper address lines will reflect either A or B depending on the instruction, so it's unlikely to be a hardware issue.
 
The OP sorted it. See post #5. The wiring used was specific to the Z80 operation of the OUT (N),A instruction. The OP had wired his LCD data bus to the high address byte and not the CPUs data bus...

When the instruction was changed to OUT (C),A this all broke, as the B register is now output on the high address lines and not a duplicate of the A register.

Dave
 
One nice thing about the OUT(C),A instruction is that you can simulate a true 16 bit IO bus (by presetting BC), making it possible to experiment with 8 bit ISA cards on the Z80. And then you can do weird things like hooking up a PC Hercules card to a Microprofessor Plus, add Basic and run Startrek :-)

2024-04-01 20.01.47.jpg2024-09-25 18.54.33-1.jpg2024-09-25 18.56.15-1.jpg
 
Last edited:
Another nice thing is that IN x,(C) sets the Z, P and S flag. This can speed up e.g. ready testing of fast I/O devices like floppy controller.
Martin
 
The OP sorted it. See post #5. The wiring used was specific to the Z80 operation of the OUT (N),A instruction. The OP had wired his LCD data bus to the high address byte and not the CPUs data bus...

When the instruction was changed to OUT (C),A this all broke, as the B register is now output on the high address lines and not a duplicate of the A register.

Dave

I missed that completely ! On two rereads. Thanks for mentioning it :) I can see how that would work for a write-only environment.
 
One nice thing about the OUT(C),A instruction is that you can simulate a true 16 bit IO bus (by presetting BC), making it possible to experiment with 8 bit ISA cards on the Z80. And then you can do weird things like hooking up a PC Hercules card to a Microprofessor Plus, add Basic and run Startrek :-)

View attachment 1311256View attachment 1311255View attachment 1311254

In this example you’re using the “B” value as address bits, another thing you can do with it is use it as data bits. For instance, there was a (somewhat) popular memory mapper, the 74LS612, that stored pages as 12 bit numbers and had a 12 bit data bus. If you’re using this with a Z80 you could get rid of the latch you otherwise need for 4 of those bits and instead spit the value you want across A and B and set it all at once with OUT(C),A.

(Obviously this only works to write the registers, if you need to read them you need a read latch and second operation.)
 
Well it's documented but may not have been intended.
It may be an artifact of gating C onto the address bus. the logic for B is intertwined with C.
When they changed the logic to get C they also got B.
The documentation feels like "I ment to do that" ;^)
Are they likely to say "Yeah we screwed up"
 
After thinking about this a bit....
OUT (C),A is working as intended. It's IN A,(C) That's broken.

A 16bit IO space would have been really useful.
 
Back
Top