1 /////////////////////////////////////////////////////////////////////
3 //// WISHBONE rev.B2 compliant synthesizable I2C Slave model ////
6 //// Authors: Richard Herveille (richard@asics.ws) www.asics.ws ////
7 //// John Sheahan (jrsheahan@optushome.com.au) ////
9 //// Downloaded from: http://www.opencores.org/projects/i2c/ ////
11 /////////////////////////////////////////////////////////////////////
13 //// Copyright (C) 2001,2002 Richard Herveille ////
14 //// richard@asics.ws ////
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.////
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. ////
35 /////////////////////////////////////////////////////////////////////
39 // $Id: i2c_slave_model.v,v 1.7 2006/09/04 09:08:51 rherveille Exp $
41 // $Date: 2006/09/04 09:08:51 $
43 // $Author: rherveille $
48 // $Log: i2c_slave_model.v,v $
49 // Revision 1.7 2006/09/04 09:08:51 rherveille
50 // fixed (n)ack generation
52 // Revision 1.6 2005/02/28 11:33:48 rherveille
53 // Fixed Tsu:sta timing check.
54 // Added Thd:sta timing check.
56 // Revision 1.5 2003/12/05 11:05:19 rherveille
57 // Fixed slave address MSB='1' bug
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'.
62 // Revision 1.3 2002/10/30 18:11:06 rherveille
63 // Added timing tests to i2c_model.
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.
72 `include "timescale.v"
74 module i2c_slave_model (scl, sda);
79 parameter I2C_ADR = 7'b001_0000;
88 // Variable declaration
92 reg [7:0] mem [3:0]; // initiate memory
93 reg [7:0] mem_adr; // memory address
94 reg [7:0] mem_do; // memory data output
99 reg [7:0] sr; // 8bit shift register
100 reg rw; // read/write direction
102 wire my_adr; // my address called ??
103 wire i2c_reset; // i2c-statemachine reset
104 reg [2:0] bit_cnt; // 3bit downcounter
105 wire acc_done; // 8bits transfered
106 reg ld; // load downcounter
108 reg sda_o; // sda-drive level
109 wire sda_dly; // delayed version of sda
111 // statemachine declaration
112 parameter idle = 3'b000;
113 parameter slave_ack = 3'b001;
114 parameter get_mem_adr = 3'b010;
115 parameter gma_ack = 3'b011;
116 parameter data = 3'b100;
117 parameter data_ack = 3'b101;
119 reg [2:0] state; // synopsys enum_state
131 // generate shift register
132 always @(posedge scl)
133 sr <= #1 {sr[6:0],sda};
136 assign my_adr = (sr[7:1] == I2C_ADR);
137 // FIXME: This should not be a generic assign, but rather
138 // qualified on address transfer phase and probably reset by stop
140 //generate bit-counter
141 always @(posedge scl)
143 bit_cnt <= #1 3'b111;
145 bit_cnt <= #1 bit_cnt - 3'h1;
147 //generate access done signal
148 assign acc_done = !(|bit_cnt);
150 // generate delayed version of sda
151 // this model assumes a hold time for sda after the falling edge of scl.
152 // According to the Phillips i2c spec, there s/b a 0 ns hold time for sda
153 // with regards to scl. If the data changes coincident with the clock, the
154 // acknowledge is missed
155 // Fix by Michael Sosnoski
156 assign #1 sda_dly = sda;
159 //detect start condition
160 always @(negedge sda)
168 $display("DEBUG i2c_slave; start condition detected at %t", $time);
173 always @(posedge scl)
176 // detect stop condition
177 always @(posedge sda)
184 $display("DEBUG i2c_slave; stop condition detected at %t", $time);
189 //generate i2c_reset signal
190 assign i2c_reset = sta || sto;
192 // generate statemachine
193 always @(negedge scl or posedge sto)
194 if (sto || (sta && !d_sta) )
196 state <= #1 idle; // reset statemachine
207 case(state) // synopsys full_case parallel_case
209 if (acc_done && my_adr)
211 state <= #1 slave_ack;
213 sda_o <= #1 1'b0; // generate i2c_ack
217 $display("DEBUG i2c_slave; command byte received (read) at %t", $time);
219 $display("DEBUG i2c_slave; command byte received (write) at %t", $time);
223 mem_do <= #1 mem[mem_adr];
227 #2 $display("DEBUG i2c_slave; data block read %x from address %x (1)", mem_do, mem_adr);
228 #2 $display("DEBUG i2c_slave; memcheck [0]=%x, [1]=%x, [2]=%x", mem[4'h0], mem[4'h1], mem[4'h2]);
238 sda_o <= #1 mem_do[7];
241 state <= #1 get_mem_adr;
246 get_mem_adr: // wait for memory address
250 mem_adr <= #1 sr; // store memory address
251 sda_o <= #1 !(sr <= 15); // generate i2c_ack, for valid address
254 #1 $display("DEBUG i2c_slave; address received. adr=%x, ack=%b", sr, sda_o);
263 data: // receive or drive data
266 sda_o <= #1 mem_do[7];
270 state <= #1 data_ack;
271 mem_adr <= #2 mem_adr + 8'h1;
272 sda_o <= #1 (rw && (mem_adr <= 15) ); // send ack on write, receive ack on read
276 #3 mem_do <= mem[mem_adr];
279 #5 $display("DEBUG i2c_slave; data block read %x from address %x (2)", mem_do, mem_adr);
284 mem[ mem_adr[3:0] ] <= #1 sr; // store data in memory
287 #2 $display("DEBUG i2c_slave; data block write %x to address %x", sr, mem_adr);
297 if(sr[0]) // read operation && master send NACK
305 sda_o <= #1 mem_do[7];
317 // read data from memory
318 always @(posedge scl)
320 mem_do <= #1 {mem_do[6:0], 1'b1}; // insert 1'b1 for host ack generation
322 // generate tri-states
323 assign sda = sda_o ? 1'bz : 1'b0;
334 specparam normal_scl_low = 4700,
335 normal_scl_high = 4000,
336 normal_tsu_sta = 4700,
337 normal_thd_sta = 4000,
338 normal_tsu_sto = 4000,
348 $width(negedge scl, normal_scl_low); // scl low time
349 $width(posedge scl, normal_scl_high); // scl high time
351 $setup(posedge scl, negedge sda &&& scl, normal_tsu_sta); // setup start
352 $setup(negedge sda &&& scl, negedge scl, normal_thd_sta); // hold start
353 $setup(posedge scl, posedge sda &&& scl, normal_tsu_sto); // setup stop
355 $setup(posedge tst_sta, posedge tst_sto, normal_tbuf); // stop to start time