-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathmcp23009.sv
120 lines (111 loc) · 1.78 KB
/
mcp23009.sv
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
108
109
110
111
112
113
114
115
116
117
118
119
120
//
// MCP23009
// (C) 2019 Alexey Melnikov
//
module mcp23009
(
input clk,
output reg [2:0] btn,
input [2:0] led,
output reg flg_sd_cd,
output reg flg_present,
output reg flg_mode,
output scl,
inout sda
);
reg start = 0;
wire ready;
wire error;
reg rw;
wire [7:0] dout;
reg [15:0] din;
i2c #(50_000_000, 500_000) i2c
(
.CLK(clk),
.START(start),
.READ(rw),
.I2C_ADDR('h20),
.I2C_WLEN(1),
.I2C_WDATA1(din[15:8]),
.I2C_WDATA2(din[7:0]),
.I2C_RDATA(dout),
.END(ready),
.ACK(error),
.I2C_SCL(scl),
.I2C_SDA(sda)
);
always@(posedge clk) begin
reg [3:0] idx = 0;
reg [1:0] state = 0;
reg [15:0] timeout = 0;
if(~&timeout) begin
timeout <= timeout + 1'd1;
start <= 0;
state <= 0;
idx <= 0;
btn <= 0;
rw <= 0;
flg_sd_cd <= 1;
flg_present <= 0;
flg_mode <= 1;
end
else begin
if(~&init_data[idx]) begin
case(state)
0: begin
start <= 1;
state <= 1;
din <= init_data[idx];
end
1: if(~ready) state <= 2;
2: begin
start <= 0;
if(ready) begin
state <= 0;
if(!error) idx <= idx + 1'd1;
end
end
endcase
end
else begin
case(state)
0: begin
start <= 1;
state <= 1;
din <= {8'h09,5'b00000,led};
end
1: if(~ready) state <= 2;
2: begin
start <= 0;
if(ready) begin
state <= 0;
rw <= 0;
if(!error) begin
if(rw) begin
{flg_sd_cd, flg_mode, btn} <= {dout[7:3]};
flg_present <= 1;
end
rw <= ~rw;
end
end
end
endcase
end
end
end
wire [15:0] init_data[12] =
'{
16'h00F8,
16'h0138,
16'h0200,
16'h0300,
16'h0400,
16'h0524,
16'h06FF,
16'h0700,
16'h0800,
16'h0900,
16'h0A00,
16'hFFFF
};
endmodule