6502.org Forum  Projects  Code  Documents  Tools  Forum
It is currently Thu Oct 03, 2024 5:28 pm

All times are UTC




Post new topic Reply to topic  [ 16 posts ]  Go to page 1, 2  Next
Author Message
PostPosted: Sat Feb 25, 2017 7:14 pm 
Offline

Joined: Sat Feb 25, 2017 6:52 pm
Posts: 2
Dear 6502 enthusiasts,

I'm currently working on a little 6502 computer project with an original 6502 as the CPU (maybe later a 65C02 as an economical upgrade) a SRAM and an EEPROM for a small monitor program and a UART module to connect via terminal to the system. I'm currently in the planning phase and got to a point where I can't continue because I don't understand a key point:

I'm missing an output signal of the 6502 which tells me: "I, the 6502, put the address of the memory location on the bus. Please put the data onto the bus I'll read it in XXX ns.". I basically want to attach other external components (µC) to perform actions on some memory locations.

I attached a timing diagram from the literature. As you can see the 6502 provides besides the ADDR[15..0] and DATA[7..0] "only" the R/W signal to indicate if memory is going to be read or written. The text states that memory access is performed when R/W is stable (point E). But I can't hook onto this condition with any external component (µC) to perform some other tasks since - I guess - the value of this signal is always "stable" - either 0 or 1. But if it is in tristate I can't use a µC to sense this.

So could you give me some kind of short explanation how I handle this problem?

Regards!


Attachments:
File comment: 6502 timing diagram
lit.png
lit.png [ 470.32 KiB | Viewed 4489 times ]
Top
 Profile  
Reply with quote  
PostPosted: Sat Feb 25, 2017 7:43 pm 
Offline
User avatar

Joined: Fri Aug 30, 2002 1:09 am
Posts: 8521
Location: Southern California
Welcome!

The part you are missing is the importance of Φ2 in a 6502 system. You might be used to the RD\ and WR\ signals of other systems. You can derive those with the circuit at the bottom of the clock-generation page (section 6) of the 6502 primer at http://wilsonminesco.com/6502primer/ClkGen.html . The primer however is organized logically into 22 sections and I recommend going through them in order (even if you don't spend as much time in some as in others).

_________________
http://WilsonMinesCo.com/ lots of 6502 resources
The "second front page" is http://wilsonminesco.com/links.html .
What's an additional VIA among friends, anyhow?


Top
 Profile  
Reply with quote  
PostPosted: Sat Feb 25, 2017 9:41 pm 
Offline

Joined: Sat Jun 04, 2016 10:22 pm
Posts: 483
Location: Australia
I think what Garth is referring to is that the data lines are only guaranteed to be stable when Φ2 is high.
The address and control signals(if I remember correctly) are valid just after Φ2 goes low, and stay that way until the next Φ2 low.

What you seem to be thinking of is an asynchronous bus. The 6502 uses a synchronous one.


Top
 Profile  
Reply with quote  
PostPosted: Sat Feb 25, 2017 10:28 pm 
Offline
User avatar

Joined: Fri Aug 30, 2002 1:09 am
Posts: 8521
Location: Southern California
DerTrueForce wrote:
I think what Garth is referring to is that the data lines are only guaranteed to be stable when Φ2 is high.
The address and control signals(if I remember correctly) are valid just after Φ2 goes low, and stay that way until the next Φ2 low.

Be sure to refer to the timing specifications. The address and control lines are guaranteed to be valid in no more than a certain number of ns after Φ2 goes low, but note that the address is not guaranteed to be valid and stable before R/W does, meaning you still have to wait for Φ2 to go high before writing; otherwise you might write to an address you didn't intend to. When writing, the data lines are not guaranteed to be stable yet when Φ2 rises; but they will be, within the guaranteed time, so you can meet the setup time that the memory or other device you're writing to needs before Φ2 falls.

_________________
http://WilsonMinesCo.com/ lots of 6502 resources
The "second front page" is http://wilsonminesco.com/links.html .
What's an additional VIA among friends, anyhow?


Top
 Profile  
Reply with quote  
PostPosted: Sun Feb 26, 2017 7:10 am 
Offline
User avatar

Joined: Thu Dec 11, 2008 1:28 pm
Posts: 10943
Location: England
Welcome angus! Just to add another possible way of thinking about this. I want you to zoom in, beyond the cycle by cycle view of the world, to the nanosecond by nanosecond view of the world.

In a 6502 world, every nanosecond, every device is doing what it must according to the signals it sees. If it is reading, all is well - as the address lines change, one by one, nanosecond by nanosecond, a RAM or ROM will be adjusting its actions to read the address in question. Once the address lines are stable, after the insides of the memory have settled down, the outputs will reflect the contents of the appropriate location. If, in the interim, various other locations were trying to be read, no harm done.

But if the device was responding to a write, it would have perturbed all those intermediate locations, and that would be no good.

For writes, then, the device needs never to see the RnW line low, unless the address is stable, and therefore also its Chip Select is stable, in order that the only address it starts to perturb is the one intended address for that cycle.

There is a little more to this: some peripheral devices will take some internal action on a read, and so for these devices it's important they don't take action even on a read until the address is stable and their chip selects are active.

There are several ways to resolve these constraints - there is no one true way - but they are tradeoffs of simplicity, speed, reliability.


Top
 Profile  
Reply with quote  
PostPosted: Sun Feb 26, 2017 1:57 pm 
Offline

Joined: Sat Feb 25, 2017 6:52 pm
Posts: 2
Thank you very much for your kind responses!

GARTHWILSON wrote:
You might be used to the RD\ and WR\ signals of other systems. You can derive those with the circuit at the bottom of the clock-generation page (section 6) of the 6502 primer at http://wilsonminesco.com/6502primer/ClkGen.html.

This is exactly what I'm looking for (I guess). So:

~RD = memory read := (~R/W) NAND ø2
~WR = memory write := R/W NAND ø2

I assume that the configuration ~RD = 0 and ~WR = 0 (at the same time) does not occur and normally (e.g. nothing read or written) the values are ~RD = 1 and ~WR = 1 to indicate "idle". Right? See the following why this is important to me ...

BigEd wrote:
If it is reading [...] a RAM or ROM will be adjusting its actions to read the address in question.
[...]
There is a little more to this: some peripheral devices will take some internal action on a read, and so for these devices it's important they don't take action even on a read until the address is stable and their chip selects are active.[...]


And that is the key point of my entire question here. I want to trigger an action by a microcontroller when a specific address is read by the 6502. Therefore I need a signal to attach an interrupt on the microcontroller to this signal to then check, inside the ISR, if the specific address is on the bus and the action should be performed by the microcontroller. And in order to do this I need a rising or falling edge on the signal and therefore it is important for me that ~RD and ~WR go back to an idle state and then perform an edge to let the microcontroller trigger the interrupt.

So is the behaviour of ~RD and ~WR the same as I described (or wish)?

Cheers!


Top
 Profile  
Reply with quote  
PostPosted: Sun Feb 26, 2017 1:59 pm 
Offline
User avatar

Joined: Thu Dec 11, 2008 1:28 pm
Posts: 10943
Location: England
(You'd check the signals on the falling edge of phi2 - they are sure to be valid there.)


Top
 Profile  
Reply with quote  
PostPosted: Sun Feb 26, 2017 2:04 pm 
Offline
User avatar

Joined: Tue Nov 16, 2010 8:00 am
Posts: 2353
Location: Gouda, The Netherlands
If the microcontroller also provides the clock, you may also read the bus at certain points in the clock cycle without waiting for a signal from the 6502.


Top
 Profile  
Reply with quote  
PostPosted: Sun Feb 26, 2017 9:31 pm 
Offline
User avatar

Joined: Fri Aug 30, 2002 1:09 am
Posts: 8521
Location: Southern California
angus wrote:
GARTHWILSON wrote:
You might be used to the RD\ and WR\ signals of other systems. You can derive those with the circuit at the bottom of the clock-generation page (section 6) of the 6502 primer at http://wilsonminesco.com/6502primer/ClkGen.html.

This is exactly what I'm looking for (I guess). So:

~RD = memory read := (~R/W) NAND ø2
~WR = memory write := R/W NAND ø2

I wish there were a way to put the overbar on text in the forum. In "R/W" which is "read, or write-not," there should be a bar over the W, meaning the signal is low for writing. It looks like you're inverting R/W for the wrong one. I'm not familiar with your ":="; but to clarify,
The read-not output signal should be the NAND of R/W itself and Φ2.
The write-not output signal should be the NAND of the inverted R/W and Φ2

Quote:
I assume that the configuration ~RD = 0 and ~WR = 0 (at the same time) does not occur and normally (e.g. nothing read or written) the values are ~RD = 1 and ~WR = 1 to indicate "idle". Right?

Most memories with an output-enable-not (basically a read-not, but the chip select has to be true too) and a write-enable-not input will ignore the output-enable-not input if write-enable-not is true (ie, low). Check the data sheet for the one you want to use of course.

Quote:
See the following why this is important to me ...

BigEd wrote:
If it is reading [...] a RAM or ROM will be adjusting its actions to read the address in question.
[...]
There is a little more to this: some peripheral devices will take some internal action on a read, and so for these devices it's important they don't take action even on a read until the address is stable and their chip selects are active.[...]

I assume he's referring to I/O ICs which may for example clear an interrupt condition if you read the status register, or a timer interrupt if you read a timer's counter registers. Debugging these was quite a challenge in the early days of the NMOS 6502 when indexing across a page boundary caused an extra (but predictable, if you knew how it worked) read of an invalid address. (CMOS does an extra read of the last instruction byte instead.)

Quote:
And that is the key point of my entire question here. I want to trigger an action by a microcontroller when a specific address is read by the 6502. Therefore I need a signal to attach an interrupt on the microcontroller to this signal to then check, inside the ISR, if the specific address is on the bus and the action should be performed by the microcontroller. And in order to do this I need a rising or falling edge on the signal and therefore it is important for me that ~RD and ~WR go back to an idle state and then perform an edge to let the microcontroller trigger the interrupt.

How fast is this microcontroller? Remember the 6502 does a new bus access in every cycle, or every "T state" in the parlance of some other processors (although a few of those, perhaps a quarter of them, are dead bus cycles). Your ISR, including finishing an already-started instruction and also the interrupt sequence and return, will have to execute in under a microsecond if the 6502 goes only 1MHz. If you run it at 20MHz, it becomes 50ns. It's possible, but unlikely, that you have a microcontroller fast enough to do that. Even if the microcontroller is only involved for I/O and ignores memory access, there can still be I/O accesses two cycles in a row.

_________________
http://WilsonMinesCo.com/ lots of 6502 resources
The "second front page" is http://wilsonminesco.com/links.html .
What's an additional VIA among friends, anyhow?


Top
 Profile  
Reply with quote  
PostPosted: Mon Feb 27, 2017 3:29 am 
Offline
User avatar

Joined: Thu May 28, 2009 9:46 pm
Posts: 8411
Location: Midwestern USA
angus wrote:
GARTHWILSON wrote:
You might be used to the RD\ and WR\ signals of other systems. You can derive those with the circuit at the bottom of the clock-generation page (section 6) of the 6502 primer at http://wilsonminesco.com/6502primer/ClkGen.html.

This is exactly what I'm looking for (I guess). So:

~RD = memory read := (~R/W) NAND ø2
~WR = memory write := R/W NAND ø2

The attached is essentially the same circuit that Garth link above, but with a truth table added. Perhaps that might help you understand what is meant by qualifying reads and writes with the Ø2 clock. This circuit will function at 20 MHz with ample timing headroom.

Incidentally, I show the use of an inverter on the one input to the NAND gate (U3). However, you can use one of the four NANDs in U3 as an inverter if you don't have an actual inverter in your system. Just tie both inputs together and connect them to RWB.


Attachments:
File comment: Read/Write
read_write_qualify_reduced.gif
read_write_qualify_reduced.gif [ 19.15 KiB | Viewed 4386 times ]

_________________
x86?  We ain't got no x86.  We don't NEED no stinking x86!
Top
 Profile  
Reply with quote  
PostPosted: Mon Feb 27, 2017 5:26 am 
Offline
User avatar

Joined: Sat Dec 07, 2013 4:32 pm
Posts: 246
Location: The Kettle Moraine
:= is mathematical symbol for "represents", the way I recall. It's used extensively in certain programming languages to denote a variable assignment. Pascal for example would use X:=Y=3 the way C (oddly) uses X=Y==3 (if my memory is correct!)

I think his usage is incorrect for the purposes of mathematical notation, but in the context of programming languages that use it as above, it does make sense.

I would prefer to state what he wrote as
/RD [memory read] = (NOT /R\W) NAND ø2
/WR [memory write] = /R\W NAND ø2
but that convention may only make sense to me. No matter what, it's confusing, lacking that overscore. And, I'm pretty sure his logic is incorrect, if I read it right.


Top
 Profile  
Reply with quote  
PostPosted: Mon Feb 27, 2017 10:24 am 
Offline
User avatar

Joined: Tue Nov 16, 2010 8:00 am
Posts: 2353
Location: Gouda, The Netherlands
GARTHWILSON wrote:
Your ISR, including finishing an already-started instruction and also the interrupt sequence and return, will have to execute in under a microsecond if the 6502 goes only 1MHz.

Actually, you'd have less than half that time, because everything needs to happen while PHI2 is high. On the other hand, the time for the interrupt return can be left out.


Top
 Profile  
Reply with quote  
PostPosted: Mon Feb 27, 2017 10:30 am 
Offline
User avatar

Joined: Thu Dec 11, 2008 1:28 pm
Posts: 10943
Location: England
In the PiTubeDirect code, we spin reading all the relevant I/O, waiting for clock high. Then we spin waiting for clock low, and when we first see clock low, we take the previous sample as having the valid data, address and RnW.

The spinning code is essentially running just two instructions, so that's the response time. Something like this:
- read i/o into register (clock goes into sign bit)
- branch backwards if negative
(You need something slightly different to apply the idea of using the previous sample:
- move register to safe register
- read i/o into register (clock goes into sign bit)
- branch backwards if negative
- use the value from the safe register
Although this spins more slowly, by using the last value with clock high the latency is slightly less critical.
)

In one incarnation, we triggered an interrupt on the falling edge of our CS, then did all the spinning within the ISR. The ISR also detected anomalous conditions, indicating that CS had merely glitched low.

In this case, the ISR has a half microsecond or so to get to the spinning code.


Top
 Profile  
Reply with quote  
PostPosted: Thu Mar 02, 2017 7:26 am 
Offline
User avatar

Joined: Thu Jun 23, 2011 2:12 am
Posts: 229
Location: Rancho Cucamonga, California
In my Propeddle and L-Star projects, I use a Propeller to bitbang the WDC 65C02 at 1MHz. The Propeller runs at 80MHz and executes about 20 million instructions per second, so the minimum time between changes on the Propeller pins is 50ns. I have the Propeller generating the clock for the 65C02 but it can also work on an external clock. Basically what I do to let the 65C02 access memory in the Propeller, is:
  1. Wait for the clock to go LOW
  2. Disable the outputs of the Propeller to the data bus (this happens 50ns after the clock goes low, which is after the minimum read hold time)
  3. Read the address bus and R/!W pin (we're approximately 100ns into the clock pulse, so after the Address bus and R/!W setup time)
  4. Determine whether the address is important, and do further preparations (such as calculating internal address based on the 6502 address)
  5. If the 65C02 is in Read mode, wait until the clock is HIGH then put the data on the data bus pins and enable the pins for output (from the viewpoint of the Propeller). Timing is not really critical in this case; the Propeller just has to make sure that the data is on the data bus by the time the clock goes low again (i.e. before the minimum read data setup time which is measured from the next clock high-low transition), because that's when the 65C02 latches it.
  6. If the 65C02 is in Write mode, wait until the clock is HIGH (that's when the data becomes available), then read the data from the data bus. The Propeller has to wait for the write data setup time, so I think I do some house keeping or a NOP (50ns) between detecting the clock HIGH and reading the data. Then the Propeller stores the data or does something useful with it.
  7. Go to step 1.

Emulating memory is pretty simple, and the Propeller can easily keep up with the 65C02 at 1MHz. It gets a little more complicated in cases when there are side-effects. For example, the PIA in the Apple 1 emulator has to read data from the keyboard and send data to the screen/serial port but it also has to do some handshaking to let the emulated hardware know that something has changed (a key has been read, or a new byte has been posted for the video display). To do this, 20 Propeller instructions aren't enough so it does the handshaking part of the operation during the next clock cycle. During that clock cycle, the Propeller doesn't pay attention to the 65C02's address bus, so if the 65C02 would do a second operation on the PIA, it would have unexpected results; however, this is not a problem in practice: the only times that the 65C02 accesses the same (or adjacent) locations in two consecutive clock cycles, are:
  • when it's reading an instruction to execute from those locations
  • when it's pushing or pulling data to/from the stack
  • when it's doing a read-modify-write instruction such as INC or DEC

All of those operations don't make sense for the PIA so it's not really important that the PIA is effectively "off the bus" for one cycle.

In case you don't know, the Propeller can run up to 8 cores ("cogs") at the same time, so other cogs can take care of e.g. putting data from a PS/2 keyboard on the emulated PIA input and reading text output from the emulated PIA output. For other emulations such as the Superboard / UK101, it can even generate a video signal based on a memory area that's mapped into 6502 address space.

Hope this helps.

===Jac


Top
 Profile  
Reply with quote  
PostPosted: Thu Mar 02, 2017 7:42 am 
Offline
User avatar

Joined: Thu Dec 11, 2008 1:28 pm
Posts: 10943
Location: England
Interesting detail Jac! We had another case to worry about: a write to a peripheral using an indexed addressing mode (as you are using a 'C02 you're fine.) In our case, interfacing with the Beeb's NMOS 6502, this case means we can get two consecutive accesses, and it's the second one which is important. So, after a read access, we have a quick look to see if chip select is still active. This cost a bit of performance when we were doing the bit-banging in the ISR.


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

All times are UTC


Who is online

Users browsing this forum: No registered users and 10 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:  
cron