summaryrefslogtreecommitdiff
path: root/spi_controller.v
blob: 33ad80a639baec33977bae43af2f036b1bf1d179 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
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