11

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
    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. – user3570736 Oct 9 '17 at 4:17
  • 3
    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 '18 at 14:48
8

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 us, 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 a 6502 system like the C64.

  • 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 '17 at 6:16
  • 3
    @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 '17 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 '17 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 '17 at 19:15
8

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.

7

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.
  • 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 '17 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 '17 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 '17 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 '17 at 12:36
  • @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 '17 at 13:13
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 ...

  • 2
    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 '17 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 '18 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 '18 at 15:37
2

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.

1

(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.

  • 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 '17 at 1:42
  • 1
    ... 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 '17 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 '17 at 9:33

Your Answer

By clicking "Post Your Answer", you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.