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