spi接口的Verilog程序

spi接口的Verilog程序,第1张

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片选信号

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


欢迎分享,转载请注明来源:内存溢出

原文地址:https://www.54852.com/yw/8230730.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2023-04-14
下一篇2023-04-14

发表评论

登录后才能评论

评论列表(0条)

    保存