-
Notifications
You must be signed in to change notification settings - Fork 1
/
spi_core.v
91 lines (70 loc) · 2.01 KB
/
spi_core.v
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
module spi_core(input clk, input rst, input cs, input rd, input wr, input [DWIDTH-1:0] din,
output [DWIDTH-1:0] dout, input miso, output mosi, output sclk, output done);
parameter DWIDTH = 8;
reg [DWIDTH-1:0] dout;
reg done;
reg sclk;
reg [DWIDTH-1:0] tmp_dat;
reg [$clog2(DWIDTH) + 1:0] edge_cnt;
reg [2:0] sclk_div;
reg xfer_in_progress;
reg prev_xfer_prog;
reg prev_sclk;
reg tmp_in;
wire sclk_negedge, sclk_posedge;
assign mosi = tmp_dat[DWIDTH - 1];
assign sclk_negedge = (prev_sclk & ~sclk);
assign sclk_posedge = (~prev_sclk & sclk);
initial sclk = 0;
initial prev_sclk = 0;
initial prev_xfer_prog = 0;
initial xfer_in_progress = 0;
always @* begin
if (prev_xfer_prog == 0 && xfer_in_progress == 0) begin
done <= 1;
end else begin
done <= 0;
end
end
// CPOL = 0, CPHA = 0
always @(posedge clk) begin
if(xfer_in_progress) begin
if(sclk_div == 0) begin
sclk <= ~sclk;
sclk_div <= 4;
edge_cnt <= edge_cnt - 1;
end else begin
sclk_div <= sclk_div - 1;
end
end else begin
sclk_div <= 4;
sclk <= 0;
edge_cnt <= 2*DWIDTH;
end
prev_sclk <= sclk;
end
always @(posedge clk) begin
if(edge_cnt == 0) begin
xfer_in_progress <= 0;
end
if (sclk_negedge) begin
tmp_dat <= { tmp_dat[DWIDTH - 2:0], tmp_in };
end
if(wr & ~rd & cs & ~xfer_in_progress) begin
tmp_dat <= din;
xfer_in_progress <= 1;
end
if (prev_xfer_prog & ~xfer_in_progress) begin
dout <= tmp_dat;
end
if (sclk_posedge) begin
tmp_in <= miso;
end
end
always @(posedge clk) begin
prev_xfer_prog <= xfer_in_progress;
end
`ifdef FORMAL
assume property (edge_cnt <= 16);
`endif
endmodule