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
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
|
//
// Copyright 2015 Ettus Research LLC
//
`ifndef LOG2
`define LOG2(N) (\
N < 2 ? 0 : \
N < 4 ? 1 : \
N < 8 ? 2 : \
N < 16 ? 3 : \
N < 32 ? 4 : \
N < 64 ? 5 : \
N < 128 ? 6 : \
N < 256 ? 7 : \
N < 512 ? 8 : \
N < 1024 ? 9 : \
10)
`endif
module spi_slave
#(
parameter DEPTH = 64
)
(
// sys connect
input clk,
input rst,
// spi slave port
input ss,
input mosi,
output miso,
input sck,
// parallel data io port
output parallel_stb,
input [DEPTH-1:0] parallel_din,
output [DEPTH-1:0] parallel_dout
);
reg mosi_d, mosi_q;
reg ss_d, ss_q;
reg sck_d, sck_q;
reg sck_old_d, sck_old_q;
reg miso_d, miso_q;
reg [DEPTH-1:0] data_d, data_q;
reg parallel_stb_d, parallel_stb_q;
reg [`LOG2(DEPTH)-1:0] bit_ct_d, bit_ct_q;
reg [DEPTH-1:0] parallel_dout_d, parallel_dout_q;
assign miso = miso_q;
assign parallel_stb = parallel_stb_q;
assign parallel_dout = parallel_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;
parallel_stb_d = 1'b0;
bit_ct_d = bit_ct_q;
parallel_dout_d = parallel_dout_q;
if (ss_q) begin
bit_ct_d = 'h0;
data_d = parallel_din;
miso_d = data_q[DEPTH-1];
end
else begin
if (!sck_old_q && sck_q) begin // rising edge
data_d = {data_q[DEPTH-1-1:0], mosi_q};
bit_ct_d = bit_ct_q + 1'b1;
if (bit_ct_q == (DEPTH - 1)) begin
parallel_dout_d = {data_q[DEPTH-1-1:0], mosi_q};
parallel_stb_d = 1'b1;
data_d = parallel_din;
end
end
else if (sck_old_q && !sck_q) begin // falling edge
miso_d = data_q[DEPTH-1];
end
end
end
always @(posedge clk) begin
if (rst) begin
parallel_stb_q <= 1'b0;
bit_ct_q <= 'h0;
parallel_dout_q <= 'h0;
miso_q <= 1'b1;
end else begin
parallel_stb_q <= parallel_stb_d;
bit_ct_q <= bit_ct_d;
parallel_dout_q <= parallel_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
|