Great Series - One interesting I/O instruction is IN A,(C) - loads A register from Port in C, but also puts B on A8 to A15 - used on the ZX Spectrum to scan keyboard. Where B has the bit set for each segment of the keyboard to scan and get the button back. So output and input one instruction. A great processor trick built in by Zilog.
This mechanism was originally used with the ZX 80. With the later 81 and Spectrum copying it. Doing it this way saves the cost of hardware. It's unclear why Zilog didn't use IN ,(BC) and OUT (BC), for these instructions.
I'm really enjoying your series. So much so that I'm rewatching them to better understand some Z80 fundamentals. Also, I started a RUclips playlist on my fumbling progress of building a Z80 system. Emphasis on fumbling around. LOL
@@JohnsBasement That is so cool. I never thought I'd reach 100. Thank you so much for subscribing and hitting the 100 mark. I'm honored. Next goal: 200. 😀Now, if you'll excuse me, I need to binge watch your videos. #binging_johns_basement_videos 😂🤣
The conflict being discussed around 10:00 ... How about replacing U8 with a '245 and attaching the 'DIRECTION' pin to R/W? Now writing to it could possibly conflict with the printer status pins but #1, at least the conflict is something external and #2, I'm not sure, those pins may be used for one of the bidirectional parallel port standards /anyway/
That would be a good ifea.. If they went to an OR gate inside the chip. But they don't work that way. Each enables 1/2 the chip. It is a dual quad buffer.
IO address space on the Z80 is actually 16-bit, not 8-bit. IN A,(nn) will put AAnn on the address bus (where AA is the A register). Likewise, IN A,(C) will put BC on the address bus. The peripherals can fully take advantage of this. The ZX Spectrum, for example, uses this technique to select keyboard rows to read from in the high byte.
I knew about the IN A,(C) putting B on the high bits. But I don't recall the IN A,(nn) feature you mention. Were both of these made official? (I know the first one was.)
Hi Why didn't you use the /WR signal as /OE for the 74HC374 chips for the GP OUTPUT and PRINTER DATA ports? PCB routing problems? BTW, instead of a pair of resistors for the level translation between 5V and 3.3V, you could have used a MOSFET and resistor arrangement. It would provide a clean level translation with about the same PCB real estate. I've been using it for years with very good results, at clock speeds high above the ones used in this board.
@@JohnsBasement on a bi direction printer port you can use the PRN_ERR, PRN_STAT and soo on as I/0. Sorry English is not my main lang. :-) Love your your and i know 3 more Danish will build your Z80 system to :-)
@@JyskMaker you can do what the schematic lets you do. Obviously, the Retro does not have a bidirectional printer port. So you need to use pins with the appropriate signal direction for your application.
Still learning and one question occurred to me: According to Rev 4.2 schematic it looks like Z80 output ports 50-6F Hex are not currently used. So we have 16 bits of native I/O we could use if we wired it to something and added the right code in bios? Am I on the right track or did I miss something?
@@JohnsBasement For I/O 80-FF .. One would need another 74HC138 where A7 is inverted and then tied to E2 is that right? It seems weird that it could be that simple, but given the size of an electron it amazes me any of this stuff works at all. :)
@@johnhansen4794 That is one way to do it. Yeah. But it depends on if you want the 'enable' lines from the '138 to go on in 16-port groups like they do on the retro board. My having done it that way could be considered wasteful as in some cases I have a single latch connected to, say IORQ_10. Because IORQ_10 is true for all ports from 0x10-0x1F. Many, many, systems do this sort of thing to save money when they don't need, in this example, all the ports. My point is, if YOU want more enables and don't care about wasting some of the port numbers, you can save a chip (by not inverting A7, for example) and then connect the CPU A7, A6, and A5 lines to A2, A1, and A0 on the '138 with E2 grounded. Then you'd have 4 enable lines that overlap with the 8 on U9 and 4 other enable lines on your new chip that would go on for 32 ports each from 0x80-0xff. If you want enable lines that are true only on an input operation (as opposed to both IN and OUT like I did with U9) then I'd connect M1 to E3, RD to E2, and IORQ to E1 with A7, A6, and A5 connected to the '138's A3-A0 pins. Likewise if you only want output operation enables, connect WR to E2 (rather than RD.) OR... you can play games like connect M1 to E3, A7 to E2, IORQ to E1 and then put RD on '138-A2 with A6 and A5 on the '138 A1 and A0 pins and end up with half of the enable outputs going true on input operations and the other half true for outputs. STILL another way would be to add a '138 with E1 connected to, say U9's O6 pin and then connect the CPU A1-3 to the new '138 A0-2 lines with E2 grounded or connected to the CPU RD or WR line with the E3 pin pulled high. Eh?
These videos with your explanations of how it works helps a lot. I'm working on my own design that is similar when it comes to CPU/RAM/ROM/SD but consolidates the I/O into an Atmega chip. Also I'm thinking of adding an onboard AM9511A FPU. What do you think of FPUs (math coprocessors) in general, are they worth it or too much bother?
Back in the day I couldn't afford one!! 😳 So they weren't for me. If you need floating point math then they may help... Even with their slow (by today's standards) clock speeds. But count the cycles & decide if it is viable.
@@JohnsBasement Yeah I guess at the end of the day it comes down to novelty factor rather than a real need, but it would also be pretty interesting learning how to run code on an FPU. There was one blog I read where someone found that an AM9511A at 2MHz was faster at calculating prime numbers in Basic than a Z180 at almost 40MHz, which is pretty wild. Definitely it'd be interesting to see that happen in person!
@@JohnsBasement It would be very slow, especially running code like Mandelbrot in Basic would take a long time. And well I guess that even if I don't include an FPU in the design, it can always be added later via the 40-pin header so it's not essential to integrate it into the design. Dealing with the additional +12V requirement is a bit annoying.
@DriveAndMaintain if you add it later, make CERTAIN that ALL the signals you need are on the header!!! One shortcoming in the retro design is that you can't run in IRQ mode 2 and generate IRQs from an add-on board. 😞 ...because the daisy chain is confined to the retro board. Other modes can work though. Another possible issue is that you can only add things to the unused I/O ports (no memory mapped add-ons).... Which should not be an issue for this FPU.
As a followup to the Z80 Retro project, would you consider doing an FPGA version of the same board? You're talking through the entire board function; it would be super interesting to see you formally develop the logic in Verilog targeting some cheapish dev board. Not suggesting another hardware project, but rather a complete description of the logic to the point of synthesis. Thanks!
The glue logic in the fullest sense - the reset circuit, shadow ROM, I/0 select, etc. - basically anything that isn't LSI/MSI. The big stuff could just be black boxed - I know the Z80 is already modeled, not sure about the CTC, SIO, etc. I'd like to see the relationship between the logic in Verilog and the logic in hardware in a project that is simple enough to understand for an non-EE hobbyist and complex enough to be interesting.
@@jackrubin For glue logic it'd make more sense to go with a GAL. If I added an FPGA to the retro project, I'd use it to replace all the glue logic, I/O ports, and far more useful variations of the SIO and CTC. -- Doing a CPU in an FPGA would push the limits of what can fit into a cheap FPGA that is hand-solderable for benchtop tinkering (which is my preferred environment.) I have been mulling over an FPGA project to do just this plus add a floppy controller and a high speed SD card interface with DMA. Add your ideas to the list for consideration!
Hello John from around 9:00 to 12:00 minute you are talking about writing to port zero is no good and can damage the Z80 and to prevent this you need more logic and more logic equal more money what about if you use one of the OE of the chip with the /RD signal so if you try to wright on port zero the chip will be disabled.
Yeah .. that's right. To 'fix' it without adding more chips, I sometimes put /RD onto A0 of the 138. That makes every other output bit a read or write enable. BUT in this case I can't because the 138 also enables the CTC and SIO. So, this is what I ended up with.
Whaddaya mean by 16 bits? In an OUT instruction, the A reg is replicated on A8-A15 and D0-D7 with the IO port number on A0-A7. 🤔You mean an OUT (C) instruction??? I never noticed that the B reg is put on the MSB of the address bus in that insn. Something odd plays out with OUTI, PTIR, OUTD, and OTDR as well. I suppose you could abuse the value in the B register to think of it as a part of an address (or even as data.)
@@JohnsBasement I've heard that it was initially not intended by designers, but OUT r,(C) and IN (C),r puts entire BC register on address bus. As far as I understand it is consistent across all variants of Z80. This feature was used in ZX80/81, and maybe later ones too, to scan keyboard. And few years ago it got included in official Zilog documantation :)
@@Torshak0 I knew that the MSB of the address bus repeated the data bus and that there were other oddities going on during /IORQ. But it has no real impact on the Retro board design. If you want to use it by way of an add-on card, you can... as long as the 8-bit port address does not conflict with those used on the main board. So it's all good.
The short on output Z80 and input pins 1 and 19 of input buffer both go to address decoder. If 1 goes to not RD instead then enable would only work on read.
@@SimonJackson13 I used an abstract symbol for that chip. Have a look at the detailed view in the datasheet. Then let me know if the suggestion stands. 😉
Officially my favourite ongoing series on RUclips now! Thanks John :D
😀 officially my favorite subscriber!
I agree, I'm learning a lot from your videos.
Great Series - One interesting I/O instruction is IN A,(C) - loads A register from Port in C, but also puts B on A8 to A15 - used on the ZX Spectrum to scan keyboard. Where B has the bit set for each segment of the keyboard to scan and get the button back. So output and input one instruction. A great processor trick built in by Zilog.
Hey! That's a cool application of that feature.
This mechanism was originally used with the ZX 80. With the later 81 and Spectrum copying it. Doing it this way saves the cost of hardware.
It's unclear why Zilog didn't use IN ,(BC) and OUT (BC), for these instructions.
I'm really enjoying your series. So much so that I'm rewatching them to better understand some Z80 fundamentals. Also, I started a RUclips playlist on my fumbling progress of building a Z80 system. Emphasis on fumbling around. LOL
I'm glad you're having fun! [It looks like I'm subscriber #100 on your channel 😀 ]
@@JohnsBasement That is so cool. I never thought I'd reach 100. Thank you so much for subscribing and hitting the 100 mark. I'm honored. Next goal: 200. 😀Now, if you'll excuse me, I need to binge watch your videos. #binging_johns_basement_videos 😂🤣
The conflict being discussed around 10:00 ... How about replacing U8 with a '245 and attaching the 'DIRECTION' pin to R/W? Now writing to it could possibly conflict with the printer status pins but #1, at least the conflict is something external and #2, I'm not sure, those pins may be used for one of the bidirectional parallel port standards /anyway/
🤔 An interesting idea. But I like the 244's Schmitt inputs on those potentially sloppy inputs.
Dumb question: Why not tie one of the output enables on the Input GPIO 74ls244 to the Z80 read line(Also active low) ?
That would be a good ifea.. If they went to an OR gate inside the chip. But they don't work that way.
Each enables 1/2 the chip. It is a dual quad buffer.
@@JohnsBasement - Ahhh ... shoulda looked up the data sheet before commenting :/
@@JanEringa8k ;-)
IO address space on the Z80 is actually 16-bit, not 8-bit. IN A,(nn) will put AAnn on the address bus (where AA is the A register). Likewise, IN A,(C) will put BC on the address bus. The peripherals can fully take advantage of this. The ZX Spectrum, for example, uses this technique to select keyboard rows to read from in the high byte.
I knew about the IN A,(C) putting B on the high bits. But I don't recall the IN A,(nn) feature you mention. Were both of these made official? (I know the first one was.)
Hi
Why didn't you use the /WR signal as /OE for the 74HC374 chips for the GP OUTPUT and PRINTER DATA ports? PCB routing problems?
BTW, instead of a pair of resistors for the level translation between 5V and 3.3V, you could have used a MOSFET and resistor arrangement. It would provide a clean level translation with about the same PCB real estate. I've been using it for years with very good results, at clock speeds high above the ones used in this board.
I'm curious as to why you pull up the data bus instead of leaving it floating?
I find it tough to let myself allow a tri-state signal float if it is an input to a CMOS device.
So you can't use the printer port as a IO thing and tre control line as IO eather?
I don't understand this question. A printer port IS an IO thing. It is just bits. Connect them and use them any way you wish!
@@JohnsBasement on a bi direction printer port you can use the PRN_ERR, PRN_STAT and soo on as I/0. Sorry English is not my main lang. :-) Love your your and i know 3 more Danish will build your Z80 system to :-)
@@JyskMaker you can do what the schematic lets you do. Obviously, the Retro does not have a bidirectional printer port. So you need to use pins with the appropriate signal direction for your application.
@@JohnsBasement Yes i know, but if you one day make a other version, maby its somthing to thing about 🙂
Still learning and one question occurred to me:
According to Rev 4.2 schematic it looks like Z80 output ports 50-6F Hex are not currently used. So we have 16 bits of native I/O we could use if we wired it to something and added the right code in bios? Am I on the right track or did I miss something?
Yep. 50-6f are not used. Neither are 80-ff.
@@JohnsBasement Sweet. Thanks for the reply.
@@JohnsBasement For I/O 80-FF .. One would need another 74HC138 where A7 is inverted and then tied to E2 is that right?
It seems weird that it could be that simple, but given the size of an electron it amazes me any of this stuff works at all. :)
@@johnhansen4794 That is one way to do it. Yeah.
But it depends on if you want the 'enable' lines from the '138 to go on in 16-port groups like they do on the retro board. My having done it that way could be considered wasteful as in some cases I have a single latch connected to, say IORQ_10. Because IORQ_10 is true for all ports from 0x10-0x1F.
Many, many, systems do this sort of thing to save money when they don't need, in this example, all the ports.
My point is, if YOU want more enables and don't care about wasting some of the port numbers, you can save a chip (by not inverting A7, for example) and then connect the CPU A7, A6, and A5 lines to A2, A1, and A0 on the '138 with E2 grounded. Then you'd have 4 enable lines that overlap with the 8 on U9 and 4 other enable lines on your new chip that would go on for 32 ports each from 0x80-0xff.
If you want enable lines that are true only on an input operation (as opposed to both IN and OUT like I did with U9) then I'd connect M1 to E3, RD to E2, and IORQ to E1 with A7, A6, and A5 connected to the '138's A3-A0 pins. Likewise if you only want output operation enables, connect WR to E2 (rather than RD.)
OR... you can play games like connect M1 to E3, A7 to E2, IORQ to E1 and then put RD on '138-A2 with A6 and A5 on the '138 A1 and A0 pins and end up with half of the enable outputs going true on input operations and the other half true for outputs.
STILL another way would be to add a '138 with E1 connected to, say U9's O6 pin and then connect the CPU A1-3 to the new '138 A0-2 lines with E2 grounded or connected to the CPU RD or WR line with the E3 pin pulled high.
Eh?
On third rereading I think I am getting it. lol. Thanks for the reply.
These videos with your explanations of how it works helps a lot. I'm working on my own design that is similar when it comes to CPU/RAM/ROM/SD but consolidates the I/O into an Atmega chip. Also I'm thinking of adding an onboard AM9511A FPU. What do you think of FPUs (math coprocessors) in general, are they worth it or too much bother?
Back in the day I couldn't afford one!! 😳 So they weren't for me.
If you need floating point math then they may help... Even with their slow (by today's standards) clock speeds. But count the cycles & decide if it is viable.
@@JohnsBasement Yeah I guess at the end of the day it comes down to novelty factor rather than a real need, but it would also be pretty interesting learning how to run code on an FPU. There was one blog I read where someone found that an AM9511A at 2MHz was faster at calculating prime numbers in Basic than a Z180 at almost 40MHz, which is pretty wild. Definitely it'd be interesting to see that happen in person!
@@jimtekkit Faster than a basic app? Most certainly! Basic is pretty slow. Especially if you are using floating point variables!
@@JohnsBasement It would be very slow, especially running code like Mandelbrot in Basic would take a long time. And well I guess that even if I don't include an FPU in the design, it can always be added later via the 40-pin header so it's not essential to integrate it into the design. Dealing with the additional +12V requirement is a bit annoying.
@DriveAndMaintain if you add it later, make CERTAIN that ALL the signals you need are on the header!!!
One shortcoming in the retro design is that you can't run in IRQ mode 2 and generate IRQs from an add-on board. 😞 ...because the daisy chain is confined to the retro board. Other modes can work though.
Another possible issue is that you can only add things to the unused I/O ports (no memory mapped add-ons).... Which should not be an issue for this FPU.
Boards ordered
Coolness! Are you going custom or building a Rev 4? Let us know how your build goes.
@@JohnsBasement Will do your build until I know enough to do a custom - then maybe I can sell a few -?
As a followup to the Z80 Retro project, would you consider doing an FPGA version of the same board? You're talking through the entire board function; it would be super interesting to see you formally develop the logic in Verilog targeting some cheapish dev board. Not suggesting another hardware project, but rather a complete description of the logic to the point of synthesis. Thanks!
For the glue logic? Or are ypu thinking more?
The glue logic in the fullest sense - the reset circuit, shadow ROM, I/0 select, etc. - basically anything that isn't LSI/MSI. The big stuff could just be black boxed - I know the Z80 is already modeled, not sure about the CTC, SIO, etc. I'd like to see the relationship between the logic in Verilog and the logic in hardware in a project that is simple enough to understand for an non-EE hobbyist and complex enough to be interesting.
@@jackrubin For glue logic it'd make more sense to go with a GAL. If I added an FPGA to the retro project, I'd use it to replace all the glue logic, I/O ports, and far more useful variations of the SIO and CTC.
-- Doing a CPU in an FPGA would push the limits of what can fit into a cheap FPGA that is hand-solderable for benchtop tinkering (which is my preferred environment.)
I have been mulling over an FPGA project to do just this plus add a floppy controller and a high speed SD card interface with DMA. Add your ideas to the list for consideration!
@@JohnsBasement KISS (submitted respectfully!)
Hello John from around 9:00 to 12:00 minute you are talking about writing to port zero is no good and can damage the Z80 and to prevent this you need more logic and more logic equal more money what about if you use one of the OE of the chip with the /RD signal so if you try to wright on port zero the chip will be disabled.
sorry John stupid me i forgot that OEa is for the A outputs of the chip and OEb is for the B outputs forget my privies comment
Yeah .. that's right.
To 'fix' it without adding more chips, I sometimes put /RD onto A0 of the 138. That makes every other output bit a read or write enable. BUT in this case I can't because the 138 also enables the CTC and SIO.
So, this is what I ended up with.
Small rectification: Z80 is able to address 16-bit IO - not just the lower 8 bits.
Whaddaya mean by 16 bits? In an OUT instruction, the A reg is replicated on A8-A15 and D0-D7 with the IO port number on A0-A7.
🤔You mean an OUT (C) instruction??? I never noticed that the B reg is put on the MSB of the address bus in that insn. Something odd plays out with OUTI, PTIR, OUTD, and OTDR as well. I suppose you could abuse the value in the B register to think of it as a part of an address (or even as data.)
@@JohnsBasement Yes the OUT (C), r and IN r, (C) instructions. The other variants (OUTI and INI etc) are off limits if you decode MSB-A for IO.
@@JohnsBasement I've heard that it was initially not intended by designers, but OUT r,(C) and IN (C),r puts entire BC register on address bus. As far as I understand it is consistent across all variants of Z80. This feature was used in ZX80/81, and maybe later ones too, to scan keyboard.
And few years ago it got included in official Zilog documantation :)
@@Torshak0 I knew that the MSB of the address bus repeated the data bus and that there were other oddities going on during /IORQ. But it has no real impact on the Retro board design. If you want to use it by way of an add-on card, you can... as long as the 8-bit port address does not conflict with those used on the main board. So it's all good.
Yep! It's an intentional feature and is documented in the original Zilog literature. It's a great feature that's used by the microbee and Amstrad CPC.
GP Input pin 19 to /RD.
??
The short on output Z80 and input pins 1 and 19 of input buffer both go to address decoder. If 1 goes to not RD instead then enable would only work on read.
@@SimonJackson13 I used an abstract symbol for that chip. Have a look at the detailed view in the datasheet. Then let me know if the suggestion stands. 😉