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

Subversion Repositories i2c

[/] [i2c/] [tags/] [rel_1/] [rtl/] [verilog/] [i2c_master_bit_ctrl.v] - Blame information for rev 14

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

powered by: WebSVN 2.1.0

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