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

Subversion Repositories i2c

[/] [i2c/] [trunk/] [rtl/] [verilog/] [i2c_master_bit_ctrl.v] - Blame information for rev 52

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 14 rherveille
/////////////////////////////////////////////////////////////////////
2
////                                                             ////
3
////  WISHBONE rev.B2 compliant I2C Master bit-controller        ////
4
////                                                             ////
5
////                                                             ////
6
////  Author: Richard Herveille                                  ////
7
////          richard@asics.ws                                   ////
8
////          www.asics.ws                                       ////
9
////                                                             ////
10
////  Downloaded from: http://www.opencores.org/projects/i2c/    ////
11
////                                                             ////
12
/////////////////////////////////////////////////////////////////////
13
////                                                             ////
14
//// Copyright (C) 2001 Richard Herveille                        ////
15
////                    richard@asics.ws                         ////
16
////                                                             ////
17
//// This source file may be used and distributed without        ////
18
//// restriction provided that this copyright statement is not   ////
19
//// removed from the file and that any derivative work contains ////
20
//// the original copyright notice and the associated disclaimer.////
21
////                                                             ////
22
////     THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY     ////
23
//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED   ////
24
//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS   ////
25
//// FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR      ////
26
//// OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,         ////
27
//// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES    ////
28
//// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE   ////
29
//// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR        ////
30
//// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF  ////
31
//// LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT  ////
32
//// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT  ////
33
//// OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE         ////
34
//// POSSIBILITY OF SUCH DAMAGE.                                 ////
35
////                                                             ////
36
/////////////////////////////////////////////////////////////////////
37
 
38
//  CVS Log
39 10 rherveille
//
40 52 rherveille
//  $Id: i2c_master_bit_ctrl.v,v 1.11 2004-05-07 11:02:26 rherveille Exp $
41 10 rherveille
//
42 52 rherveille
//  $Date: 2004-05-07 11:02:26 $
43
//  $Revision: 1.11 $
44 14 rherveille
//  $Author: rherveille $
45
//  $Locker:  $
46
//  $State: Exp $
47 10 rherveille
//
48 14 rherveille
// Change History:
49
//               $Log: not supported by cvs2svn $
50 52 rherveille
//               Revision 1.10  2003/08/09 07:01:33  rherveille
51
//               Fixed a bug in the Arbitration Lost generation caused by delay on the (external) sda line.
52
//               Fixed a potential bug in the byte controller's host-acknowledge generation.
53
//
54 38 rherveille
//               Revision 1.9  2003/03/10 14:26:37  rherveille
55
//               Fixed cmd_ack generation item (no bug).
56
//
57 36 rherveille
//               Revision 1.8  2003/02/05 00:06:10  rherveille
58
//               Fixed a bug where the core would trigger an erroneous 'arbitration lost' interrupt after being reset, when the reset pulse width < 3 clk cycles.
59
//
60 35 rherveille
//               Revision 1.7  2002/12/26 16:05:12  rherveille
61
//               Small code simplifications
62
//
63 30 rherveille
//               Revision 1.6  2002/12/26 15:02:32  rherveille
64
//               Core is now a Multimaster I2C controller
65
//
66 29 rherveille
//               Revision 1.5  2002/11/30 22:24:40  rherveille
67
//               Cleaned up code
68
//
69 27 rherveille
//               Revision 1.4  2002/10/30 18:10:07  rherveille
70
//               Fixed some reported minor start/stop generation timing issuess.
71
//
72 24 rherveille
//               Revision 1.3  2002/06/15 07:37:03  rherveille
73
//               Fixed a small timing bug in the bit controller.\nAdded verilog simulation environment.
74
//
75 22 rherveille
//               Revision 1.2  2001/11/05 11:59:25  rherveille
76
//               Fixed wb_ack_o generation bug.
77
//               Fixed bug in the byte_controller statemachine.
78
//               Added headers.
79
//
80 10 rherveille
 
81
//
82
/////////////////////////////////////
83
// Bit controller section
84
/////////////////////////////////////
85
//
86
// Translate simple commands into SCL/SDA transitions
87
// Each command has 5 states, A/B/C/D/idle
88
//
89
// start:       SCL     ~~~~~~~~~~\____
90
//      SDA     ~~~~~~~~\______
91
//               x | A | B | C | D | i
92
//
93
// repstart     SCL     ____/~~~~\___
94
//      SDA     __/~~~\______
95
//               x | A | B | C | D | i
96
//
97
// stop SCL     ____/~~~~~~~~
98
//      SDA     ==\____/~~~~~
99
//               x | A | B | C | D | i
100
//
101
//- write       SCL     ____/~~~~\____
102
//      SDA     ==X=========X=
103
//               x | A | B | C | D | i
104
//
105
//- read        SCL     ____/~~~~\____
106
//      SDA     XXXX=====XXXX
107
//               x | A | B | C | D | i
108
//
109
 
110 24 rherveille
// Timing:     Normal mode      Fast mode
111 10 rherveille
///////////////////////////////////////////////////////////////////////
112 24 rherveille
// Fscl        100KHz           400KHz
113
// Th_scl      4.0us            0.6us   High period of SCL
114
// Tl_scl      4.7us            1.3us   Low period of SCL
115
// Tsu:sta     4.7us            0.6us   setup time for a repeated start condition
116
// Tsu:sto     4.0us            0.6us   setup time for a stop conditon
117
// Tbuf        4.7us            1.3us   Bus free time between a stop and start condition
118 10 rherveille
//
119
 
120 29 rherveille
// synopsys translate_off
121 10 rherveille
`include "timescale.v"
122 29 rherveille
// synopsys translate_on
123
 
124 10 rherveille
`include "i2c_master_defines.v"
125
 
126 29 rherveille
module i2c_master_bit_ctrl(
127
        clk, rst, nReset,
128
        clk_cnt, ena, cmd, cmd_ack, busy, al, din, dout,
129
        scl_i, scl_o, scl_oen, sda_i, sda_o, sda_oen
130
        );
131 10 rherveille
 
132
        //
133
        // inputs & outputs
134
        //
135
        input clk;
136
        input rst;
137
        input nReset;
138
        input ena;            // core enable signal
139
 
140
        input [15:0] clk_cnt; // clock prescale value
141
 
142
        input  [3:0] cmd;
143 29 rherveille
        output       cmd_ack; // command complete acknowledge
144 10 rherveille
        reg cmd_ack;
145 29 rherveille
        output       busy;    // i2c bus busy
146 10 rherveille
        reg busy;
147 29 rherveille
        output       al;      // i2c bus arbitration lost
148
        reg al;
149 10 rherveille
 
150
        input  din;
151
        output dout;
152
        reg dout;
153
 
154
        // I2C lines
155 29 rherveille
        input  scl_i;         // i2c clock line input
156
        output scl_o;         // i2c clock line output
157
        output scl_oen;       // i2c clock line output enable (active low)
158 10 rherveille
        reg scl_oen;
159 29 rherveille
        input  sda_i;         // i2c data line input
160
        output sda_o;         // i2c data line output
161
        output sda_oen;       // i2c data line output enable (active low)
162 10 rherveille
        reg sda_oen;
163
 
164
 
165
        //
166
        // variable declarations
167
        //
168
 
169 22 rherveille
        reg sSCL, sSDA;             // synchronized SCL and SDA inputs
170
        reg dscl_oen;               // delayed scl_oen
171 29 rherveille
        reg sda_chk;                // check SDA output (Multi-master arbitration)
172 10 rherveille
        reg clk_en;                 // clock generation signals
173
        wire slave_wait;
174 22 rherveille
//      reg [15:0] cnt = clk_cnt;   // clock divider counter (simulation)
175 10 rherveille
        reg [15:0] cnt;             // clock divider counter (synthesis)
176
 
177 52 rherveille
        // state machine variable
178
        reg [16:0] c_state; // synopsys enum_state
179
 
180 10 rherveille
        //
181
        // module body
182
        //
183
 
184 29 rherveille
        // whenever the slave is not ready it can delay the cycle by pulling SCL low
185 22 rherveille
        // delay scl_oen
186
        always @(posedge clk)
187 24 rherveille
          dscl_oen <= #1 scl_oen;
188 22 rherveille
 
189
        assign slave_wait = dscl_oen && !sSCL;
190 10 rherveille
 
191 29 rherveille
 
192 10 rherveille
        // generate clk enable signal
193 24 rherveille
        always @(posedge clk or negedge nReset)
194
          if(~nReset)
195
            begin
196
                cnt    <= #1 16'h0;
197
                clk_en <= #1 1'b1;
198
            end
199
          else if (rst)
200
            begin
201
                cnt    <= #1 16'h0;
202
                clk_en <= #1 1'b1;
203
            end
204 29 rherveille
          else if ( ~|cnt || ~ena)
205
            if (~slave_wait)
206
              begin
207
                  cnt    <= #1 clk_cnt;
208
                  clk_en <= #1 1'b1;
209
              end
210
            else
211
              begin
212
                  cnt    <= #1 cnt;
213
                  clk_en <= #1 1'b0;
214
              end
215 24 rherveille
          else
216
            begin
217 29 rherveille
                cnt    <= #1 cnt - 16'h1;
218 24 rherveille
                clk_en <= #1 1'b0;
219
            end
220 10 rherveille
 
221
 
222
        // generate bus status controller
223 29 rherveille
        reg dSCL, dSDA;
224 10 rherveille
        reg sta_condition;
225
        reg sto_condition;
226
 
227 29 rherveille
        // synchronize SCL and SDA inputs
228
        // reduce metastability risc
229 35 rherveille
        always @(posedge clk or negedge nReset)
230
          if (~nReset)
231
            begin
232
                sSCL <= #1 1'b1;
233
                sSDA <= #1 1'b1;
234 29 rherveille
 
235 35 rherveille
                dSCL <= #1 1'b1;
236
                dSDA <= #1 1'b1;
237
            end
238
          else if (rst)
239
            begin
240
                sSCL <= #1 1'b1;
241
                sSDA <= #1 1'b1;
242 29 rherveille
 
243 35 rherveille
                dSCL <= #1 1'b1;
244
                dSDA <= #1 1'b1;
245
            end
246
          else
247
            begin
248
                sSCL <= #1 scl_i;
249
                sSDA <= #1 sda_i;
250
 
251
                dSCL <= #1 sSCL;
252
                dSDA <= #1 sSDA;
253
            end
254
 
255 10 rherveille
        // detect start condition => detect falling edge on SDA while SCL is high
256
        // detect stop condition => detect rising edge on SDA while SCL is high
257 35 rherveille
        always @(posedge clk or negedge nReset)
258
          if (~nReset)
259
            begin
260
                sta_condition <= #1 1'b0;
261
                sto_condition <= #1 1'b0;
262
            end
263
          else if (rst)
264
            begin
265
                sta_condition <= #1 1'b0;
266
                sto_condition <= #1 1'b0;
267
            end
268
          else
269
            begin
270
                sta_condition <= #1 ~sSDA &  dSDA & sSCL;
271
                sto_condition <= #1  sSDA & ~dSDA & sSCL;
272
            end
273 10 rherveille
 
274 30 rherveille
        // generate i2c bus busy signal
275 24 rherveille
        always @(posedge clk or negedge nReset)
276
          if(!nReset)
277
            busy <= #1 1'b0;
278
          else if (rst)
279
            busy <= #1 1'b0;
280
          else
281 27 rherveille
            busy <= #1 (sta_condition | busy) & ~sto_condition;
282 10 rherveille
 
283 29 rherveille
        // generate arbitration lost signal
284
        // aribitration lost when:
285
        // 1) master drives SDA high, but the i2c bus is low
286
        // 2) stop detected while not requested
287 38 rherveille
        reg cmd_stop;
288 35 rherveille
        always @(posedge clk or negedge nReset)
289
          if (~nReset)
290 38 rherveille
            cmd_stop <= #1 1'b0;
291 35 rherveille
          else if (rst)
292 38 rherveille
            cmd_stop <= #1 1'b0;
293
          else if (clk_en)
294
            cmd_stop <= #1 cmd == `I2C_CMD_STOP;
295
 
296
        always @(posedge clk or negedge nReset)
297
          if (~nReset)
298
            al <= #1 1'b0;
299
          else if (rst)
300
            al <= #1 1'b0;
301 35 rherveille
          else
302 52 rherveille
            al <= #1 (sda_chk & ~sSDA & sda_oen) | (|c_state & sto_condition & ~cmd_stop);
303 10 rherveille
 
304 29 rherveille
 
305
        // generate dout signal (store SDA on rising edge of SCL)
306
        always @(posedge clk)
307
          if(sSCL & ~dSCL)
308
            dout <= #1 sSDA;
309
 
310 10 rherveille
        // generate statemachine
311
 
312
        // nxt_state decoder
313 24 rherveille
        parameter [16:0] idle    = 17'b0_0000_0000_0000_0000;
314
        parameter [16:0] start_a = 17'b0_0000_0000_0000_0001;
315
        parameter [16:0] start_b = 17'b0_0000_0000_0000_0010;
316
        parameter [16:0] start_c = 17'b0_0000_0000_0000_0100;
317
        parameter [16:0] start_d = 17'b0_0000_0000_0000_1000;
318
        parameter [16:0] start_e = 17'b0_0000_0000_0001_0000;
319
        parameter [16:0] stop_a  = 17'b0_0000_0000_0010_0000;
320
        parameter [16:0] stop_b  = 17'b0_0000_0000_0100_0000;
321
        parameter [16:0] stop_c  = 17'b0_0000_0000_1000_0000;
322
        parameter [16:0] stop_d  = 17'b0_0000_0001_0000_0000;
323
        parameter [16:0] rd_a    = 17'b0_0000_0010_0000_0000;
324
        parameter [16:0] rd_b    = 17'b0_0000_0100_0000_0000;
325
        parameter [16:0] rd_c    = 17'b0_0000_1000_0000_0000;
326
        parameter [16:0] rd_d    = 17'b0_0001_0000_0000_0000;
327
        parameter [16:0] wr_a    = 17'b0_0010_0000_0000_0000;
328
        parameter [16:0] wr_b    = 17'b0_0100_0000_0000_0000;
329
        parameter [16:0] wr_c    = 17'b0_1000_0000_0000_0000;
330
        parameter [16:0] wr_d    = 17'b1_0000_0000_0000_0000;
331 10 rherveille
 
332 24 rherveille
        always @(posedge clk or negedge nReset)
333
          if (!nReset)
334
            begin
335
                c_state <= #1 idle;
336
                cmd_ack <= #1 1'b0;
337 27 rherveille
                scl_oen <= #1 1'b1;
338
                sda_oen <= #1 1'b1;
339 29 rherveille
                sda_chk <= #1 1'b0;
340 24 rherveille
            end
341 29 rherveille
          else if (rst | al)
342 24 rherveille
            begin
343
                c_state <= #1 idle;
344
                cmd_ack <= #1 1'b0;
345 27 rherveille
                scl_oen <= #1 1'b1;
346
                sda_oen <= #1 1'b1;
347 29 rherveille
                sda_chk <= #1 1'b0;
348 24 rherveille
            end
349
          else
350
            begin
351 27 rherveille
                cmd_ack   <= #1 1'b0; // default no command acknowledge + assert cmd_ack only 1clk cycle
352
 
353 24 rherveille
                if (clk_en)
354 52 rherveille
                  case (c_state) // synopsys full_case parallel_case
355 27 rherveille
                    // idle state
356
                    idle:
357
                    begin
358 52 rherveille
                        case (cmd) // synopsys full_case parallel_case
359 27 rherveille
                          `I2C_CMD_START:
360
                             c_state <= #1 start_a;
361 10 rherveille
 
362 27 rherveille
                          `I2C_CMD_STOP:
363
                             c_state <= #1 stop_a;
364 10 rherveille
 
365 27 rherveille
                          `I2C_CMD_WRITE:
366
                             c_state <= #1 wr_a;
367 10 rherveille
 
368 27 rherveille
                          `I2C_CMD_READ:
369
                             c_state <= #1 rd_a;
370 10 rherveille
 
371 27 rherveille
                          default:
372
                            c_state <= #1 idle;
373
                        endcase
374 10 rherveille
 
375 27 rherveille
                        scl_oen <= #1 scl_oen; // keep SCL in same state
376
                        sda_oen <= #1 sda_oen; // keep SDA in same state
377 29 rherveille
                        sda_chk <= #1 1'b0;    // don't check SDA output
378 27 rherveille
                    end
379 10 rherveille
 
380 27 rherveille
                    // start
381
                    start_a:
382
                    begin
383
                        c_state <= #1 start_b;
384
                        scl_oen <= #1 scl_oen; // keep SCL in same state
385
                        sda_oen <= #1 1'b1;    // set SDA high
386 29 rherveille
                        sda_chk <= #1 1'b0;    // don't check SDA output
387 27 rherveille
                    end
388 10 rherveille
 
389 27 rherveille
                    start_b:
390
                    begin
391
                        c_state <= #1 start_c;
392
                        scl_oen <= #1 1'b1; // set SCL high
393
                        sda_oen <= #1 1'b1; // keep SDA high
394 29 rherveille
                        sda_chk <= #1 1'b0; // don't check SDA output
395 27 rherveille
                    end
396 10 rherveille
 
397 27 rherveille
                    start_c:
398
                    begin
399
                        c_state <= #1 start_d;
400
                        scl_oen <= #1 1'b1; // keep SCL high
401
                        sda_oen <= #1 1'b0; // set SDA low
402 29 rherveille
                        sda_chk <= #1 1'b0; // don't check SDA output
403 27 rherveille
                    end
404 10 rherveille
 
405 27 rherveille
                    start_d:
406
                    begin
407
                        c_state <= #1 start_e;
408
                        scl_oen <= #1 1'b1; // keep SCL high
409
                        sda_oen <= #1 1'b0; // keep SDA low
410 29 rherveille
                        sda_chk <= #1 1'b0; // don't check SDA output
411 27 rherveille
                    end
412 10 rherveille
 
413 27 rherveille
                    start_e:
414
                    begin
415
                        c_state <= #1 idle;
416
                        cmd_ack <= #1 1'b1;
417
                        scl_oen <= #1 1'b0; // set SCL low
418
                        sda_oen <= #1 1'b0; // keep SDA low
419 29 rherveille
                        sda_chk <= #1 1'b0; // don't check SDA output
420 27 rherveille
                    end
421 10 rherveille
 
422 27 rherveille
                    // stop
423
                    stop_a:
424
                    begin
425
                        c_state <= #1 stop_b;
426
                        scl_oen <= #1 1'b0; // keep SCL low
427
                        sda_oen <= #1 1'b0; // set SDA low
428 29 rherveille
                        sda_chk <= #1 1'b0; // don't check SDA output
429 27 rherveille
                    end
430 10 rherveille
 
431 27 rherveille
                    stop_b:
432
                    begin
433
                        c_state <= #1 stop_c;
434
                        scl_oen <= #1 1'b1; // set SCL high
435
                        sda_oen <= #1 1'b0; // keep SDA low
436 29 rherveille
                        sda_chk <= #1 1'b0; // don't check SDA output
437 27 rherveille
                    end
438 10 rherveille
 
439 27 rherveille
                    stop_c:
440
                    begin
441
                        c_state <= #1 stop_d;
442
                        scl_oen <= #1 1'b1; // keep SCL high
443
                        sda_oen <= #1 1'b0; // keep SDA low
444 29 rherveille
                        sda_chk <= #1 1'b0; // don't check SDA output
445 27 rherveille
                    end
446 10 rherveille
 
447 27 rherveille
                    stop_d:
448
                    begin
449
                        c_state <= #1 idle;
450 36 rherveille
                        cmd_ack <= #1 1'b1;
451 27 rherveille
                        scl_oen <= #1 1'b1; // keep SCL high
452
                        sda_oen <= #1 1'b1; // set SDA high
453 29 rherveille
                        sda_chk <= #1 1'b0; // don't check SDA output
454 27 rherveille
                    end
455 10 rherveille
 
456 27 rherveille
                    // read
457
                    rd_a:
458
                    begin
459
                        c_state <= #1 rd_b;
460
                        scl_oen <= #1 1'b0; // keep SCL low
461
                        sda_oen <= #1 1'b1; // tri-state SDA
462 29 rherveille
                        sda_chk <= #1 1'b0; // don't check SDA output
463 27 rherveille
                    end
464 10 rherveille
 
465 27 rherveille
                    rd_b:
466
                    begin
467
                        c_state <= #1 rd_c;
468
                        scl_oen <= #1 1'b1; // set SCL high
469
                        sda_oen <= #1 1'b1; // keep SDA tri-stated
470 29 rherveille
                        sda_chk <= #1 1'b0; // don't check SDA output
471 27 rherveille
                    end
472 10 rherveille
 
473 27 rherveille
                    rd_c:
474
                    begin
475
                        c_state <= #1 rd_d;
476
                        scl_oen <= #1 1'b1; // keep SCL high
477 29 rherveille
                        sda_oen <= #1 1'b1; // keep SDA tri-stated
478
                        sda_chk <= #1 1'b0; // don't check SDA output
479 27 rherveille
                    end
480 10 rherveille
 
481 27 rherveille
                    rd_d:
482
                    begin
483
                        c_state <= #1 idle;
484 36 rherveille
                        cmd_ack <= #1 1'b1;
485 27 rherveille
                        scl_oen <= #1 1'b0; // set SCL low
486 29 rherveille
                        sda_oen <= #1 1'b1; // keep SDA tri-stated
487
                        sda_chk <= #1 1'b0; // don't check SDA output
488 27 rherveille
                    end
489 10 rherveille
 
490 27 rherveille
                    // write
491
                    wr_a:
492
                    begin
493
                        c_state <= #1 wr_b;
494
                        scl_oen <= #1 1'b0; // keep SCL low
495
                        sda_oen <= #1 din;  // set SDA
496 29 rherveille
                        sda_chk <= #1 1'b0; // don't check SDA output (SCL low)
497 27 rherveille
                    end
498 10 rherveille
 
499 27 rherveille
                    wr_b:
500
                    begin
501
                        c_state <= #1 wr_c;
502
                        scl_oen <= #1 1'b1; // set SCL high
503
                        sda_oen <= #1 din;  // keep SDA
504 29 rherveille
                        sda_chk <= #1 1'b1; // check SDA output
505 27 rherveille
                    end
506 10 rherveille
 
507 27 rherveille
                    wr_c:
508
                    begin
509
                        c_state <= #1 wr_d;
510
                        scl_oen <= #1 1'b1; // keep SCL high
511
                        sda_oen <= #1 din;
512 29 rherveille
                        sda_chk <= #1 1'b1; // check SDA output
513 27 rherveille
                    end
514 24 rherveille
 
515 27 rherveille
                    wr_d:
516
                    begin
517
                        c_state <= #1 idle;
518
                        cmd_ack <= #1 1'b1;
519
                        scl_oen <= #1 1'b0; // set SCL low
520
                        sda_oen <= #1 din;
521 29 rherveille
                        sda_chk <= #1 1'b0; // don't check SDA output (SCL low)
522 27 rherveille
                    end
523 24 rherveille
 
524 27 rherveille
                  endcase
525
            end
526 24 rherveille
 
527 27 rherveille
 
528
        // assign scl and sda output (always gnd)
529
        assign scl_o = 1'b0;
530
        assign sda_o = 1'b0;
531
 
532 10 rherveille
endmodule

powered by: WebSVN 2.1.0

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