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 = 2'b00;
parameter send_data=2'b01;
parameter receive_data=2'b10;
initial
begin
spics<=1'b1;
spiclk<=1'b1;
spido<=1'b1;
end
always @(posedge clk)
begin
if(!rst)
begin
spistate<=idle;
spics<=1'b1;
spiclk<=1'b1;
spido<=1'b1;
dstate<=8'd0;
end
else
begin
case(spistate)
2'b00:
begin
if((wr==1'b0)&&(rd==1'b1))//发送数据转换
begin
spistate<=send_data;
dstate<=8'd0;
dsend<=datain;
end
else if((wr==1'b1)&&(rd==1'b0))//接受数据转换
begin
spistate<=receive_data;
dstate<=8'd0;
end
else
begin
spistate<=idle;
dstate<=8'd0;
end
end
2'b01://发送数据状态
begin
case(state)
8'd0://产生片选信号有效
begin
spics<=1'b0;
spiclk<=1'b1;
spicdo<=1'b1;
dstate<=8'd1;
8'd1:
begin
spics<=1'b0;
spiclk<=1'b1;
spido<=1'b1;
dstate<=8'd2;
end
8'd2:
begin
spics<=1'b0;
spiclk<=1'b0;
spido<=1'b1;
dstate<=8'd3;
end
8'd3:
begin
spics<=1'b0;
spiclk<=1'b1;
spido<=dsend[7];//发送数据最高位
dstate<=8'd4;
end
8’d4:
begin
spics<=1'b0;
spiclk<=1'b0;
spido<=dsend[7];
dstate<=8'd5;
end
8'd5:
begin
spics<=1'b0;
spiclk<=1'b1;
spido<=dsend[6];
dstate<=8'd6;
end
8'd6:
begin
spics<=1'b0;
spiclk<=1'b0;
spido<=dsend[6];
dstate<=8'd7;
end
8'd7:
begin
spics<=1'b0;
spiclk<=1'b1;
spido<=dsend[5];
dstate<=8'd8;
end
8'd8:
begin
spics<=1'b0;
spiclk<=1'b1;
spido<=dsend[5];
dstate<=8'd9;
end
8'd9:
begin
spics<=1'b0;
spiclk<=1'b1;
spido<=dsend[4];
dstate<=8'd10;
end
8'd10:
begin
spics<=1'b0;
spiclk<=1'b0;
spido<=dsend[4];
dstate<=8'd11;
end
8'd11:
begin
spics<=1'b0;
spiclk<=1'b1;
spido<=dsend[3];
dstate<=8'd12;
end
8'd12:
begin
spics<=1'b0;
spiclk<=1'b1;
spido<=dsend[3];
dstate<=8'd13;
end
8'd13:
begin
spics<=1'b0;
spiclk<=1'b0;
spido<=dsend[2];
dstate<=8'd14;
end
8'd14:
begin
spics<=1'b0;
spiclk<=1'b1;
spido<=dsend[2];
dstate<=8'd15;
end
8'd15:
begin
spics<=1'b0;
spiclk<=1'b0;
spido<=dsend[1];
dstate<=8'd7;
end
8'd16:
begin
spics<=1'b0;
spiclk<=1'b1;
spido<=dsend[1];
dstate<=8'd17;
end
8'd17:
begin
spics<=1'b0;
spiclk<=1'b0;
spido<=dsend[0];
dstate<=8'd18;
end
8'd18:
begin
spics<=1'b0;
spiclk<=1'b1;
spido<=dsend[0];
dstate<=8'd19;
end
8'd19:
begin
spics<=1'b1;
spiclk<=1'b1;
spido<=1'b1;
dstate<=8'd20;
end
8'd20:
begin
spics<=1'b1;
spiclk<=1'b1;
spido<=1'b1
dstate<=8'd0;
spistate<=idle;
end
default
begin
spics<=1'b1;
spiclk<=1'b1;
spido<=1'b1;
spistate<=idle;
end
endcase
end
2'b10://接受数据状态
begin
case(dstate)//片选信号有效
begin
case (dstate) //片选信号有效
8'd0:
begin
spics <= 1'b0;
spiclk <= 1'b1;
spido <= 1'b1;
dstate <= 8'd1;
end
8'd1:
begin
spics <= 1'b0;
spiclk <= 1'b1;
spido <= 1'b1;
dstate <= 8'd2;
end
8'd2:
begin
spics <= 1'b0;
spiclk <= 1'b0;
spido <= 1'b1;
dstate <= 8'd3;
end
8'd3:
begin
spics <= 1'b0;
spiclk <= 1'b1;
dstate <= 8'd4;
end
8'd4:
begin
spics <= 1'b0;
spiclk <= 1'b0; //紧接着上升沿的下降沿数据被读取
dreceive[7] <= spidi; //接收数据最高位
dstate <= 8'd5;
end
8'd5:
begin
spics <= 1'b0;
spiclk <= 1'b1;
dstate <= 8'd6;
end
8'd6:
begin
spics <= 1'b0;
spiclk <= 1'b0;
dreceive[6] <= spidi;
dstate <= 8'd7;
end
8'd7:
begin
spics <= 1'b0;
spiclk <= 1'b1;
dstate <= 8'd8;
end
8'd8:
begin
spics <= 1'b0;
spiclk <= 1'b0;
dreceive[5] <= spidi;
dstate <= 8'd9;
end
8'd9:
begin
spics <= 1'b0;
spiclk <= 1'b1;
dstate <= 8'd10;
end
8'd10:
begin
spics <= 1'b0;
spiclk <= 1'b0;
dreceive[4] <= spidi;
dstate <= 8'd11;
end
8'd11:
begin
spics <= 1'b0;
spiclk <= 1'b1;
dstate <= 8'd12;
end
8'd12:
begin
spics <= 1'b0;
spiclk <= 1'b0;
dreceive[3] <= spidi;
dstate <= 8'd13;
end
8'd13:
begin
spics <= 1'b0;
spiclk <= 1'b1;
dstate <= 8'd14;
end
8'd14:
begin
spics <= 1'b0;
spiclk <= 1'b0;
dreceive[2] <= spidi;
dstate <= 8'd15;
end
8'd15:
begin
spics <= 1'b0;
spiclk <= 1'b1;
dstate <= 8'd16;
end
8'd16:
begin
spics <= 1'b0;
spiclk <= 1'b0;
dreceive[1] <= spidi;
dstate <= 8'd17;
end
8'd17:
begin
spics <= 1'b0;
spiclk <= 1'b1;
dstate <= 8'd18;
end
8'd18:
begin
spics <= 1'b0;
spiclk <= 1'b0;
dreceive[0] <= spidi; //接收数据最低位
dstate <= 8'd19;
end
8'd19:
begin
spics <= 1'b0;
spiclk <= 1'b1;
spido <= 1'b1;
dstate <= 8'd20;
dataout<= dreceive;
end
8'd20:
begin
spics <= 1'b1; //片选信号无效
spiclk <= 1'b1;
spido <= 1'b1;
dstate <= 8'd0;
spistate <= idle;
end
endcase
end
default:
begin
spics <= 1'b1;
spiclk <= 1'b1;
spido <= 1'b1;
spistate <= idle;
end
endcase //对应上面的发送数据情形
end //对应上面的RST没有按下的情形
end //对应最上面的always@(posedge clk)
endmodule