OpenCores
URL https://opencores.org/ocsvn/i2crepeater/i2crepeater/trunk

Subversion Repositories i2crepeater

[/] [i2crepeater/] [trunk/] [i2crepeater.v] - Blame information for rev 2

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 egallimore
////////////////////////////////////////////////////////////////////////////////
2
/// \file i2crepeater.v
3
/// \brief I2C Repeater module
4
///
5
/// \author Eric Gallimore <egallimore@whoi.edu>
6
///
7
///
8
/// Incorporates a start/stop detection technique by gszakacs found on Xilinx forums.
9
///
10
////////////////////////////////////////////////////////////////////////////////
11
 
12
module i2crepeater(reset, system_clk, master_scl, master_sda, slave_scl, slave_sda, sda_direction_tap, start_stop_tap, incycle_tap);
13
 
14
        input reset;
15
        input system_clk;
16
        inout master_sda;
17
        input master_scl;
18
        output slave_scl;
19
        inout slave_sda;
20
        output sda_direction_tap;       // For probing
21
        output start_stop_tap;          // For probing
22
        output incycle_tap;                     // For probing
23
 
24
 
25
        // Direction of SDA signal
26
        enum { MOSI, MISO } sda_direction;
27
        assign sda_direction_tap = (sda_direction == MISO) ? 1 : 0;
28
 
29
        // States
30
        enum { IDLE, ADDRESS, RWBIT, SLAVEACK, MASTERACK, DATATOSLAVE, DATAFROMSLAVE } State;
31
 
32
        // Just pass the clock through from master to slave.
33
        assign slave_scl = master_scl;
34
 
35
 
36
        // Assignment of I/O.
37
        assign slave_sda = (sda_direction == MOSI) ? master_sda : 'z;
38
        assign master_sda = (sda_direction == MISO) ? slave_sda : 'z;
39
 
40
 
41
        // Sample the SDA and SCL lines to do start and stop detection
42
        // Only the master can generate start and stop signals.
43
        logic [4:0] scl_samples; // Multiple samples used to debounce signal.
44
        logic [4:0] sda_samples;
45
        logic scl_new;
46
        logic scl_old;
47
        logic sda_new;
48
        logic sda_old;
49
        logic got_start;
50
        logic got_stop;
51
        always @(posedge system_clk or posedge reset) begin
52
                if (reset) begin
53
                        scl_samples <= 5'b11111;  // I2C signals are pulled up by default
54
                        sda_samples <= 5'b11111;
55
                        scl_new <= 1;
56
                        scl_old <= 1;
57
                        sda_new <= 1;
58
                        sda_old <= 1;
59
                        got_start <= 0;
60
                        got_stop <= 0;
61
 
62
                end else begin
63
                        // Sample the signals and store them
64
                        // Shift the old samples left by one bit to make room for the new ones.
65
                        scl_samples <= {scl_samples[3:0], master_scl};
66
                        sda_samples <= {sda_samples[3:0], master_sda};
67
                        // Keep track of previous values
68
                        scl_old <= scl_new;
69
                        sda_old <= sda_new;
70
                        // Turn samples into scl and sda values.
71
                        if (scl_samples == 5'b11111)
72
                                scl_new <= 1;
73
                        else if (scl_samples == 5'b00000)
74
                                scl_new <= 0;
75
 
76
                        if (sda_samples == 5'b11111)
77
                                sda_new <= 1;
78
                        else if (sda_samples == 5'b00000)
79
                                sda_new <= 0;
80
 
81
                        // Do edge detection to find start and stop values.
82
                        // If SCL remained high while SDA fell, we have a a start.
83
                        if (scl_new & scl_old & !sda_new & sda_old)
84
                                got_start <= 1;
85
                        else if (!scl_new & !scl_old)   // clear got_start when SCL falls.
86
                                got_start <= 0;
87
 
88
                        // If SCL remained high while SDA rose, we have a stop.
89
                        got_stop <= scl_new & scl_old & sda_new & !sda_old;     // will clear on next clock edge
90
                end
91
        end
92
 
93
 
94
 
95
        // Sample the data bits on the positive edge of each clock cycle
96
        // Get both and decide what to do with them later.
97
        logic master_sda_bit;
98
        logic slave_sda_bit;
99
        always @(posedge master_scl) begin
100
                master_sda_bit <= master_sda;
101
                slave_sda_bit <= slave_sda;
102
        end
103
 
104
 
105
 
106
        // Bit counter with state tracking
107
        logic [3:0] bitcount;    // Counts 8 bits of data plus the ACK
108
        logic isread;   // Is this packet a read request?
109
        logic newcycle;
110
 
111
        always @(negedge master_scl or posedge reset or posedge got_start or posedge got_stop) begin
112
                if (reset || got_start || got_stop) begin
113
                        State <= IDLE;
114
                        sda_direction <= MOSI;
115
                        bitcount <= 4'h7;
116
                        isread <= 0;
117
                end else begin
118
                        case (State)
119
                                IDLE: begin
120
                                                // We are not idle any more, and are now waiting for an address
121
                                                State <= ADDRESS;
122
                                                bitcount <= 4'h6; // We miss an edge at the start.
123
                                        end
124
 
125
                                ADDRESS: begin
126
                                                // We need to keep track of what bit we are on
127
                                                if (bitcount == 4'h1) // We have finished the 7 bit address, so the next bit is R/W
128
                                                        State <= RWBIT;
129
                                                else
130
                                                        bitcount <= bitcount - 4'h1;
131
                                        end
132
 
133
                                RWBIT: begin
134
                                                isread <= master_sda_bit;
135
                                                sda_direction <= MISO;
136
                                                State <= SLAVEACK;
137
                                        end
138
 
139
                                SLAVEACK: begin
140
                                                bitcount <= 4'h7;       // We will be waiting for a byte of data in one direction or the other
141
                                                if (isread) begin
142
                                                        sda_direction <= MISO;
143
                                                        State <= DATAFROMSLAVE;
144
                                                end else begin
145
                                                        sda_direction <= MOSI;
146
                                                        State <= DATATOSLAVE;
147
                                                end
148
                                        end
149
 
150
                                DATAFROMSLAVE: begin
151
                                                // We need to keep track of what bit we're on, again.
152
                                                if (bitcount == 4'h0) begin // We just finished this byte.
153
                                                        sda_direction <= MOSI;
154
                                                        State <= MASTERACK;
155
                                                end else
156
                                                        bitcount <= bitcount - 4'h1;
157
                                        end
158
 
159
                                MASTERACK: begin
160
                                                        // At this point, we will either get a start/stop or start on the next byte
161
                                                        // Start/stop conditions dump us back to the beginning
162
                                                        if (master_sda_bit == 1) begin  // NACK
163
                                                                sda_direction <=MOSI;   // We will send a STOP next.
164
                                                                State <= IDLE;
165
                                                        end else begin
166
                                                                bitcount <= 4'h7;       // We will be waiting for a byte of data
167
                                                                sda_direction <= MISO;
168
                                                                State <= DATAFROMSLAVE;
169
                                                        end
170
                                                end
171
 
172
                                DATATOSLAVE: begin
173
                                                // We need to keep track of what bit we're on, again.
174
                                                if (bitcount == 4'h0) begin // We just finished this byte.
175
                                                        sda_direction <= MISO;
176
                                                        State <= SLAVEACK;
177
                                                end else
178
                                                        bitcount <= bitcount - 4'h1;
179
                                        end
180
                        endcase
181
                end
182
        end
183
 
184
 
185
endmodule

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.