module SPI_Slave(
clk, //system clock 50MHz
SCK, SSEL, MOSI,MISO//SPI communication pin
);
input SCK, SSEL, MOSI;
output MISO;
// sync SCK to the FPGA clock using a 3-bits shift register
reg [2:0] SCKr;
always @(posedge clk) SCKr <= {SCKr[1:0], SCK};
wire SCK_risingedge = (SCKr[2:1]==2'b01); // now we can detect SCK rising edges
wire SCK_fallingedge = (SCKr[2:1]==2'b10); // and falling edges
// same thing for SSEL
reg [2:0] SSELr;
always @(posedge clk) SSELr <= {SSELr[1:0], SSEL};
wire SSEL_active = ~SSELr[1]; // SSEL is active low
wire SSEL_startmessage = (SSELr[2:1]==2'b10); // message starts at falling edge
wire SSEL_endmessage = (SSELr[2:1]==2'b01); // message stops at rising edge
// and for MOSI
reg [1:0] MOSIr;
always @(posedge clk) MOSIr <= {MOSIr[0], MOSI};
wire MOSI_data = MOSIr[1];
reg [2:0] bitcnt; // we handle SPI in 8-bits format, so we need a 3 bits counter to count the bits as they come in
//-------------------receive data-------------------------------------------------
reg byte_received; // high when a byte has been received
reg [7:0] byte_data_received,rev_data;
reg [7:0] byte_data_sent,sent_data;
always @(posedge clk)
begin
if( SSEL_active )
begin
if(SSEL_startmessage)
byte_data_sent <= sent_data;
end
if(~SSEL_active)
begin
bitcnt <= 3'b000;
byte_data_sent <= 8'h00; // after that, we send 0s///////////
end
else
if(SCK_risingedge)
begin
bitcnt <= bitcnt + 3'b001;
byte_data_received <= {byte_data_received[6:0], MOSI_data}; // implement a shift-left
//register (since we receive the data MSB first)
byte_data_sent <= {byte_data_sent[6:0], 1'b0};///////////
end
end
always @(posedge clk) byte_received <= SSEL_active && SCK_risingedge && (bitcnt==3'b111);
//-----------------------receive data---------------------
always @(posedge clk)
if(byte_received)
begin
rev_data <= byte_data_received;
end
//-----------------------send data----------------------
assign MISO = byte_data_sent[7]; // send MSB first
endmodule