A simple 6502 computer (doesn't work though)

For discussing the 65xx hardware itself or electronics projects.
jgroth
Posts: 60
Joined: 15 Sep 2016
Location: UK

A simple 6502 computer (doesn't work though)

Post by jgroth »

I wanted to build a small, simple 6502 computer with as few components as possible and found Garth Wilson's address decoder in his 6502 primer. My computer has 32k ROM, 16k RAM and a 65C22S for I/O. There is also a 74HCT74 and a TL7705.
simple6502.pdf
(69.88 KiB) Downloaded 161 times
If I understand Garth's primer correctly the ROM is selected with A15 goes high (A15 is inverted and OE and CS goes low so ROM is selected).
The RAM is selected when the clock is high A15 is low and A14 is low (address $0000-$3fff).
The VIA is selected when the A15 is low, A14 is high and A13 is high.
R/W is connected to W (pin 27 on the RAM).

Have I got this correct?

I wrote a small program that put PA and PB first high then low then high again with a delay of ca 5 sec in between. The program works in another computer and so does all other ICs but that computer has a modified version of 8Bit address decoder.
In my minimalist computer nothing happens.

Code: Select all

;;;
;; coldstart - initialises all hardware
;; power up and reset procedure.
;;;
coldstart: .block
        sei                     ;Turn off interrupts
        cld                     ;Make sure MPU is in binary mode
        ldx  #0
l1:
        stz  0,x                ;zero ZP
        dex
        bne  l1
        dex                     ;effectively ldx #$ff
        txs                     ;Initialise stack register
        jsr via_init
        cli
;;;
;; test code of CPLD's decoding part.
;; Blink a LED every second connected to PA0 on VIA.
;;;
        lda #$ff
        sta via1ddra        ; set all PA pins to be outputs
        sta via1ddrb        ; set all PB ping to be outputs
loop:
        lda #$ff
        sta via1ra
        sta via1rb
        ; bra loop
        jsr delay
        lda #0
        sta via1ra
        sta via1rb
        jsr delay
        bra loop

delay: .proc
        ldx #$20
loop1:
        jsr one_sec_delay
        dex
        bne loop1
        rts
        .pend

one_sec_delay: .proc
        phx
        phy
        ldx #$ff
loop1:
        ldy #$ff
loop2:
        dey
        bne loop2
        dex
        bne loop1
        ply
        plx
        rts
        .pend
Last edited by jgroth on Thu Jun 20, 2019 8:34 pm, edited 1 time in total.
User avatar
GARTHWILSON
Forum Moderator
Posts: 8773
Joined: 30 Aug 2002
Location: Southern California
Contact:

Re: A simple 6502 computer (doesn't work though)

Post by GARTHWILSON »

I see the word "Attachment" there, but it does not seem to be attached.

What do you have the VIA addresses set to in your equates? And what's in subroutine via_init?

BTW, the CMOS processor always comes out of reset with the I flag set and the D flag clear. (I see you're using the CMOS processor. The NMOS won't necessarily come out of reset with D clear, but the CMOS does.) Also, you can omit the LDA #0 in the lda #0, sta via1ra, sta via1rb sequence and replace the STA's with STZ. There's no need to zero-out ZP either. There's nothing wrong with your code there; these are only suggestions for shortening it. Edit: actually there's more that could be done to shorten it, but I'll leave it alone now.
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?
User avatar
BigEd
Posts: 11464
Joined: 11 Dec 2008
Location: England
Contact:

Re: A simple 6502 computer (doesn't work though)

Post by BigEd »

What kind of diagnostic tools do you have? First thing to check is that the CPU comes out of reset, reads the reset vector, and jumps to the start of your code. You might be able to check this is working just by putting appropriate code in your ROM and checking the frequency of the SYNC output. Or by going into a tight loop and reading off all the high order bits of the address bus.
jgroth
Posts: 60
Joined: 15 Sep 2016
Location: UK

Re: A simple 6502 computer (doesn't work though)

Post by jgroth »

GARTHWILSON wrote:
I see the word "Attachment" there, but it does not seem to be attached.
There should be a file attached now.
GARTHWILSON wrote:
What do you have the VIA addresses set to in your equates? And what's in subroutine via_init?
This piece of code:

Code: Select all

        via1base = $6000
        ;;;via1base = $7fc0
        via1rb   = via1base+0     ; write output register b, read input register b
        via1ra   = via1base+1     ; write output register a, read input register a
        via1ddrb = via1base+2     ; data direction register b
        via1ddra = via1base+3     ; data direction register a
        via1t1cl = via1base+4     ; write t1 low-order latches, read t1 low-order counter
        via1t1ch = via1base+5     ; t1 high-order counter
        via1t1ll = via1base+6     ; t1 low-order latches
        via1t1lh = via1base+7     ; t1 high-order latches
        via1t2cl = via1base+8     ; write t2 low-order latches, read t2 low-order counter
        via1t2ch = via1base+9     ; t2 high-order counter
        via1sr   = via1base+$a    ; shift register
        via1acr  = via1base+$b    ; auxiliary control register
        via1pcr  = via1base+$c    ; peripheral control register
        via1ifr  = via1base+$d    ; interrupt flag register
        via1ier  = via1base+$e    ; interrupt enable register
        via1ranh = via1base+$f    ; same as reg a except no "handshake"

        via1ifrirq = %00000111
        via1timer1mask = %00000110
        via1timer2mask = %00000101

        via_timer2_irq_mask = %00100000

via1_init_table
        .byte   $00     ; PRB
        .byte   $00     ; PRA
        .byte   $00     ; DDRB
        .byte   $00     ; DDRA
        .byte   $00     ; T1CL
        .byte   $00     ; T1CH
        .byte   $00     ; T1LL
        .byte   $00     ; T1LH
        .byte   $00     ; T2CL
        .byte   $00     ; T2CH
        .byte   $00     ; SR
        .byte   $00     ; ACR
        .byte   $00     ; PCR
        .byte   $7F     ; IFR
        .byte   $7F     ; IER
n_via1_registers=*-via1_init_table-1

via_init: .proc
        jsr  via1_init
        rts
        .pend

via1_init: .proc
        ldx  #n_via1_registers
next:
        lda via1_init_table,x
        sta via1base,x
        dex
        bpl  next
        rts
        .pend
Quote:
BTW, the CMOS processor always comes out of reset with the I flag set and the D flag clear. (I see you're using the CMOS processor. The NMOS won't necessarily come out of reset with D clear, but the CMOS does.) Also, you can omit the LDA #0 in the lda #0, sta via1ra, sta via1rb sequence and replace the STA's with STZ. There's no need to zero-out ZP either. There's nothing wrong with your code there; these are only suggestions for shortening it. Edit: actually there's more that could be done to shorten it, but I'll leave it alone now.
Please do note that this code is just a small part of a bios and monitor I'm writing for another SBC that works just fine with the code above, ie I know the code works and yes it can be optimised but what is the point. It is not code I'm going to keep, it just proves that the RAM/ROM and VIA are being decoded correctly. That other SBC is using 8Bit's (Daryl Ritcher) decoder which uses three 74xx. I thought it would be interesting to build something so minimalist that it only takes one NAND to address decode everything.
jgroth
Posts: 60
Joined: 15 Sep 2016
Location: UK

Re: A simple 6502 computer (doesn't work though)

Post by jgroth »

BigEd wrote:
What kind of diagnostic tools do you have? First thing to check is that the CPU comes out of reset, reads the reset vector, and jumps to the start of your code. You might be able to check this is working just by putting appropriate code in your ROM and checking the frequency of the SYNC output. Or by going into a tight loop and reading off all the high order bits of the address bus.
Well, I've got two logic probes and a 4 channel 'scope. But I think I would need a single stepper to do what you are proposing properly I think (I think I saw one in Garth's primer or did I dream that). The code how ever works just fine in another SBC I've built that is using Daryl Ricter's decoder. Only difference is the VIA base is $7FE0 on that computer.
So unless I've have misinterpreted Garth's decoder completely or wired something wrong it should work. Or am I missing something?
The schematic should now be attached to my original message.
rwiker
Posts: 294
Joined: 03 Mar 2011

Re: A simple 6502 computer (doesn't work though)

Post by rwiker »

It looks like you have the wrong address for the VIA in your test program: $6000 is three quarters of the way through the RAM address space.

If the VIA is selected by A15*/A14*A13, then this corresponds to the address range $a000-$bfff. In that case, $a000 should be a good choice for the VIA base address.
User avatar
BigEd
Posts: 11464
Joined: 11 Dec 2008
Location: England
Contact:

Re: A simple 6502 computer (doesn't work though)

Post by BigEd »

Edit: crossed in post. Maybe rwiker has spotted the error.

It's because something might be wrong - and something is wrong - that it could be worth starting with basics, like whether it's acting as a computer and running your code. Could you have shorted or swapped address or data? Could you have an open on your glue logic?

A logic probe and scope should be enough. By setting up tight loops and jumping to them, you can control the frequency of SYNC in the loop. If SYNC has the right frequency, then you succeeded in getting to the loop. You can use the logic probe to check that (almost all) of the address bus is where it should be.

A NOP test is another way to check something about your setup: whether the CPU is clocked and is coming out of reset.
User avatar
GARTHWILSON
Forum Moderator
Posts: 8773
Joined: 30 Aug 2002
Location: Southern California
Contact:

Re: A simple 6502 computer (doesn't work though)

Post by GARTHWILSON »

rwiker wrote:
It looks like you have the wrong address for the VIA in your test program: $6000 is three quarters of the way through the RAM address space.

If the VIA is selected by A15*/A14*A13, then this corresponds to the address range $a000-$bfff. In that case, $a000 should be a good choice for the VIA base address.
The ROM uses all of 8000-FFFF. The RAM uses 0000-3FFF. You can write to it at 4000-7FFF, but you cannot read it back, because A14 keeps its output enable false in that range. It's kind of a sneaky way to get another chip-select input on the RAM, using a 32KB RAM as a 16KB. The way he has it puts the VIA at 6000-7FFF, which is fine. So its 16 addresses will be, in binary, 011xxxxxxxxxXXXX, where the lower-case x's are "don't cares" and the capital ones select the VIA register. That part looks ok.
Quote:
I know the code works and yes it can be optimised but what is the point.
Even if the code works elsewhere, simplifying is part of troubleshooting, and might expose why it works on one hardware but not another.
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?
jgroth
Posts: 60
Joined: 15 Sep 2016
Location: UK

Re: A simple 6502 computer (doesn't work though)

Post by jgroth »

GARTHWILSON wrote:
Even if the code works elsewhere, simplifying is part of troubleshooting, and might expose why it works on one hardware but not another.
OK, here's an optimised version of the via test program (or at least as well as I can optimise it). The code works well on the other computer (let's call it the ref board). Doesn't work on the minimalist board (I'm going to call it the NAND-board).

Code: Select all

       * = $8000
       .cpu = "w65c02"

;;; via1 device addresses:
        via1base = $6000
        ; via1base = $7fc0
        via1rb   = via1base+0     ; write output register b, read input register b
        via1ra   = via1base+1     ; write output register a, read input register a
        via1ddrb = via1base+2     ; data direction register b
        via1ddra = via1base+3     ; data direction register a
        via1t1cl = via1base+4     ; write t1 low-order latches, read t1 low-order counter
        via1t1ch = via1base+5     ; t1 high-order counter
        via1t1ll = via1base+6     ; t1 low-order latches
        via1t1lh = via1base+7     ; t1 high-order latches
        via1t2cl = via1base+8     ; write t2 low-order latches, read t2 low-order counter
        via1t2ch = via1base+9     ; t2 high-order counter
        via1sr   = via1base+$a    ; shift register
        via1acr  = via1base+$b    ; auxiliary control register
        via1pcr  = via1base+$c    ; peripheral control register
        via1ifr  = via1base+$d    ; interrupt flag register
        via1ier  = via1base+$e    ; interrupt enable register
        via1ranh = via1base+$f    ; same as reg a except no "handshake"

        via1ifrirq = %00000111
        via1timer1mask = %00000110
        via1timer2mask = %00000101

        via_timer2_irq_mask = %00100000

via1_init_table
        .byte   $00     ; PRB
        .byte   $00     ; PRA
        .byte   $00     ; DDRB
        .byte   $00     ; DDRA
        .byte   $00     ; T1CL
        .byte   $00     ; T1CH
        .byte   $00     ; T1LL
        .byte   $00     ; T1LH
        .byte   $00     ; T2CL
        .byte   $00     ; T2CH
        .byte   $00     ; SR
        .byte   $00     ; ACR
        .byte   $00     ; PCR
        .byte   $7F     ; IFR
        .byte   $7F     ; IER
n_via1_registers=*-via1_init_table-1

via_init: .proc
        ldx  #n_via1_registers
next:
        lda via1_init_table,x
        sta via1base,x
        dex
        bpl  next
        rts
        .pend

nmi:
irq:
;;;
;; coldstart - initialises all hardware
;; power up and reset procedure.
;;;
coldstart: .block
        sei                     ;Turn off interrupts
        ldx #$ff
        txs                     ;Initialise stack register
l2:
        jsr via_init          ;Initialise via

;;;
;; test code
;; Test code for setting PA and PB off, on, off endlessly
;;;
        lda #$ff
        sta via1ddra        ; set all PA pins to be outputs
        sta via1ddrb        ; set all PB ping to be outputs
loop:
        stz via1ra          ; low on all out ports
        stz via1rb          ; low on all out ports
        jsr delay           ; wait for a while
        dec via1ra          ; high on all out ports
        dec via1rb          ; high on all out ports
        jsr delay           ; wait for a while
        bra loop
.bend

delay: .proc
        lda #$20
loop1:
        ldx #$ff
loop2:
        ldy #$ff
loop3:
        dey
        bne loop3
        dex
        bne loop2
        dea                 ; decrease .A with 1
        bne loop1
        rts
        .pend

    * = $fffa
    .word   nmi         ;NMI
    .word   coldstart   ;RESET
    .word   irq         ;IRQ

It was also suggested to me that a NOP test might reveal whether the CPU comes out of reset and puts $EA on the databus. The program for that looks like this:

Code: Select all

    * = $8000
    .fill $8000, $ea
When I measure the data bus pins on the CPU they are indeed $EA (%11101010) so the CPU leaves reset and reads the reset vector in the ROM and starts execute NOP. I'm beginning to wonder whether I've missed something when I connected the RAM. Don't know how to check that other than physically check all connections on the bread board. I know there is nothing wrong with the IC it self because it works just fine in REF board.
User avatar
Dr Jefyll
Posts: 3526
Joined: 11 Dec 2009
Location: Ontario, Canada
Contact:

Re: A simple 6502 computer (doesn't work though)

Post by Dr Jefyll »

Can you post some photos of the project? Often it's helpful to examine things visually.

( And remember, on this forum you're allowed to attach images with your post. There's no need to use a third-party site such as Imgur.)

-- Jeff
In 1988 my 65C02 got six new registers and 44 new full-speed instructions!
https://laughtonelectronics.com/Arcana/ ... mmary.html
jgroth
Posts: 60
Joined: 15 Sep 2016
Location: UK

Re: A simple 6502 computer (doesn't work though)

Post by jgroth »

Dr Jefyll wrote:
Can you post some photos of the project? Often it's helpful to examine things visually.

( And remember, on this forum you're allowed to attach images with your post. There's no need to use a third-party site such as Imgur.)

-- Jeff
I can indeed. I built it on a solder less bread board though so there are wires everywhere.
The entire board.
The entire board.
Just the CPU
Just the CPU
CPU, 74HCT00 (left) and 74HCT74 (right).
CPU, 74HCT00 (left) and 74HCT74 (right).
CPU, RAM and VIA
CPU, RAM and VIA
RAM, ROM and reset circuit.
RAM, ROM and reset circuit.
jgroth
Posts: 60
Joined: 15 Sep 2016
Location: UK

Re: A simple 6502 computer (doesn't work though)

Post by jgroth »

The dream is to get this computer to work.
DSC_0363.JPG
User avatar
drogon
Posts: 1671
Joined: 14 Feb 2018
Location: Scotland
Contact:

Re: A simple 6502 computer (doesn't work though)

Post by drogon »

jgroth wrote:
The dream is to get this computer to work.
DSC_0363.JPG
Looks interesting - what is it?

-Gordon
--
Gordon Henderson.
See my Ruby 6502 and 65816 SBC projects here: https://projects.drogon.net/ruby/
jgroth
Posts: 60
Joined: 15 Sep 2016
Location: UK

Re: A simple 6502 computer (doesn't work though)

Post by jgroth »

drogon wrote:
jgroth wrote:
The dream is to get this computer to work.
DSC_0363.JPG
Looks interesting - what is it?

-Gordon
It's a 65C02 based computer with 32k ROM and RAM, an SC28L92 DUART, a Lattice MACH4A5 CPLD and some surrounding logic. A very experimental IDE interface is also there. Half of the implementation of the IDE interface is in the CPLD and the rest on the board (http://blog.retroleum.co.uk/electronics ... interface/. But since I can't even get a NOP ROM to work I thought it is time to go back to basic hence the bread board computer where the NOP ROM does work BTW. The VIA doesn't want to play ball though (still wonder if it got something to do with the RAM though).
User avatar
GARTHWILSON
Forum Moderator
Posts: 8773
Joined: 30 Aug 2002
Location: Southern California
Contact:

Re: A simple 6502 computer (doesn't work though)

Post by GARTHWILSON »

One step to try might be to pare it down further, if you're comfortable with that. You have a lot there that's not necessary. For example, the data sheet says, "The reset input clears all internal registers to logic 0 (except T1 and T2 latches and counters and the shift register). This places all peripheral interface lines in the input state, disables the timers, shift register, etc. and disables interrupt from the chip." So the only setup you need it to make port B (PB) all outputs, by writing FF to DDRB. Then decrementing PB, regardless of where it started from, will cycle all the bits, bit 7 being slowest, cycling about every 2/3 second at 1MHz, 1/3 second @ 2MHz, etc., plenty easy to see with a flashing LED.

Code: Select all

       * = $8000
       .cpu = "w65c02"

;;; via1 device addresses:
        via1base = $6000
        via1rb   = via1base+0     ; write output register b, read input register b
        via1ddrb = via1base+2     ; data direction register b


nmi:
irq:
;;;
;; coldstart - initialises PB as all outputs.
;; (The rest is taken care of by the RST-low pulse.)
;;;
coldstart:  .block
        ldx  #$ff
        txs                  ; Initialise stack pointer register
        stx  via1ddrb        ; and make PB0-PB7 all outputs.

;;;
;; Test code for toggling PB7 (and other bits too, but faster), endlessly
;;;

loop:   dec  via1rb          ; PB7 will cycle high & low
        jsr  delay           ; at about 2/3 second at 1MHz, PB6 at
        bra  loop            ; twice that rate, PB5 4x that rate, etc..
.bend                        ; (That's plenty easy to see with an LED.)


delay: .proc
        ldx  #$ff
loop2:  ldy  #$ff
loop3:  dey
        bne  loop3
        dex
        bne  loop2
        rts
        .pend


    * = $fffa
    .word   nmi         ;NMI
    .word   coldstart   ;RESET
    .word   irq         ;IRQ
The 65c02 can be single-cycled; so using a single-cycle circuit like what's 3/4 of the way down the clock-generation page of the 6502 primer, you can stop at each phase-2-high time and probe around looking at logic states and looking for voltages that are not a solid logic high or low, indicating bus contention. (The power supply's current meter might also tell you that when you get to the troublesome cycle.) WDC's W65C02S allows you to stop in either phase of the clock, not just the phase-2-high time; but you will still need to debounce.
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?
Post Reply