6502.org Forum  Projects  Code  Documents  Tools  Forum
It is currently Sat Nov 23, 2024 5:31 pm

All times are UTC




Post new topic Reply to topic  [ 33 posts ]  Go to page 1, 2, 3  Next
Author Message
PostPosted: Wed Jun 16, 2021 4:43 pm 
Offline

Joined: Sun May 30, 2021 2:16 am
Posts: 375
Hi,

So, I've been experimenting with various SoCs and combinations consisting of actual 65xx hardware and analogous FPGA implementations of the same. However, the chip that is constantly throwing me curveballs is the 65c22 VIA. I've got a weird FPGA situation where writing to the VIA (hard or soft) works just fine. That is a direct connection between the cpu unit (i.e., cpu, ram, rom, and acia - with a simple monitor up and running). However, if I stick an FPGA in the middle, for glue logic, writes work, but reads don't (work properly). Even with an actual 65c22.

Stated differently, I can write to the 65c22 registers just fine, and set the ports (output), but when I try to read-back the state of the same port, I get garbage. I even did away with the decode logic, just to see what would happen with a direct connection through the FPGA (Arty A7-100), and I get the same problem.

Here is the current code:

Code:
`timescale 1ns / 1ps
module top_peri(
    input wire slow_clk, //1mhz ext
    input wire clk,
    input wire rwb,
    input wire resb,
    input wire ext_bus, //external bus enabled signal
    input wire [12:0] addr,
    inout logic [7:0] dio,
    inout logic [7:0] via_io,
    //peripheral out
    output wire phi2,
    output wire [3:0] rs,
    output wire led,
    output wire csb,
    output wire rw,
    output wire res,
    output wire phi
    );

   logic [7:0] bus_in;
   logic [7:0] bus_out;
   logic [7:0] eo;
   logic [12:0] address;
   //logic [7:0] via1_in;
   //reg [7:0] via1_out;
   logic [7:0] via_in;
   logic [7:0] via_out;
   logic [7:0] v;
   
   //wire via1_strobe = address >= 16'h0800 && address <= 16'h080F;
   
   assign phi2 = clk;
   assign address = addr;

   assign eo = bus_out;
   assign dio = (rwb) ? eo : 'bZ;
   assign bus_in = dio;
   
   assign v = via_out;
   assign via_io = (rwb) ? 'bZ : v;
   assign via_in  = via_io;
   
   assign via_out = bus_in;
   assign bus_out = via_in;
   
   assign rs = address[3:0];
   assign rw = rwb;
   assign res = resb;
   assign phi = clk;
   assign csb = ext_bus;
   
   assign led = ~resb;
endmodule


I even tried registering the data in the "read" direction (from the '22 back to the cpu), and that didn't fix it. I am beyond perplexed.

Any thoughts or solutions? I'm sure I'm just making some dumb rookie error, but, who knows?

Jon


Top
 Profile  
Reply with quote  
PostPosted: Wed Jun 16, 2021 5:28 pm 
Offline
User avatar

Joined: Thu May 28, 2009 9:46 pm
Posts: 8509
Location: Midwestern USA
Jmstein7 wrote:
However, the chip that is constantly throwing me curveballs is the 65c22 VIA...

The real 65C22, like other 65xx peripherals, requires that all inputs on the MPU side to be stabilized before the rise of Ø2. In other words, do not qualify chip selects or RWB with Ø2. The 65C22 "knows" about the 65xx bus cycle and will sample or write the data bus at the appropriate time.

_________________
x86?  We ain't got no x86.  We don't NEED no stinking x86!


Top
 Profile  
Reply with quote  
PostPosted: Wed Jun 16, 2021 5:46 pm 
Offline

Joined: Sun May 30, 2021 2:16 am
Posts: 375
BigDumbDinosaur wrote:
Jmstein7 wrote:
However, the chip that is constantly throwing me curveballs is the 65c22 VIA...

The real 65C22, like other 65xx peripherals, requires that all inputs on the MPU side to be stabilized before the rise of Ø2. In other words, do not qualify chip selects or RWB with Ø2. The 65C22 "knows" about the 65xx bus cycle and will sample or write the data bus at the appropriate time.


Hmmmm... I don't think I've done that here. Did I miss something?


Top
 Profile  
Reply with quote  
PostPosted: Wed Jun 16, 2021 8:17 pm 
Offline
User avatar

Joined: Fri Aug 30, 2002 1:09 am
Posts: 8545
Location: Southern California
Jmstein7 wrote:
BigDumbDinosaur wrote:
Jmstein7 wrote:
However, the chip that is constantly throwing me curveballs is the 65c22 VIA...

The real 65C22, like other 65xx peripherals, requires that all inputs on the MPU side to be stabilized before the rise of Ø2. In other words, do not qualify chip selects or RWB with Ø2. The 65C22 "knows" about the 65xx bus cycle and will sample or write the data bus at the appropriate time.

Hmmmm... I don't think I've done that here. Did I miss something?

Yes; check the tACR and tACW in the timing diagrams in the data sheet. I got bit by this the first time I tried to use a '22, in about 1986. In the 14MHz ones, it's 10ns minimum. When I was dealing with 2MHz parts, it was 90ns.

_________________
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: Wed Jun 16, 2021 8:42 pm 
Offline

Joined: Sun May 30, 2021 2:16 am
Posts: 375
GARTHWILSON wrote:
Yes; check the tACR and tACW in the timing diagrams in the data sheet. I got bit by this the first time I tried to use a '22, in about 1986. In the 14MHz ones, it's 10ns minimum. When I was dealing with 2MHz parts, it was 90ns.[/color]


Garth, I'm still fairly new to all this. What strategy do I need to adopt to deal with this issue? How did you handle it? My guess would be to grab it on the falling edge of phi2?

Thanks!

Jon


Top
 Profile  
Reply with quote  
PostPosted: Wed Jun 16, 2021 11:03 pm 
Offline

Joined: Sun May 30, 2021 2:16 am
Posts: 375
Code:
   always @(negedge clk) begin
        if (rwb == 1 && csb == 0)
            via_in <= via_io;
        else if (rwb == 0 && csb == 0)
            v <= via_out;
   end
   
   assign via_io = v;
   
   assign via_out = bus_in;
   assign bus_out = via_in;


This was my solution. It kind of works 80% of the time. :?
Now it just outputs the last value I wrote. Over and over.


Top
 Profile  
Reply with quote  
PostPosted: Thu Jun 17, 2021 4:57 am 
Offline
User avatar

Joined: Fri Aug 30, 2002 1:09 am
Posts: 8545
Location: Southern California
Jmstein7 wrote:
GARTHWILSON wrote:
Yes; check the tACR and tACW in the timing diagrams in the data sheet. I got bit by this the first time I tried to use a '22, in about 1986. In the 14MHz ones, it's 10ns minimum. When I was dealing with 2MHz parts, it was 90ns.

Garth, I'm still fairly new to all this. What strategy do I need to adopt to deal with this issue? How did you handle it? My guess would be to grab it on the falling edge of phi2?

I should specify that I was not doing anything in programmable logic, just trying to prototype a computer with OTS parts. The crazy story is in the 8th paragraph of my "Introduce yourself" post at viewtopic.php?p=16164#p16164 . For that project, I ended up not using the '22; but I did get it going. I don't think I have any schematics of what I did, but I did figure out pretty quickly that Φ2 needs to be kept out of the chip-enable circuits for the '22. The '22 needs the chip-select, register-select, and R/W lines to be valid ahead of the rise of Φ2, so it can be preparing for action. I made an I/O board for the C64 for our son in probably the late 1990's. Since the 6522 needs the CS lines valid before its phase 2 goes up and the C64 doesn't meet that requirement, I had to put in a circuit to delay the rising edge of phase 2 but not the falling edge. You can see it at http://6502.org/users/garth/projects.php?project=7 .

_________________
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 17, 2021 8:42 am 
Offline

Joined: Sun Jun 29, 2014 5:42 am
Posts: 352
Can I ask a few more questions...

In the above tests, is the "CPU" in all cases a core within the FPGA Module?

If so, which core is being used?

[ again, a link to the actual project you were testing would help, as you are changing things about quite a lot ]

What's the full manufacturer/part number of the real 65C22 you are using?

What voltage is the 65C22 running off?

Was it bought from a reputable supplier (i.e. is it definitely genuine)?

There are a couple of general reasons why a read of a real 6502 might fail:
1. The signals presented to the 65C22 do not conform to the requirements laid out in the data sheet
2. The read data is latched at the wrong time

Dave


Top
 Profile  
Reply with quote  
PostPosted: Thu Jun 17, 2021 2:44 pm 
Offline

Joined: Sun May 30, 2021 2:16 am
Posts: 375
hoglet wrote:
Can I ask a few more questions...

In the above tests, is the "CPU" in all cases a core within the FPGA Module?

If so, which core is being used?

Dave,

No, the cpu is a core within a separate FPGA module. Jens 'c02 core. This is the project:

https://github.com/jmstein7/65c02_errata/blob/main/t65_beta_done.zip

hoglet wrote:

What's the full manufacturer/part number of the real 65C22 you are using?

What voltage is the 65C22 running off?

Was it bought from a reputable supplier (i.e. is it definitely genuine)?


It is the WDC W65C22S6TPG-14 SA1947A.

3.3v.

From Mouser, directly.

hoglet wrote:
There are a couple of general reasons why a read of a real 6502 might fail:
1. The signals presented to the 65C22 do not conform to the requirements laid out in the data sheet
2. The read data is latched at the wrong time

Dave


It's so odd, because when I had it directly hooked up to the FPGA with the core, it worked just fine. However, when I added the FPGA for glue logic, the problems started.

At the end of the day, these are really just side experiments incidental to the main project I was working on with you - the SoC.
https://github.com/jmstein7/65c02_errata

I started these little experiments because I just could not get an external bus to work on our SoC - even when I added the address lines back in to the external outputs. So, I thought it might be the core. As such, I started experiments with Jens's core, which claims to be completely cycle accurate.

Jonathan


Top
 Profile  
Reply with quote  
PostPosted: Thu Jun 17, 2021 2:48 pm 
Offline

Joined: Sun May 30, 2021 2:16 am
Posts: 375
GARTHWILSON wrote:
I don't think I have any schematics of what I did, but I did figure out pretty quickly that Φ2 needs to be kept out of the chip-enable circuits for the '22. The '22 needs the chip-select, register-select, and R/W lines to be valid ahead of the rise of Φ2, so it can be preparing for action.


Garth,

That is the other odd thing. The designs I'm using here, in particular, are completely asynchronous.

Jon


Top
 Profile  
Reply with quote  
PostPosted: Thu Jun 17, 2021 3:49 pm 
Offline

Joined: Sun Jun 29, 2014 5:42 am
Posts: 352
Jmstein7 wrote:
I started these little experiments because I just could not get an external bus to work on our SoC - even when I added the address lines back in to the external outputs. So, I thought it might be the core.

There are a couple of changes you could experiment with.

1. Add a register to capture data on the falling edge of Phi2:

Code:
reg [7:0] bus_data;

-- capture the bus data on the falling edge of Phi2
always @(negedge Phi2) begin
    bus_data <= data_io;
end

-- use the registered bersion of bus data
   assign cpu_din = ram_e  ? ram_dout   :
                    rom_e  ? rom_dout   :
                    acia_e ? acia_dout  :
                    via_e  ? via_dout_r :
                    bus_data;


2. Provide additional address hold time, by clocking the 6502 core later

The relative phase of Phi2 and the output signals (address, data, rnw) is managed by the clken_ctr and the cpu_clken signal.

The MSB of the counter is used as Phi2 - consider that fixed.

The CPU is clocked when cpu_clken is asserted.
Code:
always @(posedge clk) begin
    ....
     cpu_clken <= &clken_ctr; // active when all 1's
    ....
end


Consider CLKEN_BITS being 3:
Code:
clken_ctr phi2 cpu_clken address
110       1    0         XXXX
111       1    0         XXXX
000       0    1         XXXX
001       0    0         YYYY
010       0    0         YYYY
011       0    0         YYYY
100       1    0         YYYY
101       1    0         YYYY

So currently the address (and other outputs) changes (from XXXX to YYYY) one clk cycle after the falling edge of phi2.

It might be worth delaying this a bit to provide extra address hold time.

Currently we have:
Code:
always @(posedge clk) begin
    ....
     cpu_clken <= &clken_ctr; // active when all 1's
    ....
end

This is the same as:
Code:
always @(posedge clk) begin
    ....
     cpu_clken <= (clken_ctr == (2**CLKEN_BITS-1));
    ....
end

To add one more clk cycle of delay to the outputs you would use:
Code:
always @(posedge clk) begin
    ....
     cpu_clken <= (clken_ctr == 0);
    ....
end

To add a further clk cycles of delay to the outputs you would use:
Code:
always @(posedge clk) begin
    ....
     cpu_clken <= (clken_ctr == 1);
    ....
end

What I would suggest is:

Use a system clock of 50MHz, so each clk cycle is 20ns.

Use CLKEN_BITS of 4, so Phi2 is 50/(2**4) = 3.125MHz (a Phi2 cycle time of 320ns)

Adjust the clocking of the CPU core to give ~2 clk cycles (40ns) of address hold time.
Code:
always @(posedge clk) begin
    ....
     cpu_clken <= (clken_ctr == 0);
    ....
end

This, together with registering the bus_data on the falling edge of Phi2, should give you a bus interface that is fairly similar to a 3-4MHz 6502.

I'll try and set this up myself on a breadboard tomorrow, if I can find a 65C22. If not, I'll have to order one, and it will be a few days.

Dave


Top
 Profile  
Reply with quote  
PostPosted: Thu Jun 17, 2021 4:47 pm 
Offline

Joined: Sun May 30, 2021 2:16 am
Posts: 375
How is that decoder going, by the way, Dave? I know you had been working pretty hard on it.

Jon


Top
 Profile  
Reply with quote  
PostPosted: Thu Jun 17, 2021 5:48 pm 
Offline

Joined: Sun Jun 29, 2014 5:42 am
Posts: 352
Jmstein7 wrote:
How is that decoder going, by the way, Dave? I know you had been working pretty hard on it.

I finished what I was working on: it can now decode samples from Arlet and AlanD's FPGA cores.

Dave


Top
 Profile  
Reply with quote  
PostPosted: Thu Jun 17, 2021 8:57 pm 
Offline

Joined: Sun May 30, 2021 2:16 am
Posts: 375
hoglet wrote:
Jmstein7 wrote:
How is that decoder going, by the way, Dave? I know you had been working pretty hard on it.

I finished what I was working on: it can now decode samples from Arlet and AlanD's FPGA cores.

Dave

Awesome. Any cool insights?

Jon


Top
 Profile  
Reply with quote  
PostPosted: Fri Jun 18, 2021 10:42 am 
Offline

Joined: Sun Jun 29, 2014 5:42 am
Posts: 352
Jmstein7 wrote:
Awesome. Any cool insights?

I suppose the main one is just being greatful to Klaus Dormann for his excellent 6502 and 65C02 test suites.

hoglet wrote:
I'll try and set this up myself on a breadboard tomorrow, if I can find a 65C22. If not, I'll have to order one, and it will be a few days.

Back onto the external VIA issue.

I hunted around and found a small board that has a W65C22S on it:
Attachment:
IMG_0067.JPG
IMG_0067.JPG [ 654.56 KiB | Viewed 1278 times ]


I hooked this up to the Spartan board with some jumper wires:
Attachment:
IMG_0070.JPG
IMG_0070.JPG [ 682.29 KiB | Viewed 1278 times ]

(I updated the UCF file to make the wiring easy)

I wanted to make the minimum changes to the original design, to see if I could reproduce the problem you were having.

I just added the chip select and a few address lines:
Code:
   output        viacsb,
   output [3:0]  addr,
...
   assign addr = cpu_addr[3:0];
   assign viacsb = !(cpu_addr >= 16'h8100 && cpu_addr <= 16'h810F);
...

This is running off a 50MHz clock with CLKEN_BITS=2, so the 65C22 is being clocked at 12.5MHz, so actually quite fast.

Rather frustratingly, this all seems to work fine!
Attachment:
Screenshot from 2021-06-18 11-09-13.png
Screenshot from 2021-06-18 11-09-13.png [ 51.25 KiB | Viewed 1278 times ]


You can see the two counters (at 8104/5 and 8108/9 changing, and the IER at 810E is initialized to 80). I can then write to the PA/PB DDR and Port registers, and read back the new values.

I then went ahead and made the changes I suggested in the thread further up:
https://github.com/hoglet67/65c02_errat ... t/f7b136fa

Sampling the external bus data on the falling edge of Phi2 is still a good idea. Otherwise you are relying on the bus capacitance to hold the value after the 65C22 stops driving.

I tested this version as well and it works correctly as well.

This doesn't explain why this isn't working for you. I have a couple of possibilities:
1. Your 65C22 is wired incorrectly? (which is easy to do!)
2. Your 65C22 is has been damaged?
3. Noise on the nRST line is causing the 65C22 to randomly reset, loosing what has been written?

I've been bitten by the last of these when using this board in a real BBC Master system. That's why the 65C22's nRST line is pulled high and not connected to a jumper.

I would suggest you try to re-create this setup again, then we can do a bit more debugging. Specifically:
- What values are returned if you read the 65C22 registers several times
- Instead of driving nRST from the FPGA board, just tie it to 3.3V via a 1K resistor close to the 65C22. Does anything change?

I've pushed all of my changed to github:
https://github.com/hoglet67/65c02_errata

Dave


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

All times are UTC


Who is online

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