fvdhoef / vera-module

Versatile Embedded Retro Adapter
MIT License
107 stars 44 forks source link

Back-to-back reads not returning incremented address data #4

Open jburks opened 2 years ago

jburks commented 2 years ago

DS1Z_QuickPrint2

This was seen in a test setup driving communication from a Raspberry Pi connected via I2C to a 16 bit GPIO expander and then to a VERA implemented using an UPduino 3.1 on a solderless breadboard. The official X16 emulator was modified such that all register IO within the emulator system and the emulated VERA was duplicated out to the VERA on the breadboard. The results of all register reads from the emulator are compared and mismatches are reported. The only mismatches observed so far happens during a cursor blink (at a "READY." prompt) at which time the second read always, or almost always, comes back with the same data from the first read as though the address had not been incremented.

Attached is a logic analyzer trace from the UPduino-based VERA. D7 of the analyzer appears to have an internal connection and is always reading ground but probing it separately does show the D7 signal behaving as expected. The analyzer probes are connected between the GPIO expander and the UPduino module. The Pi and GPIO expander are both operating with 3.3v IO. The only change to the VERA source code was the addition of a PLL to derive a 25MHz clock from the 12MHz clock on the module. A log of video activity from the emulator and VERA HW activity was collected on some runs, the relevant portion of a failure similar to the one in the LA trace looks like this:

VERA  READ $(00) == $0C
VERA  READ $(01) == $B8
VERA  READ $(02) == $11
VERA WRITE $(00) <= $00
VIDEO WRITE $(00) <= $00
VERA WRITE $(01) <= $B9
VIDEO WRITE $(01) <= $B9
VERA WRITE $(02) <= $11
VIDEO WRITE $(02) <= $11
VERA  READ $(03) == $20
READ  video_space[$1B900] = $20
VERA  READ $(03) == $20
READ  video_space[$1B901] = $61
!! MISMATCH !! ($03): 20 != 61

The emulator VERA correctly returned $61 while the hardware VERA returned $20. Immediately preceding the mis-matched read is a successfully matched read of $20 and a write to ADDR_L/_M/_H of $1B900 and setting the increment to 1.

In the attached trace, Cursor A (solid vertical line) on the left is marking the approximate location of the write to ADDR_H with the value $11. Cursor B (dotted vertical line) is marking the approximate location of the first read of DATA0 and getting the value $20. The next CS# assertion to the right of Cursor B is the second read of DATA0 which gets the erroneous value of $20.

A python script to perform a similar sequence was also written but always sees the correct, address-incremented value. A trace when that script is running has not yet been collected, but when it is the result will be posted as a reply to this issue.

jburks commented 2 years ago

DS1Z_QuickPrint4 Attached are the same reads from the working case (a Python module written for talking to VERA). The two reads are marked by the cursors. The first read returns $20, the second $61 as expected. The only difference that is readily apparent on initial inspection is that the Python module does not zero the address bus between the two reads.

One potential explanation here is that the VERA module in an X16 system deasserts the OE# pin to the data bus transceiver when CS# is deasserted which would cause all of those signals to go to a high impedance state between the transceiver and the FPGA.

jburks commented 2 years ago

DS1Z_QuickPrint5 Re-tested with changes to put the data bus into high-Z between the two reads; the second read still failed. Changed again to hold the address bus steady between reads and the mismatches no longer occur. Modifying the address bus between reads seems to prevent the auto increment function from working. This suggests that there is an address hold time constraint on VERA that requires CS#/RD# to deassert while the address bus is stable. Changing the code again to deassert CS#/RD# and then drive the address lines low also worked with no mismatched registers between the emulator and hardware.

The root cause of this issue was not holding the address bus when one or both of CS# and RD# were deasserted.

Since the address should be stable before both CS# and RD# are both asserted (since CS# generation is most likely dependent on the address bus value), a potential fix for this could be to sample rdaddr_r on posedge of bus_read. The design could be left as is, but the 6502's address hold time after negedge PHI2 is very close to the propagation delay of many logic ICs and there is could be a danger of CS# or RD# deassertion happening too long after the falling edge of PHI2 and the autoincrement may get missed.