diff options
Diffstat (limited to 'spi_controller.v')
-rw-r--r-- | spi_controller.v | 61 |
1 files changed, 61 insertions, 0 deletions
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 |