SPI一共4个线:
*)SCK 串行时钟线:时钟信号
*)MISO 主机输入/从机输出线;
*)MOSI 主机输出/从机输入线;
*)CS 片选那个从机进行通信。
无应答机制
一定要搞清楚从设备是上升沿还是下降沿接受数据。
时钟极性:一根线上比如:主的SDO和从的SDI时钟极性相反,也就是如果主SDO是上升沿有效,那么从SDI下降沿有效。
时钟相位为0:第一个跳变沿数据采样,所以时钟前采样,时钟后输出;
时钟相位为1:第二个跳变沿数据采样,所以时钟前输出,时钟后采样。
一般使用0模式。
管脚SS非为判断主从的标志,SS非为低为从,高为主。
IP可划分为:硬IP,软IP,和两者之间的固IP
SPI
module spi_mosi(rst,clk,rd,wr,datain,spics,spiclk,spido,spidi,dataout);
input rst;//置位信号,低有效
input clk;//时钟信号
input rd;//接受数据命令
input wr;//发送数据命令
input spidi;//SPI数据输入信号
input [7:0] datain;//待发送数据~输入
output spics;//SPI片选信号
ouput spiclk;//SPI时钟信号
output spido;//SPI数据输出信号
output [7:0] dataout;//待接受数据~输出
reg spics;
reg spiclk;
reg spido;
reg [7:0] dstate,dsend,dataout,dreceive;
reg [1:0] spistate;
parameter idle = 2b00;
parameter send_data=2b01;
parameter receive_data=2b10;
initial
begin
spics<=1b1;
spiclk<=1b1;
spido<=1b1;
end
always @(posedge clk)
begin
if(!rst)
begin
spistate<=idle;
spics<=1b1;
spiclk<=1b1;
spido<=1b1;
dstate<=8d0;
end
else
begin
case(spistate)
2b00:
begin
if((wr==1b0)&&(rd==1b1))//发送数据转换
begin
spistate<=send_data;
dstate<=8d0;
dsend<=datain;
end
else if((wr==1b1)&&(rd==1b0))//接受数据转换
begin
spistate<=receive_data;
dstate<=8d0;
end
else
begin
spistate<=idle;
dstate<=8d0;
end
end
2b01://发送数据状态
begin
case(state)
8d0://产生片选信号有效
begin
spics<=1b0;
spiclk<=1b1;
spicdo<=1b1;
dstate<=8d1;
8d1:
begin
spics<=1b0;
spiclk<=1b1;
spido<=1b1;
dstate<=8d2;
end
8d2:
begin
spics<=1b0;
spiclk<=1b0;
spido<=1b1;
dstate<=8d3;
end
8d3:
begin
spics<=1b0;
spiclk<=1b1;
spido<=dsend[7];//发送数据最高位
dstate<=8d4;
end
8’d4:
begin
spics<=1b0;
spiclk<=1b0;
spido<=dsend[7];
dstate<=8d5;
end
8d5:
begin
spics<=1b0;
spiclk<=1b1;
spido<=dsend[6];
dstate<=8d6;
end
8d6:
begin
spics<=1b0;
spiclk<=1b0;
spido<=dsend[6];
dstate<=8d7;
end
8d7:
begin
spics<=1b0;
spiclk<=1b1;
spido<=dsend[5];
dstate<=8d8;
end
8d8:
begin
spics<=1b0;
spiclk<=1b1;
spido<=dsend[5];
dstate<=8d9;
end
8d9:
begin
spics<=1b0;
spiclk<=1b1;
spido<=dsend[4];
dstate<=8d10;
end
8d10:
begin
spics<=1b0;
spiclk<=1b0;
spido<=dsend[4];
dstate<=8d11;
end
8d11:
begin
spics<=1b0;
spiclk<=1b1;
spido<=dsend[3];
dstate<=8d12;
end
8d12:
begin
spics<=1b0;
spiclk<=1b1;
spido<=dsend[3];
dstate<=8d13;
end
8d13:
begin
spics<=1b0;
spiclk<=1b0;
spido<=dsend[2];
dstate<=8d14;
end
8d14:
begin
spics<=1b0;
spiclk<=1b1;
spido<=dsend[2];
dstate<=8d15;
end
8d15:
begin
spics<=1b0;
spiclk<=1b0;
spido<=dsend[1];
dstate<=8d7;
end
8d16:
begin
spics<=1b0;
spiclk<=1b1;
spido<=dsend[1];
dstate<=8d17;
end
8d17:
begin
spics<=1b0;
spiclk<=1b0;
spido<=dsend[0];
dstate<=8d18;
end
8d18:
begin
spics<=1b0;
spiclk<=1b1;
spido<=dsend[0];
dstate<=8d19;
end
8d19:
begin
spics<=1b1;
spiclk<=1b1;
spido<=1b1;
dstate<=8d20;
end
8d20:
begin
spics<=1b1;
spiclk<=1b1;
spido<=1b1
dstate<=8d0;
spistate<=idle;
end
default
begin
spics<=1b1;
spiclk<=1b1;
spido<=1b1;
spistate<=idle;
end
endcase
end
2b10://接受数据状态
begin
case(dstate)//片选信号有效
begin
case (dstate) //片选信号有效
8d0:
begin
spics <= 1b0;
spiclk <= 1b1;
spido <= 1b1;
dstate <= 8d1;
end
8d1:
begin
spics <= 1b0;
spiclk <= 1b1;
spido <= 1b1;
dstate <= 8d2;
end
8d2:
begin
spics <= 1b0;
spiclk <= 1b0;
spido <= 1b1;
dstate <= 8d3;
end
8d3:
begin
spics <= 1b0;
spiclk <= 1b1;
dstate <= 8d4;
end
8d4:
begin
spics <= 1b0;
spiclk <= 1b0; //紧接着上升沿的下降沿数据被读取
dreceive[7] <= spidi; //接收数据最高位
dstate <= 8d5;
end
8d5:
begin
spics <= 1b0;
spiclk <= 1b1;
dstate <= 8d6;
end
8d6:
begin
spics <= 1b0;
spiclk <= 1b0;
dreceive[6] <= spidi;
dstate <= 8d7;
end
8d7:
begin
spics <= 1b0;
spiclk <= 1b1;
dstate <= 8d8;
end
8d8:
begin
spics <= 1b0;
spiclk <= 1b0;
dreceive[5] <= spidi;
dstate <= 8d9;
end
8d9:
begin
spics <= 1b0;
spiclk <= 1b1;
dstate <= 8d10;
end
8d10:
begin
spics <= 1b0;
spiclk <= 1b0;
dreceive[4] <= spidi;
dstate <= 8d11;
end
8d11:
begin
spics <= 1b0;
spiclk <= 1b1;
dstate <= 8d12;
end
8d12:
begin
spics <= 1b0;
spiclk <= 1b0;
dreceive[3] <= spidi;
dstate <= 8d13;
end
8d13:
begin
spics <= 1b0;
spiclk <= 1b1;
dstate <= 8d14;
end
8d14:
begin
spics <= 1b0;
spiclk <= 1b0;
dreceive[2] <= spidi;
dstate <= 8d15;
end
8d15:
begin
spics <= 1b0;
spiclk <= 1b1;
dstate <= 8d16;
end
8d16:
begin
spics <= 1b0;
spiclk <= 1b0;
dreceive[1] <= spidi;
dstate <= 8d17;
end
8d17:
begin
spics <= 1b0;
spiclk <= 1b1;
dstate <= 8d18;
end
8d18:
begin
spics <= 1b0;
spiclk <= 1b0;
dreceive[0] <= spidi; //接收数据最低位
dstate <= 8d19;
end
8d19:
begin
spics <= 1b0;
spiclk <= 1b1;
spido <= 1b1;
dstate <= 8d20;
dataout<= dreceive;
end
8d20:
begin
spics <= 1b1; //片选信号无效
spiclk <= 1b1;
spido <= 1b1;
dstate <= 8d0;
spistate <= idle;
end
endcase
end
default:
begin
spics <= 1b1;
spiclk <= 1b1;
spido <= 1b1;
spistate <= idle;
end
endcase //对应上面的发送数据情形
end //对应上面的RST没有按下的情形
end //对应最上面的always@(posedge clk)
endmodule