`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 (busy) 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