Files
rose/devlog/2025-05-10-Back-on-track.md

3.1 KiB

SPI slave implementation on the Tang Primer 20K

Date: 2025-05-04

Goals and expectations

Get back on track.

I've been stalling even more due to the co-op term starting and having a lot to learn every day. But they also gave me a lot of inspiration, especially DCTCP and some efforts from UET's congestion management methods, with its adaptive adjusting of transmission windows.

It feels good to see some more ideas getting integrated into ROSE, but also daunting because I know if I don't get moving soon, this will end up in the trash.

Results

Decent. Decent progress considering the past week, I managed to solve the sync issue.

My first approach was to just use 2 flip-flops to detect the rising and the falling edges, but somehow the transmission part is delayed by exactly 1 bit (sclk cycle). It's normal for the 2 flip-flop method to induce a one-time delay of 1-2 cycles (resolvable by dumping the first byte), but not normal for it to actually be permanently delayed. It would've been great if I just set miso with the second most significant bit, but that's not a solution if I want to pipe entire bytes to a queue somewhere else.

Thanks to the tutorial on https://www.fpga4fun.com/SPI2.html, I found the problem - I have to prepare the sending bit before the falling edge, and by the time my edge detection has reported a falling edge, the testbench had already sampled the miso line.

With that out of the way, I can finally start thinking about how to implement a simple routing logic.

Reflections

  1. Elegance matters. The first approach was "okay" in the sense that it actually did what I want, but "not okay" in the sense that it fits terribly in a system. If it's not elegant, it probably won't fit.
  2. Plan small. I never thought that syncing across clock domains could be such a problem, and it can even reveal problems in a working design (i.e. the module I wrote on the first day that uses sclk directly, it tries to assign the new miso value upon negedge sclk and worked perfectly fine in the sim). Plan small and hope that you can do more.
  3. Read other people's code, see how other people do it, find good resources. I originally didn't try to use other people's code simply because the code I found on GitHub were to generalized and complex for my current understanding, and that they used Verilog, which would be pain if I tried to run it in SystemVerilog. But once I switched the keywords from "SPI SystemVerilog" to "SPI FPGA", the referenced tutorial came up and it was a lifesaver. Cleanest code for implementing the features I wanted.
  4. Plan well. The first approach was caught as a somehow-running-bug immediately as I try to integrate it into the larger system. This is planning helping you navigate the project and signaling pitfalls very early on.

Final thoughts

Hopefully, co-op would ease (as I digest all the incoming info from all the training), and we make progress.

I can't imagine how metastability in systems running on higher clocks could be built if all the people builds stuff like I do ;)

The next step

Implement FIFO modules. Try to send a byte stream backwards.