|
/****************************************************************
模块名称:SPI 主发送模块
模块功能:用于串行接发数据,一共分四个管脚,同步时钟管脚、数据发
送端、数据接收端、片选端。发送时,高位在前低位在后,全双工、上
升沿发送数据,下降沿接收数据。
******************************************************************/
module SPI ( reset_n,sclk,clk , mosi, ss ,miso,data_out );
parameter WIDE=8; //发送数据的位宽
parameter[8:0] S0=9'd0, S1=9'd1, S2=9'd2, S3=9'd4, S4=9'd8,
S5=9'd16, S6=9'd32, S7=9'd64, S8=9'd128;
parameter[8:0] R0=9'd0, R1=9'd1, R2=9'd2, R3=9'd4, R4=9'd8,
R5=9'd16, R6=9'd32, R7=9'd64, R8=9'd128;
input sclk,miso,reset_n;
output reg mosi,clk,ss;
output [WIDE-1:0 ]data_out;
reg [WIDE-1:0 ]s_data=8'B11010101,r_data; //待发送数据寄存器
reg [WIDE:0 ] cs_send,ns_send,cs_rec,ns_rec;
/*******************************************************/
always @ ( posedge sclk )
begin
if(!reset_n) //允许收发
begin
ss<=1'b1;
clk<=1'b0;
end
else
begin
clk<=~clk;
ss<=1'b0;
end
end
/*---------------------接收数据--------------------------- */
always @ ( posedge clk ) //上升沿 发送数据
begin
if(!ss)
begin
cs_send<=ns_send;
end
else cs_send<=S0;
end
/*---------------------接收数据--------------------------- */
always @ ( negedge clk ) //上升沿 发送数据
begin
if(!ss)
begin
cs_rec<=ns_rec;
end
else cs_rec<=R0;
end
/*--------------发送状态变换---------------------------------*/
always @ (cs_send)
begin
if(!ss)
case(cs_send)
S0:ns_send=S1;
S1:ns_send=S2;
S2:ns_send=S3;
S3:ns_send=S4;
S4:ns_send=S5;
S5:ns_send=S6;
S6:ns_send=S7;
S7:ns_send=S8;
S8:ns_send=S0;
default:ns_send=S0;
endcase
else ns_send=S0;
end
/*---------------------发送数据输出---------------------------*/
always @ (posedge clk)
begin
if(!ss)
case(ns_send)
S1:mosi<=s_data[WIDE-1];
S2:mosi<=s_data[WIDE-2];
S3:mosi<=s_data[WIDE-3];
S4:mosi<=s_data[WIDE-4];
S5:mosi<=s_data[WIDE-5];
S6:mosi<=s_data[WIDE-6];
S7:mosi<=s_data[WIDE-7];
S8:mosi<=s_data[WIDE-8];
endcase
end
/*--------------接收状态变换---------------------------------*/
always @ (cs_rec)
begin
if(!ss)
case(cs_rec)
R0:ns_rec=R1;
R1:ns_rec=R2;
R2:ns_rec=R3;
R3:ns_rec=R4;
R4:ns_rec=R5;
R5:ns_rec=R6;
R6:ns_rec=R7;
R7:ns_rec=R8;
R8:ns_rec=R0;
default:ns_rec=R0;
endcase
else ns_rec=R0;
end
/*--------------------导入接收数据---------------------------*/
always @ (negedge clk)
begin
if(!ss)
case(ns_rec)
R1:r_data[WIDE-1]<=miso;
R2:r_data[WIDE-2]<=miso;
R3:r_data[WIDE-3]<=miso;
R4:r_data[WIDE-4]<=miso;
R5:r_data[WIDE-5]<=miso;
R6:r_data[WIDE-6]<=miso;
R7:r_data[WIDE-7]<=miso;
R8:r_data[WIDE-8]<=miso;
endcase
end
assign data_out = r_data;
endmodule
//-----------------------------------------------------------------------------------------------------------------------------------------------------------------
//------------------------------------------------------下面是从机模块------------------------------------------------------------------------------------------
//-----------------------------------------------------------------------------------------------------------------------------------------------------------------
/****************************************************************
模块名称:SPI2 从机模块
模块功能:用于串行接发数据,一共分四个管脚,同步时钟管脚、数据发
送端、数据接收端、片选端。发送时,高位在前低位在后,全双工、上
升沿发送数据,下降沿接收数据。
******************************************************************/
module SPI2 ( clk , miso, ss ,mosi, data);
parameter WIDE=8; //发送数据的位宽
parameter T0=9'd0,T1=9'd1,T2=9'd2,T3=9'd4,T4=9'd8,T5=9'd16,
T6=9'd32,T7=9'd64,T8=9'd128;
parameter R0=9'd0,R1=9'd1,R2=9'd2,R3=9'd4,R4=9'd8,R5=9'd16,
R6=9'd32,R7=9'd64,R8=9'd128;
input clk,miso,ss;
output mosi;
reg mosi_r;
reg [WIDE-1:0 ]t_data=8'B10001111,r_data; //待发送数据寄存器
reg [8:0]state_send,next_state;
reg [8:0] state_recive,next_rec;
output wire [WIDE-1:0 ]data;
/*------------------------状态转换模块----------------------------*/
always @ (posedge clk)
begin
if(!ss)
state_send<=next_state;
else
state_send<=T0;
end
always @ (negedge clk )
begin
if(!ss)
state_recive<=next_rec;
else
state_recive<=R0;
end
/*---------------------send数据---------------------------*/
always @ (state_send ) //上升沿 发送数据
begin
if(!ss)
begin
case(state_send)
T0:next_state=T1;
T1:next_state=T2;
T2:next_state=T3;
T3:next_state=T4;
T4:next_state=T5;
T5:next_state=T6;
T6:next_state=T7;
T7:next_state=T8;
T8:next_state=T0;
default:next_state=T0;
endcase
end
else next_state=T0;
end
always @ ( posedge clk ) //上升沿 发送数据
begin
if(!ss)
begin
case(next_state)
T1: begin
mosi_r<=t_data[WIDE-1];
end
T2: begin
mosi_r=t_data[WIDE-2];
end
T3: begin
mosi_r<=t_data[WIDE-3];
end
T4: begin
mosi_r<=t_data[WIDE-4];
end
T5: begin
mosi_r<=t_data[WIDE-5];
end
T6: begin
mosi_r<=t_data[WIDE-6];
end
T7: begin
mosi_r<=t_data[WIDE-7];
end
T8: begin
mosi_r<=t_data[WIDE-8];
end
endcase
end
end
assign mosi=mosi_r;
/*---------------------接收数据---------------------------*/
always @ (state_recive)
begin
if(!ss)
begin
case(state_recive)
R0:next_rec=R1;
R1: begin
next_rec=R2;
end
R2: begin
next_rec=R3;
end
R3: begin
next_rec=R4;
end
R4: begin
next_rec=R5;
end
R5: begin
next_rec=R6;
end
R6: begin
next_rec=R7;
end
R7: begin
next_rec=R8;
end
R8: begin
next_rec=R0;
end
default:next_rec=R0;
endcase
end
else next_rec=R0;
end
always @ (negedge clk)
begin
if(!ss)
case(next_rec)
R1: begin
r_data[WIDE-1]<=miso;
end
R2: begin
r_data[WIDE-2]<=miso;
end
R3: begin
r_data[WIDE-3]<=miso;
end
R4: begin
r_data[WIDE-4]<=miso;
end
R5: begin
r_data[WIDE-5]<=miso;
end
R6: begin
r_data[WIDE-6]<=miso;
end
R7: begin
r_data[WIDE-7]<=miso;
end
R8: begin
r_data[WIDE-8]<=miso;
end
endcase
end
assign data=r_data;
endmodule
//希望大家多多指点^ |
阿莫论坛20周年了!感谢大家的支持与爱护!!
知道什么是神吗?其实神本来也是人,只不过神做了人做不到的事情 所以才成了神。 (头文字D, 杜汶泽)
|