17

Back in the 8-bit days, I used 6502 computers, where the story about memory access was easy to understand. RAM chips of the late seventies and early eighties could do 2 MHz (or a bit more e.g. 2.6 in the datasheet I found), a 1 MHz 6502 took half the bandwidth leaving the other half for video which translated into a maximum of about 10K of video RAM. (Variation on a theme: the BBC Micro used the new fast RAM chips, which allowed a doubling of all those numbers.)

I'm writing a story that involves among other things a fictional Z80-based home computer at the end of the seventies; the protagonists selected that CPU in the belief that it was slightly faster than the 6502 (takes an average of perhaps three times as many clock cycles to do things, but has four times the clock speed). The computer has 16K of RAM (about the max affordable at the time) and graphics similar to those of the Sinclair Spectrum. I'm belatedly checking the situation with regard to sharing memory access, and...

http://www.worldofspectrum.org/faq/reference/48kreference.htm#Contention

... it's looking surprisingly terrible? The video seems to be using 3/4 of the memory bandwidth rather than the expected 1/2 even though it's only 6K of video RAM. The Z80 needs memory access at what are in this context effectively random intervals, which means it will very often trip over the video chip. Worse yet:

https://en.wikipedia.org/wiki/ZX_Spectrum_Contended_Memory

"However, the ULA must wait for a Z80 read or write to complete before it can stop the Z80's clock and access the memory. As the ULA has no capacity to prefetch and store data in advance, it relies upon the memory being available to read to produce a clean and true video display. If an existing Z80 access is in progress when the ULA must read video data, the read is missed and the display shows blank white pixels in place of the correct video pixels. On the next frame, they may well be read correctly. The consequences of this often appeared as a flickering of missing pixels on the display, or 'snow' as it was also called. To avoid snow, some programs and games only copied data to the display on interrupt, as the Spectrum maskable interrupt was generated by the display vertical refresh signal."

... that seems to mean that a program that spends most of its time updating the display (like games, which, let's be honest, are the main consumers of CPU cycles on home computers), must effectively shut down operations while the screen is being displayed, which is most of the time. The combination of these would seem to imply that you'll only actually see a small fraction of the nominal performance of the CPU. Even the separate memory banks on the 48K Spectrum won't help all that much, because the CPU does still need to update video memory.

I don't think it can really be that bad. If it was, nobody would ever have used a Z80 for any computer with a graphical display, and in practice, the Spectrum, Amstrad, MSX and probably some other machines I'm forgetting, did happily use the Z80. What am I missing?

3
  • 5
    This page gives a better explanation of the 'snow effect' ( faqwiki.zxnet.co.uk/wiki/ZX_Spectrum_ULA ) and as far as I know the above Wikipedia article is wrong. It's not triggered by normal memory access to contented memory at all, you have to be doing something with interrupts. Oct 9, 2017 at 4:17
  • 6
    Yeah, that Wikipedia article is absolutely terrible. Complete misinformation. You have to be very deliberate to create snow on the Spectrum; most people didn't even realise it was a possibility and, in any case, there isn't enough time to copy a whole frame during vertical blanking and the interrupt doesn't fire until the actual sync, not at the end of pixels, so approximately half of the blank is gone by then anyway. Somebody has just made up a lot of nonsense.
    – Tommy
    May 10, 2018 at 14:48
  • 1
    It may be more helpful to look at how Amstrad arranged video memory access a few years later. They paused the Z80 on 3 cycle instructions to make all instructions equal to 4 cycles long during screen display , then used 2 of those cycles to access the video ram for display. Aug 22, 2022 at 8:12

9 Answers 9

17

I think you've let your understanding of the situation as it was in the late 70s/early 80s become somewhat more simplified than it actually was. For example:

RAM chips of the late seventies and early eighties could do 2 MHz (or a bit more e.g. 2.6 in the datasheet I found)

You say you're looking at a 16K design, so it's highly likely it'd be based on the 4116 series of DRAM chips. The 4116 was available in a variety of speed grades at different times; it happens the datasheet I have in front of me is for Motorola's implementation of it and dated October 1979, at which time they offered access times down to 150ns (which is nominal latency from RAS to data being available, assuming your timing between asserting RAS and switching to CAS is optimal). The 150ns wasn't especially common, but the 200ns variant was more so (for example, this issue of Byte magazine from 1979 has a lot of adverts for products including 4116-200, and quite a few with 4116-250s, but only a single advert for the 150ns variant (on p282, listed as "4116-2", which was a common designator for this speed, used e.g. in the Mostek implementation.

But in the end, 150ns or 200ns, you still get the same overall full cycle time of 375ns, which as you say is about 2.6MHz. But that's fine, because the Z80 didn't use its bus anything like as efficiently as the 6502, so it doesn't matter that your memory is slower than the CPU bus.

The 6502 is renowned for using its memory bus for (depending on how you clocked it exactly) around about half of each of its processor cycles. This lets you interleave its accesses one-to-one with accesses to your video hardware, and it works out very neatly.

The Z80 memory interface, on the other hand, is messy.

  • The Z80 clock rate is much faster in relation to both CPU processing and memory accesses than the 6502 is.
  • The Z80 subdivides its cycles into machine cycles (labeled M1, M2, etc) and T-states (T1, T2, etc, which correspond to bus cycles). Each machine cycle contains at least 3 T-states.
  • The first T-state of the M1 cycle is easily identified, because the CPU explicitly signals the start of M1 cycles.
  • How the Z80 uses memory depends on what it's doing.
  • When the Z80 fetches instructions, it performs the following operations:
    • It places the address on the bus in sync with a negative edge of its clock in cycle T1 (cycles are counted positive edge to positive edge).
    • roughly a quarter cycle later, during the low phase, it asserts MREQ and RD.
    • at the next negative edge, the Z80 samples the WAIT line. If it isn't asserted, it reads the memory contents on the next positive edge after that, which is to say at the start of cycle T3, a full cycle and a half after it signaled the memory request. Perhaps not coincidentally, this is 375ns for a 4MHz Z80A.
    • because you've had enough time for a complete memory cycle during this process, you can immediately start using the memory for other things. After reading an instruction, you have the T3 and T4 cycles (i.e. at least 500ns at 4MHz) before the next machine cycle starts.
  • When a memory read or write is performed during executing an instruction, the sequence is slightly different.
    • The address is placed on the bus at the rising edge of T1, not falling.
    • The MREQ and RD signals are asserted on the falling edge of T1, or for a write WR at the falling edge of T2.
    • The data is read (assuming no WAIT signal is asserted) on the falling edge of T3, i.e. a full 500ns after the control signals at 4MHz. Data for writing is available from falling edge of T1 until just after the rising edge of T3, giving several hundred ns of variability.

All machine cycles are at least 3 T-states long, and in each machine cycle you can tell during the first T-state whether the CPU is going to be using memory.

Even in the absolute worst case where every machine cycle is hitting memory (and it would be rather difficult to achieve this with a practical program), you get 500ns of time for display memory access between each CPU memory access. OK, you need to perform memory refresh in this time, but there's more than enough time for that during times you won't be producing video output (you need to hit all 128 rows every 2ms; the horizontal blanking period between each row of a typical TV screen will contain 8 M1 cycles so you can refresh your memory in horizontal blanking every 16 lines of display, which is less than 1ms).

So you get 500ns out of every µs, but that only gets you 1 memory access per microsecond, right? There's a 375ns cycle time on the memory, after all...

Well, it turns out that's not quite the end of the story. 375ns is the cycle time for random access. But video graphics is decidedly non-random. You're pulling lines of data out of a linear buffer. You can easily optimize your memory accesses so that you hit two adjacent memory slots on each use. Doing this lets you use your memory in what's referred to as "page mode", which is substantially more efficient. Accessing two adjacent memory slots (assuming you don't cross a page boundary) can be done by only using RAS once and then CAS twice. The time for such a cycle of two addresses on a 150ns 4116 is: tRCD + 2*tCAS + tCP + tRSH + tRP + 2*tASC = 460ns.

As to why the Spectrum suffers from snow when accessing the display: the Spectrum is notoriously cheap. It didn't synchronize its accesses with the CPU's in any way (despite this not being hard to achieve), in order to allow the board to be built particularly cheaply. Avoiding treading on the Z80 isn't hard, it's just a little bit harder than it is on a 6502 system like the C64.

5
  • 1
    How hard would it have been to have some FIFO chips which would get loaded with video data during the second half of each M1 cycle when the FIFO wasn't nearly empty, or during bus-requested cycles when it was? A 4MHz Z80 may not have quite enough M1 cycles to satisfy the video system's needs when running typical code, but it could likely come close.
    – supercat
    Oct 10, 2017 at 6:16
  • 4
    @supercat, unfortunately the Sinclair-led attitude was if you can do it in software and save hardware, do it and save the parts. As an aside, if they could have added something to the Spectrum, I'd rather it was a partially-programmable screen start address :-)
    – TonyM
    Oct 10, 2017 at 9:07
  • 1
    @supercat - the primary problem with this approach isn't so much cost (a small FIFO is cheap, and I believe the incremental cost of switching to a slightly larger ULA chip would have been trivial) as the lack of predictability. We're used to machines these days that take a varying amount of time to do things for effectively random reasons, but I'm not sure the home computer industry in the 1980s, which was defined by machine-language programmers writing cycle-exact code to get the maximum possible performance out of the hardware, was ready for that.
    – Jules
    Oct 10, 2017 at 18:22
  • 1
    @Jules: A lot of computers had a number of parts whose phase relationship was essentially unpredictable. Unless a Z80-based system forcibly syncs up the CPU with the display hardware (as was the case on e.g. the ZX-80 or ZX-81) the timing is going to generally be unpredictable depending upon the exact mix of instructions being executed.
    – supercat
    Oct 10, 2017 at 19:15
  • "...in sync with a negative edge of its clock..." It would be good if you explicitly specified whether that's the ϕ1 or ϕ2 clock.
    – cjs
    Mar 12 at 2:50
13

The 6502 situation isn't quite that rosy — the Vic-20 has a 12-bit data bus so that it can fetch both pixels and colours during its gap, the C64 has a complete CPU lock-out for the first row of every character line, the Atari 400/800/etc use a special modified 6502 on which they can stop the clock to get the CPU out of the way, the Oric runs the 6502 for only one in three memory cycles in order to give the video 2/3rds of the memory bandwidth...

That being said, the most powerful Z80 instructions move two bytes rather than one. Only PUSHs and POPs achieve that with a single-byte opcode. So the instruction stream is always an easy majority of memory accesses in a real program. On a Spectrum, even if you're heavy on screen painting, you still hit the lower bank much less frequently than the higher assuming you've located your code sensibly.

Other options:

Be like the MSX (or ColecoVision, or Master System, or anything else with a member of that family of VDP). Its VDP doesn't share bandwidth with the CPU, it instead has its own memory. You have to post bytes to IO ports to write into it, but then it's tiles and sprites so ongoing adjustments aren't as heavy. The CPU has full bandwidth access to its RAM. MSX caveat: the RAM need only be fast enough to serve a value every three cycles; an extra WAIT is inserted into opcode fetches, which would otherwise expect a response in two cycles.

The CPC is especially interesting because prototypes had a 6502, which was switched out for a Z80 before production, and it effectively recreates the 6502 two-phase memory access cycle with the Z80, strobing WAIT so that in every four-cycle block the Z80 gets one memory access during the first two cycles, and the video gets to use both of the other two cycles (with only one RAS — both video values are from the same row). This kind of has the opposite effect of the MSX scheme as opcode fetches cost exactly the normal amount but the three-cycle accesses that constitute most of the rest of CPU activity are stretched to four. Received rule of thumb is that the nominally 4Mhz CPU acts like it is 3.3Mhz.

So, my net argument: the Z80 isn't as weighed down as you think, and other options are available, and many of the 6502 machines were more affected than you describe.

9

Some facts about ZX Spectrum 16/48k:

  1. Video DRAM was unable to work at Z80 frequency (3.5MHz) [i.e. making full access every clock], therefore the need to "contend" Z80 cycles. For the DRAM working at Z80 frequency, there would be no need to contend Z80 at all (for example, russian Pentagons did like so).
  2. ULA does have some buffering capability as it reads screen data two pixel bytes ahead (2 pixel bytes plus two attribute bytes) in a single burst.
  3. It does so every 16 pixel clocks (i.e every 8 Z80 clocks), hence the notorious 6-2 pattern in Z80 contention.
  4. ULA uses "page mode" to access pixel and attribute bytes, i.e. it issues single RAS-address to the DRAM and then two CAS-addresses. Without the page mode, ULA would have to stop CPU for the duration of the whole line fetch (i.e. for 128 Z80 clocks).
  5. The requirement of being able to access pixels and attributes within single CAS-page creates that famous funny layout of ZX screen.
5
  • 2
    The layout isn't that funny though, right? If you're plotting one character row at a time, it is always the case that you can add or subtract one from your address to move left or right a column, or add or subtract 256 to move up or down a pixel row. Which makes for very easy use of HL as a pixel pointer for character or attribute-aligned graphic output. So it's odd, but they picked a good oddness.
    – Tommy
    Oct 9, 2017 at 14:17
  • 2
    For me it's more of by-product of the page mode requirements and yes, somehow page-mode requirements and easiness of 8x8 character printing were fused in this 'funny' layout :)
    – lvd
    Oct 9, 2017 at 17:01
  • 1
    @Tommy, they picked an odd and not a good odd :-) The benefit to character printing is small but the detriment to graphics operations like line drawing is much bigger. I used to write ZX Spectrum graphics assembler, along with an amateur games programmer, and it was far more of a hindrance. Hence the Sam Coupe using linear addressing in no-Spectrum display modes.
    – TonyM
    Oct 10, 2017 at 9:04
  • @TonyM yes, I expressed myself poorly. I more meant: having been required to pick an odd ordering, they made a good selection from the range of options. I've been a Sam Coupe programmer in my time; never touched Mode 2 (the Spectrum-esque but linear and with 8x1 attributes mode) though. Or Mode 1, because why accept the extra wait states?
    – Tommy
    Oct 10, 2017 at 12:36
  • 1
    @Tommy, my full apologies to you, you're right and I'm wrong here. I hadn't realised that the Spectrum screen layout is for DRAM timing. Which, if I'd read the answer I was actually commenting on properly, instead of jumping on your point, I would have done :-) I though I knew the Spectrum truly absolutely inside and out, from hundreds of hours poring over the innards of the ROM disassembly decades ago right through to the ULA book a few years back. I hadn't read the latter properly by the looks of it. Thanks, I've read up and see it now and your point stands.
    – TonyM
    Oct 12, 2017 at 13:13
6

This looks like not so much a premise for a fictitious story as what we did in real life combining a Z80 with the 6502 in the Commodore C128. There should be real life numbers for integrating to a DRAm bus with set cycle times, working around the video chip and also things like refresh.

6

In normal operation, there is no ‘snow’ visible on the screen of a ZX Spectrum. The ULA perfectly controls its own access and the Z80 CPU access so that no screen data is missed. You only have to watch the countless videos on YouTube that show ZX Spectrum games to confirm this.

It is however possible to set the machine up to generate snow. Sinclair Research almost got the design of the ULA correct, but there were some problems - mostly with the design of the memory and I/O contention circuitry (I/O needed because the ULA was mapped to the Z80 I/O address space). You also need to understand that the ULA controls the DRAM chip control signals when the Z80 CPU access the 16k bytes of RAM where the screen data is stored.

Now to understand what is really happening, you need to have a good understanding of how the Z80 CPU really works. During every instruction cycle, the Z80 carries out a DRAM refresh cycle. There is no way to switch off this function. Address bits A0 to A7 come from the R (refresh) register. But address bits A8 to A15 come from the I (Interrupt) register. The I register stores the most significant byte of a two byte value used for interrupt mode 2. During normal operation, this points to a sensible address in ROM or high RAM and therefore the ULA does not see the refresh address generated by the Z80 as a problem. But set the I register to certain values and then the ULA memory control circuitry sees the Z80 refresh cycle address as memory access to this RAM, but the contention circuitry is not activated so it does not pause the Z80 CPU. As the ULA has activated the DRAM control signals for a CPU access, the ULA is unable to fetch the correct screen data and a ‘snow’ effect is visible on the video screen.

More info if you're interested.

2

The contention is not the only thing that is considered while designing computer. The Z80 was so popular also due to fact It contain all the logic for refreshing of dynamic memories as SRAM was too expensive at that time.

I think that is the missing piece of contention Tommy's answer is pointing out. In your 6502 system you account for sharing memory by CPU and graphic chip. But the memories must be periodically refreshed too which also takes some bandwidth and or CPU cycles.

As Z80 does this on its own there is no need for additional circuitry which would lead to 3 object contention instead of 2 ...

4
  • 3
    Not realy, with screen memory within main memory, screen access will easy deliver the refresh without any loss of cycles on a 6502. That's the way the Apple II (and otehrs) did it. After all, 6502 relies on having 'double speed' RAM. A 1MHz CPU needs 2 MHz RAM (450ns). Thats why it's easy to do hidden video access without strangling the CPU. All needed is to arrange the address lines in a way, to spread video access across all RAM rows. After all, there is no reason, that A13 of the CPU has to be A13 of the DRAM. Unlike today, they didn't care for consecutive access patterns.
    – Raffzahn
    Oct 8, 2017 at 21:28
  • 1
    @Raffzahn: I wouldn't describe the as relying upon "double-speed RAM". If the CPU's memory isn't shared with anything else, the time available for memory to respond to an access request will extend from near the start of phi1 to the end of phi2. The data for a write will not be available until shortly after the start of phi2, but most on most memory chips the data setup time is far shorter than the address setup time. A 6502-with-no-video system could get by with memory that was about half the speed of what would be required when using video.
    – supercat
    May 10, 2018 at 15:33
  • 1
    @Raffzahn: One thing that is curious, though, is that 6502 systems that gated the address bus with phi2 always used two-phase clocking, but there's nothing magical about that. It would be fairly easy to throw ten 6502 chips on a bus, with each being clocked by a couple of outputs from a 4017. Increasing the number of processors would make it necessary to run them slower, but being able to interleave many independent operations might be useful for some purposes.
    – supercat
    May 10, 2018 at 15:37
  • As well as Raffzahn's point above, you get "3 objection contention" anyway even with the Z80 because it doesn't "magically" refresh the memory without doing additional accesses; it is essentially just a built-in version of an external DRAM refresh circuit.
    – cjs
    Mar 12 at 3:06
2

(I had originally a rather lengthy answer written, until I figured that your question is way too unspecific to be answered in detail. Without the type of Video generation mentioned, including resolution and colours as well as access patterns, no useful answer can be given. So here just a few basic numbers)

Let's go for the hard limits.

On each TV line about 17% (US NTSC) of time has no (data based) signal, so this time is available to the CPU.

Similar for the whole picture where only 483 of the 576 lines are used, leaving another 16% available. So completely holding the CPU during video access would leave about 30% to the CPU.

Next, real ~1980 contemporary computer video resolution will be way less (here your input is missing). Vertical resolution (horizontal doesn't matter here) might be just 200 lines per half frame. So only 70% (400/576) is needed, leaving 42% for the CPU. The video logic will now only steal a tad more than half of the cycles. No special trick used by now and native resolution with this timing might be up to 704 pixel in NTSC-M.

I seriously wouldn't call this "which is most of the time"

(Now I've got to use assumptions again - due missing input)

Depending on the amount of data the video circuitry needs to fetch per line, there may be additional access holes within a line. With like a 240x200 b/w display this would be 30 bytes per line (and about 6000 bytes video RAM). The visible part of a line is about 51us. Thus a RAM speed of 850ns (which is slow by 1980s standard) or better would already deliver double the needed bandwidth, thus the video logic would only need to stop the CPU for one single byte access and then leave the same time for the CPU.

In simple numbers this would now reduce the time the CPU gets slowed down to 29%. Already more than 2/3rd (71%) are now left to the CPU.

Looking at the Z80, you will notice, that depending on the instruction, there are often T-cycles outside an M-cycle. Thus depending on the instruction, the Z80 may even continue to work while memory access is blocked. Thus real blockage will already be less than about 29%.

Here a lot of possibilities open for tweeking RAM and CPU speed to get even less usage due video access. With the right chips, the number can be lowered to 15%. So again, not what I would call a great slow down.

Now, if we separate video RAM from program RAM, much like in the Spectrum, real magic happens:

While the Z80 does a lot of memory access, only a small percentage is for 'real' data. most goes to program code. And even of the data part, only a fraction is writing to the screen. For example moving a block of display data onto the screen via LDIR will mean that only 3 of the 21 cycles are writing video memory, while the remaining 18 cycles work internally or access program or source memory. Thus filling the screen with LDIR will get virtually **not at all slowed down* In fact, here it would even be sufficient if the video logic would only offer a gap every 6 or 7 bytes. Impact would still be almost impossible to detect. Same is true for basically all other access patterns.

Beyond this point speeding up the RAM access time would go hand in hand with geting a faster CPU. But again, very dependant on your design.

So video doesn't need to slow down the CPU at all. Even when using a Z80.

Addendum: Video games really don't access the video RAM itself as much as you assume. But proving this is a different topic.

3
  • 1
    Of course, once you've separated the video and main memory, you can look at having different types of memory, and then things can get really interesting. A block-coloured 256x192 framebuffer needs about 7KB of RAM (6KB for the monochrome bits, plus just under a KB for colour info). A Z80A accessing non-instruction memory (we'll assume you don't expect to execute code from your framebuffer!) expects access times of 2 whole cycles, i.e. 500ns. 200ns static RAMs cost about $20/KB at retail in 1979, so for $140 you can have a framebuffer that is fast enough that your video hardware can ...
    – Jules
    Oct 9, 2017 at 1:42
  • 2
    ... access it interleaved with your CPU and the CPU will never even notice the difference. (source of SRAM pricing here; see '2114-200' ICs on left page bottom-middle section) Given the specifications in the question, I'm assuming you're aiming to compete with the TRS-80, being the main system with similar specs of the era. The TRS-80 with 16K of RAM retailed for about $800. Having 23K at $1000 but better & faster displays could be pretty good differentiation.
    – Jules
    Oct 9, 2017 at 1:46
  • @Jules Right, still, I'd say any careful designed video logic will leave plenty of room for a CPU even while both are accessing the same chips. At least while we're talking resonable (for back then) resolutions. It's all about sharing.
    – Raffzahn
    Oct 9, 2017 at 9:33
2

I read all the answers and it seems to me that most of them are quite technical and, in a way, do not clearly address your concerns. Hence, I would like to offer direct comments on at least two of your statements (my thinking is similar to Raffzahn's, but I'll use a specific example of ZX Spectrum to give you some hard numbers).

  1. "that seems to mean that a program that spends most of its time updating the display (like games, which, let's be honest, are the main consumers of CPU cycles on home computers), must effectively shut down operations while the screen is being displayed, which is most of the time".
     
    Display updates do not take most of the time on ZX Spectrum 16K. The overall frame contains 312 lines of 224 clock cycles. The contention however occupies only 128 clock cycles in 192 lines. You can say that contention only affects the CPU (128x192)/(224x312) ~ 35.2% of the time. Hence, even in the worst case scenario the display updates occupy less than about one third of the CPU time.
     

  2. "Even the separate memory banks on the 48K Spectrum won't help all that much, because the CPU does still need to update video memory."
     
    Separate memory banks on the 48K Spectrum help quite a lot. You put your code into the fast (upper) memory and immediately the majority of the RAM access cycles issued by Z80 work uncontended.
    Suppose that we perform random memory writes to the screen RAM using a command writing one byte at a time (something like LD (DE),A). The contention will introduce a penalty of 0, 0, 1, 2, 3, 4, 5 or 6 clock cycles, depending on the precise time of our write. (See a detailed explanation on Sinclair Wiki.) On average, the delay you introduce will be (0+0+1+2+3+4+5+6)/8 ~ 2.6 clock cycles. The delay will only happen during 35.2% of the CPU time, so the average for the whole frame will now be 0.352*2.6 ~ 0.92 clock cycles. For a command like LD (DE),A this means average execution time of 7.92 clock cycles, which is only (7 + 0.92) / 7 ~ 13% slower than expected. Since you won't want to just issue LD (DE),A commands all the time, the real slowdown is less than this. Well written routines for ZX Spectrum 48K have no more than ~5% slowdown compared to no contention at all.

  3. Since your computer is imaginary, you can also consider installing slightly faster RAM. ZX Spectrum 16K used 4116 chips with 150ns access time. If you could source similar chips with 120ns access time (Fujitsu, Hitachi or NEC all made them apparently), then you can implement the trick from Pentagon 48K and get no RAM contention at all (this was discussed at some length elsewhere).

1

To all the above interesting answers I will only add two observations:

  1. DRAM refresh is best done by the video chip, because it anyway accesses memory more heavily, faster, than the CPU. Commodore 64 had the VIC-II chip take care of DRAM refresh. This makes the high memory bandwidth hog better able to control the refresh. The Z80 can only do refresh right after opcode fetch in the M1 stage. And that is harder to control. Besides, IO could possibly hold Z80 in /WAIT state so long that DRAM refresh will not occur fast enough. Even the video circuit could stop the CPU if it needs priority, with CPU being required for DRAM all of that gets more complicated.

Of course there can always be work-arounds.

  1. LDIR and related instructions aren't that much of a benefit, as I have personally seen that Z80 will interpose M1 wasted fetches (2 memory accesses) for each of the read and write operations of the payload bytes moved. And even the 16 bit arithmetic performed inside is causing additional slowness.
5
  • 3
    As a coder, I disagree with your item 2 (although, for the record, it was not me who -1ed your answer). Data copying using LDIR is, indeed, not the fastest way of copying data on Z80, but its simiplicity means that it is a viable option in many places. E.g., pretty much every decompressor uses LDIR a lot (because the slow-downs due to the LDIR are minor compared with the slowdowns due to the decompression overhead). A block of unrolled LDIs is pretty close to the theoretical maximum speed of copying, and it is also used very commonly.
    – introspec
    Aug 20, 2022 at 22:46
  • @introspec: If the Z80 had included a two-byte LDI2 instruction that would always copy exactly two bytes without affecting BC, it could straightforwardly have operated as an instruction that behaves like POP Z, but using post-increment HL, followed by a PUSH Z, but using post-increment DE, thus taking a total of 20 cycles. Twice as much useful work as LDIR, but half the execution time.
    – supercat
    Aug 22, 2022 at 17:38
  • @supercat, yes, copying at 10t per byte would have been lovely, but I thought we were talking about actual real world architectures? :)
    – introspec
    Aug 23, 2022 at 9:00
  • @introspec: I wasn't certain whether the "theoretical" maximum you were describing was related to the Z80 architecture and control circuitry as wired, or to what would have been possible with the general chip layout by making a few small tweaks. The maximum speed achievable via software on the Z80 would depend upon whether one needs to allow for the possibility of interrupts, and--if interrupts can be disabled and one is copying a large multiple of 256 bytes between pages would probably be something like...
    – supercat
    Aug 23, 2022 at 15:28
  • patch1: ld sp,__PATCHED1__ / pop bc / pop de / pop ix / pop iy / inc (hl) / exx / inc (hl) / pop bc / pop de / patch2: ld sp,__PATCHED2__ / push de / push bc / exx / push iy / push ix / push de / push bc / sub a,1 / jp nz,patch1 which would copy 12 bytes from each page (assume BC and BC' are loaded with the MSBs of both patch locations, __PATCH1__ starts at source+12, and __PATCHED2__ starts dest-244. After running that loop once for each page, modify patch1+1 and patch2+1 do do another 12 bytes from each page.
    – supercat
    Aug 23, 2022 at 15:43

You must log in to answer this question.

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