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