[1766] | 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 | |
---|
| 143 | module 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 | |
---|
| 576 | endmodule |
---|