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 22

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

powered by: WebSVN 2.1.0

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