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

Subversion Repositories oms8051mini

[/] [oms8051mini/] [trunk/] [verif/] [agents/] [i2cs/] [i2c_slave_model.v] - Blame information for rev 29

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 29 dinesha
/////////////////////////////////////////////////////////////////////
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: not supported by cvs2svn $
49
//               Revision 1.6  2005/02/28 11:33:48  rherveille
50
//               Fixed Tsu:sta timing check.
51
//               Added Thd:sta timing check.
52
//
53
//               Revision 1.5  2003/12/05 11:05:19  rherveille
54
//               Fixed slave address MSB='1' bug
55
//
56
//               Revision 1.4  2003/09/11 08:25:37  rherveille
57
//               Fixed a bug in the timing section. Changed 'tst_scl' into 'tst_sto'.
58
//
59
//               Revision 1.3  2002/10/30 18:11:06  rherveille
60
//               Added timing tests to i2c_model.
61
//               Updated testbench.
62
//
63
//               Revision 1.2  2002/03/17 10:26:38  rherveille
64
//               Fixed some race conditions in the i2c-slave model.
65
//               Added debug information.
66
//               Added headers.
67
//
68
 
69
 
70
module i2c_slave_model (scl, sda);
71
 
72
        //
73
        // parameters
74
        //
75
        parameter I2C_ADR = 7'b001_0000;
76
 
77
        //
78
        // input && outpus
79
        //
80
        input scl;
81
        inout sda;
82
 
83
        //
84
        // Variable declaration
85
        //
86
        wire debug = 1'b1;
87
 
88
        reg [7:0] mem [255:0]; // initiate memory
89
        reg [7:0] mem_adr;   // memory address
90
        reg [7:0] mem_do;    // memory data output
91
 
92
        reg sta, d_sta;
93
        reg sto, d_sto;
94
 
95
        reg [7:0] sr;        // 8bit shift register
96
        reg       rw;        // read/write direction
97
 
98
        wire      my_adr;    // my address called ??
99
        wire      i2c_reset; // i2c-statemachine reset
100
        reg [2:0] bit_cnt;   // 3bit downcounter
101
        wire      acc_done;  // 8bits transfered
102
        reg       ld;        // load downcounter
103
 
104
        reg       sda_o;     // sda-drive level
105
        wire      sda_dly;   // delayed version of sda
106
 
107
        // statemachine declaration
108
        parameter idle        = 3'b000;
109
        parameter slave_ack   = 3'b001;
110
        parameter get_mem_adr = 3'b010;
111
        parameter gma_ack     = 3'b011;
112
        parameter data        = 3'b100;
113
        parameter data_ack    = 3'b101;
114
 
115
        reg [2:0] state; // synopsys enum_state
116
 
117
        //
118
        // module body
119
        //
120
 
121
        initial
122
        begin
123
           sda_o = 1'b1;
124
           state = idle;
125
        end
126
 
127
        // generate shift register
128
        always @(posedge scl)
129
          sr <= #1 {sr[6:0],sda};
130
 
131
        //detect my_address
132
        assign my_adr = (sr[7:1] == I2C_ADR);
133
        // FIXME: This should not be a generic assign, but rather
134
        // qualified on address transfer phase and probably reset by stop
135
 
136
        //generate bit-counter
137
        always @(posedge scl)
138
          if(ld)
139
            bit_cnt <= #1 3'b111;
140
          else
141
            bit_cnt <= #1 bit_cnt - 3'h1;
142
 
143
        //generate access done signal
144
        assign acc_done = !(|bit_cnt);
145
 
146
        // generate delayed version of sda
147
        // this model assumes a hold time for sda after the falling edge of scl.
148
        // According to the Phillips i2c spec, there s/b a 0 ns hold time for sda
149
        // with regards to scl. If the data changes coincident with the clock, the
150
        // acknowledge is missed
151
        // Fix by Michael Sosnoski
152
        assign #1 sda_dly = sda;
153
 
154
 
155
        //detect start condition
156
        always @(negedge sda)
157
          if(scl)
158
            begin
159
                sta   <= #1 1'b1;
160
                d_sta <= #1 1'b0;
161
                sto   <= #1 1'b0;
162
 
163
                if(debug)
164
                  $display("DEBUG i2c_slave; start condition detected at %t", $time);
165
            end
166
          else
167
            sta <= #1 1'b0;
168
 
169
        always @(posedge scl)
170
          d_sta <= #1 sta;
171
 
172
        // detect stop condition
173
        always @(posedge sda)
174
          if(scl)
175
            begin
176
               sta <= #1 1'b0;
177
               sto <= #1 1'b1;
178
 
179
               if(debug)
180
                 $display("DEBUG i2c_slave; stop condition detected at %t", $time);
181
            end
182
          else
183
            sto <= #1 1'b0;
184
 
185
        //generate i2c_reset signal
186
        assign i2c_reset = sta || sto;
187
 
188
        // generate statemachine
189
        always @(negedge scl or posedge sto)
190
          if (sto || (sta && !d_sta) )
191
            begin
192
                state <= #1 idle; // reset statemachine
193
 
194
                sda_o <= #1 1'b1;
195
                ld    <= #1 1'b1;
196
            end
197
          else
198
            begin
199
                // initial settings
200
                sda_o <= #1 1'b1;
201
                ld    <= #1 1'b0;
202
 
203
                case(state) // synopsys full_case parallel_case
204
                    idle: // idle state
205
                      if (acc_done && my_adr)
206
                        begin
207
                            state <= #1 slave_ack;
208
                            rw <= #1 sr[0];
209
                            sda_o <= #1 1'b0; // generate i2c_ack
210
 
211
                            #2;
212
                            if(debug && rw)
213
                              $display("DEBUG i2c_slave; command byte received (read) at %t", $time);
214
                            if(debug && !rw)
215
                              $display("DEBUG i2c_slave; command byte received (write) at %t", $time);
216
 
217
                            if(rw)
218
                              begin
219
                                  mem_do <= #1 mem[mem_adr];
220
 
221
                                  if(debug)
222
                                    begin
223
                                        #2 $display("DEBUG i2c_slave; data block read %x from address %x (1)", mem_do, mem_adr);
224
                                        #2 $display("DEBUG i2c_slave; memcheck [%x]=%x", mem_adr, mem[mem_adr]);
225
                                    end
226
                              end
227
                        end
228
 
229
                    slave_ack:
230
                      begin
231
                          if(rw)
232
                            begin
233
                                state <= #1 data;
234
                                sda_o <= #1 mem_do[7];
235
                            end
236
                          else
237
                            state <= #1 get_mem_adr;
238
 
239
                          ld    <= #1 1'b1;
240
                      end
241
 
242
                    get_mem_adr: // wait for memory address
243
                      if(acc_done)
244
                        begin
245
                            state <= #1 gma_ack;
246
                            mem_adr <= #1 sr; // store memory address
247
                            sda_o <= #1 !(sr <= 255); // generate i2c_ack, for valid address
248
 
249
                            if(debug)
250
                              #1 $display("DEBUG i2c_slave; address received. adr=%x, ack=%b", sr, sda_o);
251
                        end
252
 
253
                    gma_ack:
254
                      begin
255
                          state <= #1 data;
256
                          ld    <= #1 1'b1;
257
                      end
258
 
259
                    data: // receive or drive data
260
                      begin
261
                          if(rw)
262
                            sda_o <= #1 mem_do[7];
263
 
264
                          if(acc_done)
265
                            begin
266
                                state <= #1 data_ack;
267
                                mem_adr <= #2 mem_adr + 8'h1;
268
                                sda_o <= #1 (rw && (mem_adr <= 255) ); // send ack on write, receive ack on read
269
 
270
                                if(rw)
271
                                  begin
272
                                      #3 mem_do <= mem[mem_adr];
273
 
274
                                      if(debug)
275
                                        #5 $display("DEBUG i2c_slave; data block read %x from address %x (2)", mem_do, mem_adr);
276
                                  end
277
 
278
                                if(!rw)
279
                                  begin
280
                                      mem[ mem_adr ] <= #1 sr; // store data in memory
281
 
282
                                      if(debug)
283
                                        #2 $display("DEBUG i2c_slave; data block write %x to address %x", sr, mem_adr);
284
                                  end
285
                            end
286
                      end
287
 
288
                    data_ack:
289
                      begin
290
                          ld <= #1 1'b1;
291
 
292
                          if(rw)
293
                            if(sr[0]) // read operation && master send NACK
294
                              begin
295
                                  state <= #1 idle;
296
                                  sda_o <= #1 1'b1;
297
                              end
298
                            else
299
                              begin
300
                                  state <= #1 data;
301
                                  sda_o <= #1 mem_do[7];
302
                              end
303
                          else
304
                            begin
305
                                state <= #1 data;
306
                                sda_o <= #1 1'b1;
307
                            end
308
                      end
309
 
310
                endcase
311
            end
312
 
313
        // read data from memory
314
        always @(posedge scl)
315
          if(!acc_done && rw)
316
            mem_do <= #1 {mem_do[6:0], 1'b1}; // insert 1'b1 for host ack generation
317
 
318
        // generate tri-states
319
        assign sda = sda_o ? 1'bz : 1'b0;
320
 
321
 
322
        //
323
        // Timing checks
324
        //
325
 
326
        wire tst_sto = sto;
327
        wire tst_sta = sta;
328
 
329
        specify
330
          specparam normal_scl_low  = 4700,
331
                    normal_scl_high = 4000,
332
                    normal_tsu_sta  = 4700,
333
                    normal_thd_sta  = 4000,
334
                    normal_tsu_sto  = 4000,
335
                    normal_tbuf     = 4700,
336
 
337
                    fast_scl_low  = 1300,
338
                    fast_scl_high =  600,
339
                    fast_tsu_sta  = 1300,
340
                    fast_thd_sta  =  600,
341
                    fast_tsu_sto  =  600,
342
                    fast_tbuf     = 1300;
343
 
344
          $width(negedge scl, normal_scl_low);  // scl low time
345
          $width(posedge scl, normal_scl_high); // scl high time
346
 
347
          $setup(posedge scl, negedge sda &&& scl, normal_tsu_sta); // setup start
348
          $setup(negedge sda &&& scl, negedge scl, normal_thd_sta); // hold start
349
          $setup(posedge scl, posedge sda &&& scl, normal_tsu_sto); // setup stop
350
 
351
          $setup(posedge tst_sta, posedge tst_sto, normal_tbuf); // stop to start time
352
        endspecify
353
 
354
endmodule
355
 
356
 

powered by: WebSVN 2.1.0

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