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