When you're working on any kind of code, tightening up the write-compile-test loop is always helpful, especially when you're first learning. In the case of the SPI module, the most important thing to test is the timing of the SPI outputs. To do that we need to simulate the verilog and inspect the outputs. Here are the tools I used to do that.
I use neovim, but it doesn't really matter. I do highly recommend something with syntax highlighting, a robust find and replace, and cross-platform capability so you can use it everywhere you go.
This is where the magic happens, this script takes an argument in the form of the file you're currently working on, and waits for it to be saved. Once it is saved, the script compiles that file, simulates it, and updates GTKWave's output. I'm using it for verilog here, but you could replace the stuff after inotifywait with whatever would be useful for the project you're working on. This could be a compiler, linter, etc. I keep it's output in the top left pane of my workspace, so I can inspect any errors that come up.
while true; do inotifywait -e close_write $1 iverilog -o main $1 vvp main -lxt2 gconftool-2 --type string --set /com.geda.gtkwave/0/reload 0 done
This really is the key to the script. inotifywait exits when the file given to the script as the first argument is closed, if it was opened as writeable. That way if you cat the file, or diff it, it won't do anything. It doesn't look inside the file to see if changes were made though, it just knows the file was closed.
Icarus Verilog is a verilog synthesis and simulation tool. iVerilog compiles the source into an intermediate assembly-like source that is then executed by another part of the iVerilog toolset, vvp. Doing that outputs a .lxt file that stores the waveforms of the various wires and registers in the verilog.
In the script, the -o option to iverilog names the output file, here we just use main. Then we call vvp on main, and tell vvp to output the waveforms to a .lxt file.
When you simulate verilog, you can use printf-like statements, or you can dump the status of every line and register into a file. To look at the register dump. I'm using GTKWave. It is, in my opinion, a perfect piece of software. It does everything I need when I want to inspect the waveforms, and nothing else.
In the script, we call gconftool-2 to update the waveform. I have no idea why they chose a config tool to do this, but it works, so who am I to complain?
-Caleb and Adam