Skip to content

Commit 7428dff

Browse files
committed
SPI: Represent inputs/outputs as records
1 parent a26bb9e commit 7428dff

File tree

3 files changed

+91
-65
lines changed

3 files changed

+91
-65
lines changed

clash-cores/src/Clash/Cores/SPI.hs

Lines changed: 71 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,12 @@
99
module Clash.Cores.SPI
1010
( SPIMode(..)
1111
-- * SPI master
12+
, SpiMasterIn(..)
13+
, SpiMasterOut(..)
1214
, spiMaster
1315
-- * SPI slave
16+
, SpiSlaveIn(..)
17+
, SpiSlaveOut(..)
1418
, SPISlaveConfig(..)
1519
, spiSlave
1620
-- ** Vendor configured SPI slaves
@@ -26,6 +30,53 @@ import Clash.Sized.Internal.BitVector
2630

2731
import Clash.Cores.LatticeSemi.ICE40.IO
2832
import Clash.Cores.LatticeSemi.ECP5.IO
33+
import Clash.Class.HasDomain
34+
35+
-- | Input signals of an SPI subordinate.
36+
data SpiSlaveIn (ds :: BiSignalDefault) (dom :: Domain) (misoLanes :: Nat) (mosiLanes :: Nat) =
37+
SpiSlaveIn {
38+
spiSlaveMosi :: "MOSI" ::: Signal dom (BitVector mosiLanes),
39+
-- ^ Master-out, slave-in
40+
spiSlaveMisoIn :: "MISO" ::: BiSignalIn ds dom misoLanes,
41+
-- ^ Master-in, slave-out
42+
spiSlaveSck :: "SCK" ::: Signal dom Bit,
43+
-- ^ Serial Clock
44+
spiSlaveSs :: "SS" ::: Signal dom Bit
45+
-- ^ Slave select
46+
}
47+
48+
type instance TryDomain t (SpiSlaveIn ds dom misoLanes mosiLanes) = 'Found dom
49+
50+
-- | Output signals of an SPI subordinate.
51+
data SpiSlaveOut (ds :: BiSignalDefault) (dom :: Domain) (misoLanes :: Nat) (mosiLanes :: Nat) =
52+
SpiSlaveOut {
53+
spiSlaveMisoOut :: "MISO" ::: BiSignalOut ds dom misoLanes
54+
-- ^ Master-in, slave-out
55+
}
56+
57+
type instance TryDomain t (SpiSlaveOut ds dom misoLanes mosiLanes) = 'Found dom
58+
59+
-- | Output signals of an SPI master.
60+
data SpiMasterOut (dom :: Domain) (misoLanes :: Nat) (mosiLanes :: Nat) =
61+
SpiMasterOut {
62+
spiMasterMosi :: "MOSI" ::: Signal dom (BitVector mosiLanes),
63+
-- ^ Master-out, slave-in
64+
spiMasterSck :: "SCK" ::: Signal dom Bit,
65+
-- ^ Serial Clock
66+
spiMasterSs :: "SS" ::: Signal dom Bit
67+
-- ^ Slave select
68+
}
69+
70+
type instance TryDomain t (SpiMasterOut dom misoLanes mosiLanes) = 'Found dom
71+
72+
-- | Input signals of an SPI master.
73+
data SpiMasterIn (dom :: Domain) (misoLanes :: Nat) (mosiLanes :: Nat) =
74+
SpiMasterIn {
75+
spiMasterMiso :: "MISO" ::: Signal dom (BitVector misoLanes)
76+
-- ^ Master-in, slave-out
77+
}
78+
79+
type instance TryDomain t (SpiMasterIn dom misoLanes mosiLanes) = 'Found dom
2980

3081
-- | SPI mode
3182
--
@@ -184,35 +235,29 @@ spiSlave
184235
. (HiddenClockResetEnable dom, KnownNat n, 1 <= n)
185236
=> SPISlaveConfig ds dom
186237
-- ^ Configure SPI mode and tri-state buffer
187-
-> Signal dom Bool
188-
-- ^ Serial Clock (SCLK)
189-
-> Signal dom Bit
190-
-- ^ Master Output Slave Input (MOSI)
191-
-> BiSignalIn ds dom 1
192-
-- ^ Master Input Slave Output (MISO)
193-
--
194-
-- Inout port connected to the tri-state buffer for the MISO
195-
-> Signal dom Bool
196-
-- ^ Slave select (SS)
238+
-> SpiSlaveIn ds dom 1 1
239+
-- ^ SPI interface
197240
-> Signal dom (BitVector n)
198-
-- ^ Data to send from master to slave
241+
-- ^ Data to send from slave to master.
199242
--
200243
-- Input is latched the moment slave select goes low
201-
-> ( BiSignalOut ds dom 1
244+
-> ( SpiSlaveOut ds dom 1 1
202245
, Signal dom Bool
203246
, Signal dom (Maybe (BitVector n)))
204247
-- ^ Parts of the tuple:
205248
--
206249
-- 1. The "out" part of the inout port of the MISO; used only for simulation.
207250
--
208-
-- 2. (Maybe) the word send by the master
209-
spiSlave (SPISlaveConfig mode latch buf) sclk mosi bin ss din =
251+
-- 2. the acknowledgement for the data sent from the master to the slave.
252+
--
253+
-- 2. (Maybe) the word sent by the master
254+
spiSlave (SPISlaveConfig mode latch buf) (SpiSlaveIn mosi bin sclk ss) din =
210255
let ssL = if latch then delay undefined ss else ss
211256
mosiL = if latch then delay undefined mosi else mosi
212257
sclkL = if latch then delay undefined sclk else sclk
213-
(miso, ack, dout) = spiCommon mode ssL mosiL sclkL din
214-
bout = buf bin (not <$> ssL) miso
215-
in (bout, ack, dout)
258+
(miso, ack, dout) = spiCommon mode (bitToBool <$> ssL) (head . bv2v <$> mosiL) (bitToBool <$> sclkL) din
259+
bout = buf bin (not . bitToBool <$> ssL) miso
260+
in (SpiSlaveOut bout, ack, dout)
216261

217262
-- | SPI master configurable in the SPI mode and clock divider
218263
--
@@ -237,11 +282,8 @@ spiMaster
237282
-> Signal dom (Maybe (BitVector n))
238283
-- ^ Data to send from master to slave, transmission starts when receiving
239284
-- /Just/ a value
240-
-> Signal dom Bit
241-
-- ^ Master Input Slave Output (MISO)
242-
-> ( Signal dom Bool -- SCK
243-
, Signal dom Bit -- MOSI
244-
, Signal dom Bool -- SS
285+
-> SpiMasterIn dom 1 1
286+
-> ( SpiMasterOut dom 1 1
245287
, Signal dom Bool -- Busy
246288
, Signal dom Bool -- Acknowledge
247289
, Signal dom (Maybe (BitVector n)) -- Data: Slave -> Master
@@ -254,15 +296,15 @@ spiMaster
254296
-- 4. Busy signal indicating that a transmission is in progress, new words on
255297
-- the data line will be ignored when /True/
256298
-- 5. (Maybe) the word send from the slave to the master
257-
spiMaster mode fN fW din miso =
258-
let (mosi, ack, dout) = spiCommon mode ssL misoL sclkL
299+
spiMaster mode fN fW din (SpiMasterIn miso) =
300+
let (mosi, ack, dout) = spiCommon mode ssL (head . bv2v <$> misoL) sclkL
259301
(fromMaybe undefined# <$> din)
260302
latch = snatToInteger fN /= 1
261303
ssL = if latch then delay undefined ss else ss
262304
misoL = if latch then delay undefined miso else miso
263305
sclkL = if latch then delay undefined sclk else sclk
264306
(ss, sclk, busy) = spiGen mode fN fW din
265-
in (sclk, mosi, ss, busy, ack, dout)
307+
in (SpiMasterOut (v2bv . singleton <$> mosi) (boolToBit <$> sclk) (boolToBit <$> ss), busy, ack, dout)
266308

267309
-- | Generate slave select and SCK
268310
spiGen
@@ -339,21 +381,12 @@ spiSlaveLatticeSBIO
339381
-- Clock: 2*SCK < Core
340382
--
341383
-- * Set to /False/ when core clock is twice as fast, or as fast, as the SCK
342-
-> Signal dom Bool
343-
-- ^ Serial Clock (SCLK)
344-
-> Signal dom Bit
345-
-- ^ Master Output Slave Input (MOSI)
346-
-> BiSignalIn 'Floating dom 1
347-
-- ^ Master Input Slave Output (MISO)
348-
--
349-
-- Inout port connected to the tri-state buffer for the MISO
350-
-> Signal dom Bool
351-
-- ^ Slave select (SS)
384+
-> SpiSlaveIn 'Floating dom 1 1
352385
-> Signal dom (BitVector n)
353386
-- ^ Data to send from slave to master
354387
--
355388
-- Input is latched the moment slave select goes low
356-
-> ( BiSignalOut 'Floating dom 1
389+
-> ( SpiSlaveOut 'Floating dom 1 1
357390
, Signal dom Bool
358391
, Signal dom (Maybe (BitVector n)))
359392
-- ^ Parts of the tuple:
@@ -385,21 +418,12 @@ spiSlaveLatticeBB
385418
-- Clock: 2*SCK < Core
386419
--
387420
-- * Set to /False/ when core clock is twice as fast, or as fast, as the SCK
388-
-> Signal dom Bool
389-
-- ^ Serial Clock (SCLK)
390-
-> Signal dom Bit
391-
-- ^ Master Output Slave Input (MOSI)
392-
-> BiSignalIn 'Floating dom 1
393-
-- ^ Master Input Slave Output (MISO)
394-
--
395-
-- Inout port connected to the tri-state buffer for the MISO
396-
-> Signal dom Bool
397-
-- ^ Slave select (SS)
421+
-> SpiSlaveIn 'Floating dom 1 1
398422
-> Signal dom (BitVector n)
399423
-- ^ Data to send from slave to master
400424
--
401425
-- Input is latched the moment slave select goes low
402-
-> ( BiSignalOut 'Floating dom 1
426+
-> ( SpiSlaveOut 'Floating dom 1 1
403427
, Signal dom Bool
404428
, Signal dom (Maybe (BitVector n)))
405429
-- ^ Parts of the tuple:

clash-cores/test/Test/Cores/Internal/SampleSPI.hs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -72,16 +72,16 @@ sampleCycling genM genS divHalf wait mVals sVals mode latch duration =
7272
samples = sampleN (getDuration duration) $ bundle (mOut, mAck, sOut, sAck)
7373
slaveIn = genS clk rst sVals sAck
7474

75-
(misoZ, sAck, sOut) =
75+
(SpiSlaveOut misoZ, sAck, sOut) =
7676
withClockResetEnable clk rst enableGen
77-
(spiSlaveLatticeSBIO mode latch sclk mosi miso ss slaveIn)
77+
(spiSlaveLatticeSBIO mode latch (SpiSlaveIn mosi miso sclk ss) slaveIn)
7878

7979
miso = veryUnsafeToBiSignalIn misoZ
8080
masterIn = genM clk rst mVals mAck bp
8181

82-
(sclk, mosi, ss, bp, mAck, mOut) =
82+
(SpiMasterOut mosi sclk ss, bp, mAck, mOut) =
8383
withClockResetEnable clk rst enableGen
84-
(spiMaster mode divHalf wait masterIn (readFromBiSignal miso))
84+
(spiMaster mode divHalf wait masterIn (SpiMasterIn $ readFromBiSignal miso))
8585

8686
clk = systemClockGen
8787
rst = systemResetGen

clash-cores/test/Test/Cores/SPI/MultiSlave.hs

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -23,18 +23,20 @@ slaveAddressRotate
2323
. (KnownDomain dom, KnownNat n, 1 <= n)
2424
=> Clock dom
2525
-> Reset dom
26-
-> (Signal dom Bool, Signal dom Bool)
27-
-> Vec n (Signal dom Bool)
28-
slaveAddressRotate clk rst =
29-
E.mealyB clk rst enableGen
30-
(\(cntQ, bQ) (ss, b) ->
26+
-> (Signal dom Bit, Signal dom Bool)
27+
-> Vec n (Signal dom Bit)
28+
slaveAddressRotate clk rst (ss,bp) =
29+
map (fmap boolToBit)
30+
$ E.mealyB clk rst enableGen
31+
(\(cntQ, bQ) (ss', b) ->
3132
let bF = bQ && not b
3233
cntD | bF = if cntQ == maxBound then 0 else cntQ + 1
3334
| otherwise = cntQ
3435

35-
oH = (ss ||) <$> (unpack . complement $ bin2onehot cntQ)
36+
oH = (ss' ||) <$> (unpack . complement $ bin2onehot cntQ)
3637
in ((cntD, b), oH))
3738
(0 :: Index n, False)
39+
(bitToBool <$> ss, bp)
3840
where
3941
bin2onehot = setBit 0 . fromEnum
4042

@@ -60,17 +62,17 @@ testMasterMultiSlave divHalf wait mVal sVal mode latch duration =
6062
,(L.nub masterOutS,P.length masterOutS))
6163
where
6264
slaveIn = pure sVal
63-
(misoZ0, _, slaveOut0) =
65+
(SpiSlaveOut misoZ0, _, slaveOut0) =
6466
withClockResetEnable clk rst enableGen
65-
(spiSlaveLatticeSBIO mode latch sclk mosi miso ss0 slaveIn)
67+
(spiSlaveLatticeSBIO mode latch (SpiSlaveIn mosi miso sclk ss0) slaveIn)
6668

67-
(misoZ1, _, slaveOut1) =
69+
(SpiSlaveOut misoZ1, _, slaveOut1) =
6870
withClockResetEnable clk rst enableGen
69-
(spiSlaveLatticeSBIO mode latch sclk mosi miso ss1 slaveIn)
71+
(spiSlaveLatticeSBIO mode latch (SpiSlaveIn mosi miso sclk ss1) slaveIn)
7072

71-
(misoZ2, _, slaveOut2) =
73+
(SpiSlaveOut misoZ2, _, slaveOut2) =
7274
withClockResetEnable clk rst enableGen
73-
(spiSlaveLatticeSBIO mode latch sclk mosi miso ss2 slaveIn)
75+
(spiSlaveLatticeSBIO mode latch (SpiSlaveIn mosi miso sclk ss2) slaveIn)
7476

7577
miso = veryUnsafeToBiSignalIn
7678
(mergeBiSignalOuts (misoZ2 :> misoZ1 :> misoZ0 :> Nil))
@@ -79,9 +81,9 @@ testMasterMultiSlave divHalf wait mVal sVal mode latch duration =
7981

8082
(ss2 `Cons` ss1 `Cons` ss0 `Cons` _) = slaveAddressRotate @3 clk rst (ss,bp)
8183

82-
(sclk, mosi, ss, bp, masterAck, masterOut) =
84+
(SpiMasterOut mosi sclk ss, bp, masterAck, masterOut) =
8385
withClockResetEnable clk rst enableGen
84-
(spiMaster mode divHalf wait masterIn (readFromBiSignal miso))
86+
(spiMaster mode divHalf wait masterIn (SpiMasterIn $ readFromBiSignal miso))
8587

8688
clk = systemClockGen
8789
rst = systemResetGen

0 commit comments

Comments
 (0)