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 68

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

powered by: WebSVN 2.1.0

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