TTL 6502 Here I come

For discussing the 65xx hardware itself or electronics projects.
User avatar
BigDumbDinosaur
Posts: 9426
Joined: 28 May 2009
Location: Midwestern USA (JB Pritzker’s dystopia)
Contact:

Re: TTL 6502 Here I come

Post by BigDumbDinosaur »

GARTHWILSON wrote:
Drass wrote:
I think I recall seeing a 100Hz IRQ in your POC 1 design, which is a nice round number. (I should check what tasks you assigned to the the "Jiffy" IRQ there).
I use the same rate, and the IRQ\ output of VIA#1 (whose timer causes the 100Hz interrupt) is the only thing on the board that's on NMI\. There's no polling, because there's only one possible cause. (T1 timeout is the only interrupt enabled in that VIA.) The NMI ISR runs the clock and calendar, and alarms. Nothing else. Multiple programs can refer to it though for a wide range of things.
The nice thing about using the counter/timer in the NXP UARTs (all of the 26... and 28... series have C/Ts) is it is driven by the X1 clock that runs the UART. Changing the Ø2 clock in such a system obviously would not affect timekeeping. The relationship between the counter/timer and X1 clock is such that an exact 100 Hz jiffy IRQ can be programmed, the accuracy and stability of which is as good as the accuracy and stability of the X1 clock generator itself. POC V1.1 drifts less than a second per month, which I determined by comparing its timekeeping to that of one of my Linux boxes that is set up for NTP.

It's not really practical to attach a UART as complex as the 28L92 to NMI, as there are multiple interrupt sources and it would quickly become a programming nightmare to avoid a deadlock problem caused by a missed interrupt.
x86?  We ain't got no x86.  We don't NEED no stinking x86!
White Flame
Posts: 704
Joined: 24 Jul 2012

Re: TTL 6502 Here I come

Post by White Flame »

BigDumbDinosaur wrote:
In the C-64, timer A in CIA number 1 generated the jiffy IRQ. As the timer rate is ultimately slaved to the Ø2 clock rate, Commodore used a Ø2 rate in the C-64 that was evenly divisible by 60 or 50 so the IRQ would maintain reasonably accurate timekeeping
I don't think that divisibility is true, is it? I found 985,248 Hz for PAL, and 1,022,730 for NTSC, and neither are exactly divisible by 50 or 60.

Both NTSC and PAL C64s had their CIA jiffy timer set for 60Hz, though. Looking at the ROM sources, on PAL it loads up the timer with $4025, and NTSC gets $4295. PAL ends up with 59.999269228 Hz, and NTSC with 60.001760047 Hz, with these numbers.

But in any case, yeah it was useless for exact timing because things would SEI, and the numbers aren't exactly right to begin with.
User avatar
BigDumbDinosaur
Posts: 9426
Joined: 28 May 2009
Location: Midwestern USA (JB Pritzker’s dystopia)
Contact:

Re: TTL 6502 Here I come

Post by BigDumbDinosaur »

White Flame wrote:
BigDumbDinosaur wrote:
In the C-64, timer A in CIA number 1 generated the jiffy IRQ. As the timer rate is ultimately slaved to the Ø2 clock rate, Commodore used a Ø2 rate in the C-64 that was evenly divisible by 60 or 50 so the IRQ would maintain reasonably accurate timekeeping
I don't think that divisibility is true, is it? I found 985,248 Hz for PAL, and 1,022,730 for NTSC, and neither are exactly divisible by 50 or 60.
Oops! The word "almost" was supposed to be in there. I edited my earlier post.
Quote:
But in any case, yeah it was useless for exact timing because things would SEI, and the numbers aren't exactly right to begin with.
The TOD clocks in the CIAs were the go-to time source in the C-64 and C-128. They were run off the mains frequency and could work with 50 or 60 Hz power. The accuracy was as good as the frequency stability of the power utility. In our area, at least, a drift of ±250 milliseconds per month is typical.

Of course, what would a 65xx peripheral device be without one or two hardware bugs? :D The TOD clocks had an alarm feature that could be set up to generate an interrupt when the alarm time was reached. However, if the alarm time tenths-of-a-second register was set to zero the alarm wouldn't work. The work-around was to set that register to something other than zero.

There was also a nasty bug involving the timer B interrupt, which was behind a lot of the fake RS-232 errors that these computers experienced. If the CIA's interrupt status register was read one or two clock cycles before timer B was to underflow and interrupt, that IRQ might not ever come. Since CIA #2's timer B was the baud rate generator for the fake RS-232 receiver, the result of this little contretemps was usually a whole bunch of dropped bits and major corruption. It was a horrid mess. :evil:
x86?  We ain't got no x86.  We don't NEED no stinking x86!
User avatar
Drass
Posts: 428
Joined: 18 Oct 2015
Location: Toronto, ON

Re: TTL 6502 Here I come

Post by Drass »

BigDumbDinosaur wrote:
It was possible to configure the C-64's VIC to generate a raster interrupt, but that feature was mostly used to produce the illusion of more sprites on the screen or to toggle the VIC between bitmap and text mode when the scan reached a certain raster line.
Yes, that's true, but I also used a raster IRQ to signal when the VIC had finished painting the screen and trigger logic to draw the next frame. It's all a bit foggy now, but IIRC, this was to ensure all motion was free of any glitches, particularly for smooth scrolling (moving a sprite or changing the background at the moment it was being drawn could generate visible artifacts, flashing, breakup, etc). That "refresh" IRQ effectively became the timing reference used.
C74-6502 Website: https://c74project.com
User avatar
Rob Finch
Posts: 465
Joined: 29 Dec 2002
Location: Canada
Contact:

Re: TTL 6502 Here I come

Post by Rob Finch »

Quote:
In the C-64, timer A in CIA number 1 generated the jiffy IRQ. As the timer rate is ultimately slaved to the Ø2 clock rate, Commodore used a Ø2 rate in the C-64 that was almost evenly divisible by 60 or 50 so the IRQ would maintain reasonably accurate timekeeping
The C64 had the time-of-day signal on the CIA driven by the AC power at 50 or 60Hz. It's strange they didn't use that for timing.
User avatar
BigDumbDinosaur
Posts: 9426
Joined: 28 May 2009
Location: Midwestern USA (JB Pritzker’s dystopia)
Contact:

Re: TTL 6502 Here I come

Post by BigDumbDinosaur »

Rob Finch wrote:
The C64 had the time-of-day signal on the CIA driven by the AC power at 50 or 60Hz. It's strange they didn't use that for timing.
Commodore did a lot of strange things. :D The fake RS-232 routines in the kernel would example of that.
x86?  We ain't got no x86.  We don't NEED no stinking x86!
User avatar
Drass
Posts: 428
Joined: 18 Oct 2015
Location: Toronto, ON

Re: TTL 6502 Here I come

Post by Drass »

Now I'm confused ...

As I understood it, the WDC65C02 fixes the spurious reads which afflict the NMOS 6502 during dead bus cycles. Specifically for indexed addressing, it does so by re-reading the last instruction byte rather than the "partial" target address. But, to my surprise, single-cycling the SBC shows the processor puts $8000 on the address bus in the cycle preceding the write when executing this:

LDY #0
STA $8000,Y

Did I make a mistake or does the 'C02 generate spurious reads during indexed store operations?

I ran into this issue when tracking down the source of some "flakiness" in the interaction with the NXP UART. The device has one of those I/O registers where otherwise harmless reads have specific side-effects. Of course, I happened to be using indexed addressing to configure the UART and I was seeing all sorts of seemingly unpredictable behavior; behaviour which in fact could be explained by a spurious read moving the goal posts on the configuration writes. More investigation confirmed the UART registers were not set up correctly, and after confirming with the single-cycle clock, a change to absolute addressing fixed everything! :shock:. The UART is now solid (albeit with minimal testing at this point). Good news for the SBC, but it certainly left me wondering about those spurious reads.

Anyway, I really enjoyed working with the UART once out of that config quagmire. The interrupt mechanism is very well behaved, and I was able to get service routines working fairly quickly (using a buffering scheme I adapted from BDD's POC1 firmware - very nicely done BDD, thank you). I ended up with a little BIOS with the following functions (the C-like syntax below is for documentation only. Function arguments are actually passed in registers):

reset_io
chn = open(device, port)
close(chn)
byte = getc(chn)
putc(chn, byte)

It's a start, and I suspect I'll end up using and extending it further later. As it stands, the scheme handles interrupt driven I/O from concurrent channels and can be easily extended to multiple devices. Be that as it may, the main event is that the UART is now fully functional and reliable. Very happy with that.

The next step for the SBC is to get a simple file upload going to load software into RAM. At that point, the SBC will have met it's primary objective of being a test platform for the TTL CPU (and thanks to dr Jefyll's good suggestion, a terrific learning experience as well). I'll have a little cleaning up to do (e.g., missing LEDs, etc.) and then it will be time to order the boards for the TTL CPU itself!

Can't wait! :)
C74-6502 Website: https://c74project.com
User avatar
BigDumbDinosaur
Posts: 9426
Joined: 28 May 2009
Location: Midwestern USA (JB Pritzker’s dystopia)
Contact:

Re: TTL 6502 Here I come

Post by BigDumbDinosaur »

Drass wrote:
As I understood it, the WDC65C02 fixes the spurious reads which afflict the NMOS 6502 during dead bus cycles. Specifically for indexed addressing, it does so by re-reading the last instruction byte rather than the "partial" target address.
According to the data sheet on page 30, indexing across a page boundary would cause the 65C02 to re-read the opcode. Are you crossing a page boundary with any instructions that access to DUART? If not, you may have discovered new errata in the 65C02.
Quote:
But, to my surprise, single-cycling the SBC shows the processor puts $8000 on the address bus in the cycle preceding the write when executing this:

LDY #0
STA $8000,Y

Did I make a mistake or does the 'C02 generate spurious reads during indexed store operations?
Good question. The above doesn't cross a page boundary. How are you qualifying reads and writes on the DUART? What happens if you index with .X instead of .Y?
Quote:
The device has one of those I/O registers where otherwise harmless reads have specific side-effects.
An inadvertent read on some registers, such as registers $0E and $0F, can trigger actions that are not anticipated in the code. This is not a unique characteristic of the DUART. For example, an inadvertent read of the 65C22's interrupt status register could clear a pending interrupt that has yet to be serviced.

Also, you have to be careful to not do a read on write-only registers, such as the channel command registers ($02 and $0A), as doing so may trigger some kind of hinkiness in the DUART.
Quote:
Of course, I happened to be using indexed addressing to configure the UART and I was seeing all sorts of seemingly unpredictable behavior; behaviour which in fact could be explained by a spurious read moving the goal posts on the configuration writes. More investigation confirmed the UART registers were not set up correctly, and after confirming with the single-cycle clock, a change to absolute addressing fixed everything! :shock:. The UART is now solid (albeit with minimal testing at this point). Good news for the SBC, but it certainly left me wondering about those spurious reads.
What you are describing is what I encountered with the 2692 in my first iteration of POC V1. In that case, I used the 65C816's VDA and VPA outputs to qualify memory cycles and was able to eliminate the problem. I'm not sure how you would go about achieving a similar behavior with the 65C02. It's a real waste of code space to have to use absolute addressing.
Quote:
The interrupt mechanism is very well behaved, and I was able to get service routines working fairly quickly (using a buffering scheme I adapted from BDD's POC1 firmware - very nicely done BDD, thank you).
What I like about the DUART's interrupt mechanism is that the interrupt status register (register $05) is a real-time register and you don't have to do anything special to clear all but one of the IRQs.
x86?  We ain't got no x86.  We don't NEED no stinking x86!
User avatar
Dr Jefyll
Posts: 3526
Joined: 11 Dec 2009
Location: Ontario, Canada
Contact:

Re: TTL 6502 Here I come

Post by Dr Jefyll »

Drass wrote:
Did I make a mistake or does the 'C02 generate spurious reads during indexed store operations?
I'm only mildly surprised that you observed $8000 on the address bus in the cycle preceding the write. Can you tell us what happens if you alter the code so the page crossing is guaranteed to happen (rather than guaranteed NOT to happen)? In case of a page crossing I expect the CPU will re-read the last instruction byte (rather than the unacceptable alternative of putting a partially-formed address on the bus).

It's true the CMOS '02 introduced changes that address the NMOS '02 problem of partially-formed addresses appearing on the bus during indexing; and yes one tactic is to place PC on the bus during the "dead" cycle in question. But that's not to say you'll see PC appear in every case where an unused bus cycle occurs.

The fixes are not as predictable as all that, and there are irregularities not described in the doc. For example, dclxvi reported the anomaly summarized here. As shown in the original and amended charts below, there are inconsistencies even between almost-identical instructions! :shock: This pertains to a different NMOS bug that got fixed in the 'C02, but it illustrates that corrections aren't necessarily uniformly applied.
Table 7-1 excerpt (original).gif
Table 7-1 excerpt (original).gif (6.04 KiB) Viewed 1860 times
Table 7-1 excerpt (corrected).gif
Table 7-1 excerpt (corrected).gif (8.17 KiB) Viewed 1860 times
BigDumbDinosaur wrote:
you may have discovered new errata in the 65C02.
Yup. We know there are irregularities. And irregularities are alright as long as they're benign (like the one Drass reported). It's comparatively harmless to read a byte you're about to write to -- there's less risk of trouble with that (as compared to the nasty NMOS behavior of perhaps reading an unrelated byte located $100 below the intended address :shock: ).

-- Jeff
In 1988 my 65C02 got six new registers and 44 new full-speed instructions!
https://laughtonelectronics.com/Arcana/ ... mmary.html
User avatar
Drass
Posts: 428
Joined: 18 Oct 2015
Location: Toronto, ON

Re: TTL 6502 Here I come

Post by Drass »

BigDumbDinosaur wrote:
you may have discovered new errata in the 65C02.
Sure seems that way ... :shock:
Dr Jefyll wrote:
Can you tell us what happens if you alter the code so the page crossing is guaranteed to happen (rather than guaranteed NOT to happen)?
Ok, so far as I can tell:

1) If there is a page crossing, both LDA and STA absolute indexed correctly put PC on the address bus during the dead cycle (re-reading the last instruction byte).

2) If there is not a page crossing, LDA absolute indexed has no dead cycle, but STA does and generates a spurious read on that cycle.

Which I think agrees with your prediction Jeff, and seems to be the case for both the indexed with X and Y variants.
BigDumbDinosaur wrote:
I used the 65C816's VDA and VPA outputs to qualify memory cycles and was able to eliminate the problem. I'm not sure how you would go about achieving a similar behavior with the 65C02.
Not sure there is an alternative to absolute addressing on the 'C02. As it happens, it's only the write to MR1 (Mode Register 1) that suffers from the problem (since reading MR0 or MR2 has no adverse effect). That one line of code has to be duplicated for each port (and a branch added to select between them). It's not so much the additional code space, as the diminished clarity in the code, that bothers me - unfortunate for sure.
Dr Jefyll wrote:
It's comparatively harmless to read a byte you're about to write to ...
I agree, except when you're not expecting it! Took some time to figure this one out ... but who am I kidding, it's actually all part of the fun :mrgreen:
C74-6502 Website: https://c74project.com
User avatar
Dr Jefyll
Posts: 3526
Joined: 11 Dec 2009
Location: Ontario, Canada
Contact:

Re: TTL 6502 Here I come

Post by Dr Jefyll »

Thanks for reporting this, Drass. Yes, the followup agrees with my prediction but the initial observation was news to me.

This behavior is not entirely benign, even though the spurious read is from the same address which is about to be written to. It's not uncommon for an I/O device to place two registers at the same address, with all reads coming from one register and all writes going to the other register. So, writing to the latter register also entails an unexpected read of the former when 65C02 indexed addressing is used in the same manner as in your test.

The 'C02 lacks a VDA output, but there's a software workaround. Just rearrange the code in a way that guarantees a page crossing every time. For example, replace this

Code: Select all

STA   IO_PAGE, y   ;  0 <= y <= $FF
with this:

Code: Select all

STA   IO_PAGE-1, y ;  1 <= y <= $FF
IO_PAGE-1 is a value whose LS byte is $FF, so any non-zero value of Y guarantees a page crossing. Only 255 IO registers can be addressed -- IO_PAGE+$FF is unreachable except by bypassing the workaround.

.
Drass wrote:
Took some time to figure this one out ... but who am I kidding, it's actually all part of the fun :mrgreen:
If you're having THAT much fun, maybe you won't mind doing another experiment! :) If you can spare us a moment, kindly try doing the writes with (ind),y address mode rather than abs,y. Both modes can result in page crossings. It'll be interesting to see how the dead-cycle addresses compare.

cheers
Jeff
In 1988 my 65C02 got six new registers and 44 new full-speed instructions!
https://laughtonelectronics.com/Arcana/ ... mmary.html
User avatar
BigDumbDinosaur
Posts: 9426
Joined: 28 May 2009
Location: Midwestern USA (JB Pritzker’s dystopia)
Contact:

Re: TTL 6502 Here I come

Post by BigDumbDinosaur »

Drass wrote:
Dr Jefyll wrote:
It's comparatively harmless to read a byte you're about to write to ...
I agree, except when you're not expecting it! Took some time to figure this one out ... but who am I kidding, it's actually all part of the fun :mrgreen:
The channel mode registers are touchy about dummy accesses. At power-on or reset, MR1 is in context. A read or a write of MR1 will cause the UART to bring MR2 into context. So a dummy read on MR when it is pointing to MR1 is not harmless, because when the write occurs it will be to MR2. Furthermore, timing may be violated because the dummy read occurs only one cycle before the (valid) write, which could be a big problem with high Ø2 rates.

The same problem exists if MR0 is in context. The dummy read causes MR1 to come into context and the subsequent write is to the wrong register.

This behavior was one of the maladies that I had to grapple with in POC V1.0, which was resolved with the VDA/VPA logic. If, in fact, the 65C02 is randomly touching registers during intermediate cycles of an instruction I would consider that a product defect. It seems Jeff's solution might be the salvation if using index addressing to read and write the DUART registers.

Meanwhile, if we can get a coherent picture of exactly what the 'C02 is doing when index addressing is in use, that information could be disseminated to WDC as a report of an apparent product defect, since the behavior is not as described in the data sheet.

BTW, what is the date code of the 65C02 you are using? Also, I don't recall if you are using a 26C92 or 28L92.
x86?  We ain't got no x86.  We don't NEED no stinking x86!
User avatar
BigDumbDinosaur
Posts: 9426
Joined: 28 May 2009
Location: Midwestern USA (JB Pritzker’s dystopia)
Contact:

Re: TTL 6502 Here I come

Post by BigDumbDinosaur »

Drass wrote:
Now I'm confused ...

As I understood it, the WDC65C02 fixes the spurious reads which afflict the NMOS 6502 during dead bus cycles...
After I made my previous post something jogged my brain a bit and I went back and reviewed your schematics. In examining your /OE and /WR signal generation, I noted that /OE doesn't appear to be qualified by Ø2. That could explain why the DUART is apparently getting flummoxed by spurious address generation. /OE could be going low before the address bus has settled, causing the 'C02 to touch two different DUART registers in rapid succession. How hard would it be for you to rework the logic to qualify /OE with Ø2?

BTW, I noted that you had said you were using an SC2692.
x86?  We ain't got no x86.  We don't NEED no stinking x86!
User avatar
Drass
Posts: 428
Joined: 18 Oct 2015
Location: Toronto, ON

Re: TTL 6502 Here I come

Post by Drass »

Dr Jefyll wrote:
If you're having THAT much fun, maybe you won't mind doing another experiment! :)
LOL, I had that coming :). I'm supposed to be building a cycle-accurate version of the CPU so I too would like to get to the bottom of this! The TTL CPU has a jumper to select between reading the partial address or reading PC during dead cycles. This was in an effort to accommodate both CMOS and NMOS behaviour. Sadly, it's an all or nothing switch so this new-found idiosyncrasy will have to go on the list of caveats after all :(
Quote:
try doing the writes with (ind),y address mode rather than abs,y
yup, I was thinking exactly the same thing ... will have to wait for the weekend before I get time to try it. I'll report back thereafter.
Quote:
The same problem exists if MR0 is in context.
You're absolutely right. Nice catch.
Quote:
It seems Jeff's solution might be the salvation if using index addressing to read and write the DUART registers.
I agree. I'll be changing the code according to his suggestion.
Quote:
what is the date code of the 65C02 you are using
Marking on the IC:"1148G016".
Quote:
I noted that /OE doesn't appear to be qualified by Ø2. That could explain why the DUART is apparently getting flummoxed by spurious address generation. /OE could be going low before the address bus has settled, causing the 'C02 to touch two different DUART registers in rapid succession.
Now that's interesting! In actual fact, /OE is derived by inverting R/W and is likely already low from the previous read cycle. If so, the critical timing would seem to hinge on /CEN (Chip Enable), which is derived from A15..13 after 3 gate delays (for the address decoder). Is it possible for A15..13 to assert /CEN before A3..0 select the right UART register? I have no idea, but it certainly seems possible if the values on the address lines change randomly before stabilizing (or if the low order lines are somehow delayed relative to the high-order ones).
Quote:
How hard would it be for you to rework the logic to qualify /OE with Ø2?
Unfortunately that would take non-trivial surgery on the current board. I'd like to re-test the current dead-cycle hypothesis before attempting that. The UART certainly seems stable with the fix, but I'll be double checking everything when I get some time. Stay tuned ...
C74-6502 Website: https://c74project.com
User avatar
BigDumbDinosaur
Posts: 9426
Joined: 28 May 2009
Location: Midwestern USA (JB Pritzker’s dystopia)
Contact:

Re: TTL 6502 Here I come

Post by BigDumbDinosaur »

Drass wrote:
BigDumbDïnosaur wrote:
I noted that /OE doesn't appear to be qualified by Ø2. That could explain why the DUART is apparently getting flummoxed by spurious address generation. /OE could be going low before the address bus has settled, causing the 'C02 to touch two different DUART registers in rapid succession.
Now that's interesting! In actual fact, /OE is derived by inverting R/W and is likely already low from the previous read cycle. If so, the critical timing would seem to hinge on /CEN (Chip Enable), which is derived from A15..13 after 3 gate delays (for the address decoder). Is it possible for A15..13 to assert /CEN before A3..0 select the right UART register? I have no idea, but it certainly seems possible if the values on the address lines change randomly before stabilizing (or if the low order lines are somehow delayed relative to the high-order ones).
You can't do much about the effect of prop delay through the I/O decoding circuits, However, you can prevent the 'C02 from inadvertently reading a UART register it shouldn't.

If you can believe the 65C02 timing diagram, all address bus lines should stabilize at the same time. Hence the UART will see a stable address at A0-A3 before the decoder asserts /CE on the UART, this being the result of prop delay through the glue logic. Continuing with this line of thinking, I'd say the address bus per se is not your problem. As you say, RWB is likely to be high at that time due to the previous cycle being a read, e.g., the MPU was fetching the MSB of the current instruction's operand. During the momentary period when the address bus is in a state of flux the wrong UART register might be selected, followed by selection of the correct register. That in itself might be harmless. However, with RWB being high at the time and /OE not being qualified by Ø2 and therefore continuously low, there is a strong possibility of a spurious read of the UART upsetting the apple cart.
x86?  We ain't got no x86.  We don't NEED no stinking x86!
Post Reply