sy2002 / QNICE-FPGA

QNICE-FPGA is a 16-bit computer system for recreational programming built as a fully-fledged System-on-a-Chip in portable VHDL.
http://qnice-fpga.com
Other
69 stars 16 forks source link

Refactor Daisy-chaining in all devices and provide a proven-to-work implementation for future devices #104

Closed sy2002 closed 4 years ago

sy2002 commented 4 years ago

Currently, the way VGA is implemented, it ignores the mechanisms of our Daisy-chained architecture. So the TODO of this issue is to implement it. This issue blocks issue #17

Here is a description of how the mechanism / protocol works:

https://github.com/sy2002/QNICE-FPGA/blob/develop/doc/int-device.md#daisy-chaining

I copied the most important parts here, the full info is in doc/int-device.md:

Daisy chaining

CPU <=> Device 1 <=> Device 2 <=> ... <=> Device n
MJoergen commented 4 years ago

Thank you for the detailed description.

As mentioned in Issue #108, the current VGA interrupt mechanism is completely broken (it corrupts the data bus), and I'm in the process of re-implementing it according to the above description. However, I'm running into some problems, so I would like to have some things clarified related to when the ISR address is being presented to the CPU.

In the following I'm referring to this diagram:

image

Here is my understanding:

I notice that when the VGA module is connected as the last device in the daisy chain, the GRANT_N input to the VGA module is delayed some clock cycles compared to GRANT_N coming from the CPU, and therefore when the CPU releases GRANT_N, the VGA module is still pushing the ISR address onto the data bus, which leads to corruption.

So it appears there is a requirement that the GRANT_N signal be passed combinatorially through the entire daisy chain. This requirement should be made more explicit in the description of the daisy chain process. This requirement is seemingly not obeyed by the TImer device in timer.vhd. I remember an earlier version of timer.vhd where the GRANT_N signal was connected combinatorially but changed to registered in order to break a combinatorial loop. It would seem that the register must be placed on the INT_N signal rather than the GRANT_N signal.

I would presume the same problem exists with the Timer 1 module since it too receives a (slightly less) delayed version of GRANT_N. I have not yet tried to confirm this experimentally, but it could perhaps be as easy as placing a Timer 1 ISR around address 0xE500 like in Issue #108.

MJoergen commented 4 years ago

And a more general comment about the interrupt daisy chaining architecture:

Currently we have two timers and a VGA module. Soon we will have an Ethernet module too. All these devices are required to adhere to the same strict handshaking protocol whose implementation is non-trivial. So as not to have to spend too much time debugging hardware interrupt implementation, I have attempted to make a general daisy chaining module vhdl/daisy_chain.vhd in a new branch dev-vga-int.

The idea is that this module is responsible for all the intricacies of the daisy chaining protocol, whereas the individual devices (Timer, VGA, Ethernet, etc.) may remain agnostic about the overall interrupt architecture of the system. You can see an example of how this is connected in the file vhdl/vga_multicolour.vhd.

In other words, future devices (Ethernet, etc) who want to issue interrupts, should instantiate this daisy chaining module, and then everything will work out-of-the-box.

sy2002 commented 4 years ago

Excellent thoughts!

I particularly love your idea about having a general daisy chain module that everybody can and should use.

So here is my proposed the roadmap about this issue:

MJoergen commented 4 years ago

Fixed in the branch dev-vga-int.

sy2002 commented 4 years ago

Done with commit e9d4f3deeafca2e4766806e924437044795003bf

I did some extended smoke tests on hardware, here is what works:

The Smoke Test (including loading Q-TRIS via SD/FAT32 while the timer interrupt is running) ✅ fancy stand alone, mode F and then mode Bfancy in parallel with Q-TRIS (but due to issue #109, Q-TRIS was already in memory) ✅ large file load: qbin/adventure.out from SD Card while test_programs/timer_test is running and playing it

Here is what does not work, but these are separate issues that have been there before the Daisy chain module was implemented in the timer that do not prevent this one from closing: