10

Looking at the pinout of e.g. the 8088, it multiplexes the data lines onto eight of the address lines; presumably the designers judged that being able to squeeze the chip into a 40-pin package, would save more total system cost than the extra logic required in the memory system.

Was there also a potential slowdown due to having to use the same pin for two different signals one after the other, instead of having separate pins? Or is it irrelevant because address has to come before data anyway?

Not that it would matter in the specific case of the 8088, which didn't drive the memory bus all that fast anyway, but I'm wondering if it would have been a limiting factor on a chip that did try to max out the memory bandwidth, e.g. using fast page mode where possible, and if so, whether 'we might need to make a cost-reduced version that multiplexes address and data lines' might have been one consideration to explain why pre-ARM CPUs did not max out the memory bandwidth (a surprising state of affairs in my opinion; memory bandwidth was a scarce resource, why leave some of it unused?).

3 Answers 3

11

In general: memory needs stable address for a while. So the real access time is "time to address available + memory access time". If you use the CPU with a full address bus (Z80, 6502, ...), it can expose the whole address in one cycle, wait only "memory access time" interval, and you can read.

On the other hand, let's take the 8085 CPU with a multiplexed data/address bus. Due its timing diagram, the address is completely ready (i.e. buffered with the ALE signal) in the second half of T1. And then you have to wait for the memory. At 2 MHz it is OK, safely under the memory access speed, but with faster CPU it should request some wait state.

So the answer is: yes, multiplexing is a little bit slower. Think about multiplexing as a special case of "serial-parallel interface" (or "a serial interface on 8 data lines").

8

The 65816 does the same thing; the most-significant 8 address bits are multiplexed onto the data bus pins during the Phi1 half of each clock cycle, and it reverts to being a data bus during the Phi2 half. The WDC datasheet illustrates a simple external logic circuit which latches the address bits and isolates the data bus pins from a device responding prematurely to a read cycle.

In fact this doesn't slow down memory access at all, provided you use sufficiently fast devices in the latching circuit. There are people running the W65C816S-14 (rated up to 14MHz) at 16 and even 20 MHz, without any memory wait-states.

6

The 8088 (and Z80 and 1802 and many other older CPU designs, including minicomputers and mainframes) required multiple clock cycles to run each machine code instruction. This was due to being implemented by internal microcoding, limited shared resources, or non-pipelined state machines, due to much lower transistor counts than todays processors.

As long as the bus multiplex rate is sufficiently faster (in cycle time) than the CPU instructions that do memory loads and stores, there is no slow down.

(Unless wait states are required, which can be needed on either multiplexed or non-multiplexed bus configurations, depending on memory subsystem latencies).

Later designs of (internally)RISC or pipelined processor cores, which can execute one or more load/store instruction per clock cycle, require caches, non-multiplexed buses, and/or much wider buses to keep the CPU closer to fully utilized.

6
  • 3
    I used to think the Z80's long cycle counts were a consequence of microcoding, but they're primarily driven by a single-ported register array, a 16-bit increment/decrement unit that is shared among multiple purposes, and a 4-bit (not 8-bit!) ALU. Given those constraints, most Z80 instructions run at near optimal speed, though the behavior of some could have been tweaked to be faster [e.g. LDI could probably have been about 4 cycles faster if it ignored BC].
    – supercat
    Jan 7, 2020 at 0:02
  • @supercat most uses of LDI and LDIR need that decrement of BC to be useful. Without, LDI would only be useful for "move a small fixed number of bytes from a to b" (and open-coding those becomes incredibly inefficient use of memory after about, well, two bytes' worth). LDIR was used for all sorts of things like copying bitmapped characters to the framebuffer in terminal emulators, and admittedly that could perhaps be written a series of LDI, but that binds you to always use the same size characters... Jan 9, 2020 at 2:55
  • @WillCrawford: If leaving BC alone would shave four cycles off an LDI, then a sequence of four LDI instructions followed by DJNZ would be faster than four repetitions of LDIR. Though thinking about it, an even better approach might have been to have LDIR loop while bit 7 of BC is clear. Decrementing a 16-bit register while checking for zero takes 4-5 cycles since it must be processed through the 4-bit ALU, but a 16-bit decrement without the zero check would only take two cycles. I suspect the Z80 instruction set was designed at a time when it was expected to have an 8-bit ALU, since...
    – supercat
    Jan 9, 2020 at 7:16
  • ...the new features really don't make sense with a 4-bit one. If there were a prefix which meant "compute IX+disp and use that in place of HL in the following instruction", with the prefix preceding the next opcode, that would have saved 3 cycles off the cost of "IX+d" addressing by allowing the IX+d computation to start while the next opcode byte is being fetched. As it is, the only instructions that benefit from that are the CB-family bit shifts when used with IX+d or IY+d addressing.
    – supercat
    Jan 9, 2020 at 7:21
  • @WillCrawford: Perhaps ideal would have been an instruction that would be like LDI, but which allowed a three- or four-bit repetition count to be specified within the opcode, and which would have an execution time of about 10+6n cycles during which interrupts and refresh would not be processed. People using the instruction would need to ensure that they do things in small enough chunks to avoid violating their system's interrupt or DRAM timing requirements, but e.g. a four-byte LDI and DJNZ loop would take about 47 cycles, or 12 cycles per byte--much faster than LDIR. If 16-cycle chunks...
    – supercat
    Jan 9, 2020 at 16:30

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .