module SPIController (
  // System Interfaces
  input wire clk,
  input wire rst,

  // SPI Bus Interfaces
  output reg CS0,
  output reg CS1,
  output reg SPICLK,
  output reg MOSI,
  input wire MISO,

  // Input Signals
  input wire Addr15, 		// Sampled on Phase 01
  input wire Read_notWrite,	// Sampled on Phase 16
  input wire Addr,		// Sampled on Phase 18[bit0/LSB], 20[bit1], ..., 44[bit13], 46[bit14/MSB], bit 15 not sampled (see Addr15)
  input wire Data,		// Sampled on Phase 50[bit0/LSB], 52[bit1], ..., 78[bit14], 80[bit15/MSB]


  // Timing Output Signals
  output reg ShiftAddr,		// Asserted when the Address should be shifted
  output reg ShiftDataRead,     // Asserted when the data register collecting data read from memory should be shifted
  output reg ShiftDataWrite,    // Asserted when the data regsiter providing data to be written to memory should be shifted
  output reg PresetCarry,       // Asserted the clock before data motion starts
  output reg EndOfPhase,        //
  output reg PrepOutput
);

  // SPI sequencer
  reg [6:0] SPIphase;
  always @(posedge clk) begin
    if (rst)
      SPIphase <= 0;
    else if (SPIphase == 83)
      SPIphase <= 0;
    else
      SPIphase <= SPIphase + 1;
  end

  // SPI bus signal generator
  always @(posedge clk) begin
    if (SPIphase <= 1) begin
      CS0 <= 1;
      CS1 <= 1;
      SPICLK <= 0;
      MOSI <= 0;
    end else begin
      CS0 <= CSreg;
      CS1 <= !CSreg;
      if (SPIphase <= 81)
        SPICLK <= SPIphase[0];
      else
        SPICLK <= 0;

      if (SPIphase <= 13)
        MOSI <= 0;
      else if (SPIphase <= 15)
        MOSI <= 1;
      else if (SPIphase <= 17) begin
        if (SPIphase[0] == 0)
          MOSI <= Read_notWrite;
      end else if (SPIphase <= 47) begin
        if (SPIphase[0] == 0)
          MOSI <= Addr;
      end else if (SPIphase <= 49)
        MOSI <= 0;
      else begin
        if (Read_notWrite)
          MOSI <= 0;
        else begin
          if (SPIphase[0] == 0)
            MOSI <= Data;
        end
      end
    end
  end

  // Generate Address Shift Enable Signals
  always @(posedge clk) begin
    ShiftAddr <= ((SPIphase >= 18) && (SPIphase <= 48) && (SPIphase[0] == 0));
    ShiftDataRead <= ((SPIphase >= 51) && (SPIphase <= 81) && (SPIphase[0] == 1) && Read_notWrite);
    ShiftDataWrite <= ((SPIphase >= 50) && (SPIphase <= 80) && (SPIphase[0] == 0) && !Read_notWrite);
    PresetCarry <= (SPIphase == 17);
    EndOfPhase <= (SPIphase == 83);
    PrepOutput <= (SPIphase == 49);
  end

  reg CSreg;
  always @(posedge clk) begin
    if (SPIphase == 1)
      CSreg <= Addr15;
  end

endmodule