6502.org Forum  Projects  Code  Documents  Tools  Forum
It is currently Thu Nov 21, 2024 5:19 pm

All times are UTC




Post new topic Reply to topic  [ 32 posts ]  Go to page 1, 2, 3  Next
Author Message
PostPosted: Sun Mar 21, 2010 8:39 am 
Offline
User avatar

Joined: Fri Dec 11, 2009 3:50 pm
Posts: 3367
Location: Ontario, Canada
This post is a spin-off regarding my expanded-instruction-set 6502 computer -- a topic already in discussion in the 6502.org Forth forum. I'm belatedly mentioning it here because the hardware seems noteworthy (quite apart from the KimKlone computer's special appeal to Forth fans). But I'm also spurred by something I learned recently about 6502 interrupts.

To recognize when an interrupt is commencing, the address bus yields an obvious clue. It's easy for hardware to detect when the addresses FFFA-FFFF appear. Still, the appearance of these addresses isn't conclusive proof -- it doesn't amount to a reliable Interrupt Acknowledge.

Most systems have no need for an Interrupt Acknowledge, but such a signal can be crucial if you're trying to implement something fancy -- a prioritized vector scheme, maybe, or a peripheral interface with unusual timing requirements. Fortunately, a little bit of glue logic can easily generate a reliable Interrupt Acknowledge signal -- one that becomes valid several cycles before the vector fetch even begins! Here's how. (Admittedly I haven't built such a circuit yet, and perhaps I'm not the first to come up with the idea.)

In normal operation the CPU always follows an opcode fetch with a fetch of the byte at the subsequent address; this is to allow pipelined operation. But I noticed on the 65c816 Data Sheet (and I bet this applies to 6502 and 'c02 as well) that the address bus does NOT increment following the op-code fetch cycle on which an interrupt is recognized. In other words, the interrupt sequence begins with an op-code fetch cycle (ie, the SYNC pin is active) but the op-code fetched from memory is ignored, and internally the CPU more or less feeds itself a BRK instruction. The following cycle will fetch and ignore the op-code again. (The address bus doesn't increment because the bus is driven by PC, and it's the un-incremented PC that needs to get pushed on stack.) Therefore,
IF {SYNC was true last cycle} AND {A0 is unchanged from last cycle to this cycle} THEN we can confidently conclude that an interrupt sequence is commencing. We know the next few cycles will be writes to the stack; then the vector fetch will occur.

If anyone sees a flaw in this, please speak up, but so far I'm pretty pleased with this idea. ':D' Only thing is, it would've come in awfully handy for my KimKlone computer, so I wish I'd though of it twenty years ago. ':oops:' Another possible application is for schemes that involve re-mapping the 6502 stack space; it may be beneficial to have advance warning that a Push is about to occur.


Top
 Profile  
Reply with quote  
PostPosted: Mon Mar 22, 2010 3:59 am 
Offline
User avatar

Joined: Thu May 28, 2009 9:46 pm
Posts: 8504
Location: Midwestern USA
The '816 has a signal called VPB (vector pull) for the purpose of ascertaining when the MPU is handling an interrupt. From the '816 data sheet:

2.28 Vector Pull (VPB)

The Vector Pull active low output indicates that a vector location is being addressed during an interrupt sequence. VPB is low during the last two interrupt sequence cycles, during which time the processor loads the PC with the interrupt handler vector location. The VPB signal may be used to select and prioritize interrupts from several sources by modifying the vector addresses.


Although I have not taken advantage of VPB in my POC computer, I have studied how it behaves as POC is running and processing RTC interrupts. I believe the logic required to modify the interrupt vector on the fly according to the source would be relatively easy to implement.

_________________
x86?  We ain't got no x86.  We don't NEED no stinking x86!


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Mon Mar 22, 2010 4:09 am 
Offline
User avatar

Joined: Fri Aug 30, 2002 1:09 am
Posts: 8543
Location: Southern California
Quote:
The '816 has a signal called VPB (vector pull) for the purpose of...

WDC's 65c02 has it too, on pin 1 of the DIP and pin 2 of the PLCC. (It also has ML\ (memory lock) on pin 5 of the DIP and pin 6 of the PLCC, and BE (bus enable) on pin 36 of the DIP and 40 of the PLCC.)


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Mon Mar 22, 2010 4:11 am 
Offline

Joined: Sat Jan 04, 2003 10:03 pm
Posts: 1706
Whoa -- sudden font-size change initially looked like you were yelling. Yikes! Then I remembered, perhaps its a cut-n-paste artifact.


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Mon Mar 22, 2010 5:11 am 
Offline

Joined: Mon Mar 02, 2009 7:27 pm
Posts: 3258
Location: NC, USA
An XC9536, which has 30+ I/O pins, might be up to the job of opcode modifications, especially a 5ns part. I put a 44-pin QFP on a DIP adapter last week (I do these things to calm my nerves). I did this with the future intention of a data bus "snoop" which will work with phase 2 and SYNC. After reading your article on your homepage about extending the 65C02 memory to a "contiguous" 16MB, I was/ and am motivated to try and duplicate something similar on my project. Currently I'm trying to implement a XC9572 10ns CPLD to do simple memory decoding with a 16K memory window into 512K. After I get it 100% wired up (so far power, bypass caps, and JTAG programming are done), I plan on working on opcode mods... I for one thank you for posting your ideas here in the hardware section. I'm curious though, how do you go about discovering these in depth inner workings of the 6502? They're not in the data sheet...

_________________
65Org16:https://github.com/ElEctric-EyE/verilog-6502


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Mon Mar 22, 2010 7:05 am 
Offline
User avatar

Joined: Fri Dec 11, 2009 3:50 pm
Posts: 3367
Location: Ontario, Canada
Thanks, guys. I was aware that the '816 offered a Vector Pull output, but I didn't realize that some 'C02s feature it as well -- that's good to know.
Quote:
I believe the logic required to modify the interrupt vector on the fly according to the source would be relatively easy to implement.

In general, that's true. But I did try to emphasize that my idea was for fancy solutions to non-"run of the mill" problems.

Really what's unique about my proposed circuit is the advance warning that it gives you. It lets you ascertain -- several cycles before the vector fetch -- that an interrupt is being recognized. It's conceivable that, for some designs, those extra cycles of leeway might ease the task of generating a prioritized interrupt vector. But there are better examples I could cite. Such as...

Garth, in one of the Forth topics you mentioned Bruce's idea of using the RTS instruction as an extremely high-speed alternative to NEXT. Neat idea, except one of the downsides is that it monopolizes the Stack Pointer for code-fetch purposes, precluding its use for saving PC and P during interrupts. The use of interrupts would therefore seem to be impossible. However, using the technique I mentioned, you could have your cake and eat it too by mapping a private stack memory for exclusive use by interrupts. Thanks to the advance warning, this could kick in in time to allow PC and P to be successfully pushed to a small scratch ram (rather than overwriting the list of code pointers).

My final example addresses another seemingly intractable problem. My KimKlone computer in certain cases used two-instruction sequences as a single instruction. The sequences were supposed to be atomic -- indivisible -- and were treated as such by the microcode. But if an interrupt happened to occur in the midst of a sequence the machine would derail completely, because there was no means to redirect the microcode when the 'C02 suddenly changed what it was doing.

I've omitted some details about both of these scenarios; for instance there's a better solution to Bruce's proposal -- one already mentioned on 6502.org. But at least I've clarified the unusual sorts of circumstances for which my proposed circuit might be useful. Maybe in future one of you will remember the idea and find it handy for something else -- I hope so.

Quote:
I'm curious though, how do you go about discovering these in depth inner workings of the 6502? They're not in the data sheet...

My best source of information, by far, was the excellent set of manuals that came with my MOS KIM-1 computer. In particular, there is detailed info on cycle-by-cycle behavior to be found in Appendix A of the Mcs6500 Family Hardware Manual. (For cycle-by-cycle behavior of WDS's 65c816, see Table 5-7 of the '816 data sheet.)

Unfortunately I know of no cycle-by-cycle references for the Rockwell or WDS 65c02. That was a problem for me back when KimKlone was being planned! But, since I had access to the chip itself, I was able to scope out (literally) the Rockwell 65c02 behavior by using my Tektronix 465. For any given instruction in question I'd just include it in a very short machine language loop and then use the oscilloscope to determine what the R/W, address & data lines were doing on each cycle. [Edit: minor tweaks; add links to last paragraph]


Last edited by Dr Jefyll on Sun Jun 06, 2010 8:14 pm, edited 1 time in total.

Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Mon Mar 22, 2010 9:34 am 
Online
User avatar

Joined: Thu Dec 11, 2008 1:28 pm
Posts: 10985
Location: England
I like this very-early-interrupt-handling detection! Inasmuch as it makes use of the CPU's need to push an unincremented PC, it has a good chance of working with various implementations. (Although, this doc suggests BRK does read from PC+1 before then pushing PC)

Remapping the stack before a push gives an approximation to a supervisory stack, too.

A related observation, which detects interrupt servicing just a little later, is that 3 consecutive writes can only be the pushing of the PC and status register. (At least, for 6502-mode: not sure about 65816 in native mode.) See 64doc.txt


Last edited by BigEd on Tue Mar 23, 2010 12:33 pm, edited 1 time in total.

Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Mon Mar 22, 2010 8:51 pm 
Offline
User avatar

Joined: Thu May 28, 2009 9:46 pm
Posts: 8504
Location: Midwestern USA
kc5tja wrote:
Whoa -- sudden font-size change initially looked like you were yelling. Yikes! Then I remembered, perhaps its a cut-n-paste artifact.

Actually, I enlarged the font because I was having trouble reading it. Ever since I started visiting this site I have struggled with small fonts and sometimes bad color contrasts. That's part of the deal when one is developing macular degeneration.

_________________
x86?  We ain't got no x86.  We don't NEED no stinking x86!


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Mon Mar 22, 2010 9:14 pm 
Offline
User avatar

Joined: Fri Aug 30, 2002 1:09 am
Posts: 8543
Location: Southern California
You can probably turn up the size of all the text in the whole window (if not also the pictures) by pressing <CTRL+>, or by rotating the scroll wheel up while pressing CTRL, or by going into the "View" dropdown menu and selecting "Zoom".


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Tue Mar 23, 2010 9:16 am 
Offline
User avatar

Joined: Fri Dec 11, 2009 3:50 pm
Posts: 3367
Location: Ontario, Canada
I've just added a post to The secret, hidden, transparent 6502 DMA channel topic, linking it to here. I did that because Jorge's creative scheme for recycling "dead" 6502 bus cycles into useful DMA bandwidth is another case where an Early Interrupt Acknowledge signal would be useful. In fact it's the same scenario as with my KimKlone computer -- Jorge & I use the same approach to tracking instruction execution. (Great minds think alike! :wink: )

Although the KimKlone has an extra layer of pitfalls (as noted in my previous post), there's an underlying problem that's simple and which I should've stated straightaway: the op-code fetched when SYNC is high doesn't necessarily get executed. [Edit: Similarly, on an '816: the op-code fetched when VPA and VDP are high doesn't necessarily get executed. See entry 22a, Table 5-7 of the Aug 3, 2009 version of WDC 's W65C816S Data Sheet]

That makes it impossible to track instruction execution -- unless you stop using interrupts or have the Early Interrupt Acknowledge or something similar. Your logic needs to know when the fetched op-code is being internally replaced by a BRK-like operation. (Maybe there are some 02's that keep SYNC low as this occurs, although I doubt it. BTW my own experience is with a Rockwell 65C02.)

(OK, there are other options, such as gating the interrupt requests and assuming you can predict the CPU's delay in responding. Or you could generate your interrupts externally by forcing a BRK op-code on the data bus, and you'd never need to use the CPU's IRQ and NMI pins at all. Someday I'll add an appendix to my KimKlone article regarding my efforts along these lines.)


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Fri Jun 04, 2010 9:16 pm 
Offline

Joined: Mon Mar 02, 2009 7:27 pm
Posts: 3258
Location: NC, USA
Dr. Jefyll, I would like to use yours' and Jorge's ideas for opcode "mod's" on my final iteration of the digital pulse width analyzer project. Namely, the mod that can address 16MB with 1 undefined opcode and the databus...

Presently I am using a WDC65C02 (I know you said you used Rockwell), but I don't plan on using interrupts, just polling bits on ports (input latches). No interruption of the processor will be needed.

My plan is to use a WDC65C02, at least 1 2Mx8 10nS SRAM, an 8Kx8 EEPROM (for OS), and 1 5nS Spartan 2 FPGA to manipulate the address lines and data bus based on the SYNC, and Phase2 lines. A total of 4 IC's, the FPGA running X-times faster than the 6502, where X is the number of operations the PFGA has to perform to memory before the CPU takes back over.

Am I on the right track? I am expecting parts next week to wire it up.

_________________
65Org16:https://github.com/ElEctric-EyE/verilog-6502


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Sat Jun 05, 2010 12:48 am 
Offline
User avatar

Joined: Fri Dec 11, 2009 3:50 pm
Posts: 3367
Location: Ontario, Canada
ElEctric_EyE wrote:
...Namely, the mod that can address 16MB with 1 undefined opcode and the databus... ...Am I on the right track? I am expecting parts next week to wire it up.

Perhaps you're taking a different approach to handling 16Mb addressing. (What I did with KK is by no means the only solution.) I encourage you to look at the problem in your own way: think about what needs to be done, and how it might be accomplished using the resources at your disposal. Basically you need to create some hardware that will let the programmer "talk" to a few extra address lines (thus yielding a bigger-than-64K memory space). Usually such schemes are controlled by operations on designated I/O addresses, and are relatively easy to design & build. Mapping new operations into the processor's instruction space is a greater challenge, one which may be overkill for your application.

As for the KK, it sounds like you're suggesting a single undefined opcode controls everything, which is not the case. I regret that my article fails to explicitly list all the new opcodes, but there are 44.

I invite you (and everyone reading this) to help me improve the KK article. If, after careful reading, there are any issues that remain unclear I hope you will bring them to my attention -- and I will cheerfully & sheepishly remedy the situation!


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Sat Jun 05, 2010 1:24 am 
Offline

Joined: Mon Mar 02, 2009 7:27 pm
Posts: 3258
Location: NC, USA
Initially, I was using a simple 5-bit adressable flip-flop to control the upper address lines above A15. Simple enough, my thread explains it as a 16K window...

Your design uses an "undefined" opcode and the associated 8-bit data for the extended address selection, correct?

_________________
65Org16:https://github.com/ElEctric-EyE/verilog-6502


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Sat Jun 05, 2010 2:04 am 
Offline
User avatar

Joined: Fri Dec 11, 2009 3:50 pm
Posts: 3367
Location: Ontario, Canada
ElEctric_EyE wrote:
Your design uses an "undefined" opcode and the associated 8-bit data for the extended address selection, correct?

No. 44 undefined codes are used, many of which have no associated data (relying on the contents of the new registers instead). Forgive me, but have you actually read my article? I'm sensing a disconnect here. I hope the article doesn't neglect any key points.

I confess I haven't read your thread. But the addressable flip-flop to control the upper address lines sounds like a viable approach.


Last edited by Dr Jefyll on Sat Jun 05, 2010 5:29 pm, edited 1 time in total.

Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Sat Jun 05, 2010 5:23 pm 
Offline
User avatar

Joined: Fri Dec 11, 2009 3:50 pm
Posts: 3367
Location: Ontario, Canada
ElEctric_EyE wrote:
Your design uses an "undefined" opcode and the associated 8-bit data for the extended address selection, correct?

This quote describes yet another workable option -- and possibly an excellent solution for your project.

Hex 42, C2 and E2 are undefined opcodes which (on my Rockwell chip, at least) are two-byte, two-cycle NOP instructions. Using your FPGA it would be feasible to detect when one of these coincides with SYNC. Then on the subsequent cycle, as the 2nd byte is fetched and discarded by the CPU, your logic could grab those 8 bits from the data bus and latch them for use as extra address bits.
Executing your new instruction would cause the 8 bits to appear in your Window Select Register, thus determining what appears in the window. This is in contrast with the usual practice of mapping the select register(s) as an I/O port(s). The op-code approach is faster and doesn't require the use of any CPU registers.

Some limitations apply, but they may be unimportant. Although I suggested that you update your address bits from the new op's Immediate operand, that may or may not be convenient. Immediate is great for static, literal values (already known at assembly time); the assembler can just hard-code such a value into the instruction, end of story. But it's a different kettle of fish if your code needs to compute new window addresses at run time -- in order to randomly fetch items from a >64K array, for instance. Results of the computation would have to be written into the 2nd byte of the special instruction, then it would need to be executed -- which is slightly awkward (not to mention un-ROMable). For that reason you may wish to make the Window Select Register also writable in the more usual manner via an I/O address, giving you two ways to update the window bits. This is just a nicety, really -- either method on its own would probably suffice.

(Afterthought: You could even have 2 or 3 independent windows, especially since there are three suitable op-codes available! )
[Edit: extra detail; rearrange the last paragraph; prune some ka-ka out of the one before it. :oops: Also,
an Afterafterthought: nothing says you have to choose immediate mode for the new instruction. Your other options (now that I review the matter) include Immediate, Absolute, Z-Pg and Z-Pg,X modes. There are unused opcodes for this; details in the KK article on my site.]


Last edited by Dr Jefyll on Wed Jun 09, 2010 9:21 pm, edited 1 time in total.

Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 32 posts ]  Go to page 1, 2, 3  Next

All times are UTC


Who is online

Users browsing this forum: No registered users and 24 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to: