From 85f12c75f1aeb7ef6140d028b941d5dde4bed4ba Mon Sep 17 00:00:00 2001 From: Byron Lathi Date: Fri, 21 Jul 2023 22:10:39 -0700 Subject: [PATCH] Start spi controller and tb --- .gitignore | 1 + .vscode/settings.json | 5 -- hw/efinix_fpga/simulation/Makefile | 5 +- .../simulation/spi_controller_tb.sv | 69 +++++++++++++++ hw/efinix_fpga/spi_controller.sv | 84 +++++++++++++++++++ 5 files changed, 158 insertions(+), 6 deletions(-) create mode 100644 .gitignore delete mode 100644 .vscode/settings.json create mode 100644 hw/efinix_fpga/simulation/spi_controller_tb.sv create mode 100644 hw/efinix_fpga/spi_controller.sv diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..722d5e7 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.vscode diff --git a/.vscode/settings.json b/.vscode/settings.json deleted file mode 100644 index 0cbf8a7..0000000 --- a/.vscode/settings.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "files.associations": { - "conio.h": "c" - } -} \ No newline at end of file diff --git a/hw/efinix_fpga/simulation/Makefile b/hw/efinix_fpga/simulation/Makefile index 2befbaf..ebaffce 100644 --- a/hw/efinix_fpga/simulation/Makefile +++ b/hw/efinix_fpga/simulation/Makefile @@ -1,4 +1,4 @@ -TARGETS= timer interrupt_controller +TARGETS= timer interrupt_controller spi_controller TB=$(patsubst %, %_tb.sv, $(TARGETS)) all: $(TARGETS) @@ -6,6 +6,9 @@ all: $(TARGETS) timer: timer_tb.sv iverilog -g2005-sv -s sim -o $@ $@_tb.sv ../$@.sv +spi_controller: spi_controller_tb.sv + iverilog -g2005-sv -s sim -o $@ $@_tb.sv ../$@.sv + interrupt_controller: interrupt_controller_tb.sv iverilog -g2005-sv -s sim -o $@ $@_tb.sv ../$@.sv diff --git a/hw/efinix_fpga/simulation/spi_controller_tb.sv b/hw/efinix_fpga/simulation/spi_controller_tb.sv new file mode 100644 index 0000000..37c1ae3 --- /dev/null +++ b/hw/efinix_fpga/simulation/spi_controller_tb.sv @@ -0,0 +1,69 @@ +module sim(); + +timeunit 10ns; +timeprecision 1ns; + +logic clk_50; + +logic i_clk; +logic i_rst; + +logic i_cs; +logic i_rwb; +logic [1:0] i_addr; +logic [7:0] i_data; +logic [7:0] o_data; + +logic o_spi_cs; +logic o_spi_clk; +logic o_spi_mosi; +logic i_spi_miso; + +spi_controller dut(.*); + +always #1 clk_50 = clk_50 === 1'b0; +always #100 i_clk = i_clk === 1'b0; + +task write_reg(input logic [2:0] _addr, input logic [7:0] _data); + @(negedge i_clk); + i_cs <= '1; + i_addr <= _addr; + i_rwb <= '0; + i_data <= '1; + @(posedge i_clk); + i_data <= _data; + @(negedge i_clk); + i_cs <= '0; + i_rwb <= '1; +endtask + +task read_reg(input logic [2:0] _addr, output logic [7:0] _data); + @(negedge i_clk); + i_cs <= '1; + i_addr <= _addr; + i_rwb <= '1; + i_data <= '1; + @(posedge i_clk); + _data <= o_data; + @(negedge i_clk); + i_cs <= '0; + i_rwb <= '1; +endtask + +initial +begin + $dumpfile("spi_controller.vcd"); + $dumpvars(0,sim); +end + +initial begin + i_rst <= '1; + repeat(5) @(posedge i_clk); + i_rst <= '0; + + repeat(5) @(posedge i_clk); + + $finish(); +end + +endmodule \ No newline at end of file diff --git a/hw/efinix_fpga/spi_controller.sv b/hw/efinix_fpga/spi_controller.sv new file mode 100644 index 0000000..9b806f7 --- /dev/null +++ b/hw/efinix_fpga/spi_controller.sv @@ -0,0 +1,84 @@ +module spi_controller( + input i_clk, + input i_rst, + + input i_cs, + input i_rwb, + input [1:0] i_addr, + input [7:0] i_data, + output logic [7:0] o_data, + + output o_spi_cs, + output o_spi_clk, + output o_spi_mosi, + input i_spi_miso +); + + +// We need a speed register +// an input data register +// and an output data register +// and then a control register for cs + +logic [7:0] r_baud_rate; +logic [7:0] r_input_data; +logic [7:0] r_output_data; +logic [7:0] r_control; + +logic [8:0] r_clock_counter; + +logic active; +logic spi_clk; + +logic r_spi_mosi; + +always @(posedge i_clk) begin + if (i_rst) begin + r_baud_rate <= 8'h10; + r_input_data <= '0; + r_output_data <= '0; + r_control <= '0; + r_clock_counter <= '0; + spi_clk <= '0; + end else begin + if (~i_rwb & i_cs) begin + unique case (i_addr) + 0: r_baud_rate <= i_data; + 1:; + 2: begin + r_output_data <= i_data; + active <= '1; + end + 3: r_control <= i_data; + endcase + end + + if (active) begin + r_spi_mosi <= r_output_data[0]; + r_clock_counter <= r_clock_counter + 9'b1; + if (r_clock_counter >= r_baud_rate) begin + r_clock_counter <= '0; + spi_clk <= ~spi_clk; + if (spi_clk == '0) begin + r_output_data <= r_output_data >> 1; + end + if (spi_clk == '1) begin + r_input_data <= {r_input_data[7:1], i_spi_miso}; + end + end + + end + end +end + +always_comb begin + unique case (i_addr) + 0: o_data = r_baud_rate; + 1: o_data = r_input_data; + 2:; + 3: o_data = r_control; + endcase +end + + +endmodule \ No newline at end of file