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

Subversion Repositories mips_enhanced

[/] [mips_enhanced/] [trunk/] [grlib-gpl-1.0.19-b3188/] [lib/] [gaisler/] [sim/] [i2c_slave_model.v] - Blame information for rev 2

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 dimamali
/////////////////////////////////////////////////////////////////////
2
////                                                             ////
3
////  WISHBONE rev.B2 compliant synthesizable I2C Slave model    ////
4
////                                                             ////
5
////                                                             ////
6
////  Authors: Richard Herveille (richard@asics.ws) www.asics.ws ////
7
////           John Sheahan (jrsheahan@optushome.com.au)         ////
8
////                                                             ////
9
////  Downloaded from: http://www.opencores.org/projects/i2c/    ////
10
////                                                             ////
11
/////////////////////////////////////////////////////////////////////
12
////                                                             ////
13
//// Copyright (C) 2001,2002 Richard Herveille                   ////
14
////                         richard@asics.ws                    ////
15
////                                                             ////
16
//// This source file may be used and distributed without        ////
17
//// restriction provided that this copyright statement is not   ////
18
//// removed from the file and that any derivative work contains ////
19
//// the original copyright notice and the associated disclaimer.////
20
////                                                             ////
21
////     THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY     ////
22
//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED   ////
23
//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS   ////
24
//// FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR      ////
25
//// OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,         ////
26
//// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES    ////
27
//// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE   ////
28
//// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR        ////
29
//// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF  ////
30
//// LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT  ////
31
//// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT  ////
32
//// OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE         ////
33
//// POSSIBILITY OF SUCH DAMAGE.                                 ////
34
////                                                             ////
35
/////////////////////////////////////////////////////////////////////
36
 
37
//  CVS Log
38
//
39
//  $Id: i2c_slave_model.v,v 1.7 2006/09/04 09:08:51 rherveille Exp $
40
//
41
//  $Date: 2006/09/04 09:08:51 $
42
//  $Revision: 1.7 $
43
//  $Author: rherveille $
44
//  $Locker:  $
45
//  $State: Exp $
46
//
47
// Change History:
48
//               $Log: i2c_slave_model.v,v $
49
//               Revision 1.7  2006/09/04 09:08:51  rherveille
50
//               fixed (n)ack generation
51
//
52
//               Revision 1.6  2005/02/28 11:33:48  rherveille
53
//               Fixed Tsu:sta timing check.
54
//               Added Thd:sta timing check.
55
//
56
//               Revision 1.5  2003/12/05 11:05:19  rherveille
57
//               Fixed slave address MSB='1' bug
58
//
59
//               Revision 1.4  2003/09/11 08:25:37  rherveille
60
//               Fixed a bug in the timing section. Changed 'tst_scl' into 'tst_sto'.
61
//
62
//               Revision 1.3  2002/10/30 18:11:06  rherveille
63
//               Added timing tests to i2c_model.
64
//               Updated testbench.
65
//
66
//               Revision 1.2  2002/03/17 10:26:38  rherveille
67
//               Fixed some race conditions in the i2c-slave model.
68
//               Added debug information.
69
//               Added headers.
70
//
71
 
72
//               Disabled debug print out and timing checks - jan@gaisler.com
73
 
74
`timescale 1ns / 10ps // removed include of timescale.v - jan@gaisler.com
75
 
76
module i2c_slave_model (scl, sda);
77
 
78
        //
79
        // parameters
80
        //
81
        parameter I2C_ADR = 7'b101_0000;
82
 
83
        //
84
        // input && outpus
85
        //
86
        input scl;
87
        inout sda;
88
 
89
        //
90
        // Variable declaration
91
        //
92
        wire debug = 1'b0;
93
 
94
        reg [7:0] mem [3:0]; // initiate memory
95
        reg [7:0] mem_adr;   // memory address
96
        reg [7:0] mem_do;    // memory data output
97
 
98
        reg sta, d_sta;
99
        reg sto, d_sto;
100
 
101
        reg [7:0] sr;        // 8bit shift register
102
        reg       rw;        // read/write direction
103
 
104
        wire      my_adr;    // my address called ??
105
        wire      i2c_reset; // i2c-statemachine reset
106
        reg [2:0] bit_cnt;   // 3bit downcounter
107
        wire      acc_done;  // 8bits transfered
108
        reg       ld;        // load downcounter
109
 
110
        reg       sda_o;     // sda-drive level
111
        wire      sda_dly;   // delayed version of sda
112
 
113
        // statemachine declaration
114
        parameter idle        = 3'b000;
115
        parameter slave_ack   = 3'b001;
116
        parameter get_mem_adr = 3'b010;
117
        parameter gma_ack     = 3'b011;
118
        parameter data        = 3'b100;
119
        parameter data_ack    = 3'b101;
120
 
121
        reg [2:0] state; // synopsys enum_state
122
 
123
        //
124
        // module body
125
        //
126
 
127
        initial
128
        begin
129
           sda_o = 1'b1;
130
           state = idle;
131
        end
132
 
133
        // generate shift register
134
        always @(posedge scl)
135
          sr <= #1 {sr[6:0],sda};
136
 
137
        //detect my_address
138
        assign my_adr = (sr[7:1] == I2C_ADR);
139
        // FIXME: This should not be a generic assign, but rather
140
        // qualified on address transfer phase and probably reset by stop
141
 
142
        //generate bit-counter
143
        always @(posedge scl)
144
          if(ld)
145
            bit_cnt <= #1 3'b111;
146
          else
147
            bit_cnt <= #1 bit_cnt - 3'h1;
148
 
149
        //generate access done signal
150
        assign acc_done = !(|bit_cnt);
151
 
152
        // generate delayed version of sda
153
        // this model assumes a hold time for sda after the falling edge of scl.
154
        // According to the Phillips i2c spec, there s/b a 0 ns hold time for sda
155
        // with regards to scl. If the data changes coincident with the clock, the
156
        // acknowledge is missed
157
        // Fix by Michael Sosnoski
158
        assign #1 sda_dly = sda;
159
 
160
 
161
        //detect start condition
162
        always @(negedge sda)
163
          if(scl)
164
            begin
165
                sta   <= #1 1'b1;
166
                d_sta <= #1 1'b0;
167
                sto   <= #1 1'b0;
168
 
169
                if(debug)
170
                  $display("DEBUG i2c_slave; start condition detected at %t", $time);
171
            end
172
          else
173
            sta <= #1 1'b0;
174
 
175
        always @(posedge scl)
176
          d_sta <= #1 sta;
177
 
178
        // detect stop condition
179
        always @(posedge sda)
180
          if(scl)
181
            begin
182
               sta <= #1 1'b0;
183
               sto <= #1 1'b1;
184
 
185
               //if(debug)
186
               //  $display("DEBUG i2c_slave; stop condition detected at %t", $time);
187
            end
188
          else
189
            sto <= #1 1'b0;
190
 
191
        //generate i2c_reset signal
192
        assign i2c_reset = sta || sto;
193
 
194
        // generate statemachine
195
        always @(negedge scl or posedge sto)
196
          if (sto || (sta && !d_sta) )
197
            begin
198
                state <= #1 idle; // reset statemachine
199
 
200
                sda_o <= #1 1'b1;
201
                ld    <= #1 1'b1;
202
            end
203
          else
204
            begin
205
                // initial settings
206
                sda_o <= #1 1'b1;
207
                ld    <= #1 1'b0;
208
 
209
                case(state) // synopsys full_case parallel_case
210
                    idle: // idle state
211
                      if (acc_done && my_adr)
212
                        begin
213
                            state <= #1 slave_ack;
214
                            rw <= #1 sr[0];
215
                            sda_o <= #1 1'b0; // generate i2c_ack
216
 
217
                            #2;
218
                            if(debug && rw)
219
                              $display("DEBUG i2c_slave; command byte received (read) at %t", $time);
220
                            if(debug && !rw)
221
                              $display("DEBUG i2c_slave; command byte received (write) at %t", $time);
222
 
223
                            if(rw)
224
                              begin
225
                                  mem_do <= #1 mem[mem_adr];
226
 
227
                                  if(debug)
228
                                    begin
229
                                        #2 $display("DEBUG i2c_slave; data block read %x from address %x (1)", mem_do, mem_adr);
230
                                        #2 $display("DEBUG i2c_slave; memcheck [0]=%x, [1]=%x, [2]=%x", mem[4'h0], mem[4'h1], mem[4'h2]);
231
                                    end
232
                              end
233
                        end
234
 
235
                    slave_ack:
236
                      begin
237
                          if(rw)
238
                            begin
239
                                state <= #1 data;
240
                                sda_o <= #1 mem_do[7];
241
                            end
242
                          else
243
                            state <= #1 get_mem_adr;
244
 
245
                          ld    <= #1 1'b1;
246
                      end
247
 
248
                    get_mem_adr: // wait for memory address
249
                      if(acc_done)
250
                        begin
251
                            state <= #1 gma_ack;
252
                            mem_adr <= #1 sr; // store memory address
253
                            sda_o <= #1 !(sr <= 15); // generate i2c_ack, for valid address
254
 
255
                            if(debug)
256
                              #1 $display("DEBUG i2c_slave; address received. adr=%x, ack=%b", sr, sda_o);
257
                        end
258
 
259
                    gma_ack:
260
                      begin
261
                          state <= #1 data;
262
                          ld    <= #1 1'b1;
263
                      end
264
 
265
                    data: // receive or drive data
266
                      begin
267
                          if(rw)
268
                            sda_o <= #1 mem_do[7];
269
 
270
                          if(acc_done)
271
                            begin
272
                                state <= #1 data_ack;
273
                                mem_adr <= #2 mem_adr + 8'h1;
274
                                sda_o <= #1 (rw && (mem_adr <= 15) ); // send ack on write, receive ack on read
275
 
276
                                if(rw)
277
                                  begin
278
                                      #3 mem_do <= mem[mem_adr];
279
 
280
                                      if(debug)
281
                                        #5 $display("DEBUG i2c_slave; data block read %x from address %x (2)", mem_do, mem_adr);
282
                                  end
283
 
284
                                if(!rw)
285
                                  begin
286
                                      mem[ mem_adr[3:0] ] <= #1 sr; // store data in memory
287
 
288
                                      if(debug)
289
                                        #2 $display("DEBUG i2c_slave; data block write %x to address %x", sr, mem_adr);
290
                                  end
291
                            end
292
                      end
293
 
294
                    data_ack:
295
                      begin
296
                          ld <= #1 1'b1;
297
 
298
                          if(rw)
299
                            if(sr[0]) // read operation && master send NACK
300
                              begin
301
                                  state <= #1 idle;
302
                                  sda_o <= #1 1'b1;
303
                              end
304
                            else
305
                              begin
306
                                  state <= #1 data;
307
                                  sda_o <= #1 mem_do[7];
308
                              end
309
                          else
310
                            begin
311
                                state <= #1 data;
312
                                sda_o <= #1 1'b1;
313
                            end
314
                      end
315
 
316
                endcase
317
            end
318
 
319
        // read data from memory
320
        always @(posedge scl)
321
          if(!acc_done && rw)
322
            mem_do <= #1 {mem_do[6:0], 1'b1}; // insert 1'b1 for host ack generation
323
 
324
        // generate tri-states
325
        assign sda = sda_o ? 1'bz : 1'b0;
326
 
327
 
328
        //
329
        // Timing checks
330
        //
331
 
332
        wire tst_sto = sto;
333
        wire tst_sta = sta;
334
 
335
        specify
336
          specparam normal_scl_low  = 4700,
337
                    normal_scl_high = 4000,
338
                    normal_tsu_sta  = 4700,
339
                    normal_thd_sta  = 4000,
340
                    normal_tsu_sto  = 4000,
341
                    normal_tbuf     = 4700,
342
 
343
                    fast_scl_low  = 1300,
344
                    fast_scl_high =  600,
345
                    fast_tsu_sta  = 1300,
346
                    fast_thd_sta  =  600,
347
                    fast_tsu_sto  =  600,
348
                    fast_tbuf     = 1300;
349
 
350
          // $width(negedge scl, fast_scl_low);  // scl low time
351
          // $width(posedge scl, fast_scl_high); // scl high time
352
 
353
          // $setup(posedge scl, negedge sda &&& scl, fast_tsu_sta); // setup start
354
          // $setup(negedge sda &&& scl, negedge scl, fast_thd_sta); // hold start
355
          // $setup(posedge scl, posedge sda &&& scl, fast_tsu_sto); // setup stop
356
 
357
          // $setup(posedge tst_sta, posedge tst_sto, fast_tbuf); // stop to start time
358
        endspecify
359
 
360
endmodule
361
 
362
 

powered by: WebSVN 2.1.0

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