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 36

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

powered by: WebSVN 2.1.0

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