Z80 I/O Port Address Decoding - Page 1
Forum section: electronics / beginners

author: pyromaniac4382
author_rank: Contributor
timestamp: November 05, 2014, 08:52:25 pm
content: I have been thinking of ways to get the most out of my Z80 in terms of Ports. I know that only the lower 8-bits in peripheral mapped I/O are used to address I/O by the Z80 this means 256 ports if each peripheral device only has one address. In the case of say 16550 UART we need to address 8 registers and select the device. Using this as the basis for moving forward. I figured the following drawing would be a good representation of what I wanted to get done.{See Attached Image}I would decode the higher addresses for the device selects, and the lower addresses would provide the exact address within that space. Is there any easy way other that this to maximize the amount of devices? this seems like the simplest solution to me, but I would love to hear other peoples' opinions. Thanks.

author: Simon123
author_rank: Regular Contributor
timestamp: November 05, 2014, 10:51:55 pm
content: Proably you could divide your datamap to Inputs And output(RD and WR).Btw you only want serial I/O ?

author: T3sl4co1l
author_rank: Super Contributor
timestamp: November 05, 2014, 11:50:46 pm
content: Yes, that's the way to do it. Make sure the RD/WR strobes are resolved correctly (with IORQ / MEMRQ and so on).Tim

author: pyromaniac4382
author_rank: Contributor
timestamp: November 06, 2014, 02:23:46 pm
content: I noticed I made a mistake A0->A3 have 2^4 possibilities which means : 16 choices.(rather 0 -> F) So the map changes a bit.Honestly I modeled the I/O map off of the 16550 UART and controlling it. It seemed to need an enable signal, /WR signal, /RD signal, three address bus lines to identify 1 of 8 internal registers, the ( 8 ) data bus lines to exchange data, a reset signal, and an oscillator to get the correct baud rate.I could categorize this as a device (peripheral) by hooking up one of the 16 outputs of the 4-to-16 decoder and the bottom three address lines to identify each register. Say I picked the fire output of the 4-to-16 decoder, then the UART is mapped to ports 00H -> 0FH and 00H to 08H will be used to identify each internal register of the 16550.It is a waste though for say an LED output port of 8 LEDS on say the second output of the 4-to-16 decoder. The output port would be enabled by writing to any address between 10H and 1FH.I guess you could further decode the signal for instance by sending the second output of the 4-to-16 decoder to another 4-to-16 decoder as well as the lower three addresses. Then the map would get you individual "chip enable" signals for 10H -> 18H.It seems easier to decode this way than to use 8-input NANDS each time a device needs an address.Also, the RD WR signals will need to be involved with the Memory and IO Signals as follows to produce Memory RD/WR and IO RD/WR.

author: ryanmoore
author_rank: Contributor
timestamp: November 06, 2014, 02:50:53 pm
content: You can have more that 256 ports if you really need them. The Z80 puts the contents of the B register on the upper 8-bits of the address bus during all I/O operations, and the lower 8-bits come from either the C register or a numeric operand. The downside is that it's up to you as the programmer to make sure that B contains the address you want when doing I/O, but it means you don't have to worry so much about "wasting" I/O addresses because you have 65536 of them now.

author: pyromaniac4382
author_rank: Contributor
timestamp: November 06, 2014, 03:53:55 pm
content: That seems like a good solution. I wanted to keep things as simple as possible though. I can't see myself adding much more than a keyboard, display, external storage, GPIO (LED OUTPUT PORT / SWITCH INPUT PORT), and UART. So it isn't really about waste as so much as just keeping things expandable enough while keeping the scheme easy to follow.A little background I have an STD-BUS Card Cage with back-plane, and I am currently working on a plug-able "system board" that will host the Z80, 32KB RAM, 32KB ROM, and some circuitry for single stepping. I have 9-slots in the cage so I figured the next logical step is to make a sort of I/O Board so I am trying to plan ahead to see if I would need anything else on the system board before diving into the IO board.

author: grumpydoc
author_rank: Super Contributor
timestamp: November 06, 2014, 06:15:56 pm
content: QuoteNearly.IN A, (nn) and OUT A, (nn) put the accumulator on the high address bits.IN r, (C) and OUT r, (C) are really IN r, (BC) and OUT r, (BC) as you suggest.

author: Simon123
author_rank: Regular Contributor
timestamp: November 06, 2014, 07:00:00 pm
content: Maybe LD HL, (nn) and LD (nn), HL could also be handy. (16bit addres from H and L register pair)They would share datamap with RAM and ROM, but better then nothing right

author: westfw
author_rank: Super Contributor
timestamp: November 07, 2014, 02:31:59 am
content: To get the most ports, you'd usually divide the address space into regions of different-sized groups, and connect the necessary number of low bits to the actual peripheral chips. Really easy to do with some sort of PAL logic, or you can cascade decoders, or do parallel decoding...

author: grumpydoc
author_rank: Super Contributor
timestamp: November 07, 2014, 08:20:28 am
content: QuoteMemory-mapped I/O is perfectly OK on a Z80. In fact if you have a simple system with just RAM, ROM a few ports and a UART you probably don't need to decode I/O ports at all which can save the decoder and/or gates needed to do so.

author: janoc
author_rank: Super Contributor
timestamp: November 07, 2014, 02:07:31 pm
content: Quote from: grumpydoc on November 07, 2014, 08:20:28 amMemory mapped I/O is OK, but why to waste address space on a CPU that can only deal with 64kB? It is not MC68k where you have always at least a megabyte (the 8-bit bus variant) and you can afford throwing addresses "out of the window". Most Z80 software needs as much RAM as it can get, so you often see banked designs and what not.Unlike the 8080, the Z80 has separate I/O address space, so it would be a shame to not use it.

author: grumpydoc
author_rank: Super Contributor
timestamp: November 07, 2014, 02:14:02 pm
content: QuoteIf you need to have 64k of ROM and/or RAM, sure use the I/O space.I did once toy with the idea of using the whole 64k I/O space for RAM (and just the low 256 addresses for real ports) so you could have a system with an extra 64k of data space. Never actually built it.If you don't need to fill the address space with memory why not decrease the overall complexity of the system and use some of it for ports?

author: sunnyhighway
author_rank: Frequent Contributor
timestamp: November 07, 2014, 02:43:20 pm
content: I'd go for bank switching. Plenty of examples how to accomplish that. Just make sure you use IORQ instead of MREQ.

author: grumpydoc
author_rank: Super Contributor
timestamp: November 07, 2014, 03:06:28 pm
content: Quote from: sunnyhighway on November 07, 2014, 02:43:20 pmBank switching the memory or I/O space?I've built bank switched (or more accurately mapped) systems using a couple of TTL SRAMS to expand the address bus to 20 bits (seethis thread).Never felt the need to bank switch the I/O space.The main reason I never built a system with 64k of RAM decoded in the I/O space is that access to it is pretty limited - you're limited to moving 8 bits to/from an address in BC to a register and it's slow - if you do LD BC, nnnn; IN/OUT A, (C) that comes to 15 t-states. You can load into the accumulator from a fixed address with LD A, <high byte>; IN A, (<low byte>) in 12 t-states but you can't write that way as the accumulator can't simultaneously hold the byte to write and the address to write it to.

author: sunnyhighway
author_rank: Frequent Contributor
timestamp: November 07, 2014, 04:41:46 pm
content: Quote from: grumpydoc on November 07, 2014, 03:06:28 pmBank switching the I/O spaceUse a single address in the I/O space for being able to select the I/O bank you want by writing the appropriate byte to it.This gives you 256 banks.By choosing a 128 byte bank size you can swap (the bank selector address must be outside the switchable bank) you can have 32K worth of I/O address to play with.

author: grumpydoc
author_rank: Super Contributor
timestamp: November 07, 2014, 04:50:15 pm
content: QuoteI don't see why you'd bother.You can have 64k of I/O space as long as you don't mind losing the ability to use OUT A, (nn) with less hardware complexity as there's no need to implement a port decode and latch for the bank itself - just use the upper 8 bits of the address bus.