6502.org Forum  Projects  Code  Documents  Tools  Forum
It is currently Fri Nov 22, 2024 10:58 am

All times are UTC




Post new topic Reply to topic  [ 19 posts ]  Go to page 1, 2  Next
Author Message
PostPosted: Thu Jun 09, 2022 8:24 pm 
Offline

Joined: Sat Oct 09, 2021 11:21 am
Posts: 718
Location: Texas
Hello everyone!

While I am waiting in between the Acolyte project (here viewtopic.php?f=4&t=7154) I went back to an idea I had back a while ago. Inspired by Jeff's "illegal instruction" trick (here viewtopic.php?f=4&t=1945) I decided to build an ultra-minimal 6502 build that still includes VGA. Attached are schematics. It only uses 10 ICs! I have other versions that only use 8 ICs, wow! This includes the 6502, RAM, ROM, and the rest are 74HC logic chips.

To get this to work, I'm using a style called "race the beam", similar to what the Atari 2600 does. Basically the 6502 has to manually draw each pixel on the screen itself, leaving little time for anything else. This build would do this through Jeff's "illegal instructions". Each $_3 instruction's high nibble is pixel data, and each $_B instruction's high nibble contains sync signal data.

Some stats:
W65C02 running at 6.29 MHz (1/4 of the 25.175 MHz VGA clock speed)
$0000-$7FFF = 32KB of RAM, but two banks totals to 64KB RAM
$8000-$BFFF = 16KB unused for further expansion
$C000-$FFFF = 16KB ROM
320x240 effective screen resolution with 4 colors.
8 tactile buttons for input through the SOB line on the 6502.

The idea is that this is a "handheld" gaming console, controller contained in the console itself. Just plug in USB for 5V power and VGA to your favorite monitor, and off you go! It can also accept 16KB ROM cartridges for additional games, or perhaps a VIA with additional I/O support. The expansion port (a standard 2x20 pin header) includes all of the important 6502 lines with some extra VGA clock data included.

Some things I'm discovering is that I will have to be extremely precise with my programming. I will have very few cycles for actual game code, since the processor is drawing the screen manually. Also, nearly all of the 64KB of RAM will be used up just as Video RAM, only leaving some margins for variables and such.

I won't say this is a *good* idea. It's not a beginner's build by any means. It's gimmicky at times and the software side will be absolutely crazy! But it would be neat to see a full 6502 build with fairly good VGA output using only 10 chips! If you don't care for the tactile buttons and are ok with monochrome, cut it down to 8 chips!

The only problem I see is that I'm using 70ns FlashROM, and running 6502 at 6.29 MHz will barely give it the amount of time it needs. Though I'm only using a single 74HC00 for glue logic, and don't the address and data buses come online before PHI2 goes high? Anyways, it's pushing the margins with the ROM, but everything else should be smooth cruisin'.

I don't know when I'll be able to actually build this, but I think I'll try to program something for it first. See just how terrible a mess I've made and perhaps "turn around don't drown".

Thoughts? Comments?

Thanks everyone!

Chad


Attachments:
Schematic-Mono.pdf [255.75 KiB]
Downloaded 116 times
Schematic-Color.pdf [258.77 KiB]
Downloaded 116 times
Top
 Profile  
Reply with quote  
PostPosted: Thu Jun 09, 2022 11:18 pm 
Offline

Joined: Fri Dec 21, 2018 1:05 am
Posts: 1117
Location: Albuquerque NM USA
My experience with beam racing is software generated HSYNC and VSYNC must be exactly the same, all the time. HSYNC must be generated even during the vertical blanking period. The software generation became very challenging. I eventually added a 10-bit counter in CPLD to generate HSYNC in hardware and the problem became significantly easier.
Bill


Top
 Profile  
Reply with quote  
PostPosted: Thu Jun 09, 2022 11:21 pm 
Offline
User avatar

Joined: Tue Jul 17, 2018 9:58 am
Posts: 107
Location: Long Island, NY
Very interesting! At the very least it should be straightforward to write a converter that turns an image file into a program for this computer.

Adding a VIA could make it easier to manage the timing without having to worry that every branch of your game logic is the same number of cycles.


Top
 Profile  
Reply with quote  
PostPosted: Fri Jun 10, 2022 3:37 am 
Offline
User avatar

Joined: Fri Aug 03, 2018 8:52 am
Posts: 746
Location: Germany
The FLASH you're using is the same one as in my own SBC, and that one ran up to +10MHz without any wait states, so i'm pretty sure that the timings with it are less tight than you might think.

as an idea, couldn't you copy the contents of the ROM into the RAM below and then use one of the unused opcodes to activate a JK-FF or similar to then disable the ROM, so you can just execute from RAM?
you could also use the same FF to then bump up the CPU speed to 12.5MHz, so you got more time to execute actual code between keeping the display alive


Top
 Profile  
Reply with quote  
PostPosted: Fri Jun 10, 2022 11:14 am 
Offline

Joined: Sat Oct 09, 2021 11:21 am
Posts: 718
Location: Texas
Proxy wrote:
The FLASH you're using is the same one as in my own SBC, and that one ran up to +10MHz without any wait states, so i'm pretty sure that the timings with it are less tight than you might think.

as an idea, couldn't you copy the contents of the ROM into the RAM below and then use one of the unused opcodes to activate a JK-FF or similar to then disable the ROM, so you can just execute from RAM?
you could also use the same FF to then bump up the CPU speed to 12.5MHz, so you got more time to execute actual code between keeping the display alive


That would be good for sure, but it would add more chips, which on this build I'm trying to minimize. Still, your use of the FlashROM at 10MHz is reassuring! Thank you Proxy.

Agumander wrote:
Very interesting! At the very least it should be straightforward to write a converter that turns an image file into a program for this computer.

Adding a VIA could make it easier to manage the timing without having to worry that every branch of your game logic is the same number of cycles.


A VIA would make a *ton* of things easier, indeed! :)

plasmo wrote:
My experience with beam racing is software generated HSYNC and VSYNC must be exactly the same, all the time. HSYNC must be generated even during the vertical blanking period. The software generation became very challenging. I eventually added a 10-bit counter in CPLD to generate HSYNC in hardware and the problem became significantly easier.
Bill


Ah I had forgotten about that! Thanks for the link Bill. Yes, generating the Sync signals is tough, especially the H-Sync like you said. While I'm drawing the picture, it's whatever. But as soon as I want to actually code, it gets in the way. I was experimenting with adding an additional counter to trigger /NMI or something, but then I'm adding more chips and I guess I'm trying hard to shy away from that. Complicated software is 'ok' enough, as I'm trying to minimize chip count here. Good considerations though, thank you!

Again, I don't know when I will be able to implement this contraption. I've got multiple projects now, and life demands as well. Just wanted to see what is possible. Thanks everyone!

Chad


Top
 Profile  
Reply with quote  
PostPosted: Sat Jun 11, 2022 11:17 am 
Offline

Joined: Tue Jul 05, 2005 7:08 pm
Posts: 1043
Location: near Heidelberg, Germany
Maybe it is against the goal of minimum chip count but why not use two 6502 on opposite clock phases?
Add a second 6502, let one just do the display and the other does the work?

_________________
Author of the GeckOS multitasking operating system, the usb65 stack, designer of the Micro-PET and many more 6502 content: http://6502.org/users/andre/


Top
 Profile  
Reply with quote  
PostPosted: Sat Jun 11, 2022 12:07 pm 
Offline
User avatar

Joined: Fri Aug 03, 2018 8:52 am
Posts: 746
Location: Germany
fachat wrote:
Maybe it is against the goal of minimum chip count but why not use two 6502 on opposite clock phases?
Add a second 6502, let one just do the display and the other does the work?

i always wondered how you would go about seperating the CPUs in a system like that.
because both CPUs are sitting on the same exact bus except on different clock phases, wouldn't they just execute the same exact code? like how would one CPU know if it's the low or high clock one?

hmm, thinking about it a bit more... you could hook up the Clock signal to an Address line on the ROM, so it's 0 when the high clock CPU reads from it, and 1 when the low clock CPU reads from it.
allowing for 2 seperate ROM images for both CPUs in the same chip and at no additional logic cost.
IO for the low clock CPU would use the falling edge like normal, but the high clock CPU's IO would use the rising edge instead.
also, how would the stack work with 2 CPUs? since you have 2 independant Stack Pointers it's possible for one CPU to screw up the stack of the other.
so the CPU in charge of the Video display would need to function without using the stack or zeropage at all. unless you want to reserve some space for both which would leave less for the main CPU.

and lastly, you could bring the chip count lower again by replacing the NAND IC and PLD with a single small CPLD like an ATF1502 or 04.


Top
 Profile  
Reply with quote  
PostPosted: Sat Jun 11, 2022 12:16 pm 
Offline

Joined: Sat Oct 09, 2021 11:21 am
Posts: 718
Location: Texas
fachat wrote:
Maybe it is against the goal of minimum chip count but why not use two 6502 on opposite clock phases?
Add a second 6502, let one just do the display and the other does the work?


I'd rather add a VIA for the board space, but that does seem interesting.

Proxy wrote:
hmm, thinking about it a bit more... you could hook up the Clock signal to an Address line on the ROM, so it's 0 when the high clock CPU reads from it, and 1 when the low clock CPU reads from it.allowing for 2 seperate ROM images for both CPUs in the same chip and at no additional logic cost.


THAT is brilliant! Not exactly for multiple CPU's, but like on my Acolyte board, I use a ROM to generate the H-Sync and V-Sync signals. I could then use extra ROM to generate those signals automatically. That would simplify the coding for sure. I might need to add an external counter, hm, maybe.

Proxy wrote:
and lastly, you could bring the chip count lower again by replacing the NAND IC and PLD with a single small CPLD like an ATF1502 or 04.


I don't have any PLD's on this? :) Though I respect those who use CPLD's and such, I'm just not in the market for that right now.

Thank you Proxy, I'll be thinking this over some.

Chad


Top
 Profile  
Reply with quote  
PostPosted: Sat Jun 11, 2022 12:32 pm 
Offline

Joined: Tue Jul 05, 2005 7:08 pm
Posts: 1043
Location: near Heidelberg, Germany
Proxy wrote:
fachat wrote:
Maybe it is against the goal of minimum chip count but why not use two 6502 on opposite clock phases?
Add a second 6502, let one just do the display and the other does the work?

i always wondered how you would go about seperating the CPUs in a system like that.
because both CPUs are sitting on the same exact bus except on different clock phases, wouldn't they just execute the same exact code? like how would one CPU know if it's the low or high clock one?

hmm, thinking about it a bit more... you could hook up the Clock signal to an Address line on the ROM, so it's 0 when the high clock CPU reads from it, and 1 when the low clock CPU reads from it.
allowing for 2 seperate ROM images for both CPUs in the same chip and at no additional logic cost.
IO for the low clock CPU would use the falling edge like normal, but the high clock CPU's IO would use the rising edge instead.


The opposite clock phase approach has been done a number of times before.

For example all the Commodore Dual Disk drives had two 650x on opposite clock phases. Databus is not an issue (but not working with the 65816) as the 6502 only drives Dx on phase 2. Any shared RAM needs to have the address lines switched between the two CPUs (if the CPU does not have BE signal to decouple addresses).
Note the VIA and maybe other IO cannot be on the shared address space. Or you'd have to double the IO clock. The 6522 decodes registers during phi1 so needs stable addresses anyway already before phi2.

Edit: see eg here http://www.6502.org/users/andre/petinde ... index.html or here http://www.6502.org/users/andre/csa/copro/index.html

_________________
Author of the GeckOS multitasking operating system, the usb65 stack, designer of the Micro-PET and many more 6502 content: http://6502.org/users/andre/


Top
 Profile  
Reply with quote  
PostPosted: Sat Jun 11, 2022 1:30 pm 
Offline
User avatar

Joined: Fri Dec 11, 2009 3:50 pm
Posts: 3367
Location: Ontario, Canada
Proxy wrote:
because both CPUs are sitting on the same exact bus except on different clock phases, wouldn't they just execute the same exact code?
The solution is for the Program Counters of the two CPUs contain different values. You'd want this to take effect at reset, or very soon after.

Probably the most flexible solution is to somehow arrange for two different sets of vectors to appear, one for each CPU. Various options exist, but here's what I came up with about 40 years ago when I built a dual 6809 SBC.
Quote:
In order to provide vectors which are specific to each CPU, one CPU has the top portion of its address map slightly distorted. Whenever that CPU accesses the top 512 bytes in the 64K range, an XOR gate in address line A8 inverts that signal before it gets sent to RAM. The effect is to exchange the 256-byte page at $FF00 with the page at $FE00, but only from one CPU's point of view.

Besides diddling the vectors, there are other ways of getting the Program Counters of the two CPUs to contain different values. It's a fun challenge to play with! :)

Shortly after reset, one CPU could receive an interrupt that the other CPU doesn't -- an interrupt from which it never returns (it would just clean up the stack and continue on its way). Or, with the '02 and 'C02, the /SO input could be employed in a similar way, with one CPU receiving stimulus on this pin shortly after reset and the other cpu not. (Both would execute code that test the overflow flag, with each CPU getting a different result.)

Or, finally, if each CPU has its own IO space, then it would probably be easy to write code that has a peek and does a conditional branch based on which IO space it's seeing. Indeed, the same idea would work with shared IO space if one of the input bits gets driven by one CPU's Phi2.

-- Jeff

_________________
In 1988 my 65C02 got six new registers and 44 new full-speed instructions!
https://laughtonelectronics.com/Arcana/ ... mmary.html


Top
 Profile  
Reply with quote  
PostPosted: Sat Jun 11, 2022 4:03 pm 
Offline

Joined: Tue Jul 05, 2005 7:08 pm
Posts: 1043
Location: near Heidelberg, Germany
I think the easiest way would be to use phi2 as address input to the ROM. This way half the ROM would be one CPU, the other half the other CPu. You could program any type of different software

_________________
Author of the GeckOS multitasking operating system, the usb65 stack, designer of the Micro-PET and many more 6502 content: http://6502.org/users/andre/


Top
 Profile  
Reply with quote  
PostPosted: Sat Jun 11, 2022 5:09 pm 
Offline
User avatar

Joined: Fri Dec 11, 2009 3:50 pm
Posts: 3367
Location: Ontario, Canada
fachat wrote:
I think the easiest way would be to use phi2 as address input to the ROM.
You're quite right -- that is the easiest way. And I should have mentioned that.

Still, different solutions suit different circumstances. And "easy" doesn't always win the prize.

-- Jeff

_________________
In 1988 my 65C02 got six new registers and 44 new full-speed instructions!
https://laughtonelectronics.com/Arcana/ ... mmary.html


Top
 Profile  
Reply with quote  
PostPosted: Sat Jun 11, 2022 5:20 pm 
Offline
User avatar

Joined: Fri Aug 03, 2018 8:52 am
Posts: 746
Location: Germany
sburrow wrote:
I don't have any PLD's on this? :) Though I respect those who use CPLD's and such, I'm just not in the market for that right now.

oh sorry i somehow confused this with another board, multiple schematics got scrambled in my head.

fachat wrote:
I think the easiest way would be to use phi2 as address input to the ROM. This way half the ROM would be one CPU, the other half the other CPu. You could program any type of different software

yea, that's exactly what i suggested in my previous post...
though i also like Dr Jefyll's idea of using the ~SO pin. but you would need to use some kind of counter so that the CPUs have enough time to execute a CLV Instruction after powerup/reset.

a bit of logic could be used to check if the upper 7 bits of the address bus are 0, if they are then use the Clock on an unused Address line on the RAM. if they aren't, just pull that line to GND.
this basically seperates Page 0 and 1 of both CPUs, but keeps the rest of RAM shared between them.
and i'd say it would be simplier to avoid shared IO (since you already got shared RAM). so anything for the main CPU would just work fine, but anything for the Secondary CPU needs the clock input of any IO device inverted.


Top
 Profile  
Reply with quote  
PostPosted: Sat Jun 11, 2022 5:29 pm 
Offline

Joined: Tue Jul 05, 2005 7:08 pm
Posts: 1043
Location: near Heidelberg, Germany
Proxy, Sorry I was onbthe road forgot to give you credit. Mea culpa

_________________
Author of the GeckOS multitasking operating system, the usb65 stack, designer of the Micro-PET and many more 6502 content: http://6502.org/users/andre/


Top
 Profile  
Reply with quote  
PostPosted: Sat Jun 11, 2022 6:33 pm 
Offline
User avatar

Joined: Fri Aug 03, 2018 8:52 am
Posts: 746
Location: Germany
fachat wrote:
Proxy, Sorry I was onbthe road forgot to give you credit. Mea culpa

eh, no worries.

on a different note, in your schematic you already said that you likely won't be able to do color due to memory constraints, so why not embrase the monochrome style?
you can connect the R, G, and B channels together (or use some jumpers to allow you to manually select 2 colors) and remove one of the shift registers.
this also means you would have 4 pixels of data encoded into every $_3 opcode instead of only 2.
though I'd assume it would still be a complete pain to work with graphics data in a format like that.

on the more ridiculous side, you could stack 40 8-bit Shift Registers in series, which is enough for a whole row of pixels on the screen (assuming 320x240). every H-Blank you would load 40 bytes of data into it, and then while it's drawing you got lots of time to do work. :lol:


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

All times are UTC


Who is online

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