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

Subversion Repositories i2c

[/] [i2c/] [tags/] [asyst_3/] [rtl/] [verilog/] [i2c_master_bit_ctrl.v] - Blame information for rev 35

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

powered by: WebSVN 2.1.0

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