Bug fix: arbLost should be asserted when bitState =/= s_bit_idle (#49)
[sifive-blocks.git] / src / main / scala / devices / i2c / I2C.scala
index d767a265f05c5add29c63ef0e53e70bc96ba08c7..b3e2db5f7cb0d88556bcf027ed7f1aee5034b0ee 100644 (file)
@@ -202,7 +202,7 @@ trait HasI2CModuleContents extends MultiIOModule with HasRegMap {
        s_bit_wr_a    :: s_bit_wr_b    :: s_bit_wr_c    :: s_bit_wr_d    :: Nil) = Enum(UInt(), 18)
   val bitState    = Reg(init = s_bit_idle)
 
-  val arbLost     = Reg(init = false.B, next = (sdaChk && !sSDA && sdaOen) | ((bitState === s_bit_idle) && stopCond && !bitCmdStop))
+  val arbLost     = Reg(init = false.B, next = (sdaChk && !sSDA && sdaOen) | ((bitState =/= s_bit_idle) && stopCond && !bitCmdStop))
 
   // bit FSM
   when (arbLost) {
@@ -514,11 +514,14 @@ trait HasI2CModuleContents extends MultiIOModule with HasRegMap {
     status.arbLost          := false.B
   }
   status.transferInProgress := cmd.read || cmd.write
-  status.irqFlag            := (cmdAck || arbLost || status.irqFlag) && !cmd.irqAck
+  status.irqFlag            := (cmdAck || arbLost || status.irqFlag) && !cmd.irqAck // interrupt request flag is always generated
 
 
   val statusReadReady = Reg(init = true.B)
-  when (!statusReadReady) {
+  when (cmdAck || arbLost) {    // => cmd.read or cmd.write deassert 1 cycle later => transferInProgress deassert 2 cycles later
+    statusReadReady := false.B  // do not allow status read if status.transferInProgress is going to change
+  }
+  .elsewhen (!statusReadReady) {
     statusReadReady := true.B
   }