You might have noticed the predecode register and logic at top left of Donald Hanson's famous
6502 block diagram:
Attachment:
6502-predecode.png [ 140.6 KiB | Viewed 1885 times ]
I've had a look at
this circuitry in the visual6502, and had a bit of a chat about it with DrJefyll.
Notably, the register (latch) is clocked on phi2, which means in principle the following logic block can and will get to work predecoding the databus contents as soon as it arrives, but the input will be frozen when phi2 goes low - which is as it should be, because at that point the databus will shortly no longer be valid.
Initially I thought this was quite innovative and sneaky, if the 6502 actually uses some of the memory access time to start work on decoding the incoming instruction stream. And it might be, but we can't really tell because in latch-based design while it's possible to borrow time from the preceding stage, it's difficult to say if we always will. If the memory data actually arrives at the last instant, the logic will just take more of phi1 to do its work. Some signals generated during phi1 might become valid just a bit later than they would have done. There's a real-time tradeoff between late-arriving inputs and the timing of early outputs.
The 8 bits of opcode, having been latched, pass through the predecode logic where they are optionally zeroed - this is where the BRK behaviour would be substituted for the actual fetched opcode, in the case that an interrupt is taken. The input at top left controls this - it's a pending interrupt signal.
The optionally-zeroed opcode, still 8 bits wide, proceeds to the IR where it may be latched if this is a T1 cycle. (T1 according to Hanson's nomenclature.)
The other output shown as TZPRE is not quite what we see in visual6502. In visual6502, the predecode logic generates two logic signals, called ONEBYTE and TWOCYCLE. It does that with a handful of gates which pick off inputs from the databus value and the inverses which are locally generated, first created four predecoded signals:
node: 302 PD-xxx010x1
node: 1294 PD-1xx000x0
node: 1019 PD-xxxx10x0
node: 365 PD-0xx0xx0x
and from those two signals are derived:
node: 851 #TWOCYCLE
node: 778 ONEBYTE
Let's see what those predecodes actually are, with reference to the
instruction table:
PD-xxx010x1 - even rows of column 9, these are immediates
PD-1xx000x0 - LDX immediate
PD-xxxx10x0 - columns 8 and A, that's implicit and accumulator
PD-0xx0xx0x - even rows of upper half, columns 0,1,4,5,8,9,C,D
And these are combined like so:
ONEBYTE = not (not (
PD-xxxx10x0
))
TWOCYCLE = or(
PD-xxx010x1
PD-1xx000x0
and (
PD-xxxx10x0
not(PD-0xx0xx0x)
)
)
How does this relate to TZPRE? Perhaps it is exactly TWOCYCLE, which controls the timing state machine, setting it up to go into another SYNC cycle. We don't see ONEBYTE at all in the block diagram, but we know it controls I/PC (increment PC) which we do see - when a one byte opcode is fetched, the already-incremented PC must not be incremented again. (ONEBYTE doesn't include RTS and RTI but it doesn't matter because they will update PC from the stack.)
Here's a simulation where you can see some of the action on these signals:
http://www.visual6502.org/JSSim/expert. ... 2,t3,t4,t5(Previously, I've guessed that the predecode has something to do with the timing of branch opcodes, but the evidence is that I was wrong about that.)
[Image clip is from
this tweet]