Serial Peripheral Interface (SPI) Tutorial
Serial Peripheral Interface (SPI) Tutorial
Serial Peripheral Interface (SPI) Tutorial
Home
Tutorials
Community
Poll
Tutorials
https://embeddedmicro.com/tutorials/mojo/serial-peripheral-interface-spi
1/6
04/04/2015
SPI Slave
In the Mojo Base Project, the file spi_slave.v contains the SPI module used to
interface with the AVR. The AVR, in this case, is the master and the FPGA is the
slave. The reason the AVR is the master is because the SPI bus is used to transfer
data from the analog pins. Since the FPGA has no way of knowing when the data
would be available, the FPGA would have to keep asking the AVR if it had any data.
By making the AVR the master, it allows it to send the data right when it's ready.
https://embeddedmicro.com/tutorials/mojo/serial-peripheral-interface-spi
2/6
04/04/2015
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
module spi_slave(
inputclk,
inputrst,
inputss,
inputmosi,
outputmiso,
inputsck,
outputdone,
input[7:0]din,
output[7:0]dout
)
;
r
e
gmosi_d,mosi_q;
r
e
gss_d,ss_q;
r
e
gsck_d,sck_q;
r
e
gsck_old_d,sck_old_q;
r
e
g[7:0]data_d,data_q;
r
e
gdone_d,done_q;
r
e
g[2:0]bit_ct_d,bit_ct_q;
r
e
g[7:0]dout_d,dout_q;
r
e
gmiso_d,miso_q;
assign miso=miso_q;
assign done=done_q;
assign dout=dout_q;
always @(*)begin
ss_d=ss;
mosi_d=mosi;
miso_d=miso_q;
sck_d=sck;
sck_old_d=sck_q;
data_d=data_q;
done_d=1'b0;
bit_ct_d=bit_ct_q;
dout_d=dout_q;
if (ss_q)begin
bit_ct_d=3'b0;
data_d=din;
miso_d=data_q[7];
if (!sck_old_q&&sck_q)begin //risingedge
data_d={data_q[6:0],mosi_q};
bit_ct_d=bit_ct_q+1'b1;
if (bit_ct_q==3'b111)begin
dout_d={data_q[6:0],mosi_q};
done_d=1'b1;
data_d=din;
end
miso_d=data_q[7];
end
end
end
https://embeddedmicro.com/tutorials/mojo/serial-peripheral-interface-spi
3/6
04/04/2015
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
if (rst)begin
done_q<=1'b0;
bit_ct_q<=3'b0;
dout_q<=8'b0;
miso_q<=1'b1;
done_q<=done_d;
bit_ct_q<=bit_ct_d;
dout_q<=dout_d;
miso_q<=miso_d;
end
sck_q<=sck_d;
mosi_q<=mosi_d;
ss_q<=ss_d;
data_q<=data_d;
sck_old_q<=sck_old_d;
end
endmodule
SPI Master
Our Clock/Visualizer Shield, uses a Real-Time Clock (RTC) device that provides the
Mojo with the current time. The RTC is connected to the Mojo through an SPI bus.
In this case, the FPGA on the Mojo is the master and the RTC is the slave.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
module spi#(parameterCLK_DIV=2)(
inputclk,
inputrst,
inputmiso,
outputmosi,
outputsck,
inputstart,
input[7:0]data_in,
output[7:0]data_out,
outputbusy,
outputnew_data
)
;
l
o
calparamSTATE_SIZE=2;
l
o
calparamIDLE=2'd0,
WAIT_HALF=2'd1,
TRANSFER=2'd2;
r
e
g[STATE_SIZE-1:0]state_d,state_q;
r
e
g[7:0]data_d,data_q;
https://embeddedmicro.com/tutorials/mojo/serial-peripheral-interface-spi
4/6
04/04/2015
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
r
e
g[CLK_DIV-1:0]sck_d,sck_q;
r
e
gmosi_d,mosi_q;
r
e
g[2:0]ctr_d,ctr_q;
r
e
gnew_data_d,new_data_q;
r
e
g[7:0]data_out_d,data_out_q;
assign mosi=mosi_q;
assign sck=(~sck_q[CLK_DIV-1])&p;(state_q==
assign busy=state_q!=IDLE;
assign data_out=data_out_q;
assign new_data=new_data_q;
always @(*)begin
sck_d=sck_q;
data_d=data_q;
mosi_d=mosi_q;
ctr_d=ctr_q;
new_data_d=1'b0;
data_out_d=data_out_q;
state_d=state_q;
case (state_q)
IDLE:begin
sck_d=4'b0;
ctr_d=3'b0;
if (start==1'b1)begin
data_d=data_in;
state_d=WAIT_HALF;
end
end
WAIT_HALF:begin
sck_d=sck_q+1'b1;
if (sck_q=={CLK_DIV-1{1'b1}})begin
sck_d=1'b0;
state_d=TRANSFER;
end
end
TRANSFER:begin
sck_d=sck_q+1'b1;
if (sck_q==4'b0000)begin
mosi_d=data_q[7];
data_d={data_q[6:0],miso};
ctr_d=ctr_q+1'b1;
if (ctr_q==3'b111)begin
state_d=IDLE;
data_out_d=data_q;
new_data_d=1'b1;
end
end
end
endcase
end
if (rst)begin
https://embeddedmicro.com/tutorials/mojo/serial-peripheral-interface-spi
5/6
04/04/2015
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
ctr_q<=3'b0;
data_q<=8'b0;
sck_q<=4'b0;
mosi_q<=1'b0;
state_q<=IDLE;
data_out_q<=8'b0;
new_data_q<=1'b0;
ctr_q<=ctr_d;
data_q<=data_d;
sck_q<=sck_d;
mosi_q<=mosi_d;
state_q<=state_d;
data_out_q<=data_out_d;
new_data_q<=new_data_d;
end
end
endmodule
https://embeddedmicro.com/tutorials/mojo/serial-peripheral-interface-spi
6/6