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

Subversion Repositories i2c

[/] [i2c/] [trunk/] [bench/] [verilog/] [i2c_slave_model.v] - Blame information for rev 19

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

Line No. Rev Author Line
1 19 rherveille
/////////////////////////////////////////////////////////////////////
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 10 rherveille
//
39 19 rherveille
//  $Id: i2c_slave_model.v,v 1.2 2002-03-17 10:26:38 rherveille Exp $
40 10 rherveille
//
41 19 rherveille
//  $Date: 2002-03-17 10:26:38 $
42
//  $Revision: 1.2 $
43
//  $Author: rherveille $
44
//  $Locker:  $
45
//  $State: Exp $
46
//
47
// Change History:
48
//               $Log: not supported by cvs2svn $
49 10 rherveille
 
50
`include "timescale.v"
51
 
52
module i2c_slave_model (scl, sda);
53
 
54
        //
55
        // parameters
56
        //
57
        parameter I2C_ADR = 7'b001_0000;
58
 
59
        //
60
        // input && outpus
61
        //
62
        input scl;
63
        inout sda;
64
 
65
        //
66
        // Variable declaration
67
        //
68 19 rherveille
        wire debug = 1'b1;
69
 
70 10 rherveille
        reg [7:0] mem [3:0]; // initiate memory
71
        reg [7:0] mem_adr;   // memory address
72
        reg [7:0] mem_do;    // memory data output
73
 
74
        reg sta, d_sta;
75
        reg sto, d_sto;
76
 
77
        reg [7:0] sr;        // 8bit shift register
78
        reg       rw;        // read/write direction
79
 
80
        wire      my_adr;    // my address called ??
81
        wire      i2c_reset; // i2c-statemachine reset
82
        reg [2:0] bit_cnt;   // 3bit downcounter
83
        wire      acc_done;  // 8bits transfered
84
        reg       ld;        // load downcounter
85
 
86
        reg       sda_o;     // sda-drive level
87
 
88
        // statemachine declaration
89
        parameter idle        = 3'b000;
90
        parameter slave_ack   = 3'b001;
91
        parameter get_mem_adr = 3'b010;
92
        parameter gma_ack     = 3'b011;
93
        parameter data        = 3'b100;
94
        parameter data_ack    = 3'b101;
95
 
96
        reg [2:0] state; // synopsys enum_state
97
 
98
        //
99
        // module body
100
        //
101
 
102
        initial
103
                begin
104
                        sda_o = 1'b1;
105
                        state = idle;
106
                end
107
 
108
        // generate shift register
109
        always@(posedge scl)
110
                sr <= #1 {sr[6:0],sda};
111
 
112
        //detect my_address
113
        assign my_adr = (sr[7:1] == I2C_ADR);
114 19 rherveille
        // FIXME: This should not be a generic assign, but rather 
115
        // qualified on address transfer phase and probably reset by stop
116 10 rherveille
 
117
        //generate bit-counter
118
        always@(posedge scl)
119
                if (ld)
120
                        bit_cnt <= #1 3'b111;
121
                else
122
                        bit_cnt <= #1 bit_cnt - 3'h1;
123
 
124
        //generate access done signal
125
        assign acc_done = !(|bit_cnt);
126
 
127
        //detect start condition
128
        always@(negedge sda)
129
                if (scl)
130 19 rherveille
                begin
131 10 rherveille
                        sta <= #1 1'b1;
132 19 rherveille
 
133
                        if (debug)
134
                                $display("DEBUG i2c_slave; start condition detected at %t", $time);
135
                end
136 10 rherveille
                else
137
                        sta <= #1 1'b0;
138
 
139
        always@(posedge scl)
140
                d_sta <= #1 sta;
141
 
142
        // detect stop condition
143
        always@(posedge sda)
144
                if (scl)
145 19 rherveille
                begin
146 10 rherveille
                        sto <= #1 1'b1;
147 19 rherveille
 
148
                        if (debug)
149
                                $display("DEBUG i2c_slave; stop condition detected at %t", $time);
150
                end
151 10 rherveille
                else
152
                        sto <= #1 1'b0;
153
 
154
        //generate i2c_reset signal
155
        assign i2c_reset = sta || sto;
156
 
157
        // generate statemachine
158
        always@(negedge scl or posedge sto)
159
                if (sto || (sta && !d_sta) )
160
                        begin
161
                                state <= #1 idle; // reset statemachine
162
 
163
                                sda_o <= #1 1'b1;
164
                                ld    <= #1 1'b1;
165
                        end
166
                else
167
                        begin
168
                                // initial settings
169
                                sda_o <= #1 1'b1;
170
                                ld    <= #1 1'b0;
171
 
172
                                case (state) // synopsys full_case parallel_case
173
                                        idle: // idle state
174
                                                if (acc_done && my_adr)
175 19 rherveille
                                                begin
176
                                                        state <= #1 slave_ack;
177
                                                        rw <= #1 sr[0];
178
 
179
                                                        sda_o <= #1 1'b0; // generate i2c_ack
180
 
181
                                                        #2;
182
                                                        if (debug && rw)
183
                                                                $display("DEBUG i2c_slave; command byte received (read) at %t", $time);
184
                                                        if (debug && !rw)
185
                                                                $display("DEBUG i2c_slave; command byte received (write) at %t", $time);
186
 
187
                                                        if (rw)
188
                                                        begin
189
                                                                mem_do <= #1 mem[mem_adr];
190
 
191
                                                                if (debug)
192 10 rherveille
                                                                begin
193 19 rherveille
                                                                        #2 $display("DEBUG i2c_slave; data block read %x from address %x (1)", mem_do, mem_adr);
194
                                                                        #2 $display("DEBUG i2c_slave; memcheck [0]=%x, [1]=%x, [2]=%x", mem[4'h0], mem[4'h1], mem[4'h2]);
195 10 rherveille
                                                                end
196 19 rherveille
                                                        end
197
                                                end
198 10 rherveille
 
199
                                        slave_ack:
200
                                                begin
201
                                                        if (rw)
202 19 rherveille
                                                        begin
203
                                                                state <= #1 data;
204
                                                                sda_o <= #1 mem_do[7];
205
                                                        end
206 10 rherveille
                                                        else
207
                                                                state <= #1 get_mem_adr;
208
 
209
                                                        ld    <= #1 1'b1;
210
                                                end
211
 
212
                                        get_mem_adr: // wait for memory address
213
                                                if (acc_done)
214 19 rherveille
                                                begin
215
                                                        state <= #1 gma_ack;
216
                                                        mem_adr <= #1 sr; // store memory address
217 10 rherveille
 
218 19 rherveille
                                                        sda_o <= #1 !(sr <= 15); // generate i2c_ack, for valid address
219 10 rherveille
 
220 19 rherveille
                                                        if (debug)
221
                                                                #1 $display("DEBUG i2c_slave; address received. adr=%x, ack=%b", sr, sda_o);
222
                                                end
223
 
224 10 rherveille
                                        gma_ack:
225
                                                begin
226
                                                        state <= #1 data;
227
                                                        ld    <= #1 1'b1;
228
                                                end
229
 
230
                                        data: // receive or drive data
231
                                                begin
232
                                                        if (rw)
233
                                                                sda_o <= #1 mem_do[7];
234
 
235
                                                        if (acc_done)
236 19 rherveille
                                                        begin
237
                                                                state <= #1 data_ack;
238
 
239
                                                                mem_adr <= #2 mem_adr + 8'h1;
240
 
241
                                                                if (rw)
242 10 rherveille
                                                                begin
243 19 rherveille
                                                                        #3 mem_do <= mem[mem_adr];
244 10 rherveille
 
245 19 rherveille
                                                                        if (debug)
246
                                                                                #5 $display("DEBUG i2c_slave; data block read %x from address %x (2)", mem_do, mem_adr);
247
                                                                end
248 10 rherveille
 
249 19 rherveille
                                                                if (!rw)
250
                                                                begin
251
                                                                        mem[ mem_adr[3:0] ] <= #1 sr; // store data in memory
252
 
253
                                                                        if (debug)
254
                                                                                #2 $display("DEBUG i2c_slave; data block write %x to address %x", sr, mem_adr);
255 10 rherveille
                                                                end
256 19 rherveille
 
257
                                                                sda_o <= #1 (rw && (mem_adr <= 15) ); // send ack on write, receive ack on read
258
                                                        end
259 10 rherveille
                                                end
260
 
261
                                        data_ack:
262
                                                begin
263
                                                        ld    <= #1 1'b1;
264
 
265
                                                        if (rw)
266
                                                                if (sda) // read operation && master send NACK
267
                                                                        begin
268
                                                                                state <= #1 idle;
269
                                                                                sda_o <= #1 1'b1;
270
                                                                        end
271
                                                                else
272
                                                                        begin
273
                                                                                state <= #1 data;
274
                                                                                sda_o <= #1 mem_do[7];
275
                                                                        end
276
                                                        else
277
                                                                begin
278
                                                                        state <= #1 data;
279
                                                                        sda_o <= #1 1'b1;
280
                                                                end
281
                                                end
282
 
283
                                endcase
284
                        end
285
 
286
        // read data from memory
287
        always@(posedge scl)
288 19 rherveille
                if (!acc_done && rw)
289 10 rherveille
                        mem_do <= #1 {mem_do[6:0], 1'b1}; // insert 1'b1 for host ack generation
290
 
291
        // generate tri-states
292
        assign sda = sda_o ? 1'bz : 1'b0;
293
 
294
endmodule
295
 
296
 

powered by: WebSVN 2.1.0

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