6502.org Forum  Projects  Code  Documents  Tools  Forum
It is currently Sun Nov 24, 2024 10:10 pm

All times are UTC




Post new topic Reply to topic  [ 68 posts ]  Go to page 1, 2, 3, 4, 5  Next
Author Message
PostPosted: Thu Jun 20, 2019 7:15 pm 
Offline

Joined: Thu Sep 15, 2016 1:52 pm
Posts: 60
Location: UK
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.

Attachment:
simple6502.pdf [69.88 KiB]
Downloaded 146 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:
;;;
;; 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.

Top
 Profile  
Reply with quote  
PostPosted: Thu Jun 20, 2019 7:57 pm 
Offline
User avatar

Joined: Fri Aug 30, 2002 1:09 am
Posts: 8546
Location: Southern California
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?


Top
 Profile  
Reply with quote  
PostPosted: Thu Jun 20, 2019 8:23 pm 
Offline
User avatar

Joined: Thu Dec 11, 2008 1:28 pm
Posts: 10986
Location: England
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.


Top
 Profile  
Reply with quote  
PostPosted: Thu Jun 20, 2019 8:50 pm 
Offline

Joined: Thu Sep 15, 2016 1:52 pm
Posts: 60
Location: UK
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:
        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.


Top
 Profile  
Reply with quote  
PostPosted: Thu Jun 20, 2019 8:59 pm 
Offline

Joined: Thu Sep 15, 2016 1:52 pm
Posts: 60
Location: UK
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.


Top
 Profile  
Reply with quote  
PostPosted: Thu Jun 20, 2019 9:03 pm 
Offline

Joined: Thu Mar 03, 2011 5:56 pm
Posts: 284
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.


Top
 Profile  
Reply with quote  
PostPosted: Thu Jun 20, 2019 9:04 pm 
Offline
User avatar

Joined: Thu Dec 11, 2008 1:28 pm
Posts: 10986
Location: England
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.


Top
 Profile  
Reply with quote  
PostPosted: Thu Jun 20, 2019 9:24 pm 
Offline
User avatar

Joined: Fri Aug 30, 2002 1:09 am
Posts: 8546
Location: Southern California
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?


Top
 Profile  
Reply with quote  
PostPosted: Fri Jun 21, 2019 2:48 pm 
Offline

Joined: Thu Sep 15, 2016 1:52 pm
Posts: 60
Location: UK
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:
       * = $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:
    * = $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.


Top
 Profile  
Reply with quote  
PostPosted: Fri Jun 21, 2019 4:10 pm 
Offline
User avatar

Joined: Fri Dec 11, 2009 3:50 pm
Posts: 3367
Location: Ontario, Canada
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


Top
 Profile  
Reply with quote  
PostPosted: Fri Jun 21, 2019 5:26 pm 
Offline

Joined: Thu Sep 15, 2016 1:52 pm
Posts: 60
Location: UK
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.
Attachment:
File comment: The entire board.
DSC_0011.JPG
DSC_0011.JPG [ 6.24 MiB | Viewed 1689 times ]

Attachment:
File comment: Just the CPU
DSC_0012.JPG
DSC_0012.JPG [ 4.25 MiB | Viewed 1689 times ]

Attachment:
File comment: CPU, 74HCT00 (left) and 74HCT74 (right).
DSC_0013.JPG
DSC_0013.JPG [ 4.87 MiB | Viewed 1689 times ]

Attachment:
File comment: CPU, RAM and VIA
DSC_0014.JPG
DSC_0014.JPG [ 4.85 MiB | Viewed 1689 times ]

Attachment:
File comment: RAM, ROM and reset circuit.
DSC_0016.JPG
DSC_0016.JPG [ 4.95 MiB | Viewed 1689 times ]


Top
 Profile  
Reply with quote  
PostPosted: Fri Jun 21, 2019 5:54 pm 
Offline

Joined: Thu Sep 15, 2016 1:52 pm
Posts: 60
Location: UK
The dream is to get this computer to work.
Attachment:
DSC_0363.JPG
DSC_0363.JPG [ 3.26 MiB | Viewed 1686 times ]


Top
 Profile  
Reply with quote  
PostPosted: Fri Jun 21, 2019 6:20 pm 
Offline
User avatar

Joined: Wed Feb 14, 2018 2:33 pm
Posts: 1488
Location: Scotland
jgroth wrote:
The dream is to get this computer to work.
Attachment:
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/


Top
 Profile  
Reply with quote  
PostPosted: Fri Jun 21, 2019 7:23 pm 
Offline

Joined: Thu Sep 15, 2016 1:52 pm
Posts: 60
Location: UK
drogon wrote:
jgroth wrote:
The dream is to get this computer to work.
Attachment:
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-articles/an-8-bit-ide-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).


Top
 Profile  
Reply with quote  
PostPosted: Fri Jun 21, 2019 8:28 pm 
Offline
User avatar

Joined: Fri Aug 30, 2002 1:09 am
Posts: 8546
Location: Southern California
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:
       * = $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?


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

All times are UTC


Who is online

Users browsing this forum: Google [Bot] and 14 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: