Page 1 of 8
Let's start at the very beginning...
Posted: Sat Nov 16, 2024 2:19 pm
by DRG
Right, this time around, I’m going to seek input to my build BEFORE I start, rather than asking why it’s not working AFTER I build it! I’ll attempt to outline my requirements to you in three increasing levels of detail. This way, you can see at which point any of my assumptions become erroneous.
Level 0
6502 on breadboard running at 8MHz.
32Kb RAM, 32Kb ROM.
Powered from USB connection.
Serial-style I/O through USB connection.
Level 1
CPU: WDC65C02S6TPG-14
RAM: AS6C62256-55PCN
ROM: 39SF010A-70
VIA x2: WDC65C22S6TPG-14
Glue Logic: 2 x ATF22V10C-10PU
Comms: Arduino Nano (clone)
Level 2
Voltages: This will be a 5V system.
Breadboards: I have BusBoard BB630s.
Address decoder: My memory map is as follows…
$FF00 - $FFFF ROM
$FE00 - $FEFF I/O
$8000 - $FDFF ROM
$0100 - $7FFF RAM
$00F0 - $00FF VIA1
$0000 - $00EF RAM
One ATF22V10C will decode this above address map providing CSB for RAM, ROM, VIA1 and I/O (for page $FE) as well as WEB/OEB. The other will simultaneously decode page $FE for 10 other devices – hence, no additional propagation delay over and above 10ns for one CPD. I already have the programmer and chips required.
Speed: The slowest link in the chain is the ROM at 70ns. Adding 10ns for the address decoding, this give 80ns. Looking at the timing diagrams and specs, at 5V, tADS=30ns and tDSR=10ns. This makes a total of 120ns for tCYC which should equate to a speed of 8.333MHz. That’s close to my goal of 8Mhz but not as much headroom as I thought there would be. I will use 8MHz DIP oscillator for clock generation.
Interrupts: IRQ/NMI – Not sure what to do with these yet. Still a little too advanced for me but I understand that they may be needed for what I want my system to achieve, so I wish to be able to keep my options open and bring them into the equation later.
I/O: Now this is probably the most esoteric of the characteristics of this build. What I want is for me to just plug this SBC into the USB port on my PC (Ubuntu OS) and for that to both power the system AND provide comms back to the minicom serial communication program. At this point, my plan for making this happen is to have an Arduino Nano (a clone, actually) in the system and I would plug the USB cable into this. Power would then be available through the 5V out pin of the Nano (my research has indicated this can handle 800-1000mA).
VIA1 (in zero page) will be dedicated to communicating with the Nano. My plan is to use Port A with handshaking via CA1 & CA2 allowing 8-bit parallel data transfer and having the Nano provide the serial link back to the PC. My thinking is that this would provide quite a fast transfer rate when downloading code into the SBC. Yes, this means writing code for the Nano, but it doesn’t seem it would be hard or need a lot of code to achieve.
I appreciate that there may be other (easier?) ways to accomplish simultaneous powering and serial comms through a USB port. But, I thought this way I wouldn’t need a 65C51 and FTDI USB to serial module.
Well, I’m quite excited to receive feedback and see whether this is viable or a different approach is required to attain my high-level goals.
Thanks.
Dave
Re: Let's start at the very beginning...
Posted: Sat Nov 16, 2024 3:52 pm
by barnacle
I had a couple of questions but on re-reading your post you've already answered them.
At least I think so: from your text, I believe you will set up one of the VIAs to read/write from a port on the Arduino, mediated with CB1/2 to negotiate the details? That ought to work - but don't forget to leave the Arduino in input mode except when you're actually reading from it, and ideally leave the VIA in input mode except when actually writing to the Arduino.
There's always a risk when connecting to bidirectional ports together that you inadvertently set the up to be driving into each other; this is a Bad Thing[tm] and you should endeavour to avoid it! It might be worth your while to draw up the sequence of events for both the VIA and the Arduino as communication is attempted - basically, keep track of the ins and outs of the handshake signals and the data bus.
Neil (also a David, as it happens)
Re: Let's start at the very beginning...
Posted: Sat Nov 16, 2024 5:08 pm
by plasmo
6502 accesses memory only during the high phase of its clock, so your memory needs to be 50nS or faster for 8Mhz. Factoring in decoding delay and data setup time, it needs to be 35nS, by the data book. However, that’s worst case timing; your SST39SF010 is likely to operate at 8Mhz, but you should have a 4Mhz oscillator ready, just in case. You can also speed up ROM access by ground its chip select and assert output enable when accessing ROM.
Bill
Re: Let's start at the very beginning...
Posted: Sat Nov 16, 2024 5:38 pm
by jgharston
Address decoder: My memory map is as follows…
$FF00 - $FFFF ROM
$FE00 - $FEFF I/O
$8000 - $FDFF ROM
$0100 - $7FFF RAM
$00F0 - $00FF VIA1
$0000 - $00EF RAM
That's fiddly. You've got 32K of RAM, but then blocking out 16 bytes of it. It's easier to partition your memory map with fewer address lines, not more; and it's always better to chop up ROM/IO space than to chop up RAM space.
You've already blocked off a chunk of ROM space for I/O, I'd recommend putting the VIA in that I/O space. You could then have:
0xxx...xxxx: RAM
1xxx...xxxx: not-RAM
11111110xxxxxxxx I/O
You could then pass IO+A7/A6/A5 through a 3-to-8 decoder to give eight blocks of I/O.
Re: Let's start at the very beginning...
Posted: Sat Nov 16, 2024 5:42 pm
by DRG
barnacle - I've yet to work out the details, but it makes sense to have a default position where the VIA & Nano are in read mode. Maybe another line from Port B could act as the "flag" for transmission.
plasmo - Of course, I forgot about this high phase constraint to the timing of memory access. I have 4MHz oscillators to hand, perhaps I can get a 5 MHz and a 6 MHz one too, in order to ramp it up. Simple swap outs.
You can also speed up ROM access by ground its chip select and assert output enable when accessing ROM.
I don't quite understand how that works. Grounding its chip select will mean it is always "on" and I thought the OEB went to both RAM and ROM - so what would stop ROM from putting data on the bus when accessing a RAM address? Why wouldn't there be some kind of bus contention?
jgharston - I was looking to take advantage of zero page memory addressing when working with the VIA. I've programmed this already in the CPD and it works, so I was going to recycle the idea.
Re: Let's start at the very beginning...
Posted: Sat Nov 16, 2024 6:21 pm
by BigEd
It's possible to feed the 6502 with double-speed RAM, and many systems do that so they can also feed video. But it's not necessary. It's not true that only half the clock period is available for memory access time. Remember, memory access times start from the point that the address lines deliver a valid address, and from where decode logic provides a chip select signal.
Study some timing diagrams - there's no substitute! See Jeff's page, for example:
https://laughtonelectronics.com/Arcana/ ... iming.html
Re: Let's start at the very beginning...
Posted: Sat Nov 16, 2024 7:20 pm
by plasmo
I don't quite understand how that works. Grounding its chip select will mean it is always "on" and I thought the OEB went to both RAM and ROM - so what would stop ROM from putting data on the bus when accessing a RAM address? Why wouldn't there be some kind of bus contention?.
The longest memory access time is measured from chip select asserted to valid date out, or in case of chip select always asserted, from valid addresses to valid data out. Assuming chip select and valid addresses were already stable, the time from output enable to valid data is generally faster. In case of SST39SF010, access time is 70 nS, but output enable to valid data is 35nS, (assuming valid addresses and chip select are stable 35nS prior). By always asserting chip select, we are taking advantage of 6502 putting out valid addresses quite a bit of time before rising edge of clock, so ROM access is already in progress when output enable (which is qualified with clock high) is asserted thus realizing the faster access time.
Bill
Re: Let's start at the very beginning...
Posted: Sat Nov 16, 2024 8:47 pm
by drogon
jgharston - I was looking to take advantage of zero page memory addressing when working with the VIA. I've programmed this already in the CPD and it works, so I was going to recycle the idea.
I'm also going to say; Don't put hardware IO in Zero Page.
The advantages are minimal - you save one cycle per port access and one byte where you use it, but really - it's not significant when you're waiting on IO - especially parallel IO to an AVR acting as your serial port.
WDC did it with some of their devices - e.g. the W65C134SXB where they ROBBED me of $40 bytes of my precious zero page as a result I had to move data out of ZP and into main RAM which made the whole system slower as a result.
Really - make life easy and use the page up at $FExx. You can decode that into 16 16-byte regions, so 16 VIAs if you like.
I will say though - I am guilty of it myself, so treat this as "do as I say, not as I do" - however this was in a project I did last year where I had just 4K of ROM and 4K of RAM - I did steal some IO from $00Fx and $010X but it was a very constrained system and I really really needed all that 4K of ROM (it currently has just one byte spare) and as much RAM as I could get for program storage (It's a TinyBasic system running on the 6507)
-Gordon
Re: Let's start at the very beginning...
Posted: Sun Nov 17, 2024 9:16 am
by DRG
The longest memory access time is measured from chip select asserted to valid date out, or in case of chip select always asserted, from valid addresses to valid data out. Assuming chip select and valid addresses were already stable, the time from output enable to valid data is generally faster. In case of SST39SF010, access time is 70 nS, but output enable to valid data is 35nS, (assuming valid addresses and chip select are stable 35nS prior). By always asserting chip select, we are taking advantage of 6502 putting out valid addresses quite a bit of time before rising edge of clock, so ROM access is already in progress when output enable (which is qualified with clock high) is asserted thus realizing the faster access time.
Bill
Bill - thanks for bearing with me whilst I wrap my head around this. I get the part about the SST39SF010 being constantly in action as a consequence of a permanent chip select assertion, but I'm struggling with the output enable part. If the ROM is active (due to chip select constantly on), when happens when I read/write to RAM? Won't the chip select of the RAM be asserted (from my glue logic) and the output enable will be the same signal that goes to the RAM and ROM? I don't understand how that would work as I have two chips operating simultaneously to, say, the same CPU read instruction?
Dave
Re: Let's start at the very beginning...
Posted: Sun Nov 17, 2024 5:47 pm
by plasmo
The output enable to RAM and ROM are separate signals. Instead of 22v10 decoding chip select of ROM, its output goes to output enable of ROM (need to qualify the output with write so not to clash with 6502 during a write operation). Because output enable is faster, the 10ns delay in decoding through 22v10 does not add to the overall access time.
Bill
Re: Let's start at the very beginning...
Posted: Sun Nov 17, 2024 6:22 pm
by DRG
The output enable to RAM and ROM are separate signals. Instead of 22v10 decoding chip select of ROM, its output goes to output enable of ROM (need to qualify the output with write so not to clash with 6502 during a write operation). Because output enable is faster, the 10ns delay in decoding through 22v10 does not add to the overall access time.
Bill
Ahh! The penny drops (I think). So, for a 32/32 simplistic memory map, my 22V10 logic - would it be something like this?...
Code: Select all
RAM = Address:[0000..7FFF];
ROM = Address:[8000..FFFF];
!RAM_CS = RAM;
!ROM_CS = ROM;
!WE = CLK & !RW;
!OE = CLK & RW;
!OE_ROM = OE & !ROM_CS
Not sure if I have the logic with the "!" correct or not.

Could it be...
This kind of logic gets me confused quickly - I probably need to invest the time to look at the 65C02 timing diagrams again, rereread Garth's primer and draw the truth table for the OE.
Dave
Re: Let's start at the very beginning...
Posted: Sun Nov 17, 2024 7:49 pm
by BigDumbDinosaur
The output enable to RAM and ROM are separate signals. Instead of 22v10 decoding chip select of ROM, its output goes to output enable of ROM (need to qualify the output with write so not to clash with 6502 during a write operation). Because output enable is faster, the 10ns delay in decoding through 22v10 does not add to the overall access time.
Bill
Ahh! The penny drops (I think). So, for a 32/32 simplistic memory map, my 22V10 logic - would it be something like this?...
Code: Select all
RAM = Address:[0000..7FFF];
ROM = Address:[8000..FFFF];
!RAM_CS = RAM;
!ROM_CS = ROM;
!WE = CLK & !RW;
!OE = CLK & RW;
!OE_ROM = OE & !ROM_CS
Not sure if I have the logic with the "!" correct or not.
Dave
I disagree with Bill’s notion of continuously grounding your flash ROM’s /CS and only gating its /OE. Yes, /OE is “faster,” but only relative to when /CS is asserted. In a 6502 system, best performance is consistently achieved when chip selects are asserted during Ø2 low (required with 65xx peripherals), and output enables or write enables are asserted during Ø2 high (except 65xx peripherals, which respond directly to RWB and the clock). Such an arrangement produces the fastest response to changing address bus conditions and prevents possible contention between the MPU and another device as the bus gets set up for the next cycle.
In the case of ROM, continuously asserting its /CS means the ROM is continuously not in standby, i.e., it’s continuously consuming a not-insignificant amount of power. As 65C02 address outputs become valid during Ø2 low, there is ample time at single-digit clock speeds to select the ROM before it is expected to drive the data bus. Hence the timing of /CS is non-critical, as it will be asserted well before /OE is asserted during a read cycle. If you later decide to crank up your clock speed, you will likely have to add wait-stating to access the ROM or some other slow peripheral, so you won’t be gaining anything with a continuously asserted ROM /CS.
In your GAL logic, you should configure active-low outputs, such as WE, as active-low in your pin declarations and use positive logic to control them. For example:
Code: Select all
pin 22 = !WE; /* write enable */
...
WE = CLK & !RW; /* assert WE on PHI2 high & RWB low*/
Note that the equation is written in positive logic. Inverting the logic to make a pin go low, as you are doing in your code snippet, increases PT usage. In the case of chip selects, and depending on the granularity of your address decoding, PT consumption could exceed the device’s capabilities and result in failure to compile (with a CPLD, the design would compile, but would fail to fit).
More critically, you are using !ROM_CS as a pin node, as well as an output. The sneaky problem with doing so is your prop time is actually pin-to-pin-to-pin. In other words, a 10ns GAL will look like a 20ns GAL to !OE_ROM.
Declarations such as...
Code: Select all
RAM = Address:[0000..7FFF];
ROM = Address:[8000..FFFF];
...are technically incorrect unless all 16 address lines are connected to the GAL. If, for instance, only A15-A8 are connected, you would say...
Code: Select all
RAM = Address:[00xx..7Fxx];
ROM = Address:[80xx..FFxx];
Just as in a logic truth table, the Xes mean “don’t care” and in this case, mean “these address bits aren’t connected.”
Perhaps you should post the entirety of your GAL code for further review.
I question the need for 32K of ROM. Just what all do you plan to put in there? In most systems, RAM is more valuable, so it makes sense to maximize the amount of RAM that is exposed. For perspective, the firmware in my POC V1.3 unit occupies 12K of ROM, and that includes a SCSI driver and Supermon 816, along with interrupt handlers, serial I/O and several software timers to maintain the time of day and system uptime. Given the simple architecture you are proposing, as well as the relatively-simple nature of the 65C02 (as compared to the 65C816 I’m using), I’d think 16K of ROM would be more than enough. That would give you (potentially) 48K of RAM for code and data.
Re: Let's start at the very beginning...
Posted: Tue Nov 19, 2024 7:40 pm
by DRG
More food for thought, BDD. Thanks.
My (ultimate) ambition would to be to run BBC Basic on my 65C02 SBC - I had a BBC Micro Model B in my youth, you see. However, that could wait for the next build, I suppose!

EhBasic is only around 10K (I think) and when I was writing my monitor, I was surprised how small it was, so I totally accept the view that 32K is a lot of ROM given EhBasic and my monitor look like they'd easily fit into 16K. So 48/16 is the way forward for this build, then.
Ah, yes. WinCUPL, 22V10s and positive/negative logic - nothing there to bamboozle an electronics tyro, no? So, I already was aware of the concept of active low chip select logic and that was my intention in writing my GAL code i.e. for the pin to output a logic low for the device for the appropriate memory address. However, I wasn't aware that the way one writes the code can make a difference to the code - I assumed anything equivalent would be assembled into identical code in the GAL for example...
Code: Select all
Pin 1 = !WE
WE = CLK & !RW
and
Pin 1 = WE
!WE = CLK & !RW
...would be the same.
Taking on board some earlier comments, I will also remove my zero page VIA and settle for a more conventional memory map. So, it now looks like this...
Code: Select all
$FF00 - $FFFF ROM
$FE00 - $FEFF I/O
$C000 - $FDFF ROM
$0000 - $BFFF RAM
So, I'll go and research and think what GAL code would be needed to service that memory map. I'll post that for comment to see if I understand the nuances of what you say.
Finally, "increases PT usage" - at the risk of looking silly, what's PT?
Re: Let's start at the very beginning...
Posted: Tue Nov 19, 2024 9:15 pm
by jgharston
My (ultimate) ambition would to be to run BBC Basic on my 65C02 SBC
Then, the simplest option is RAM at $8000-$BFFF and load BBC BASIC there, which would also allow you to run something else there. 1x32K RAM, 1x16K RAM, 1x16K ROM.
Or, if you want power-on-reset into BASIC, yes, put BBC BASIC in ROM at $8000-$BFFF.
The beauty of BBC BASIC is you only need to implement the API at $FFxx, and have RAM at $0000-$07FF and BASIC will just drop into the memory map. I've done a MOS build for the BenEater and GrantSearle SBCs
link.
Re: Let's start at the very beginning...
Posted: Tue Nov 19, 2024 9:38 pm
by jgharston
So, I'll go and research and think what GAL code would be needed to service that memory map. I'll post that for comment to see if I understand the nuances of what you say.
I'm not sure how you specify GAL code, but a quick scribble gives me this:
nMEM32K = A15 ; 0000-7FFF
nMEM16K = NOT (A15 AND NOT(A14)) ; 8000-BFFF
TOP = A15 AND A14 ; C000-FFFF
pgFE = A13 AND A12 AND A11 AND A10 AND A9 AND NOT(A8)
nROM = NOT (TOP AND pgFE) ; C000-FDFF, FF00-FFFF
nIO = NOT (TOP AND NOT (pgFE)) ; FExx
In electronics, all that resolves down to loads of NANDs.
Can GALs implement 3-to-8 decoders, like a '138? In descriete ICs that's how I'd do it.