I recently wrote a 6502 emulator in Rust as part of an Atari 800 emulator.
My first pass at the CPU emulation involved not even considering timing, just emulating each instruction to update memory and register states to spec. In hindsight I think this was a good approach, as there's enough complexity involved getting all the operations and addressing modes implemented without worrying about timing. Indexed indirect versus indirect indexed, decimal mode, etc... I learned a lot and that learning definitely has guided how I am dealing with approaching cycle accuracy.
As another mentioned, Klaus Dormann's test suite is an amazing resource - getting all those tests to pass was a battle, and prompted me to write a disassembler and other tools to help guide my understanding of what the tests were doing. It was a great feeling once all the tests passed.
I'm still working on a microcode version to handle cycle timing. I've started an approach where I emulate the system bus. Memory has its own time slice where it reads or writes to the data bus each tick (2x CPU speed should suffice to mimic sub-tick memory operations). It's kind of stupidly inefficient and unnecessary, but I like the idea that each component knows nothing of each other directly, just the pin states.
My first pass at the CPU emulation involved not even considering timing, just emulating each instruction to update memory and register states to spec. In hindsight I think this was a good approach, as there's enough complexity involved getting all the operations and addressing modes implemented without worrying about timing. Indexed indirect versus indirect indexed, decimal mode, etc... I learned a lot and that learning definitely has guided how I am dealing with approaching cycle accuracy.
As another mentioned, Klaus Dormann's test suite is an amazing resource - getting all those tests to pass was a battle, and prompted me to write a disassembler and other tools to help guide my understanding of what the tests were doing. It was a great feeling once all the tests passed.
I'm still working on a microcode version to handle cycle timing. I've started an approach where I emulate the system bus. Memory has its own time slice where it reads or writes to the data bus each tick (2x CPU speed should suffice to mimic sub-tick memory operations). It's kind of stupidly inefficient and unnecessary, but I like the idea that each component knows nothing of each other directly, just the pin states.