Added license
[sifive-blocks.git] / src / main / scala / devices / i2c / I2C.scala
1 /////////////////////////////////////////////////////////////////////
2 //// ////
3 //// WISHBONE revB.2 compliant I2C Master controller Top-level ////
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 // This code was re-written in Chisel by SiFive, Inc.
39 // See LICENSE for license details.
40
41 package sifive.blocks.devices.i2c
42
43 import Chisel._
44 import config._
45 import util._
46 import regmapper._
47 import uncore.tilelink2._
48 import rocketchip.PeripheryBusConfig
49 import util.AsyncResetRegVec
50 import sifive.blocks.devices.gpio.{GPIOPinCtrl}
51
52 case class I2CConfig(address: BigInt)
53
54 trait HasI2CParameters {
55 implicit val p: Parameters
56 val params: I2CConfig
57 val c = params
58 }
59
60 class I2CPin extends Bundle {
61 val in = Bool(INPUT)
62 val out = Bool(OUTPUT)
63 val oe = Bool(OUTPUT)
64 }
65
66 class I2CPort extends Bundle {
67 val scl = new I2CPin
68 val sda = new I2CPin
69 }
70
71 trait I2CBundle extends Bundle with HasI2CParameters {
72 val port = new I2CPort
73 }
74
75 trait I2CModule extends Module with HasI2CParameters with HasRegMap {
76 val io: I2CBundle
77
78 val I2C_CMD_NOP = UInt(0x00)
79 val I2C_CMD_START = UInt(0x01)
80 val I2C_CMD_STOP = UInt(0x02)
81 val I2C_CMD_WRITE = UInt(0x04)
82 val I2C_CMD_READ = UInt(0x08)
83
84 class PrescalerBundle extends Bundle{
85 val hi = UInt(8.W)
86 val lo = UInt(8.W)
87 }
88
89 class ControlBundle extends Bundle{
90 val coreEn = Bool()
91 val intEn = Bool()
92 val reserved = UInt(6.W)
93 }
94
95 class CommandBundle extends Bundle{
96 val start = Bool()
97 val stop = Bool()
98 val read = Bool()
99 val write = Bool()
100 val ack = Bool()
101 val reserved = UInt(2.W)
102 val irqAck = Bool()
103 }
104
105 class StatusBundle extends Bundle{
106 val receivedAck = Bool() // received aknowledge from slave
107 val busy = Bool()
108 val arbLost = Bool()
109 val reserved = UInt(3.W)
110 val transferInProgress = Bool()
111 val irqFlag = Bool()
112 }
113
114 // control state visible to SW/driver
115 val prescaler = Reg(init = (new PrescalerBundle).fromBits(0xFFFF.U))
116 val control = Reg(init = (new ControlBundle).fromBits(0.U))
117 val transmitData = Reg(init = UInt(0, 8.W))
118 val receivedData = Reg(init = UInt(0, 8.W))
119 val cmd = Reg(init = (new CommandBundle).fromBits(0.U))
120 val status = Reg(init = (new StatusBundle).fromBits(0.U))
121
122
123 //////// Bit level ////////
124
125 io.port.scl.out := false.B // i2c clock line output
126 io.port.sda.out := false.B // i2c data line output
127
128 // filter SCL and SDA signals; (attempt to) remove glitches
129 val filterCnt = Reg(init = UInt(0, 14.W))
130 when ( !control.coreEn ) {
131 filterCnt := 0.U
132 } .elsewhen (!(filterCnt.orR)) {
133 filterCnt := Cat(prescaler.hi, prescaler.lo) >> 2 //16x I2C bus frequency
134 } .otherwise {
135 filterCnt := filterCnt - 1.U
136 }
137
138 val fSCL = Reg(init = UInt(0x7, 3.W))
139 val fSDA = Reg(init = UInt(0x7, 3.W))
140 when (!(filterCnt.orR)) {
141 fSCL := Cat(fSCL, io.port.scl.in)
142 fSDA := Cat(fSDA, io.port.sda.in)
143 }
144
145 val sSCL = Reg(init = true.B, next = (new Majority(fSCL.toBools.toSet)).out)
146 val sSDA = Reg(init = true.B, next = (new Majority(fSDA.toBools.toSet)).out)
147
148 val dSCL = Reg(init = true.B, next = sSCL)
149 val dSDA = Reg(init = true.B, next = sSDA)
150
151 val dSCLOen = Reg(next = io.port.scl.oe) // delayed scl_oen
152
153 // detect start condition => detect falling edge on SDA while SCL is high
154 // detect stop condition => detect rising edge on SDA while SCL is high
155 val startCond = Reg(init = false.B, next = !sSDA && dSDA && sSCL)
156 val stopCond = Reg(init = false.B, next = sSDA && !dSDA && sSCL)
157
158 // master drives SCL high, but another master pulls it low
159 // master start counting down its low cycle now (clock synchronization)
160 val sclSync = dSCL && !sSCL && io.port.scl.oe
161
162 // slave_wait is asserted when master wants to drive SCL high, but the slave pulls it low
163 // slave_wait remains asserted until the slave releases SCL
164 val slaveWait = Reg(init = false.B)
165 slaveWait := (io.port.scl.oe && !dSCLOen && !sSCL) || (slaveWait && !sSCL)
166
167 val clkEn = Reg(init = true.B) // clock generation signals
168 val cnt = Reg(init = UInt(0, 16.W)) // clock divider counter (synthesis)
169
170 // generate clk enable signal
171 when (!(cnt.orR) || !control.coreEn || sclSync ) {
172 cnt := Cat(prescaler.hi, prescaler.lo)
173 clkEn := true.B
174 }
175 .elsewhen (slaveWait) {
176 clkEn := false.B
177 }
178 .otherwise {
179 cnt := cnt - 1.U
180 clkEn := false.B
181 }
182
183 val sclOen = Reg(init = true.B)
184 io.port.scl.oe := sclOen
185
186 val sdaOen = Reg(init = true.B)
187 io.port.sda.oe := sdaOen
188
189 val sdaChk = Reg(init = false.B) // check SDA output (Multi-master arbitration)
190
191 val transmitBit = Reg(init = false.B)
192 val receivedBit = Reg(Bool())
193 when (sSCL && !dSCL) {
194 receivedBit := sSDA
195 }
196
197 val bitCmd = Reg(init = UInt(0, 4.W)) // command (from byte controller)
198 val bitCmdStop = Reg(init = false.B)
199 when (clkEn) {
200 bitCmdStop := bitCmd === I2C_CMD_STOP
201 }
202 val bitCmdAck = Reg(init = false.B)
203
204 val (s_bit_idle ::
205 s_bit_start_a :: s_bit_start_b :: s_bit_start_c :: s_bit_start_d :: s_bit_start_e ::
206 s_bit_stop_a :: s_bit_stop_b :: s_bit_stop_c :: s_bit_stop_d ::
207 s_bit_rd_a :: s_bit_rd_b :: s_bit_rd_c :: s_bit_rd_d ::
208 s_bit_wr_a :: s_bit_wr_b :: s_bit_wr_c :: s_bit_wr_d :: Nil) = Enum(UInt(), 18)
209 val bitState = Reg(init = s_bit_idle)
210
211 val arbLost = Reg(init = false.B, next = (sdaChk && !sSDA && sdaOen) | ((bitState === s_bit_idle) && stopCond && !bitCmdStop))
212
213 // bit FSM
214 when (arbLost) {
215 bitState := s_bit_idle
216 bitCmdAck := false.B
217 sclOen := true.B
218 sdaOen := true.B
219 sdaChk := false.B
220 }
221 .otherwise {
222 bitCmdAck := false.B
223
224 when (clkEn) {
225 switch (bitState) {
226 is (s_bit_idle) {
227 switch (bitCmd) {
228 is (I2C_CMD_START) { bitState := s_bit_start_a }
229 is (I2C_CMD_STOP) { bitState := s_bit_stop_a }
230 is (I2C_CMD_WRITE) { bitState := s_bit_wr_a }
231 is (I2C_CMD_READ) { bitState := s_bit_rd_a }
232 }
233 sdaChk := false.B
234 }
235
236 is (s_bit_start_a) {
237 bitState := s_bit_start_b
238 sclOen := sclOen
239 sdaOen := true.B
240 sdaChk := false.B
241 }
242 is (s_bit_start_b) {
243 bitState := s_bit_start_c
244 sclOen := true.B
245 sdaOen := true.B
246 sdaChk := false.B
247 }
248 is (s_bit_start_c) {
249 bitState := s_bit_start_d
250 sclOen := true.B
251 sdaOen := false.B
252 sdaChk := false.B
253 }
254 is (s_bit_start_d) {
255 bitState := s_bit_start_e
256 sclOen := true.B
257 sdaOen := false.B
258 sdaChk := false.B
259 }
260 is (s_bit_start_e) {
261 bitState := s_bit_idle
262 bitCmdAck := true.B
263 sclOen := false.B
264 sdaOen := false.B
265 sdaChk := false.B
266 }
267
268 is (s_bit_stop_a) {
269 bitState := s_bit_stop_b
270 sclOen := false.B
271 sdaOen := false.B
272 sdaChk := false.B
273 }
274 is (s_bit_stop_b) {
275 bitState := s_bit_stop_c
276 sclOen := true.B
277 sdaOen := false.B
278 sdaChk := false.B
279 }
280 is (s_bit_stop_c) {
281 bitState := s_bit_stop_d
282 sclOen := true.B
283 sdaOen := false.B
284 sdaChk := false.B
285 }
286 is (s_bit_stop_d) {
287 bitState := s_bit_idle
288 bitCmdAck := true.B
289 sclOen := true.B
290 sdaOen := true.B
291 sdaChk := false.B
292 }
293
294 is (s_bit_rd_a) {
295 bitState := s_bit_rd_b
296 sclOen := false.B
297 sdaOen := true.B
298 sdaChk := false.B
299 }
300 is (s_bit_rd_b) {
301 bitState := s_bit_rd_c
302 sclOen := true.B
303 sdaOen := true.B
304 sdaChk := false.B
305 }
306 is (s_bit_rd_c) {
307 bitState := s_bit_rd_d
308 sclOen := true.B
309 sdaOen := true.B
310 sdaChk := false.B
311 }
312 is (s_bit_rd_d) {
313 bitState := s_bit_idle
314 bitCmdAck := true.B
315 sclOen := false.B
316 sdaOen := true.B
317 sdaChk := false.B
318 }
319
320 is (s_bit_wr_a) {
321 bitState := s_bit_wr_b
322 sclOen := false.B
323 sdaOen := transmitBit
324 sdaChk := false.B
325 }
326 is (s_bit_wr_b) {
327 bitState := s_bit_wr_c
328 sclOen := true.B
329 sdaOen := transmitBit
330 sdaChk := false.B
331 }
332 is (s_bit_wr_c) {
333 bitState := s_bit_wr_d
334 sclOen := true.B
335 sdaOen := transmitBit
336 sdaChk := true.B
337 }
338 is (s_bit_wr_d) {
339 bitState := s_bit_idle
340 bitCmdAck := true.B
341 sclOen := false.B
342 sdaOen := transmitBit
343 sdaChk := false.B
344 }
345 }
346 }
347 }
348
349
350 //////// Byte level ///////
351 val load = Reg(init = false.B) // load shift register
352 val shift = Reg(init = false.B) // shift shift register
353 val cmdAck = Reg(init = false.B) // also done
354 val receivedAck = Reg(init = false.B) // from I2C slave
355 val go = (cmd.read | cmd.write | cmd.stop) & !cmdAck
356
357 val bitCnt = Reg(init = UInt(0, 3.W))
358 when (load) {
359 bitCnt := 0x7.U
360 }
361 .elsewhen (shift) {
362 bitCnt := bitCnt - 1.U
363 }
364 val bitCntDone = !(bitCnt.orR)
365
366 // receivedData is used as shift register directly
367 when (load) {
368 receivedData := transmitData
369 }
370 .elsewhen (shift) {
371 receivedData := Cat(receivedData, receivedBit)
372 }
373
374 val (s_byte_idle :: s_byte_start :: s_byte_read :: s_byte_write :: s_byte_ack :: s_byte_stop :: Nil) = Enum(UInt(), 6)
375 val byteState = Reg(init = s_byte_idle)
376
377 when (arbLost) {
378 bitCmd := I2C_CMD_NOP
379 transmitBit := false.B
380 shift := false.B
381 load := false.B
382 cmdAck := false.B
383 byteState := s_byte_idle
384 receivedAck := false.B
385 }
386 .otherwise {
387 transmitBit := receivedData(7)
388 shift := false.B
389 load := false.B
390 cmdAck := false.B
391
392 switch (byteState) {
393 is (s_byte_idle) {
394 when (go) {
395 when (cmd.start) {
396 byteState := s_byte_start
397 bitCmd := I2C_CMD_START
398 }
399 .elsewhen (cmd.read) {
400 byteState := s_byte_read
401 bitCmd := I2C_CMD_READ
402 }
403 .elsewhen (cmd.write) {
404 byteState := s_byte_write
405 bitCmd := I2C_CMD_WRITE
406 }
407 .otherwise { // stop
408 byteState := s_byte_stop
409 bitCmd := I2C_CMD_STOP
410 }
411
412 load := true.B
413 }
414 }
415 is (s_byte_start) {
416 when (bitCmdAck) {
417 when (cmd.read) {
418 byteState := s_byte_read
419 bitCmd := I2C_CMD_READ
420 }
421 .otherwise {
422 byteState := s_byte_write
423 bitCmd := I2C_CMD_WRITE
424 }
425
426 load := true.B
427 }
428 }
429 is (s_byte_write) {
430 when (bitCmdAck) {
431 when (bitCntDone) {
432 byteState := s_byte_ack
433 bitCmd := I2C_CMD_READ
434 }
435 .otherwise {
436 byteState := s_byte_write
437 bitCmd := I2C_CMD_WRITE
438 shift := true.B
439 }
440 }
441 }
442 is (s_byte_read) {
443 when (bitCmdAck) {
444 when (bitCntDone) {
445 byteState := s_byte_ack
446 bitCmd := I2C_CMD_WRITE
447 }
448 .otherwise {
449 byteState := s_byte_read
450 bitCmd := I2C_CMD_READ
451 }
452
453 shift := true.B
454 transmitBit := cmd.ack
455 }
456 }
457 is (s_byte_ack) {
458 when (bitCmdAck) {
459 when (cmd.stop) {
460 byteState := s_byte_stop
461 bitCmd := I2C_CMD_STOP
462 }
463 .otherwise {
464 byteState := s_byte_idle
465 bitCmd := I2C_CMD_NOP
466
467 // generate command acknowledge signal
468 cmdAck := true.B
469 }
470
471 // assign ack_out output to bit_controller_rxd (contains last received bit)
472 receivedAck := receivedBit
473
474 transmitBit := true.B
475 }
476 .otherwise {
477 transmitBit := cmd.ack
478 }
479 }
480 is (s_byte_stop) {
481 when (bitCmdAck) {
482 byteState := s_byte_idle
483 bitCmd := I2C_CMD_NOP
484
485 // assign ack_out output to bit_controller_rxd (contains last received bit)
486 cmdAck := true.B
487 }
488 }
489 }
490 }
491
492
493 //////// Top level ////////
494
495 // hack: b/c the same register offset is used to write cmd and read status
496 val nextCmd = Wire(UInt(8.W))
497 nextCmd := cmd.asUInt
498 cmd := (new CommandBundle).fromBits(nextCmd)
499
500 when (cmdAck || arbLost) {
501 cmd.start := false.B // clear command bits when done
502 cmd.stop := false.B // or when aribitration lost
503 cmd.read := false.B
504 cmd.write := false.B
505 }
506 cmd.irqAck := false.B // clear IRQ_ACK bit (essentially 1 cycle pulse b/c it is overwritten by regmap below)
507
508 status.receivedAck := receivedAck
509 when (stopCond) {
510 status.busy := false.B
511 }
512 .elsewhen (startCond) {
513 status.busy := true.B
514 }
515
516 when (arbLost) {
517 status.arbLost := true.B
518 }
519 .elsewhen (cmd.start) {
520 status.arbLost := false.B
521 }
522 status.transferInProgress := cmd.read || cmd.write
523 status.irqFlag := (cmdAck || arbLost || status.irqFlag) && !cmd.irqAck
524
525
526 regmap(
527 I2CCtrlRegs.prescaler_lo -> Seq(RegField(8, prescaler.lo)),
528 I2CCtrlRegs.prescaler_hi -> Seq(RegField(8, prescaler.hi)),
529 I2CCtrlRegs.control -> control.elements.map{ case(name, e) => RegField(e.getWidth, e.asInstanceOf[UInt]) }.toSeq,
530 I2CCtrlRegs.data -> Seq(RegField(8, r = RegReadFn(receivedData), w = RegWriteFn(transmitData))),
531 I2CCtrlRegs.cmd_status -> Seq(RegField(8, r = RegReadFn(status.asUInt), w = RegWriteFn(nextCmd)))
532 )
533
534 // tie off unused bits
535 control.reserved := 0.U
536 cmd.reserved := 0.U
537 status.reserved := 0.U
538
539 interrupts(0) := status.irqFlag & control.intEn
540 }
541
542 // Copied from UART.scala
543 class Majority(in: Set[Bool]) {
544 private val n = (in.size >> 1) + 1
545 private val clauses = in.subsets(n).map(_.reduce(_ && _))
546 val out = clauses.reduce(_ || _)
547 }
548
549
550 // Magic TL2 Incantation to create a TL2 Slave
551 class TLI2C(c: I2CConfig)(implicit p: Parameters)
552 extends TLRegisterRouter(c.address, interrupts = 1, beatBytes = p(PeripheryBusConfig).beatBytes)(
553 new TLRegBundle(c, _) with I2CBundle)(
554 new TLRegModule(c, _, _) with I2CModule)