aboutsummaryrefslogtreecommitdiff
path: root/fpga/src
diff options
context:
space:
mode:
Diffstat (limited to 'fpga/src')
-rw-r--r--fpga/src/I2C.bs85
-rw-r--r--fpga/src/TopSim.bs16
2 files changed, 89 insertions, 12 deletions
diff --git a/fpga/src/I2C.bs b/fpga/src/I2C.bs
index 2752acd..2a0614f 100644
--- a/fpga/src/I2C.bs
+++ b/fpga/src/I2C.bs
@@ -79,6 +79,22 @@ data I2CBusState
| -- | We're reading SDA, which should be the ACK bit after sending an
-- address.
GetAddrAckReadSDA
+ | -- | TODO
+ WriteLowerSCL (Bit 1) (Bit 3)
+ | -- | TODO
+ WriteWriteSDA (Bit 3)
+ | -- | TODO
+ WriteRaiseSCL (Bit 1) (Bit 3) (Bit 1)
+ | -- | TODO
+ WriteAckLowerSCL (Bit 1)
+ | -- | TODO
+ WriteAckRaiseSDA
+ | -- | TODO
+ WriteAckRaiseSCL
+ | -- | TODO
+ WriteAckReadSDA
+ | -- | TODO
+ TODO
| -- | We're about to either lower SCL or keep it low as part of reading a
-- byte from a device.
ReadLowerSCL (Bit 3) (Bit 1)
@@ -98,7 +114,13 @@ data I2CBusState
-- hold, the second is the number of cycles to hold it for.
ReadAckRaiseSCL (Bit 1) (Bit 1)
| -- | TODO
- TODO
+ StopLowerSCL
+ | -- | TODO
+ StopLowerSDA
+ | -- | TODO
+ StopRaiseSCL
+ | -- | TODO
+ StopRaiseSDA
deriving (Bits, FShow)
-- | Runs an I²C interface on the current clock.
@@ -164,8 +186,44 @@ mkI2C' rxSCL rxSDA txSCL txSDA addrReg dataReg statusReg = module
state := if rxSDA == 1 -- NACK
then TODO
else if savedAddr[0:0] == 0 -- R/!W
- then TODO -- !W
- else ReadLowerSCL 7 1
+ then WriteLowerSCL 1 7 -- !W
+ else ReadLowerSCL 7 1 -- R
+ txSCL := 1
+ txSDA := 1
+ "WriteLowerSCL": when WriteLowerSCL bit n <- state ==> do
+ state := WriteWriteSDA n
+ txSCL := 0
+ txSDA := bit
+ "WriteWriteSDA": when WriteWriteSDA n <- state ==> do
+ let bit = savedData[n:n]
+ state := WriteRaiseSCL bit n 1
+ txSCL := 0
+ txSDA := bit
+ "WriteRaiseSCL": when WriteRaiseSCL bit n time <- state ==> do
+ state := if time == 1
+ then WriteRaiseSCL bit n (time - 1)
+ else if n == 0
+ then WriteAckLowerSCL bit
+ else WriteLowerSCL bit (n - 1)
+ txSCL := 1
+ txSDA := bit
+ "WriteAckLowerSCL": when WriteAckLowerSCL bit <- state ==> do
+ state := WriteAckRaiseSDA
+ txSCL := 0
+ txSDA := bit
+ "WriteAckRaiseSDA": when WriteAckRaiseSDA <- state ==> do
+ state := WriteAckRaiseSCL
+ txSCL := 0
+ txSDA := 1
+ "WriteAckRaiseSCL": when WriteAckRaiseSCL <- state ==> do
+ state := WriteAckReadSDA
+ txSCL := 1
+ txSDA := 1
+ "WriteAckReadSDA": when WriteAckReadSDA <- state ==> do
+ statusReg := statusReg { ready = True; dataAckBit = unpack rxSDA }
+ state := if rxSDA == 1 -- NACK
+ then StopLowerSCL
+ else TODO
txSCL := 1
txSDA := 1
"ReadLowerSCL": when ReadLowerSCL n time <- state ==> do
@@ -201,9 +259,26 @@ mkI2C' rxSCL rxSDA txSCL txSDA addrReg dataReg statusReg = module
then ReadAckRaiseSCL bit (time - 1)
else if bit == 0
then ReadLowerSCL 7 1 -- ACK
- else TODO -- NACK
+ else StopLowerSCL -- NACK
txSCL := 1
txSDA := bit
+ "StopLowerSCL": when StopLowerSCL <- state ==> do
+ state := StopLowerSDA
+ txSCL := 0
+ txSDA := 1
+ "StopLowerSDA": when StopLowerSDA <- state ==> do
+ state := StopRaiseSCL
+ txSCL := 0
+ txSDA := 0
+ "StopRaiseSCL": when StopRaiseSCL <- state ==> do
+ state := StopRaiseSDA
+ txSCL := 1
+ txSDA := 0
+ "StopRaiseSDA": when StopRaiseSDA <- state ==> do
+ state := Idle
+ statusReg := statusReg { busIdle = True }
+ txSCL := 1
+ txSDA := 1
return ()
-- | Returns an I²C interface that runs on the current clock. This is not what
@@ -216,7 +291,7 @@ mkI2C rxSCL rxSDA = module
dataReg <- mkReg 0
statusReg <- mkReg (I2CStatus
{ ready = True
- ; busIdle = False
+ ; busIdle = True
; addrAckBit = False
; dataAckBit = False
; arbitrationLost = False
diff --git a/fpga/src/TopSim.bs b/fpga/src/TopSim.bs
index c512edc..e4e65c9 100644
--- a/fpga/src/TopSim.bs
+++ b/fpga/src/TopSim.bs
@@ -32,17 +32,19 @@ mkTopSim = module
timer :: Reg (Bit 16) <- mkReg 0
rules
"t0000": when (timer == 0x0000) ==> do
- i2c.addrReg := 0x20 ++ (1 :: Bit 1)
- i2c.dataReg := 0x00
+ i2c.addrReg := 0x20 ++ (0 :: Bit 1)
+ i2c.dataReg := 0x12
"t0001": when (timer == 0x0001) ==> do
i2c.statusReg := i2c.statusReg { ready = False; dataAckBit = True }
+ "t0002": when (timer == 0x0002) ==> do
+ i2c.addrReg := 0x20 ++ (0 :: Bit 1)
+ i2c.dataReg := 0xaa
"t0022": when (timer == 0x0023) ==> rxSDA := 0
"t0025": when (timer == 0x0027) ==> rxSDA := 1
- "t0049": when (timer == 0x0049) ==> do
- i2c.addrReg := 0x20 ++ (0 :: Bit 1)
- i2c.dataReg := 0x00
- "t004a": when (timer == 0x004a) ==> do
- i2c.statusReg := i2c.statusReg { ready = False }
+ -- "t0047": when (timer == 0x0047) ==> rxSDA := 0
+ -- "t0051": when (timer == 0x004b) ==> rxSDA := 1
+ -- "t004b": when (timer == 0x004b) ==> do
+ -- i2c.statusReg := i2c.statusReg { ready = False }
"advance timer": when True ==> timer := timer + 1
"finish": when (timer == 0x00ff) ==> $finish
{-