RFC - please dissect my design on a 6502 + VGA

For discussing the 65xx hardware itself or electronics projects.
ThePhysicist
Posts: 60
Joined: 17 Jun 2020

RFC - please dissect my design on a 6502 + VGA

Post by ThePhysicist »

Hello everyone

40 years ago I dreamed about building my own computer. But then buying them was so much easier. Then I saw Ben Eaters video and got really hooked. My first attempt derived from Ben's SAP1 was a success (or as my father put it "a lot of effort to calculate 1+1"). But I had to realize that expanding that system beyond the stage of "demonstration level speeds" would not really work, so I'm going for a 6502 based design as Mark2.

After about a month of research I had to realize that the biggest obstacle would be video. For modern monitors it has to be at least VGA, and I have not found any simple video chip that could be used. I don't want to use microcontrollers or FPGA. That left a solution like

https://tldr.fi/2014/09/27/zc160-vga-adapter1/
https://www.bigmessowires.com/2008/07/2 ... em-design/
or
viewtopic.php?f=4&t=3329

I especially liked the Vulcan design, although IMHO from those projects listed it's the one least documented. Unfortunately it seems to be dead in the water :( Still my design borrows heavily from Vulcan, so many thanks Brad! :D

Design goals:
VGA Video 640x480 or 800x600
no FPGA or micro crontroller
I like the Vulcan copy machine
16k part of the video buffer should be mapped to the CPU 64kb memory space
some extra memory for data (64kb is not much for data)
I also want to add a AMD coprocessor ... just for the kicks.
64 colors (2 bit per color)

I came up with this layout:
sketch1_v01.jpg
The CPU controls a number of 574 chips. I will need a number of GALs to create the selection logic. The whole address space looks like

0000-00FF Page Zero
0100-01FF Stack
0200-03FF I/O space
0400-7FFF memory
8000-BFFF 16kb window
C000-FFFF 16kb ROM
main_computer.jpg
The extra 574 register to the top right helps to map the extra memory (16kb at a time).

The Video memory is double buffered. One buffer is used by the sync counters to generate the VGA signal. The second buffer is written to in parallel either from CPU or the copy machine. That means I have a number of possible datapaths between the components, and I plan to use (a lot) 245 chips to separate each of them. Another issue is the bus width of 9 and 10 bits - that adds the need of some extra 245 chips.
video buffer and DAC.jpg
The sync signal is generated by 2 counters and a 512kb memory chip. I will need to set up correct information in the memory during initialization of the computer. The 8bits will also reset the 2 sync counters at the right time.
sync_counter.jpg
There is a copy machine. The source counter is made up of 193 chips and can be switched between 2 separate 12bit counters and a full 24bit counter. I figure a simple transistor between counter four and five should do the job, pulling the ripple input low if I need 2 separate counters.
source counter.jpg
The destination counter is made up by counter-comparator-register trios forming 2 10/9 bit counters to address the buffer ram.
target counter.jpg
This little trick should enable me to access a 64x64 (7bit by 7bit) Window of the Video memory. Adding 3x bits and 2y bits to the IPC of the 6502 should allow me to directly draw into the video buffer
64x64 mapping.jpg
64x64 mapping.jpg (24.59 KiB) Viewed 4156 times
So please tell me what you think and help me straighten up the design
thanks
Michael
No simulation survives contact with reality!
User avatar
BigEd
Posts: 11464
Joined: 11 Dec 2008
Location: England
Contact:

Re: RFC - please dissect my design on a 6502 + VGA

Post by BigEd »

Welcome Michael!

Nothing if not ambitious - anything is possible, but some things take longer to build or longer to debug. I'd recommend an incremental approach, especially for any aspect you haven't tackled before.

Also, while anything is possible, as you add complexity you are likely to be sacrificing clock speed, so if you want an unlimited complexity budget, you might not meet some specific clock speed that you had in mind. And the closer your design gets to not quite working at speed, the harder the debug. So a modest speed goal might be a good place to start.
maded2
Posts: 45
Joined: 16 Jan 2020

Re: RFC - please dissect my design on a 6502 + VGA

Post by maded2 »

very interesting design. for practical approach I personally think using a FPGA/CPLD is test out the design (I know you said you didn't want to use FPGA); otherwise it will take alot of time and effort to wire-up all the TTL chips and debug the design.
ThePhysicist
Posts: 60
Joined: 17 Jun 2020

Re: RFC - please dissect my design on a 6502 + VGA

Post by ThePhysicist »

How many chips can the WDC 6502 drive on the address bus without additional buffering? My current estimate is I need 5 GALs for the decoding logic alone.

thanks
Michael
No simulation survives contact with reality!
ThePhysicist
Posts: 60
Joined: 17 Jun 2020

Re: RFC - please dissect my design on a 6502 + VGA

Post by ThePhysicist »

maded2 wrote:
very interesting design. for practical approach I personally think using a FPGA/CPLD is test out the design (I know you said you didn't want to use FPGA); otherwise it will take alot of time and effort to wire-up all the TTL chips and debug the design.
that is my project for the next 1-2 years - time is not an issue :)
No simulation survives contact with reality!
User avatar
drogon
Posts: 1671
Joined: 14 Feb 2018
Location: Scotland
Contact:

Re: RFC - please dissect my design on a 6502 + VGA

Post by drogon »

It's a very ambitious project, but have you thought about the sort of speed the 6502 will be able to write to the video RAM? I suspect that 640x480 (at 8bits per pixel) will take far to long to clear the screen, let alone write some text to or draw a line, or scroll.

Even if you used the 65816 block-move instruction, you have 300KB of RAM to clear, so at 7 cycles per byte on a 1Mhz CPU it will take a shade over 2 seconds. It will be worse on the 6502 as it'll take more cycles.... Get the clock up to 14Mhz or more and it will obviously be much better but you're not going to get 30fps out of it...

Back in the late 70's/early 80's the consumer level display technology (ie. TV sets) mostly matched the hardware capabilities so it wasn't much an issue then - we put up with what we got - 280x192 on the Apple II taking 8KB of RAM, and a couple of years later the BBC Micro dedicated 20KB of it's 32KB RAM to the highest resolution (640x256x1bpp) and we wondered how we'd be able to write any code for it! But don't let that put you off... Especially if you can separate the video part well enough to adapt other CPUs to it in the future, should you want to - or even "FPGA" the whole video part for other retro-system to use?

Hope it goes well!

Cheers,

-Gordon
--
Gordon Henderson.
See my Ruby 6502 and 65816 SBC projects here: https://projects.drogon.net/ruby/
User avatar
GARTHWILSON
Forum Moderator
Posts: 8773
Joined: 30 Aug 2002
Location: Southern California
Contact:

Re: RFC - please dissect my design on a 6502 + VGA

Post by GARTHWILSON »

ThePhysicist wrote:
How many chips can the WDC 6502 drive on the address bus without additional buffering? My current estimate is I need 5 GALs for the decoding logic alone.

From page 5 of the 6502 primer, on logic families and timing margins:

  • You will not need bus transceivers with a CMOS 6502, especially WDC's current production W65C02S. I have done some brief tests on the W65C816S's pin drivers. Their behavior was pretty much symmetrical, able to pull up just as hard as they can pull down, unlike TTL which cannot pull up as hard. If you had to boil my test results down to approximations and treat the circuits as just a resistance, the data pin drivers acted very roughly like a SPDT switch with 50Ω in series with the common terminal (ie, the output); and the address bus pins, as a SPDT switch with 60Ω in series. I have not had the chance to test a W65C02S; but I suspect WDC used the same circuits on the '02 and the '816, which would make it much stronger than the data sheet says. The time constant of 60Ω times the capacitive load of 10 CMOS loads is around 3ns, which is less added delay than you'll get from a bus transceiver IC. Daryl Rictor had no trouble running my 4Mx8 5V 10ns SRAM module on his SBC-4 single-board computer at 12MHz with a barefoot '816 (ie, no bus transceivers), driving this module and three daughter boards at the same time. The module has 8 bussed SRAM ICs.


In the article on the differences between the NMOS and CMOS 6502's, I also added, regarding the 65c22 VIA, not the processor:

  • In a separate test on WDC's W65C22S VIA (not the W65C22N) I/O pins years earlier, I found they were each able to pull to within 0.8V of either rail with a 220-ohm resistor to the opposite rail, meaning a 19mA load, even pulling up, and give 50mA into a dead short. Rockwell's R65C22 could pull down with 100mA into a dead short, but could not pull up as hard, not being symmetrical like WDC's.
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?
ThePhysicist
Posts: 60
Joined: 17 Jun 2020

Re: RFC - please dissect my design on a 6502 + VGA

Post by ThePhysicist »

GARTHWILSON wrote:
ThePhysicist wrote:
How many chips can the WDC 6502 drive on the address bus without additional buffering? My current estimate is I need 5 GALs for the decoding logic alone.

From page 5 of the 6502 primer, on logic families and timing margins:

  • You will not need bus transceivers with a CMOS 6502, especially WDC's current production W65C02S. I have done some brief tests on the W65C816S's pin drivers. Their behavior was pretty much symmetrical, able to pull up just as hard as they can pull down, unlike TTL which cannot pull up as hard. If you had to boil my test results down to approximations and treat the circuits as just a resistance, the data pin drivers acted very roughly like a SPDT switch with 50Ω in series with the common terminal (ie, the output); and the address bus pins, as a SPDT switch with 60Ω in series. I have not had the chance to test a W65C02S; but I suspect WDC used the same circuits on the '02 and the '816, which would make it much stronger than the data sheet says. The time constant of 60Ω times the capacitive load of 10 CMOS loads is around 3ns, which is less added delay than you'll get from a bus transceiver IC. Daryl Rictor had no trouble running my 4Mx8 5V 10ns SRAM module on his SBC-4 single-board computer at 12MHz with a barefoot '816 (ie, no bus transceivers), driving this module and three daughter boards at the same time. The module has 8 bussed SRAM ICs.


In the article on the differences between the NMOS and CMOS 6502's, I also added, regarding the 65c22 VIA, not the processor:

  • In a separate test on WDC's W65C22S VIA (not the W65C22N) I/O pins years earlier, I found they were each able to pull to within 0.8V of either rail with a 220-ohm resistor to the opposite rail, meaning a 19mA load, even pulling up, and give 50mA into a dead short. Rockwell's R65C22 could pull down with 100mA into a dead short, but could not pull up as hard, not being symmetrical like WDC's.
thanks!
No simulation survives contact with reality!
ThePhysicist
Posts: 60
Joined: 17 Jun 2020

Re: RFC - please dissect my design on a 6502 + VGA

Post by ThePhysicist »

drogon wrote:
It's a very ambitious project, but have you thought about the sort of speed the 6502 will be able to write to the video RAM? I suspect that 640x480 (at 8bits per pixel) will take far to long to clear the screen, let alone write some text to or draw a line, or scroll.

Even if you used the 65816 block-move instruction, you have 300KB of RAM to clear, so at 7 cycles per byte on a 1Mhz CPU it will take a shade over 2 seconds. It will be worse on the 6502 as it'll take more cycles.... Get the clock up to 14Mhz or more and it will obviously be much better but you're not going to get 30fps out of it...

-Gordon
the main copy/clear operations happen in the video system itself based of 74F chips at 10MHz+. There is an error I discovered after posting in the data bus routing - but the idea is the 6502 writes into the 4MB video ram to set up he graphics. What is necessary is then copied via the multiple counters to either of the buffer memory. Once a buffer memory has been set up, and a VGA cycle is complete, the 6502 switches the 2 buffers.

At least that's the theory ......
No simulation survives contact with reality!
ThePhysicist
Posts: 60
Joined: 17 Jun 2020

Re: RFC - please dissect my design on a 6502 + VGA

Post by ThePhysicist »

So I've completed the first step, and wanted to report about my experiences :)

I started to layout a test board with enough connections to add the video systems step by step later.
cpu_board_layout_p2_v01_0200607.jpg
cpu_board_layout_p1_v01_0200607.jpg
cpu_board_v01_0200607.jpg
PCBway delivered very quickly:
cpu_board_v1_20200706.jpg
and after 2 weeks of debugging v1 was running (printing to LCD display and communicating over serial line with PC at 500kHz)
mark01_v1_20200706.jpg
The breadboard contains an external timing circuit to single step or up to 100Hz, as well as an LCD display (connected to VIA1) and the GAL organizing the memory layout. The board currently is only half populated, I could add one ROM, one RAM, one VIA and one ACIA chip in the future. The Arduino is only a cheap logic analyzer.

So what have I learned?
  • bringing 2 chip select lines to the external control board is really stupid (duh, now fixed on backside with wires :P)
    bringing all RW signals out to control board is probably worse (double duh, now also fixed on backside with wires)
    the reach of a 6 month old is greater than you can imagine, and you will debug for 2 hours until you find the missing resistor
    there is an irresistible force drawing 3 year old boys to wires. He will "look" with his fingers, the wires will come out - so naturally the boy will put them back (out of order) for another 2 hours of debugging....
    those chips are pretty hardy - if you think you ruined one of them, think again and check your layout. After some debugging you'll still think the chip is broken .... so THINK AGAIN (and read this forum; thanks Garth for viewtopic.php?f=4&t=4346#p49340)
    there is a 99% chance the USB-serial cables you have at home are not compatible with TTL serial from a 6551 (though the cables to connect to an Arduino work nicely)
    no matter how simple a connection, if you have 2 options you will connect them in the wrong order and then go bug hunting in the wrong places
    a simple logic probe is a good friend
    using an Arduino to watch address and data lines brings a lot of insight what the CPU is doing
lots of fun :)
Last edited by ThePhysicist on Mon Jul 06, 2020 4:31 pm, edited 1 time in total.
No simulation survives contact with reality!
User avatar
Dr Jefyll
Posts: 3526
Joined: 11 Dec 2009
Location: Ontario, Canada
Contact:

Re: RFC - please dissect my design on a 6502 + VGA

Post by Dr Jefyll »

ThePhysicist wrote:
the reach of a 6 month old is greater than you can imagine
[...]
there is an irresistible force drawing 3 year old boys to wires
Future forum members! :mrgreen:
In 1988 my 65C02 got six new registers and 44 new full-speed instructions!
https://laughtonelectronics.com/Arcana/ ... mmary.html
ThePhysicist
Posts: 60
Joined: 17 Jun 2020

Re: RFC - please dissect my design on a 6502 + VGA

Post by ThePhysicist »

So baby steps progress, but still progress!
cpu_board_v01_20200717.jpg
I put LCD and GAL on little PCBs and it's still working as expected at 500kHz. At that point I decided I need to look at a software pipeline. I need at minimum a little monitor and the ability to peek and poke around on the address bus. Probably most people here will "yell" at me - for not using pure assembler :P

But while I have some 35 years experience in c-programming, my assembler is pretty thin - and because days might pass between some time developing code, I would quickly forget my plans and start again. So c it is, and I came down with 4 alternatives

a) x86-to-6502 translator by Lefticus (https://github.com/lefticus/x86-to-6502/) - I really like the idea, modern compiler optimizations are really good .... but it failed to translate my simple monitor program. Tried it with a dozen different compilers, but no luck. As Lefticus writes correctly, that program is more of a case study then a full developed translator.
b) WDC c-compiler - I had so high hopes for it, but again it failed the basic test. Crushed with a memory error on my simple code piece. So not an option either
c) CC65 - the first one to actually compile the program.
d) gcc 6502 port found here https://github.com/itszor/gcc-6502-bits - also passed the basic test. And produced smaller code (1100 vs 1600 bytes). So for the moment this will be my plan to use in my first iteration of the monitor.
Last edited by ThePhysicist on Sat Jul 18, 2020 4:08 pm, edited 1 time in total.
No simulation survives contact with reality!
User avatar
BigEd
Posts: 11464
Joined: 11 Dec 2008
Location: England
Contact:

Re: RFC - please dissect my design on a 6502 + VGA

Post by BigEd »

There's a gcc port found here too, formerly known as puppeh's but now itszor's:
https://github.com/itszor
ThePhysicist
Posts: 60
Joined: 17 Jun 2020

Re: RFC - please dissect my design on a 6502 + VGA

Post by ThePhysicist »

BigEd wrote:
There's a gcc port found here too, formerly known as puppeh's but now itszor's:
https://github.com/itszor
That's what I'm going to use - I fixed the URL in my post. You have to use https://github.com/itszor/gcc-6502-bits, not https://github.com/itszor/gcc-6502. The later is the port, but cannot be compiled directly. gcc-6502-bits compiled without issues on Cygwin with a gcc 7, and provides tinylibc as well.

One problem - it has support for BCC, c64 and the "integrated" semi65x simulator - but self build systems are a different topic altogether. It also uses the cc65 linker (ld65), which means I'm banging my head now against the ld65 .cfg file (for memory layout). Does anyone know a good howto on the topic? The original documentation is a bit ... cumbersome. I prefer explanations along simple examples :)
No simulation survives contact with reality!
ThePhysicist
Posts: 60
Joined: 17 Jun 2020

Re: RFC - please dissect my design on a 6502 + VGA

Post by ThePhysicist »

Two steps back, one step forward ....

So I wrote a simple monitor program in C with a bit of assembler startup code. Naturally your first attempt does not produce anything, so for debugging I went looking for a simulator and was very happy to find https://github.com/sethm/symon, because it also simulates a 6551 chip! Then I run into a problem with understanding the assembler code that my toolchain (6502-gcc and ld65) produced. So I wrote a small python program that combines the annotated assembly produced by the gcc with the actual addresses created by the linker. That would result in something like

Code: Select all

                                                   	.export int4_to_hexchar
                                                   int4_to_hexchar:
                                                   ; frame size 0, pretend size 0, outgoing size 0
                                                   ;# firmware_v01_monitor_and_lcd_cc65.c:118:     if(a>9)
C0DD A9 09            lda     #$09                 	lda #$09	;# tmp98,
C0DF C5 04            cmp     $04                  	cmp _r0		;# tmp98, a
C0E1 A9 00            lda     #$00                 	lda #$00	;# tmp98,
C0E3 E5 05            sbc     $05                  	sbc _r1		;# a
C0E5 50 02            bvc     LC0E9                	bvc L@9		;#
C0E7 49 80            eor     #$80                 	eor #$80	; negate top bit
                                                   L@9:
                                                   ;# firmware_v01_monitor_and_lcd_cc65.c:119:         return('A'-9 + a);
C0E9 08               php                          	php
C0EA A5 04            lda     $04                  	lda _r0		;# <retval>, a
C0EC 28               plp                          	plp
                                                   ;# firmware_v01_monitor_and_lcd_cc65.c:118:     if(a>9)
C0ED 10 06            bpl     LC0F5                	bpl L@7		;#
                                                   ;# firmware_v01_monitor_and_lcd_cc65.c:119:         return('A'-9 + a);
C0EF 18               clc                          	clc
C0F0 69 38            adc     #$38                 	adc #$38	;#
                                                   L@10:
                                                   ;# firmware_v01_monitor_and_lcd_cc65.c:121:         return('0' + a);
C0F2 85 04            sta     $04                  	sta _r0		;# <retval>, <retval>
                                                   ;# firmware_v01_monitor_and_lcd_cc65.c:122: }
C0F4 60               rts                          	rts
                                                   L@7:
                                                   ;# firmware_v01_monitor_and_lcd_cc65.c:121:         return('0' + a);
C0F5 18               clc                          	clc
C0F6 69 30            adc     #$30                 	adc #$30	;#
C0F8 4C F2 C0         jmp     LC0F2                	jmp L@10		;#
for a simple c-code:

Code: Select all

/* convert 4bit int to hex char */
const char int4_to_hexchar(int a)
{
    if(a>9)
        return('A'-9 + a);
    else
        return('0' + a);
}
Honestly, I had to swallow hard when I saw the overhead c created. Still I started to debug away, found a couple of minor errors in logic (for instance the compiler had optimized away "unnecessary" loops), until I hit a wall. Possibly I'm too stupid...but no matter what I did, the program simply did not echo back the characetrs I sent over serial. The c-code I thought was pretty straightforward:

Code: Select all

const char acia_getc()
{
    asm("\nwait_for_receive:\n\tlda " STR_ACIA_STATUS ";\n\tand #" XSTR(ACIA_STATUS_RX_FULL)";\n\tbeq wait_for_receive;");

    return(ACIA_DATA[0]);
}

/* read a '\x0a' terminated string from ACIA1 */
void acia_gets()
{
    char c;
    *ACIA_INDEX=0;
    while(c=acia_getc() != '\x0d')
    {
        RES[0] = c;
        acia_putc(RES[0]);
.....
but the compiler gave me was

Code: Select all

                                                   acia_getc:
                                                   wait_for_receive:
C238 AD 01 88         lda     $8801                	lda $8801;
C23B 29 08            and     #$08                 	and #1 << 3;
C23D F0 F9            beq     LC238                	beq wait_for_receive;
                                                   ;# firmware_v01_monitor_and_lcd_cc65.c:179: }
C23F AD 00 88         lda     $8800                	lda $8800
C242 85 04            sta     $04                  	sta _r0
C244 60               rts                          	rts


C269 20 38 C2         jsr     LC238                	jsr acia_getc
                                                   ;# firmware_v01_monitor_and_lcd_cc65.c:186:     while(c=acia_getc() != '\x0d')
C26C A5 04            lda     $04                  	lda _r0
C26E C9 0D            cmp     #$0D                 	cmp #$0d
C270 D0 49            bne     LC2BB                	bne L@35
.....
                                                   L@35:
                                                   ;# firmware_v01_monitor_and_lcd_cc65.c:188: 	RES[0] = c;
C2BB A9 01            lda     #$01                 	lda #$01
C2BD 8D 00 03         sta     $0300                	sta $0300
                                                   ;# firmware_v01_monitor_and_lcd_cc65.c:189:         acia_putc(RES[0]);
C2C0 85 04            sta     $04                  	sta _r0
C2C2 20 01 C2         jsr     LC201                	jsr acia_putc
So a character is received in $8800 (ACIA data port), stored in _r0 aka $0004, the subroutine returns, loads _r0 into the ACC, compares with $0d, jumps to L@35, then loads 1 into ACC and stores it into _r0 before echoing the character back? Do I understand that right??? (I think I do, I pondered over that for 2 hours....)

So I abandoned gcc at that point. I seemed easier to start learning 6502 assembly for real :)
3 days later I had a working monitor, that can display and modify memory locations. So back to the hardware now to layout my first parts of the VGA card!
No simulation survives contact with reality!
Post Reply