As early as the seventies, some computers used RAM in page mode,
Just the other way around, 1976 page mode RAM (MK4116) was available, and subsequently computers did use it, so make that the late 70s.
in which you can read two or more words from sequential locations
No, they did hot have to be in sequence, all they needed to be is within the same page, hence the name.
in rapid succession by only supplying the column address once, and then just supplying the row address of each location.
(A little nitpicking The other way arround, it is row address (RAS) first and column address (CAS) next. With keeping RAS active, the row (page) was held within the read/write buffers as long as desired)
In that mode, can the decision whether to read a second word, depend on the contents of the first?
Sure, why not. Just latch the last used row address and if the actual access matches the last, skip the row addressing and continue with the column address.
That is, can you, with 1970s technology, read one word, check its contents (with fast hardwired logic, not expecting software to be fast enough for such), and on the basis of that, decide whether to read a second word in fast page mode?
Oh, I see multiple possible logic issues in these asumptions:
For one, 1970s hardware isn't less capable than todays. The underlaying logic is still the same.
Second, hardware of the same time scale will always be fast enough to handle hardware features of the same time, otherwise, why bother to create such feature?
And last, software (contemporary on contemporary hardware) will always be too slow to cope with a sum cycle issue.
Or is it the case that by the time the first word is read, plus a couple of gate delays for a minimum analysis, it's too late; to meet the timing constraints of page mode, you have to already have started the process of reading the second word if you are going to?
There are no timing constrains. A page is held open as long as RAS is asserted. There is infinite time to check whatsoever, If the check succeeds go ahead with CAS addressing, if it fails, insert a RAS cycle.
Real World Usage
Now, these RAMs where clockless. No central clocking existed nor was it needed. Just repect the timing. In the real world of clocked microprocessors, everything had to be within the borders set by such a clock. This clock usually not only synchronises the CPU to all its devices, but also drives many other things, like timers or video. Thus it might be hard to do so.
So instead of varying cycle length according to the access pattern, the clock cycle was designed to fit the fastest operation (here RAM in page mode access), and wait cycles where inserted whenever additional time was needed.
Lets take the original MK4116-2 with 375 ns access time - that's the time the hip needs at least to perform a whole read or write cycle with full addressing. So whenever a prcessor starts a read cycle it will have to wait this time before using the result. On a 6502 with it's symetric clock and reading in the second half, this translates to about 1 MHz operation - on a Z80 it's be about 4 MHz (*1).
Now when the row address is set, a page mode cycle can be done in as little as 175 ns, or close to half of that. So using a clock fitted to this cycle, and inserting one additional wait cycle whenever the page changes looks like a natural solution, doesn't it?
Ofcourse we need to increase the timing for other delays - for example to detect if the page part of an address has changed or not. A comperator in general is a complex ting, but we do not need to know about the magnitude, just equal or not, and the XOR function delivers exactly this.
A XOR B delivers a nice
low whenever both are equal. So two 7486 will nicely compare two values of up to 8 bit. Ored together we get a nice signal telling us that
we need to insert a RAS cycle which is
WAITsignal for our CPU
tunneling the row address (upper 7 bits) onto the chip (
latching it for the next comparsion
and let the RAM do its work
the next (or only) cylce is then is the CAS cycle
At the end of that cycle the CPU will sample the data lines and happy read whatever is stored(*2). All taking 1 cycle if the page was 'open', two if not.
Bottom line, the CPU can run at roughly double the speed the RAM would otherwise allow, and is braked down to 'regular' speed whenever addresses are jumping.
Nothing comes for free, this additional circuitry does eat up some time (*3). Each level of TTL can be counted as ~10-15ns, so our two level decoder will eat up 30ns for its decison. By using the open collector 74266 XNOR we can reduce this to a single level using a wired-OR. So a mere 15 ns overhead isn't a bad thing, is it?
So with a Z80, we could switch from a 4 MHz Z80A to a 8 MHz Z80H and even realize a goot part of that higher clock frequency, as all internal operations and all coonsecutive (near by) RAM access will now run at full speed, while random access (outside the page) will only add one wait cycle to the three basic cycles(*4), thus only slowing it down by 1/3rd - heck, even with no page mode we have gained much sepeed - but thats ofc another story (4).
If it's so easy, then
why hasn't it be used more?
Simple, because CPU structure and machine design would diminuish the results.
First, it needs a faster CPU. For a 4 MHz Z80A, using page mode doesn't make any difference, as it can't use the shorter access time at all.
Next we still need RAM refresh. So at least every 10 ms a row needs to be refreshed to keep it's content. that means a minumum of 10,000 full refresh cycle need to be inserted additional, each of them killing our preset row address with a 99% (*6) chance, resulting in an additional wait state for the next CPU access even if its within the same page from the CPUs view point.
CPU access is only in pat continous. While opcodes and operands are in order, every data access is not, requireing a wait state at the data access and another at the begin of the instruction.
Further some CPUs will make it more complicated (by being more comforable in the first place). The Z80 inserts a refesh cycle with every instruction. Thus, after reading an opcode, thw whole glory of above will hit - way more often than needed(*7,8).
And then there is third party access. Many (home/early) computers not only map ideo memory into the CPU address space, but rather use the CPU RAM for their video data. Especially during a line displayed on CRT, the the video circuitry will access the RAM several times, making not only the CPU wait, but also most likely changing the page address, thus requireing the next CPU access to start with a
RAS cylce and its wait state.
Bottom line, using page mode makes only sense when there is a gain - most likely speed - but results start to diminuish depending on the machines design, while additional cost for a faster CPU (and circuitry) is to be added regardless of gain.
*1 - doesn't that fall nicely in the usual ratio of common Z80 vs. 6502 comparsions? It's all about RAM access, isn't it?
*2 - Writing works with exactly the same timing, so our circuitry doesn't need to care about.
*3 - But so is all selecting etc.
*4 - With multiple banks of 4116, there's even another optimization trick. One could send the page address (row) to all banks, thus opening the same bank in all chips, making access to all pages within one cycle. Assuming a 64 KiB system using MK4116, a programm loop at address 0100..017F can access data at 0100..017F, 4100..418F, 8100..818F and C100..C17F without a wait. Thats 512 bytes of 'fast' RAM :))
*5 - The exact calculations are a bit more complex here.
*6 - More exact 127/128 or 99.2%
*7 - The refresh can be somewhat delayed, as the MK4116 gurantees data hold time of 2ms. Within these 2ms all 128 rows need to be refreshed only once. With an average of ~10µs between refresh cycles we would be on the safe side. Assuming 10 cycles per instruction on a Z80 as average, this means, on a 4 MHz Z80 doing an refresh every fourth instruction would be good (on average). Leaving out the refresh for 3 out of 4 times might be easy, but this also means we would need an external refresh counter, killing the advantage of the Z80. Or we go ahead and supress twoout of three cycles. Since 3 is prime, we will run thru all 128 row addresses within the needed time - now jumping like a rabbit instead of crawling like a slug. Still, it needs two additional TTL.
*8 - The wait state can be avoided with some additional circuitry, but that again increases the chip count