Page 1 of 1

Confused about Data Bus behaviour during write cycles

Posted: Thu Feb 26, 2026 10:44 pm
by Anarcholepsy
Hello, friends.

I'm working on a 6502 emulator as a hobby project. I've been making much use of the indispensable Visual6502 simulator in this endeavour, which has greatly aided me (along with many other resources including this forum). However, there is one behaviour of the simulator that I don't fully understand, and I was hoping someone here might be able to explain it.

In short, when executing an opcode that has multiple write cycles in succession, such as BRK or JSR pushing the PC (and processor flags, in BRKs case) to the stack, a previous value that was on the databus appears in the first half-cycle of the later write cycles.
As shown in this image, during cycles 9 and 10, the value 0x42 (the next byte after the BRK opcode) appears on the databus again. (If the image is hard to read, here's a link that should load the inputs on the simulator.)
Screenshot 2026-02-26 201803.png
As far as I can tell, no internal register or latch (at least, none that Visual6502 exposes as traceable) holds the 0x42 value during the half cycle the bus is being used for writing. The "idl" latch (which I think is the Visual6502 name for one of the latches used for ALU input and not the Input Data Latch from Hanson's diagram?) does hold this value, but that's several cycles too early.

What I suspect is happening is that the Internal Data Latch stores the last read value and it's put on the bus for that half-cycle once the write is finished? If that's the case, does this happen every time, even for read cycles (since I think the behaviour would match)? I can't seem to find any source that explicitly confirms that's what's happening though. The NESdev wiki does say that the DL is put on one of DB/ADH/ADL each Phi1, but the listed datapath node names make reference to the internal data bus instead and, in the simulator, aren't active on the cycles I'm confused about. The Breaking NES 6502 book also says that the "db" the DL/DB datapath node refers to is the internal bus.

I should also say that I'm very much approaching this from a "high-level (i.e. programmer) down" view, since I don't have a particularly strong grasp of electrical engineering (the Visual6502 diagram is very difficult for me to parse, for example), so if the answer would be obvious from a lower-level hardware perspective, I'll have to ask you to humour me.

Thanks in advance for any insight you might have.

Re: Confused about Data Bus behaviour during write cycles

Posted: Fri Feb 27, 2026 1:16 am
by GARTHWILSON
The processor is not putting data on the bus during those times, beyond just the tDHW time.  The logic states are just being held by stray capacitance in the circuit.  If all loads are CMOS, the state of a bus line that's no longer being driven may be held for milliseconds, not just microseconds or nanoseconds.

Re: Confused about Data Bus behaviour during write cycles

Posted: Fri Feb 27, 2026 5:23 am
by BigDumbDinosaur
Anarcholepsy wrote:
In short, when executing an opcode that has multiple write cycles in succession, such as BRK or JSR pushing the PC (and processor flags, in BRKs case) to the stack, a previous value that was on the databus appears in the first half-cycle of the later write cycles.
As Garth noted, the 65C02 floats the data bus (but not the address bus!) during Ø2 low.  Parasitic capacitance attempts to maintain bus state during the low clock and in an all-CMOS circuit, that state can persist for a surprisingly long time.  As soon as Ø2 goes high during a write cycle, the C02 will enable its data bus drivers.

An interesting problem arises if nothing drives the data bus during a read cycle when the clock goes high.  Parasitic capacitance may cause the 65C02 to read what it thinks is an opcode but is actually just left-over state of an indeterminate value.  There’s no telling what will happen in such a case.

BTW, the 65C02 MPU pushes SR (status register) during any interrupt, not just BRK.  The b bit in the stack copy of SR only matters during an IRQ or BRK...it is always set if SR is examined via a PHP - PLA sequence.

Re: Confused about Data Bus behaviour during write cycles

Posted: Fri Feb 27, 2026 8:04 am
by BigEd
Welcome!

Indeed, as noted, a real 6502 will be reading the bus in the first half cycle of the write, and most physical systems will do something predictable in that case, but what exactly they do depends on the system.

As for visual6502, reading the code will tell us what it does, but it's somewhat unimportant: the value printed for the first half of the cycle has no effect, and doesn't come from the 6502 internals. (I do agree that it is initially unexpected for the user!)

Re: Confused about Data Bus behaviour during write cycles

Posted: Fri Feb 27, 2026 8:17 am
by BigEd
Quote:
... there is one behaviour of the simulator that I don't fully understand, and I was hoping someone here might be able to explain it.
Addendum: If we look at the source to macros.js we find

Code: Select all

function halfStep(){
	var clk = isNodeHigh(nodenames['clk0']);
	if (clk) {setLow('clk0'); handleBusRead(); } 
	else {setHigh('clk0'); handleBusWrite();}
	eval(clockTriggers[cycle+1]);  // pre-apply next tick's inputs now, so the updates are displayed

}

function handleBusRead(){
	if(isNodeHigh(nodenames['rw'])){
		var a = readAddressBus();
		var d = eval(readTriggers[a]);
		if(d == undefined)
			d = mRead(readAddressBus());
		if(isNodeHigh(nodenames['sync']))
			eval(fetchTriggers[d]);
		writeDataBus(d);
	}
}

function handleBusWrite(){
	if(!isNodeHigh(nodenames['rw'])){
		var a = readAddressBus();
		var d = readDataBus();
		eval(writeTriggers[a]);
		mWrite(a,d);
		if(a<0x200) setCellValue(a,d);
	}
}

function readAddressBus(){return readBits('ab', 16);}
function readDataBus(){return readBits('db', 8);}
We also need to read chipsim.js

Code: Select all

function setHigh(name){
	var nn = nodenames[name];
	nodes[nn].pullup = true;
	nodes[nn].pulldown = false;
	recalcNodeList([nn]);
}

function setLow(name){
	var nn = nodenames[name];
	nodes[nn].pullup = false;
	nodes[nn].pulldown = true;
	recalcNodeList([nn]);
}
And so we see that the signals for the databus - 'db' - are updated only at the end of the first half of a read cycle, and used for effect only at the end of the second half of a write cycle. This was evidently close enough for the simulation to work! It's a switch-level simulation but it does implicitly (and necessarily) model charge storage - an undriven node will retain its state.

Edit: the upstream sources are in this repo

Re: Confused about Data Bus behaviour during write cycles

Posted: Mon Mar 02, 2026 12:34 am
by Anarcholepsy
Thanks everyone, I think I understand now.