Luke’s USB code (as adapted by Lawrie) is core to all of my TinyFPGA BX projects. How else to get data to and from the host?
A while ago I added a pipeline (Ready/Valid) interface to this code, creating this library:
One huge bummer was that it never really passed timing. But it nearly did, and the code always worked 100% (once nextpnr became available). So… onward.
Working on another library, I really needed to know how it was working timing-wise and the non-passing of the usb code was masking the critical timing path so I decided to try to fix it. To my surprise, it turned out that the problem was that there are some unintended 32b additions and subtractions in the code and the carry chain for 32 bits can not be done at 48Mhz in iCE40. Fixing this (and a few other over-wide operations) means that the code now easily achieves 48MHz. See the commit for all the relevant changes.
A side effect of this (I used Vivado to provide some additional insight into the USB internals) was that I got tempted to see if the library runs as a serial port on the Xilinx architecture. It does - at least from Vivado! I include the Xilinx wrapper (and some photos) in this repo update, but makefiles, etc. are in another soon to be released repo.