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 10

Go to most recent revision | Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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