-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathde2_i2c_controller.v
124 lines (107 loc) · 2.29 KB
/
de2_i2c_controller.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
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
121
122
123
124
/*
I2C Controller Module
Usage: controls the 2-bus I2C module
*/
module de2_i2c_controller (
CLOCK,
I2C_SCLK, // I2C CLOCK
I2C_SDAT, // I2C DATA
I2C_DATA, // DATA:[SLAVE_ADDR,SUB_ADDR,DATA]
GO, // GO transfor
END, // END transfor
W_R, // W_R
ACK, // ACK
RESET,
// TEST
SD_COUNTER,
SDO
);
input CLOCK;
input [23:0] I2C_DATA;
input GO;
input RESET;
input W_R;
inout I2C_SDAT;
output I2C_SCLK;
output END;
output ACK;
// TEST
output [5:0] SD_COUNTER;
output SDO;
reg SDO;
reg SCLK;
reg END;
reg [23:0] SD;
reg [5:0] SD_COUNTER;
wire I2C_SCLK = SCLK | (((SD_COUNTER >= 4) & (SD_COUNTER <= 30))? ~CLOCK : 0);
wire I2C_SDAT = SDO ? 1'bz : 0;
reg ACK1, ACK2, ACK3;
wire ACK = ACK1 | ACK2 | ACK3;
//--I2C COUNTER
always @(negedge RESET or posedge CLOCK)
begin
if (!RESET)
SD_COUNTER = 6'b111111;
else
begin
if (GO == 0)
SD_COUNTER = 0;
else
if (SD_COUNTER < 6'b111111)
SD_COUNTER = SD_COUNTER + 1;
end
end
always @(negedge RESET or posedge CLOCK )
begin
if (!RESET)
begin
SCLK = 1;
SDO = 1;
ACK1 = 0;
ACK2 = 0;
ACK3 = 0;
END = 1;
end
else
case (SD_COUNTER)
6'd0 : begin ACK1 = 0; ACK2 = 0; ACK3 = 0; END = 0; SDO = 1; SCLK = 1; end
// Start
6'd1 : begin SD = I2C_DATA; SDO = 0; end
6'd2 : SCLK = 0;
// Slave Address
6'd3 : SDO = SD[23];
6'd4 : SDO = SD[22];
6'd5 : SDO = SD[21];
6'd6 : SDO = SD[20];
6'd7 : SDO = SD[19];
6'd8 : SDO = SD[18];
6'd9 : SDO = SD[17];
6'd10 : SDO = SD[16];
6'd11 : SDO = 1'b1; //ACK
// Sub-address
6'd12 : begin SDO = SD[15]; ACK1 = I2C_SDAT; end
6'd13 : SDO = SD[14];
6'd14 : SDO = SD[13];
6'd15 : SDO = SD[12];
6'd16 : SDO = SD[11];
6'd17 : SDO = SD[10];
6'd18 : SDO = SD[9];
6'd19 : SDO = SD[8];
6'd20 : SDO = 1'b1; // ACK
// Data
6'd21 : begin SDO = SD[7]; ACK2 = I2C_SDAT; end
6'd22 : SDO = SD[6];
6'd23 : SDO = SD[5];
6'd24 : SDO = SD[4];
6'd25 : SDO = SD[3];
6'd26 : SDO = SD[2];
6'd27 : SDO = SD[1];
6'd28 : SDO = SD[0];
6'd29 : SDO = 1'b1; // ACK
// Stop
6'd30 : begin SDO = 1'b0; SCLK = 1'b0; ACK3 = I2C_SDAT; end
6'd31 : SCLK = 1'b1;
6'd32 : begin SDO = 1'b1; END = 1; end
endcase
end
endmodule