6502.org http://forum.6502.org/ |
|
Handling shared data bus between 65c02 and an FPGA http://forum.6502.org/viewtopic.php?f=10&t=8001 |
Page 1 of 1 |
Author: | czuhars [ Sat Mar 09, 2024 9:30 pm ] |
Post subject: | Handling shared data bus between 65c02 and an FPGA |
Hi all, I’m working a project that is based on an existing TTL logic-based design, where a 6502 shares a data bus with a 6522 and a ROM chip. It then shares this bus with external peripherals with an old DM8304 bidirectional buffer acting as gatekeeper which is controlled by other logic. I’m trying to incorporate the same setup, but connecting a FPGA on this shared bus, mainly for its onboard SDRAM. The FPGA handles the glue logic throughout the system, including the signal to let the data pass between it and the shared bus. But I’m not getting stellar results. Rather, when this “dm8304 enable” signal is active on the ‘02’s write, I’m only getting 8’bZ on my FPGA’s i/o. In my FPGA, I’m doing a bidirectional bus this way (in Verilog): inout wire [7:0] data; assign data = (r_w) ? data_to_cpu : 8’bZ; assign data_from_cpu = data; I’ve also tried using the FPGA’s primitives to handle the bidirectional transactions. My question is, should it be ok for my FPGA to be hooked directly to this external shared bus, and acting internally as the 8304 (or74245) and passing the data through in a tri-state manner? Or is it better practice to use an actual bidirectional buffer chip between this data bus and my FPGA’s GPIO, which the FPGA can control? For this setup, my external chips are a WDC 65c02 and a WDC 65c22, operating at 3.3v, the same as the FPGA (iCESugar-Pro (Lattice ECP5)). Thanks! PS: I’ve tried creating a bin file through both Lattice Diamond and the Yosys/nextpnr/ecppack tool chain with similar results. |
Author: | dmsc [ Sat Mar 09, 2024 11:33 pm ] |
Post subject: | Re: Handling shared data bus between 65c02 and an FPGA |
Hi! czuhars wrote: Hi all, I’m working a project that is based on an existing TTL logic-based design, where a 6502 shares a data bus with a 6522 and a ROM chip. It then shares this bus with external peripherals with an old DM8304 bidirectional buffer acting as gatekeeper which is controlled by other logic. I’m trying to incorporate the same setup, but connecting a FPGA on this shared bus, mainly for its onboard SDRAM. The FPGA handles the glue logic throughout the system, including the signal to let the data pass between it and the shared bus. But I’m not getting stellar results. Rather, when this “dm8304 enable” signal is active on the ‘02’s write, I’m only getting 8’bZ on my FPGA’s i/o. In my FPGA, I’m doing a bidirectional bus this way (in Verilog): inout wire [7:0] data; assign data = (r_w) ? data_to_cpu : 8’bZ; assign data_from_cpu = data; I’ve also tried using the FPGA’s primitives to handle the bidirectional transactions. My question is, should it be ok for my FPGA to be hooked directly to this external shared bus, and acting internally as the 8304 (or74245) and passing the data through in a tri-state manner? Or is it better practice to use an actual bidirectional buffer chip between this data bus and my FPGA’s GPIO, which the FPGA can control? For this setup, my external chips are a WDC 65c02 and a WDC 65c22, operating at 3.3v, the same as the FPGA (iCESugar-Pro (Lattice ECP5)). Thanks! PS: I’ve tried creating a bin file through both Lattice Diamond and the Yosys/nextpnr/ecppack tool chain with similar results. You don't use bidirectional signals in a FPGA, as those are not supported in the internal fabric. You use two separate busses, one for input and one for output. And then, you use bidirectional I/O pins in the FPGA, that should have control signals for enabling/disabling the output buffer. You should read your FPGA manual on how to instantiate the bidirectional I/O. According to the manual at https://www.latticesemi.com/-/media/Lat ... t_id=50464 , you need to instantiate a "BB" component, the example in page 23 is: Code: BB buf7 (.I(Q_out7), .T(Q_tri7), .O(buf_Data7), .B(Data[7])); There, 'T' is the "tri-state' input, 'I' the input from the FPGA to the pin, 'O' the output to the FPGA from the pin, and 'B' is the actual FPGA pin. Have Fun! |
Author: | John West [ Sun Mar 10, 2024 7:58 am ] |
Post subject: | Re: Handling shared data bus between 65c02 and an FPGA |
dmsc wrote: You don't use bidirectional signals in a FPGA, as those are not supported in the internal fabric. You use two separate busses, one for input and one for output. And then, you use bidirectional I/O pins in the FPGA, that should have control signals for enabling/disabling the output buffer. That's what czuhars has. There are no tristate signals in the internal logic; only on the I/O signals. data_to_cpu and data_from_cpu are the separate busses you're talking about. And while you can explicitly instantiate tristate I/O primitives, you shouldn't have to. Doing so ties your design to one particular FPGA and makes it harder to port. I've used an equivalent design (in VHDL, on a Spartan6) before and had it work - synthesis should convert the tristate into the right primitives, or complain if it can't. Is it possible that the error is in the logic that supplies the r_w signal? I strongly recommend setting up a testbed and running it through a simulator. Or you could route r_w to a spare pin and look at that. FPGA designs get nasty to debug when you can't see what's happening inside. |
Author: | sark02 [ Sun Mar 10, 2024 6:05 pm ] |
Post subject: | Re: Handling shared data bus between 65c02 and an FPGA |
czuhars wrote: In my FPGA, I’m doing a bidirectional bus this way (in Verilog): inout wire [7:0] data; assign data = (r_w) ? data_to_cpu : 8’bZ; assign data_from_cpu = data; Yes, that's the correct pattern to attach to a bidirectional bus. Other than that, making sure your FPGA signal standard (voltage, current) is compatible with the rest of the bus. Good luck! |
Author: | dmsc [ Sun Mar 10, 2024 11:21 pm ] |
Post subject: | Re: Handling shared data bus between 65c02 and an FPGA |
Hi! John West wrote: dmsc wrote: You don't use bidirectional signals in a FPGA, as those are not supported in the internal fabric. You use two separate busses, one for input and one for output. And then, you use bidirectional I/O pins in the FPGA, that should have control signals for enabling/disabling the output buffer. That's what czuhars has. There are no tristate signals in the internal logic; only on the I/O signals. data_to_cpu and data_from_cpu are the separate busses you're talking about. You are right, I missread. About instantiating the tristate I/O, I prefer to do that because normally you can then select buffer parameters like speed and voltages. Have Fun! |
Author: | czuhars [ Tue Mar 12, 2024 9:47 pm ] |
Post subject: | Re: Handling shared data bus between 65c02 and an FPGA |
Thanks a ton for the feedback. At least I have a better idea that I’m on the right path. I created a very simple test project to allow me to check the incoming data bus value on r_w active low (cpu write) for a given address. I’m using the BB primitive for the Lattice ECP5 in synthesis and the method mentioned above for simulation. Here’s the weirdness: When a inout pin is configured as such in my top level module: BB i_data0 (.B(i_data[0]), .I(data_to_cpu[0]), .O(data_from_cpu[0]), .T(r_w)); data_from_cpu is supposed to be the value during a write from the cpu to be processed inside the FPGA. data_to_cpu is for when I want the FPGA to send data to the cpu. The data_from_cpu is accurate, but only on the r_w high (read) and for the address where this value is read from an external ROM onto the shared data bus. The code is then supposed to write that value to to a specific address which the fpga inout pins can capture. But when r_w is low, the value of data_from_cpu is 8’bZ !! Simulation shows it working as it should. So, I thought, ok - I’ve got my from/to wires mixed up. But not so apparently. Anyway, I know this is impossible to troubleshoot with only the information I’ve given. I can only ask, have I set up my BB tri-state primitives correctly? Also, as I understand it, the PULLMODE should be set to NONE for the tri-state. Right? I’ve definitely got a solid, reproducible test that is failing, which is a good starting point to figure out what the hell is going on. |
Author: | dmsc [ Wed Mar 13, 2024 1:48 am ] |
Post subject: | Re: Handling shared data bus between 65c02 and an FPGA |
Hi! czuhars wrote: Thanks a ton for the feedback. At least I have a better idea that I’m on the right path. I created a very simple test project to allow me to check the incoming data bus value on r_w active low (cpu write) for a given address. I’m using the BB primitive for the Lattice ECP5 in synthesis and the method mentioned above for simulation. Here’s the weirdness: When a inout pin is configured as such in my top level module: BB i_data0 (.B(i_data[0]), .I(data_to_cpu[0]), .O(data_from_cpu[0]), .T(r_w)); data_from_cpu is supposed to be the value during a write from the cpu to be processed inside the FPGA. data_to_cpu is for when I want the FPGA to send data to the cpu. The data_from_cpu is accurate, but only on the r_w high (read) and for the address where this value is read from an external ROM onto the shared data bus. The code is then supposed to write that value to to a specific address which the fpga inout pins can capture. But when r_w is low, the value of data_from_cpu is 8’bZ !! Simulation shows it working as it should. So, I thought, ok - I’ve got my from/to wires mixed up. But not so apparently. Some questions: - Is the r_w signal coming from outside the FPGA? - If it is so, is it properly synchronized to your clock? - Does your FPGA logic use some master clock with the CPU or has an independent clock? As you are probably using an embedded block ram for your ROM, you need a synchronous interface to it. Have Fun! |
Author: | czuhars [ Wed Mar 13, 2024 11:57 am ] |
Post subject: | Re: Handling shared data bus between 65c02 and an FPGA |
My FPGA is generating the phi2 to the 65c02, so it is synchronized. However, I know I still need to sync the signals coming from the 65c02 into the FPGA. The original system schematic relied on the pho2 from the original NMOS 6502B to set various signals. But since I’m using the WDC version, I am generating my own internal pho2. But the test system I am working with doesn’t use this setup. I am starting to think that: 1) my FPGA “read the incoming address and read the incoming data” logic isn’t accounting properly for the address/data set up times. 2) the r_w signal coming from the 65c02 that I’m using to switch the BB primitives between reading from or writing to the bidirectional io might be reversed. I.E., when r_w is active low (cpu is writing data to the bus) then the BB .O() net is active, rather than the .I() Regardless, since I’m using the Yosys/nextpnr toolchain, I might switch those primitives to the TRELLIS_IO even though the toolchain is supposed to translate the BB primitive to the TRELLIS_IO primitives. I’ll also run it through the Lattice Diamond software to see if that makes a difference. I know the software, esp. the open source version, is supposed to do that with generic Verilog. But I’m trying to eliminate as many points of potential failure I can. |
Page 1 of 1 | All times are UTC |
Powered by phpBB® Forum Software © phpBB Group http://www.phpbb.com/ |