# 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.
