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 27

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

powered by: WebSVN 2.1.0

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