summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexis Hovorka <[email protected]>2022-10-28 11:29:28 -0600
committerAlexis Hovorka <[email protected]>2022-10-28 11:29:28 -0600
commit916c766dab5d169b8327aeb03fbcfc76e194f52e (patch)
tree5da47e11a2d52bebaf774a0cdccd49565c43be29
Initial commit
-rw-r--r--.gitignore2
-rw-r--r--Makefile15
-rw-r--r--spi_controller.v61
-rw-r--r--spi_tb.v57
4 files changed, 135 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..0545d5d
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+*.vvp
+*.vcd
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..a5df170
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,15 @@
+TESTBENCH := spi_tb
+VCDFILE := main.vcd
+
+.PHONY: all clean
+
+all: $(VCDFILE)
+
+clean:
+ rm -rf $(TESTBENCH).vvp $(VCDFILE)
+
+$(VCDFILE): $(TESTBENCH).vvp
+ vvp $(TESTBENCH).vvp
+
+$(TESTBENCH).vvp: $(wildcard *.v)
+ iverilog -o $@ $^
diff --git a/spi_controller.v b/spi_controller.v
new file mode 100644
index 0000000..33ad80a
--- /dev/null
+++ b/spi_controller.v
@@ -0,0 +1,61 @@
+`default_nettype none
+
+module spi_controller
+#(parameter CPOL = 0,
+ parameter CPHA = 0)
+ (input wire clk,
+ input wire rst,
+ input wire go,
+ input wire [7:0] i_data,
+ output reg [7:0] o_data = 8'h00,
+ output wire busy,
+
+ output wire spi_clk,
+ output wire spi_mosi,
+ input wire spi_miso);
+
+ reg [3:0] state = 4'h0;
+ reg [7:0] shift_o = 8'h00;
+ reg [7:0] shift_i = 8'h00;
+
+ wire [7:0] shifted_o = {shift_o[6:0], 1'b0};
+ wire [7:0] shifted_i = {shift_i[6:0], spi_miso};
+
+ assign busy = |state;
+ assign spi_mosi = shift_o[7];
+
+ wire spi_clk_v;
+ generate
+ if (CPOL) assign spi_clk_v = ~(busy && state[0]);
+ else assign spi_clk_v = (busy && state[0]);
+ endgenerate
+
+ generate
+ if (CPHA) assign spi_clk = spi_clk_v;
+ else begin
+ reg spi_clk_d = CPOL;
+ assign spi_clk = spi_clk_d;
+ always @(posedge clk)
+ spi_clk_d <= rst? CPOL : spi_clk_v;
+ end
+ endgenerate
+
+ always @(posedge clk) begin
+ if (rst) begin
+ shift_i <= 8'h00;
+ shift_o <= 8'h00;
+ o_data <= 8'h00;
+ state <= 4'h0;
+
+ end else if (state) begin
+ state <= state - 4'h1;
+ if (~state[0]) shift_o <= shifted_o;
+ if ( state[0]) shift_i <= shifted_i;
+ if (state == 4'h1) o_data <= shifted_i;
+
+ end else if (go) begin
+ state <= 4'hF;
+ shift_o <= i_data;
+ end
+ end
+endmodule
diff --git a/spi_tb.v b/spi_tb.v
new file mode 100644
index 0000000..f042f8d
--- /dev/null
+++ b/spi_tb.v
@@ -0,0 +1,57 @@
+`timescale 1ns/1ps
+
+module main;
+ reg clk = 0;
+ always #1 clk = ~clk;
+
+ reg go = 0;
+ reg rst = 1;
+ reg [7:0] i_data = 8'hAA;
+ wire [7:0] o_data;
+ wire busy;
+
+ wire spi_clk;
+ wire spi_mosi;
+ reg spi_miso = 0;
+
+ spi_controller dut(
+ .clk(clk), .rst(rst), .go(go /*& ~busy*/),
+ .i_data(i_data), .o_data(o_data),
+ .busy(busy),
+
+ .spi_clk(spi_clk),
+ .spi_mosi(spi_mosi),
+ .spi_miso(spi_miso));
+
+ initial begin
+ $dumpfile("main.vcd");
+ $dumpvars(2, main);
+
+ //$display("Hello world!");
+ //$monitor("T%03d | clk: %0d", $time, clk);
+
+ #2 rst = 0;
+ go = 1;
+ #2 go = 0;
+
+ #3 spi_miso = 1;
+ #4 spi_miso = 0;
+ #4 spi_miso = 1;
+ #4 spi_miso = 0;
+ #4 spi_miso = 1;
+ #4 spi_miso = 0;
+ #4 spi_miso = 1;
+ #4 spi_miso = 0;
+ #4 spi_miso = 1;
+ #4 spi_miso = 0;
+ #4 spi_miso = 1;
+
+ #32 $finish;
+ end
+
+ initial begin
+ #34 i_data = 8'h55;
+ go = 1;
+ #2 go = 0;
+ end
+endmodule