1
1
{-# LANGUAGE CPP #-}
2
2
{-# LANGUAGE RecordWildCards #-}
3
- module Clash.Cores.I2C.ByteMaster (byteMaster ) where
3
+ module Clash.Cores.I2C.ByteMaster (byteMaster , I2COperation ( .. ) ) where
4
4
5
5
import Clash.Prelude hiding (read )
6
6
@@ -11,10 +11,16 @@ import Data.Tuple
11
11
12
12
import Clash.Cores.I2C.ByteMaster.ShiftRegister
13
13
import Clash.Cores.I2C.Types
14
+ import Data.Maybe (fromJust )
14
15
15
- data ByteStateMachine = Idle | Start | Read | Write | Ack | Stop
16
+ data ByteStateMachine = Idle | Active | Start | Read | Write | Ack | Stop
16
17
deriving (Show , Generic , NFDataX )
17
18
19
+ data I2COperation = ReadData | WriteData (BitVector 8 )
20
+ deriving (Generic , NFDataX )
21
+ getWriteData :: I2COperation -> BitVector 8
22
+ getWriteData ReadData = deepErrorX " Write data undefined for ReadData in I2COperation"
23
+ getWriteData (WriteData d) = d
18
24
data ByteMasterS
19
25
= ByteS
20
26
{ _srState :: ShiftRegister
@@ -23,23 +29,20 @@ data ByteMasterS
23
29
, _coreTxd :: Bit -- coreTxd register
24
30
, _shiftsr :: Bool -- shift sr
25
31
, _ld :: Bool -- load values in to sr
26
- , _hostAck :: Bool -- host cmd acknowlegde register
27
- , _ackOut :: Bool -- slave ack register
32
+ , _i2cOpAck :: Bool -- host cmd acknowlegde register
33
+ , _slaveAck :: Bool -- slave ack register
28
34
}
29
35
deriving (Generic , NFDataX )
30
36
31
37
makeLenses ''ByteMasterS
32
38
33
39
-- |
34
40
-- 1. Statemachine reset
35
- -- 2. Start
36
- -- 3. Stop
37
- -- 4. Read
38
- -- 5. Write
39
- -- 6. Acknowledge
40
- -- 7. Data in
41
- -- 8. Bitmaster response
42
- type ByteMasterI = (Bool ,Bool ,Bool ,Bool ,Bool ,Bool ,BitVector 8 ,BitRespSig )
41
+ -- 2. Claim bus
42
+ -- 3. Bus operation
43
+ -- 4. Acknowledge
44
+ -- 5. Bitmaster response
45
+ type ByteMasterI = (Bool ,Bool ,Maybe I2COperation , Bool ,BitRespSig )
43
46
44
47
-- |
45
48
-- 1. Acknowledge for I2C controller
@@ -73,90 +76,94 @@ byteMasterInit
73
76
, _coreTxd = low
74
77
, _shiftsr = False
75
78
, _ld = False
76
- , _hostAck = False
77
- , _ackOut = True
79
+ , _i2cOpAck = False
80
+ , _slaveAck = True
78
81
}
79
82
80
83
byteMasterT :: ByteMasterS -> ByteMasterI -> (ByteMasterS , ByteMasterO )
81
84
byteMasterT s@ (ByteS {_srState = ShiftRegister {.. }, .. })
82
- (rst,start,stop,read ,write,ackIn,din,~ (coreAck,al,coreRxd)) = swap $ flip runState s $ do
83
- -- generate go-signal
84
- let go = (read || write || stop) && (not _hostAck)
85
+ (rst,claimBus,maybeI2COp,ackIn,~ (coreAck,al,coreRxd)) = swap $ flip runState s $ do
85
86
86
87
-- assign dOut the output of the shift-register
87
- dout = _sr
88
+ let dout = _sr
88
89
89
- cntDone <- zoom srState (shiftRegister rst _ld _shiftsr (bv2v din ) coreRxd)
90
+ cntDone <- zoom srState (shiftRegister rst _ld _shiftsr (bv2v (getWriteData $ fromJust maybeI2COp ) ) coreRxd)
90
91
91
92
-- state machine
92
93
coreTxd .= head dout
93
94
shiftsr .= False
94
95
ld .= False
95
- hostAck .= False
96
+ i2cOpAck .= False
96
97
97
98
if rst || al then do
98
99
coreCmd .= I2Cnop
99
100
coreTxd .= low
100
101
byteStateM .= Idle
101
- ackOut .= True
102
- else case _byteStateM of
103
- Idle -> when go $ do
102
+ slaveAck .= True
103
+ else case ( _byteStateM, maybeI2COp) of
104
+ ( Idle , _) -> when claimBus $ do
104
105
ld .= True
105
- if start then do
106
- byteStateM .= Start
107
- coreCmd .= I2Cstart
108
- else if read then do
109
- byteStateM .= Read
110
- coreCmd .= I2Cread
111
- else if write then do
112
- byteStateM .= Write
113
- coreCmd .= I2Cwrite
114
- else do -- stop
115
- byteStateM .= Stop
116
- coreCmd .= I2Cstop
117
- Start -> when coreAck $ do
106
+ byteStateM .= Start
107
+ coreCmd .= I2Cstart
108
+ (Active , Just ReadData ) -> do
109
+ byteStateM .= Read
110
+ coreCmd .= I2Cread
111
+ (Active , Just (WriteData _)) -> do
118
112
ld .= True
119
- if read then do
120
- byteStateM .= Read
121
- coreCmd .= I2Cread
122
- else do
123
- byteStateM .= Write
124
- coreCmd .= I2Cwrite
125
- Write -> when coreAck $ do
113
+ byteStateM .= Write
114
+ coreCmd .= I2Cwrite
115
+ (Active ,Nothing ) -> do
116
+ byteStateM .= Active
117
+ coreCmd .= I2Cnop
118
+ (Start , Nothing ) -> when coreAck $ do
119
+ byteStateM .= Active
120
+ coreCmd .= I2Cnop
121
+ (Start , Just ReadData ) -> when coreAck $ do
122
+ byteStateM .= Read
123
+ coreCmd .= I2Cread
124
+ (Start , Just (WriteData _)) -> when coreAck $ do
125
+ ld .= True
126
+ byteStateM .= Write
127
+ coreCmd .= I2Cwrite
128
+ (Write , _) -> when coreAck $ do
126
129
if cntDone then do
127
130
byteStateM .= Ack
128
131
coreCmd .= I2Cread
129
132
else do
130
133
coreCmd .= I2Cwrite
131
134
shiftsr .= True
132
- Read -> when coreAck $ do
135
+
136
+ (Read , _) -> when coreAck $ do
133
137
shiftsr .= True
134
138
coreTxd .= bitCoerce ackIn
135
139
if cntDone then do
136
140
byteStateM .= Ack
137
141
coreCmd .= I2Cwrite
138
142
else do
139
143
coreCmd .= I2Cread
140
- Ack -> if coreAck then do
141
- ackOut .= bitCoerce coreRxd
144
+
145
+ (Ack , _) ->
146
+ if coreAck then do
147
+ slaveAck .= bitCoerce coreRxd
142
148
coreTxd .= high
143
149
-- check for stop; Should a STOP command be generated?
144
- if stop then do
145
- byteStateM .= Stop
146
- coreCmd .= I2Cstop
147
- else do
148
- byteStateM .= Idle
150
+ if claimBus then do
151
+ byteStateM .= Active
149
152
coreCmd .= I2Cnop
150
153
-- generate command acknowledge signal
151
- hostAck .= True
154
+ i2cOpAck .= True
155
+ else do
156
+ byteStateM .= Stop
157
+ coreCmd .= I2Cstop
152
158
else
153
159
coreTxd .= bitCoerce ackIn
154
- Stop -> when coreAck $ do
160
+
161
+ (Stop , _) -> when coreAck $ do
155
162
byteStateM .= Idle
156
163
coreCmd .= I2Cnop
157
- hostAck .= True
164
+ i2cOpAck .= True
158
165
159
166
let bitCtrl = (_coreCmd,_coreTxd)
160
- outp = (_hostAck,_ackOut ,v2bv dout,bitCtrl)
167
+ outp = (_i2cOpAck,_slaveAck ,v2bv dout,bitCtrl)
161
168
162
169
return outp
0 commit comments