近期写了篇spi通讯,fpga作为从站:仿真后信号正确性是可行的;
数据位宽32位,正在测试长期运行的效果!
/*
**************************************************************************
* spi
* Filename : spi.v
* Describel : spi总线,数据移位处理模块;
* 发送,接收均为32位数据;
* 接收时,上升沿移入数据;
* 发送时,上升沿来之前放上数据
* 用于SPI从动模式
*
**************************************************************************
*/
//use SPI 1 mode,CHOL = 0,CHAL = 0
module spi( clk,
rst_n,
CS_N,
SCK,
MOSI,
MISO,
data_o,
data_in
);
input clk; //主频时钟25M
input rst_n; //复位信号
input CS_N; // spi拉低cs使能
input SCK; // spi数据发送接收时钟
input MOSI; // spi输入缓存数据
input [31:0] data_in;
//reg [7:0] txd_data; // spi发送数据
output wire MISO; // spi输出缓存数据
output reg[31:0] data_o;
/*
*********************************************************************
* 滤波
*********************************************************************
*/
wire sck_o,cs_n_o,mosi_o;
reg MISO_O;
filter u_sck (.clk_i(clk),.s_i(SCK), .s_o(sck_o));
filter u_cs_n (.clk_i(clk),.s_i(CS_N), .s_o(cs_n_o));
filter u_mosi (.clk_i(clk),.s_i(MOSI), .s_o(mosi_o));
filter u_miso (.clk_i(clk),.s_i(MISO_O), .s_o(MISO));
/*
*********************************************************************
* cpld作为从机读取数据,SPI接收部分使用有限状态机
*********************************************************************
*/
reg [5:0] rxd_state; //SPI接收部分状态机
reg [31:0] rec_data; //16位接收数据寄存器
always@(negedge sck_o ) //每次sck上升沿都会接收数据,spi的顶端模块状态机决定是否取用
begin
if(!rst_n) //复位
begin //初始个状态值
rxd_state <= 6'b0;
end
else if(!cs_n_o) //片选信号置低,移入数据
begin
case(rxd_state) //SPI接收部分使用有限状态机
6'd0:begin //SPI接收状态0
rec_data[31] <= mosi_o; //MOSI的数据移入移位寄存器rec_data[15]
rxd_state <= 6'd1; //接收状态进入下一步
end
6'd1:begin //SPI接收状态1
rec_data[30] <= mosi_o; //MOSI的数据移入移位寄存器rec_data[14]
rxd_state <= 6'd2; //接收状态进入下一步
end
6'd2:begin //SPI接收状态2
rec_data[29] <= mosi_o;
rxd_state <= 6'd3;
end
6'd3:begin //SPI接收状态3
rec_data[28] <= mosi_o;
rxd_state <= 6'd4;
end
6'd4:begin //SPI接收状态4
rec_data[27] <= mosi_o;
rxd_state <= 6'd5;
end
6'd5:begin //SPI接收状态5
rec_data[26] <= mosi_o;
rxd_state <= 6'd6;
end
6'd6:begin //SPI接收状态6
rec_data[25] <= mosi_o;
rxd_state <= 6'd7;
end
6'd7:begin //SPI接收状态7
rec_data[24] <= mosi_o;
rxd_state <= 6'd8; //接收状态进入下一步
end
6'd8:begin //SPI接收状态8
rec_data[23] <= mosi_o; //MOSI的数据移入移位寄存器rxd_data[7]
rxd_state <= 6'd9; //接收状态进入下一步
end
6'd9:begin //SPI接收状态9
rec_data[22] <= mosi_o; //MOSI的数据移入移位寄存器rxd_data[6]
rxd_state <= 6'd10; //接收状态进入下一步
end
6'd10:begin //SPI接收状态10
rec_data[21] <= mosi_o;
rxd_state <= 6'd11;
end
6'd11:begin //SPI接收状态11
rec_data[20] <= mosi_o;
rxd_state <= 6'd12;
end
6'd12:begin //SPI接收状态12
rec_data[19] <= mosi_o;
rxd_state <= 6'd13;
end
6'd13:begin //SPI接收状态13
rec_data[18] <= mosi_o;
rxd_state <= 6'd14;
end
6'd14:begin //SPI接收状态14
rec_data[17] <= mosi_o;
rxd_state <= 6'd15;
end
6'd15:begin //SPI接收状态15
rec_data[16] <= mosi_o;
rxd_state <= 6'd16;
end
6'd16:begin //SPI接收状态16
rec_data[15] <= mosi_o;
rxd_state <= 6'd17;
end
6'd17:begin //SPI接收状态17
rec_data[14] <= mosi_o;
rxd_state <= 6'd18;
end
6'd18:begin //SPI接收状态18
rec_data[13] <= mosi_o;
rxd_state <= 6'd19;
end
6'd19:begin //SPI接收状态19
rec_data[12] <= mosi_o;
rxd_state <= 6'd20;
end
6'd20:begin //SPI接收状态20
rec_data[11] <= mosi_o;
rxd_state <= 6'd21;
end
6'd21:begin //SPI接收状态21
rec_data[10] <= mosi_o;
rxd_state <= 6'd22;
end
6'd22:begin //SPI接收状态22
rec_data[9] <= mosi_o;
rxd_state <= 6'd23;
end
6'd23:begin //SPI接收状态23
rec_data[8] <= mosi_o;
rxd_state <= 6'd24;
end
6'd24:begin //SPI接收状态24
rec_data[7] <= mosi_o;
rxd_state <= 6'd25;
end
6'd25:begin //SPI接收状态25
rec_data[6] <= mosi_o;
rxd_state <= 6'd26;
end
6'd26:begin //SPI接收状态26
rec_data[5] <= mosi_o;
rxd_state <= 6'd27;
end
6'd27:begin //SPI接收状态27
rec_data[4] <= mosi_o;
rxd_state <= 6'd28;
end
6'd28:begin //SPI接收状态28
rec_data[3] <= mosi_o;
rxd_state <= 6'd29;
end
6'd29:begin //SPI接收状态29
rec_data[2] <= mosi_o;
rxd_state <= 6'd30;
end
6'd30:begin //SPI接收状态30
rec_data[1] <= mosi_o;
rxd_state <= 6'd31;
end
6'd31:begin //SPI接收状态31
rec_data[0] <= mosi_o;
rxd_state <= 6'd0;
end
default: ;
endcase
end
end
always @(negedge clk)
begin
if(!rst_n)
data_o<=32'd0;
else if(cs_n_o)
data_o<=rec_data;
end
reg [31:0] data_reg;
always @(negedge clk)
begin
if(!rst_n)
data_reg<=32'd0;
else
data_reg<= cs_n_o ? data_in :data_reg;
end
reg [5:0] rxd_state1;
always@(posedge sck_o )
begin
if(!rst_n)
begin
rxd_state1 <= 6'b0;
end
else if(!cs_n_o)
begin
case(rxd_state1) //SPI接收部分使用有限状态机
6'd0:begin //SPI发送状态0
MISO_O <=data_reg[31];
rxd_state1 <= 6'd1; //发送状态进入下一步
end
6'd1:begin //SPI发送状态1
MISO_O <=data_reg[30];
rxd_state1 <= 6'd2; //发送状态进入下一步
end
6'd2:begin //SPI发送状态2
MISO_O <=data_reg[29];
rxd_state1 <= 6'd3;
end
6'd3:begin //SPI发送状态3
MISO_O <=data_reg[28];
rxd_state1 <= 6'd4;
end
6'd4:begin //SPI发送状态4
MISO_O <=data_reg[27];
rxd_state1 <= 6'd5;
end
6'd5:begin //SPI发送状态5
MISO_O <=data_reg[26];
rxd_state1 <= 6'd6;
end
6'd6:begin //SPI发送状态6
MISO_O <=data_reg[25];
rxd_state1 <= 6'd7;
end
6'd7:begin //SPI发送状态7
MISO_O <=data_reg[24];
rxd_state1 <= 6'd8; //发送状态进入下一步
end
6'd8:begin //SPI发送状态8
MISO_O <=data_reg[23];
rxd_state1 <= 6'd9; //发送状态进入下一步
end
6'd9:begin //SPI发送状态9
MISO_O <=data_reg[22];
rxd_state1 <= 6'd10; //发送状态进入下一步
end
6'd10:begin //SPI发送状态10
MISO_O <=data_reg[21];
rxd_state1 <= 6'd11;
end
6'd11:begin //SPI发送状态11
MISO_O <=data_reg[20];
rxd_state1 <= 6'd12;
end
6'd12:begin //SPI发送状态12
MISO_O <=data_reg[19];
rxd_state1 <= 6'd13;
end
6'd13:begin //SPI发送状态13
MISO_O <=data_reg[18];
rxd_state1 <= 6'd14;
end
6'd14:begin //SPI发送状态14
MISO_O <=data_reg[17];
rxd_state1 <= 6'd15;
end
6'd15:begin //SPI发送状态15
MISO_O <=data_reg[16];
rxd_state1 <= 6'd16;
end
6'd16:begin //SPI发送状态16
MISO_O <=data_reg[15];
rxd_state1 <= 6'd17;
end
6'd17:begin //SPI发送状态17
MISO_O <=data_reg[14];
rxd_state1 <= 6'd18;
end
6'd18:begin //SPI发送状态18
MISO_O <=data_reg[13];
rxd_state1 <= 6'd19;
end
6'd19:begin //SPI发送状态19
MISO_O <=data_reg[12];
rxd_state1 <= 6'd20;
end
6'd20:begin //SPI发送状态20
MISO_O <=data_reg[11];
rxd_state1 <= 6'd21;
end
6'd21:begin //SPI发送状态21
MISO_O <=data_reg[10];
rxd_state1 <= 6'd22;
end
6'd22:begin //SPI发送状态22
MISO_O <=data_reg[9];
rxd_state1 <= 6'd23;
end
6'd23:begin //SPI发送状态23
MISO_O <=data_reg[8];
rxd_state1 <= 6'd24;
end
6'd24:begin //SPI发送状态24
MISO_O <=data_reg[7];
rxd_state1 <= 6'd25;
end
6'd25:begin //SPI发送状态25
MISO_O <=data_reg[6];
rxd_state1 <= 6'd26;
end
6'd26:begin //SPI发送状态26
MISO_O <=data_reg[5];
rxd_state1 <= 6'd27;
end
6'd27:begin //SPI发送状态27
MISO_O <=data_reg[4];
rxd_state1 <= 6'd28;
end
6'd28:begin //SPI发送状态28
MISO_O <=data_reg[3];
rxd_state1 <= 6'd29;
end
6'd29:begin //SPI发送状态29
MISO_O <=data_reg[2];
rxd_state1 <= 6'd30;
end
6'd30:begin //SPI发送状态30
MISO_O <=data_reg[1];
rxd_state1 <= 6'd31;
end
6'd31:begin //SPI发送状态31
MISO_O <=data_reg[0];
rxd_state1 <= 6'd0;
end
default: ;
endcase
end
end
endmodule
该写法过于繁琐,改进:通过移位寄存器将数据存储发送。