
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片选信号
output
spiclk
//SPI时钟信号
output
spido
//SPI数据输出信号
output
[7:0]
dataout
//接收数据输出
reg
spics
reg
spiclk
reg
spido
reg
[7:0]
dstate,
dsend,dataout,dreceive
//,cnt
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
//
cnt
<=
8'd0
spics
<=
1'b1
spiclk
<=
1'b1
spido
<=
1'b1
dstate
<=
8'd0
end
else
begin
case
(spistate)
2'b00:
begin
//
spics
<=
1'b1
//
spiclk
<=
1'b1
//
spido
<=
1'b1
//
if(cnt
==
8'd0)
//
begin
//
cnt
<=
8'd0
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
//
else
//
begin
//
cnt
<=
cnt
+
8'd1
//
end
end
2'b01:
//发送数据状态
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
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'b0
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'b0
spido
<=
dsend[3]
dstate
<=
8'd13
end
8'd13:
begin
spics
<=
1'b0
spiclk
<=
1'b1
spido
<举镇=
dsend[2]
dstate
<=
8'd14
end
8'd14:
begin
spics
<=
1'b0
spiclk
<=
1'b0
spido
<=
dsend[2]
dstate
<=
8'd15
end
8'd15:
begin
spics
<=
1'b0
spiclk
<=
1'b1
spido
<=
dsend[1]
dstate
<=
8'd16
end
8'd16:
begin
spics
<=
1'b0
spiclk
<=
1'b0
spido
<=
dsend[1]
dstate
<=
8'd17
end
8'd17:
begin
spics
<=
1'b0
spiclk
<=
1'b1
//发送最低位数据
spido
<=
dsend[0]
dstate
<=
8'd18
end
8'd18:
begin
spics
<=
1'b0
spiclk
<=
1'b0
spido
<=
dsend[0]
//spiclk的下降沿让最低位数据被读取
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)
//片选信号有效
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
你孝键可以先算出族慎散4倍与SPI时钟SCK的clkdiv,根据这个写出时钟SCK,然后posedge SCK读取MOSI线,negedge SCK向MISO写入数据,这样基本的SPI时序应该没问题,剩下就是发送命令接收数据的控制了,建议用上function,会将冗长的程序简化,但需要脑子里有较好的时序思想,若用着不顺就一位一位的读取和发送吧,云创出版社的verilog书中有SPI时兆氏序简单讲解,程序很好懂的//你的程序我看得有点晕,我这哗碰有个SPI的程序,你穗芦核看一下吧//同步猜掘
module spi(iSignRst_n,iSysClk,iSDI,oSDO,iSCK,iCS,oLED)
input iSignRst_n,iSysClk,iSDI,iSCK,iCS
output reg oSDO
output reg [7:0] oLED
reg [7:0] rIData
reg [7:0] rOData
reg rReg0Sck,rReg1Sck
reg rReg0Cs, rReg1Cs
reg rReg0Sdi,rReg1Sdi
reg [3:0] rCntShift
wire wUpSck,wDownSck
//wire wUpCs,wDownCs
wire wHighCs,wLowCs
always @(posedge iSysClk or negedge iSignRst_n)
if(~iSignRst_n)
{rReg0Sck,rReg1Sck} <= 2'd0
else
{rReg0Sck,rReg1Sck} <= {rReg1Sck,iSCK}
always @(posedge iSysClk or negedge iSignRst_n)
if(~iSignRst_n)
{rReg0Cs, rReg1Cs} <= 2'd3
else
{rReg0Cs, rReg1Cs} <= {rReg1Cs,iCS}
always @(posedge iSysClk or negedge iSignRst_n)
if(~iSignRst_n)
{rReg0Sdi,rReg1Sdi} <= 2'd0
else
{rReg0Sdi,rReg1Sdi} <= {rReg1Sdi,iSDI}
assign wUpSck= (~rReg0Sck) && rReg1Sck
assign wDownSck =rReg0Sck &&(~rReg1Sck)
//assign wUpCs = (~rReg0Cs) && rReg1Cs
//assign wDownCs =rReg0Cs &&(~rReg1Sck)
assign wHighCs =rReg0Cs && rReg1Cs
assign wLowCs = (~rReg0Cs) &&(~rReg1Cs)
always @(posedge iSysClk or negedge iSignRst_n)
if(~iSignRst_n)
rCntShift <= 4'd0
else
if(wHighCs)
rCntShift <= 4'd0
else
if(wUpSck)begin
if(rCntShift>=4'd15)
rCntShift <= 4'd15
else
rCntShift <= rCntShift + 1'b1
end
//else
//rCntShift <= rCntShift
always @(posedge iSysClk or negedge iSignRst_n)
if(~iSignRst_n)
rIData <= 8'd0
else
if(wLowCs &&wDownSck)
rIData <= {rIData[6:0],rReg0Sdi }
else
rIData <= rIData
always @(posedge iSysClk or negedge iSignRst_n)
if(~iSignRst_n)
oLED <= 8'd0
else
if((rCntShift==4'd8)&&wUpSck)
oLED <= rIData
else
oLED <= oLED
//你的oDATA不知道是怎么得出来的,我就重复上一个idata了
always @(posedge iSysClk or negedge iSignRst_n)
if(~iSignRst_n)
{oSDO,rOData} <= 9'd0
else
if(wHighCs)
{oSDO,rOData} <= {1'b0,oLED}
else
if(wUpSck)
{oSDO,rOData} <= {rOData,1'b0}
//else
// {oSDO,rOData} <= {oSDO,rOData}
endmodule
//异步
module spi(iSignRst_n,iSysClk,iSDI,oSDO,iSCK,iCS,oLED)
input iSignRst_n,iSysClk,iSDI,iSCK,iCS
output wire oSDO
output reg [7:0] oLED
reg [7:0] rIData
reg [7:0] rOData
reg [3:0] rCntShift
always @(negedge iSCK or posedge iCS)
if(iCS)
rIData <= 8'd0
else
rIData <= {rIData[6:0],iSDI}
always @(posedge iSCK or posedge iCS)
if(iCS)
rCntShift <= 4'd0
else
if(rCntShift>=4'd15)
rCntShift <= 4'd15
else
rCntShift <= rCntShift + 1'b1
always @(posedge iSCK or negedge iSignRst_n)
if(~iSignRst_n)
oLED <= 8'd0
else
if(rCntShift==4'd8)
oLED <= rIData
else
oLED <= oLED
always @(posedge iSCK or posedge iCS)
if(iCS)
rOData <= 8'd0
else
if(rCntShift==4'd0)
rOData <= oLED
else
rOData <= {rOData[6:0],1'b0}
assign oSDO = rOData[7]
endmodule
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)