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 24

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

powered by: WebSVN 2.1.0

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