source: PlatformSupport/CustomPeripherals/pcores/w3_iic_eeprom_v1_00_b/opencores_src/rtl/verilog/i2c_master_bit_ctrl.v

Last change on this file was 1766, checked in by murphpo, 12 years ago
File size: 20.6 KB
Line 
1/////////////////////////////////////////////////////////////////////
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//
40//  $Id: i2c_master_bit_ctrl.v,v 1.14 2009-01-20 10:25:29 rherveille Exp $
41//
42//  $Date: 2009-01-20 10:25:29 $
43//  $Revision: 1.14 $
44//  $Author: rherveille $
45//  $Locker:  $
46//  $State: Exp $
47//
48// Change History:
49//               $Log: $
50//               Revision 1.14  2009/01/20 10:25:29  rherveille
51//               Added clock synchronization logic
52//               Fixed slave_wait signal
53//
54//               Revision 1.13  2009/01/19 20:29:26  rherveille
55//               Fixed synopsys miss spell (synopsis)
56//               Fixed cr[0] register width
57//               Fixed ! usage instead of ~
58//               Fixed bit controller parameter width to 18bits
59//
60//               Revision 1.12  2006/09/04 09:08:13  rherveille
61//               fixed short scl high pulse after clock stretch
62//               fixed slave model not returning correct '(n)ack' signal
63//
64//               Revision 1.11  2004/05/07 11:02:26  rherveille
65//               Fixed a bug where the core would signal an arbitration lost (AL bit set), when another master controls the bus and the other master generates a STOP bit.
66//
67//               Revision 1.10  2003/08/09 07:01:33  rherveille
68//               Fixed a bug in the Arbitration Lost generation caused by delay on the (external) sda line.
69//               Fixed a potential bug in the byte controller's host-acknowledge generation.
70//
71//               Revision 1.9  2003/03/10 14:26:37  rherveille
72//               Fixed cmd_ack generation item (no bug).
73//
74//               Revision 1.8  2003/02/05 00:06:10  rherveille
75//               Fixed a bug where the core would trigger an erroneous 'arbitration lost' interrupt after being reset, when the reset pulse width < 3 clk cycles.
76//
77//               Revision 1.7  2002/12/26 16:05:12  rherveille
78//               Small code simplifications
79//
80//               Revision 1.6  2002/12/26 15:02:32  rherveille
81//               Core is now a Multimaster I2C controller
82//
83//               Revision 1.5  2002/11/30 22:24:40  rherveille
84//               Cleaned up code
85//
86//               Revision 1.4  2002/10/30 18:10:07  rherveille
87//               Fixed some reported minor start/stop generation timing issuess.
88//
89//               Revision 1.3  2002/06/15 07:37:03  rherveille
90//               Fixed a small timing bug in the bit controller.\nAdded verilog simulation environment.
91//
92//               Revision 1.2  2001/11/05 11:59:25  rherveille
93//               Fixed wb_ack_o generation bug.
94//               Fixed bug in the byte_controller statemachine.
95//               Added headers.
96//
97
98//
99/////////////////////////////////////
100// Bit controller section
101/////////////////////////////////////
102//
103// Translate simple commands into SCL/SDA transitions
104// Each command has 5 states, A/B/C/D/idle
105//
106// start:   SCL ~~~~~~~~~~\____
107//  SDA ~~~~~~~~\______
108//       x | A | B | C | D | i
109//
110// repstart SCL ____/~~~~\___
111//  SDA __/~~~\______
112//       x | A | B | C | D | i
113//
114// stop SCL ____/~~~~~~~~
115//  SDA ==\____/~~~~~
116//       x | A | B | C | D | i
117//
118//- write   SCL ____/~~~~\____
119//  SDA ==X=========X=
120//       x | A | B | C | D | i
121//
122//- read    SCL ____/~~~~\____
123//  SDA XXXX=====XXXX
124//       x | A | B | C | D | i
125//
126
127// Timing:     Normal mode      Fast mode
128///////////////////////////////////////////////////////////////////////
129// Fscl        100KHz           400KHz
130// Th_scl      4.0us            0.6us   High period of SCL
131// Tl_scl      4.7us            1.3us   Low period of SCL
132// Tsu:sta     4.7us            0.6us   setup time for a repeated start condition
133// Tsu:sto     4.0us            0.6us   setup time for a stop conditon
134// Tbuf        4.7us            1.3us   Bus free time between a stop and start condition
135//
136
137// synopsys translate_off
138`include "timescale.v"
139// synopsys translate_on
140
141`include "i2c_master_defines.v"
142
143module i2c_master_bit_ctrl (
144    input             clk,      // system clock
145    input             rst,      // synchronous active high reset
146    input             nReset,   // asynchronous active low reset
147    input             ena,      // core enable signal
148
149    input      [15:0] clk_cnt,  // clock prescale value
150
151    input      [ 3:0] cmd,      // command (from byte controller)
152    output reg        cmd_ack,  // command complete acknowledge
153    output reg        busy,     // i2c bus busy
154    output reg        al,       // i2c bus arbitration lost
155
156    input             din,
157    output reg        dout,
158
159    input             scl_i,    // i2c clock line input
160    output            scl_o,    // i2c clock line output
161    output reg        scl_oen,  // i2c clock line output enable (active low)
162    input             sda_i,    // i2c data line input
163    output            sda_o,    // i2c data line output
164    output reg        sda_oen   // i2c data line output enable (active low)
165);
166
167
168    //
169    // variable declarations
170    //
171
172    reg [ 1:0] cSCL, cSDA;      // capture SCL and SDA
173    reg [ 2:0] fSCL, fSDA;      // SCL and SDA filter inputs
174    reg        sSCL, sSDA;      // filtered and synchronized SCL and SDA inputs
175    reg        dSCL, dSDA;      // delayed versions of sSCL and sSDA
176    reg        dscl_oen;        // delayed scl_oen
177    reg        sda_chk;         // check SDA output (Multi-master arbitration)
178    reg        clk_en;          // clock generation signals
179    reg        slave_wait;      // slave inserts wait states
180    reg [15:0] cnt;             // clock divider counter (synthesis)
181    reg [13:0] filter_cnt;      // clock divider for filter
182
183
184    // state machine variable
185    reg [17:0] c_state; // synopsys enum_state
186
187    //
188    // module body
189    //
190
191    // whenever the slave is not ready it can delay the cycle by pulling SCL low
192    // delay scl_oen
193    always @(posedge clk)
194      dscl_oen <= #1 scl_oen;
195
196    // slave_wait is asserted when master wants to drive SCL high, but the slave pulls it low
197    // slave_wait remains asserted until the slave releases SCL
198    always @(posedge clk or negedge nReset)
199      if (!nReset) slave_wait <= 1'b0;
200      else         slave_wait <= (scl_oen & ~dscl_oen & ~sSCL) | (slave_wait & ~sSCL);
201
202    // master drives SCL high, but another master pulls it low
203    // master start counting down its low cycle now (clock synchronization)
204    wire scl_sync   = dSCL & ~sSCL & scl_oen;
205
206
207    // generate clk enable signal
208    always @(posedge clk or negedge nReset)
209      if (~nReset)
210      begin
211          cnt    <= #1 16'h0;
212          clk_en <= #1 1'b1;
213      end
214      else if (rst || ~|cnt || !ena || scl_sync)
215      begin
216          cnt    <= #1 clk_cnt;
217          clk_en <= #1 1'b1;
218      end
219      else if (slave_wait)
220      begin
221          cnt    <= #1 cnt;
222          clk_en <= #1 1'b0;   
223      end
224      else
225      begin
226          cnt    <= #1 cnt - 16'h1;
227          clk_en <= #1 1'b0;
228      end
229
230
231    // generate bus status controller
232
233    // capture SDA and SCL
234    // reduce metastability risk
235    always @(posedge clk or negedge nReset)
236      if (!nReset)
237      begin
238          cSCL <= #1 2'b00;
239          cSDA <= #1 2'b00;
240      end
241      else if (rst)
242      begin
243          cSCL <= #1 2'b00;
244          cSDA <= #1 2'b00;
245      end
246      else
247      begin
248          cSCL <= {cSCL[0],scl_i};
249          cSDA <= {cSDA[0],sda_i};
250      end
251
252
253    // filter SCL and SDA signals; (attempt to) remove glitches
254    always @(posedge clk or negedge nReset)
255      if      (!nReset     ) filter_cnt <= 14'h0;
256      else if (rst || !ena ) filter_cnt <= 14'h0;
257      else if (~|filter_cnt) filter_cnt <= clk_cnt >> 2; //16x I2C bus frequency
258      else                   filter_cnt <= filter_cnt -1;
259
260
261    always @(posedge clk or negedge nReset)
262      if (!nReset)
263      begin
264          fSCL <= 3'b111;
265          fSDA <= 3'b111;
266      end
267      else if (rst)
268      begin
269          fSCL <= 3'b111;
270          fSDA <= 3'b111;
271      end
272      else if (~|filter_cnt)
273      begin
274          fSCL <= {fSCL[1:0],cSCL[1]};
275          fSDA <= {fSDA[1:0],cSDA[1]};
276      end
277
278
279    // generate filtered SCL and SDA signals
280    always @(posedge clk or negedge nReset)
281      if (~nReset)
282      begin
283          sSCL <= #1 1'b1;
284          sSDA <= #1 1'b1;
285
286          dSCL <= #1 1'b1;
287          dSDA <= #1 1'b1;
288      end
289      else if (rst)
290      begin
291          sSCL <= #1 1'b1;
292          sSDA <= #1 1'b1;
293
294          dSCL <= #1 1'b1;
295          dSDA <= #1 1'b1;
296      end
297      else
298      begin
299          sSCL <= #1 &fSCL[2:1] | &fSCL[1:0] | (fSCL[2] & fSCL[0]);
300          sSDA <= #1 &fSDA[2:1] | &fSDA[1:0] | (fSDA[2] & fSDA[0]);
301
302          dSCL <= #1 sSCL;
303          dSDA <= #1 sSDA;
304      end
305
306    // detect start condition => detect falling edge on SDA while SCL is high
307    // detect stop condition => detect rising edge on SDA while SCL is high
308    reg sta_condition;
309    reg sto_condition;
310    always @(posedge clk or negedge nReset)
311      if (~nReset)
312      begin
313          sta_condition <= #1 1'b0;
314          sto_condition <= #1 1'b0;
315      end
316      else if (rst)
317      begin
318          sta_condition <= #1 1'b0;
319          sto_condition <= #1 1'b0;
320      end
321      else
322      begin
323          sta_condition <= #1 ~sSDA &  dSDA & sSCL;
324          sto_condition <= #1  sSDA & ~dSDA & sSCL;
325      end
326
327
328    // generate i2c bus busy signal
329    always @(posedge clk or negedge nReset)
330      if      (!nReset) busy <= #1 1'b0;
331      else if (rst    ) busy <= #1 1'b0;
332      else              busy <= #1 (sta_condition | busy) & ~sto_condition;
333
334
335    // generate arbitration lost signal
336    // aribitration lost when:
337    // 1) master drives SDA high, but the i2c bus is low
338    // 2) stop detected while not requested
339    reg cmd_stop;
340    always @(posedge clk or negedge nReset)
341      if (~nReset)
342          cmd_stop <= #1 1'b0;
343      else if (rst)
344          cmd_stop <= #1 1'b0;
345      else if (clk_en)
346          cmd_stop <= #1 cmd == `I2C_CMD_STOP;
347
348    always @(posedge clk or negedge nReset)
349      if (~nReset)
350          al <= #1 1'b0;
351      else if (rst)
352          al <= #1 1'b0;
353      else
354          al <= #1 (sda_chk & ~sSDA & sda_oen) | (|c_state & sto_condition & ~cmd_stop);
355
356
357    // generate dout signal (store SDA on rising edge of SCL)
358    always @(posedge clk)
359      if (sSCL & ~dSCL) dout <= #1 sSDA;
360
361
362    // generate statemachine
363
364    // nxt_state decoder
365    parameter [17:0] idle    = 18'b0_0000_0000_0000_0000;
366    parameter [17:0] start_a = 18'b0_0000_0000_0000_0001;
367    parameter [17:0] start_b = 18'b0_0000_0000_0000_0010;
368    parameter [17:0] start_c = 18'b0_0000_0000_0000_0100;
369    parameter [17:0] start_d = 18'b0_0000_0000_0000_1000;
370    parameter [17:0] start_e = 18'b0_0000_0000_0001_0000;
371    parameter [17:0] stop_a  = 18'b0_0000_0000_0010_0000;
372    parameter [17:0] stop_b  = 18'b0_0000_0000_0100_0000;
373    parameter [17:0] stop_c  = 18'b0_0000_0000_1000_0000;
374    parameter [17:0] stop_d  = 18'b0_0000_0001_0000_0000;
375    parameter [17:0] rd_a    = 18'b0_0000_0010_0000_0000;
376    parameter [17:0] rd_b    = 18'b0_0000_0100_0000_0000;
377    parameter [17:0] rd_c    = 18'b0_0000_1000_0000_0000;
378    parameter [17:0] rd_d    = 18'b0_0001_0000_0000_0000;
379    parameter [17:0] wr_a    = 18'b0_0010_0000_0000_0000;
380    parameter [17:0] wr_b    = 18'b0_0100_0000_0000_0000;
381    parameter [17:0] wr_c    = 18'b0_1000_0000_0000_0000;
382    parameter [17:0] wr_d    = 18'b1_0000_0000_0000_0000;
383
384    always @(posedge clk or negedge nReset)
385      if (!nReset)
386      begin
387          c_state <= #1 idle;
388          cmd_ack <= #1 1'b0;
389          scl_oen <= #1 1'b1;
390          sda_oen <= #1 1'b1;
391          sda_chk <= #1 1'b0;
392      end
393      else if (rst | al)
394      begin
395          c_state <= #1 idle;
396          cmd_ack <= #1 1'b0;
397          scl_oen <= #1 1'b1;
398          sda_oen <= #1 1'b1;
399          sda_chk <= #1 1'b0;
400      end
401      else
402      begin
403          cmd_ack   <= #1 1'b0; // default no command acknowledge + assert cmd_ack only 1clk cycle
404
405          if (clk_en)
406              case (c_state) // synopsys full_case parallel_case
407                    // idle state
408                    idle:
409                    begin
410                        case (cmd) // synopsys full_case parallel_case
411                             `I2C_CMD_START: c_state <= #1 start_a;
412                             `I2C_CMD_STOP:  c_state <= #1 stop_a;
413                             `I2C_CMD_WRITE: c_state <= #1 wr_a;
414                             `I2C_CMD_READ:  c_state <= #1 rd_a;
415                             default:        c_state <= #1 idle;
416                        endcase
417
418                        scl_oen <= #1 scl_oen; // keep SCL in same state
419                        sda_oen <= #1 sda_oen; // keep SDA in same state
420                        sda_chk <= #1 1'b0;    // don't check SDA output
421                    end
422
423                    // start
424                    start_a:
425                    begin
426                        c_state <= #1 start_b;
427                        scl_oen <= #1 scl_oen; // keep SCL in same state
428                        sda_oen <= #1 1'b1;    // set SDA high
429                        sda_chk <= #1 1'b0;    // don't check SDA output
430                    end
431
432                    start_b:
433                    begin
434                        c_state <= #1 start_c;
435                        scl_oen <= #1 1'b1; // set SCL high
436                        sda_oen <= #1 1'b1; // keep SDA high
437                        sda_chk <= #1 1'b0; // don't check SDA output
438                    end
439
440                    start_c:
441                    begin
442                        c_state <= #1 start_d;
443                        scl_oen <= #1 1'b1; // keep SCL high
444                        sda_oen <= #1 1'b0; // set SDA low
445                        sda_chk <= #1 1'b0; // don't check SDA output
446                    end
447
448                    start_d:
449                    begin
450                        c_state <= #1 start_e;
451                        scl_oen <= #1 1'b1; // keep SCL high
452                        sda_oen <= #1 1'b0; // keep SDA low
453                        sda_chk <= #1 1'b0; // don't check SDA output
454                    end
455
456                    start_e:
457                    begin
458                        c_state <= #1 idle;
459                        cmd_ack <= #1 1'b1;
460                        scl_oen <= #1 1'b0; // set SCL low
461                        sda_oen <= #1 1'b0; // keep SDA low
462                        sda_chk <= #1 1'b0; // don't check SDA output
463                    end
464
465                    // stop
466                    stop_a:
467                    begin
468                        c_state <= #1 stop_b;
469                        scl_oen <= #1 1'b0; // keep SCL low
470                        sda_oen <= #1 1'b0; // set SDA low
471                        sda_chk <= #1 1'b0; // don't check SDA output
472                    end
473
474                    stop_b:
475                    begin
476                        c_state <= #1 stop_c;
477                        scl_oen <= #1 1'b1; // set SCL high
478                        sda_oen <= #1 1'b0; // keep SDA low
479                        sda_chk <= #1 1'b0; // don't check SDA output
480                    end
481
482                    stop_c:
483                    begin
484                        c_state <= #1 stop_d;
485                        scl_oen <= #1 1'b1; // keep SCL high
486                        sda_oen <= #1 1'b0; // keep SDA low
487                        sda_chk <= #1 1'b0; // don't check SDA output
488                    end
489
490                    stop_d:
491                    begin
492                        c_state <= #1 idle;
493                        cmd_ack <= #1 1'b1;
494                        scl_oen <= #1 1'b1; // keep SCL high
495                        sda_oen <= #1 1'b1; // set SDA high
496                        sda_chk <= #1 1'b0; // don't check SDA output
497                    end
498
499                    // read
500                    rd_a:
501                    begin
502                        c_state <= #1 rd_b;
503                        scl_oen <= #1 1'b0; // keep SCL low
504                        sda_oen <= #1 1'b1; // tri-state SDA
505                        sda_chk <= #1 1'b0; // don't check SDA output
506                    end
507
508                    rd_b:
509                    begin
510                        c_state <= #1 rd_c;
511                        scl_oen <= #1 1'b1; // set SCL high
512                        sda_oen <= #1 1'b1; // keep SDA tri-stated
513                        sda_chk <= #1 1'b0; // don't check SDA output
514                    end
515
516                    rd_c:
517                    begin
518                        c_state <= #1 rd_d;
519                        scl_oen <= #1 1'b1; // keep SCL high
520                        sda_oen <= #1 1'b1; // keep SDA tri-stated
521                        sda_chk <= #1 1'b0; // don't check SDA output
522                    end
523
524                    rd_d:
525                    begin
526                        c_state <= #1 idle;
527                        cmd_ack <= #1 1'b1;
528                        scl_oen <= #1 1'b0; // set SCL low
529                        sda_oen <= #1 1'b1; // keep SDA tri-stated
530                        sda_chk <= #1 1'b0; // don't check SDA output
531                    end
532
533                    // write
534                    wr_a:
535                    begin
536                        c_state <= #1 wr_b;
537                        scl_oen <= #1 1'b0; // keep SCL low
538                        sda_oen <= #1 din;  // set SDA
539                        sda_chk <= #1 1'b0; // don't check SDA output (SCL low)
540                    end
541
542                    wr_b:
543                    begin
544                        c_state <= #1 wr_c;
545                        scl_oen <= #1 1'b1; // set SCL high
546                        sda_oen <= #1 din;  // keep SDA
547                        sda_chk <= #1 1'b0; // don't check SDA output yet
548                                            // allow some time for SDA and SCL to settle
549                    end
550
551                    wr_c:
552                    begin
553                        c_state <= #1 wr_d;
554                        scl_oen <= #1 1'b1; // keep SCL high
555                        sda_oen <= #1 din;
556                        sda_chk <= #1 1'b1; // check SDA output
557                    end
558
559                    wr_d:
560                    begin
561                        c_state <= #1 idle;
562                        cmd_ack <= #1 1'b1;
563                        scl_oen <= #1 1'b0; // set SCL low
564                        sda_oen <= #1 din;
565                        sda_chk <= #1 1'b0; // don't check SDA output (SCL low)
566                    end
567
568              endcase
569      end
570
571
572    // assign scl and sda output (always gnd)
573    assign scl_o = 1'b0;
574    assign sda_o = 1'b0;
575
576endmodule
Note: See TracBrowser for help on using the repository browser.