Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add clock board i2c interface #443

Draft
wants to merge 15 commits into
base: staging
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .github/synthesis/debug.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[
{"top": "fmcClockTests", "stage": "test", "targets": "Specific [-1]"}
]
2 changes: 2 additions & 0 deletions bittide-instances/bittide-instances.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ library
-- Hardware-in-the-loop tests
Bittide.Instances.Hitl.BoardTest
Bittide.Instances.Hitl.FincFdec
Bittide.Instances.Hitl.FmcClock
Bittide.Instances.Hitl.FullMeshHwCc
Bittide.Instances.Hitl.FullMeshSwCc
Bittide.Instances.Hitl.HwCcTopologies
Expand All @@ -131,6 +132,7 @@ library
Bittide.Instances.Pnr.ClockControl
Bittide.Instances.Pnr.Counter
Bittide.Instances.Pnr.ElasticBuffer
Bittide.Instances.Pnr.I2C
Bittide.Instances.Pnr.ProcessingElement
Bittide.Instances.Pnr.ScatterGather
Bittide.Instances.Pnr.Si539xSpi
Expand Down
48 changes: 48 additions & 0 deletions bittide-instances/data/constraints/fmcClockTests.xdc
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# SPDX-FileCopyrightText: 2024 Google LLC
#
# SPDX-License-Identifier: Apache-2.0


set_property BOARD_PART_PIN sysclk_125_p [get_ports {SYSCLK_125_p}]
set_property BOARD_PART_PIN sysclk_125_n [get_ports {SYSCLK_125_n}]

# FMC_HPC_GBTCLK1_M2C
set_property PACKAGE_PIN H6 [get_ports {FMC_HPC_GBTCLK1_M2C_p}]
set_property PACKAGE_PIN H5 [get_ports {FMC_HPC_GBTCLK1_M2C_n}]

set_clock_groups \
-asynchronous \
-group [get_clocks -include_generated_clocks {SYSCLK_125_p}] \
-group [get_clocks -include_generated_clocks {FMC_HPC_GBTCLK1_M2C_p}]

#FMC_HPC_LA01_CC_N
set_property PACKAGE_PIN F9 [get_ports muxSelect[0]]
set_property IOSTANDARD LVCMOS18 [get_ports muxSelect[0]]
#FMC_HPC_LA02_P
set_property PACKAGE_PIN K10 [get_ports muxSelect[1]]
set_property IOSTANDARD LVCMOS18 [get_ports muxSelect[1]]
#FMC_HPC_LA02_N
set_property PACKAGE_PIN J10 [get_ports muxSelect[2]]
set_property IOSTANDARD LVCMOS18 [get_ports muxSelect[2]]
#FMC_HPC_LA00_P
set_property PACKAGE_PIN H11 [get_ports "sclBs"]
set_property IOSTANDARD LVCMOS18 [get_ports "sclBs"]
# FMC_HPC_LA00_N
set_property PACKAGE_PIN G11 [get_ports "sdaOut"]
set_property IOSTANDARD LVCMOS18 [get_ports "sdaOut"]
# FMC_HPC_LA01_P
set_property PACKAGE_PIN G9 [get_ports "sdaIn"]
set_property IOSTANDARD LVCMOS18 [get_ports "sdaIn"]

# GPIO_LED_0_LS
set_property PACKAGE_PIN AP8 [get_ports "done"]
set_property IOSTANDARD LVCMOS18 [get_ports "done"]
# GPIO_LED_1_LS
set_property PACKAGE_PIN H23 [get_ports "success"]
set_property IOSTANDARD LVCMOS18 [get_ports "success"]

set_property PACKAGE_PIN K26 [get_ports "USB_UART_RX"]
set_property IOSTANDARD LVCMOS18 [get_ports "USB_UART_RX"]

set_property PACKAGE_PIN G25 [get_ports "USB_UART_TX"]
set_property IOSTANDARD LVCMOS18 [get_ports "USB_UART_TX"]
32 changes: 32 additions & 0 deletions bittide-instances/data/constraints/i2cTest.xdc
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# SPDX-FileCopyrightText: 2022-2023 Google LLC
#
# SPDX-License-Identifier: Apache-2.0


# CLK_125MHZ
set_property BOARD_PART_PIN sysclk_125_p [get_ports sys_125_p]
set_property BOARD_PART_PIN sysclk_125_n [get_ports sys_125_n]

#FMC_HPC_LA01_CC_N
set_property PACKAGE_PIN F9 [get_ports mux_select[0]]
set_property IOSTANDARD LVCMOS18 [get_ports mux_select[0]]

#FMC_HPC_LA02_P
set_property PACKAGE_PIN K10 [get_ports mux_select[1]]
set_property IOSTANDARD LVCMOS18 [get_ports mux_select[1]]

#FMC_HPC_LA02_N
set_property PACKAGE_PIN J10 [get_ports mux_select[2]]
set_property IOSTANDARD LVCMOS18 [get_ports mux_select[2]]

#FMC_HPC_LA00_CC_P
set_property PACKAGE_PIN H11 [get_ports "sclOut"]
set_property IOSTANDARD LVCMOS18 [get_ports "sclOut"]

# FMC_HPC_LA00_CC_N
set_property PACKAGE_PIN G11 [get_ports "sdaOut"]
set_property IOSTANDARD LVCMOS18 [get_ports "sdaOut"]

# FMC_HPC_LA01_CC_P
set_property PACKAGE_PIN G9 [get_ports "sdaIn"]
set_property IOSTANDARD LVCMOS18 [get_ports "sdaIn"]
1 change: 1 addition & 0 deletions bittide-instances/src/Bittide/Instances/Domains.hs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import Bittide.Arithmetic.Ppm
import Data.Proxy

createDomain vXilinxSystem{vName="Basic100", vPeriod= hzToPeriod 100e6}
createDomain vXilinxSystem{vName="Basic124", vPeriod=hzToPeriod 124e6}
createDomain vXilinxSystem{vName="Basic125", vPeriod= hzToPeriod 125e6}
createDomain vXilinxSystem{vName="Ext125", vPeriod= hzToPeriod 125e6, vResetKind=Asynchronous}
createDomain vXilinxSystem{vName="Basic25", vPeriod= hzToPeriod 25e6}
Expand Down
3 changes: 2 additions & 1 deletion bittide-instances/src/Bittide/Instances/Hitl/FincFdec.hs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import Data.Maybe (isJust)
import qualified Bittide.ClockControl.Si5395J as Si5395J

data TestState = Busy | Fail | Success
deriving (Generic, NFDataX, BitPack)
data Test
-- | Keep pressing FDEC, see if counter falls below certain threshold
= FDec
Expand All @@ -36,7 +37,7 @@ data Test
| FDecInc
-- | 'FInc' test followed by an 'FDec' one
| FIncDec
deriving (Enum, Generic, NFDataX, Bounded, BitPack, ShowX, Show)
deriving (Enum, Generic, NFDataX, Bounded, BitPack, ShowX, Show, Eq)

-- | Counter threshold after which a test is considered passed/failed. In theory
-- clocks can diverge at +-20 kHz (at 200 MHz), which gives the tests 500 ms to
Expand Down
237 changes: 237 additions & 0 deletions bittide-instances/src/Bittide/Instances/Hitl/FmcClock.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,237 @@
-- SPDX-FileCopyrightText: 2024 Google LLC
--
-- SPDX-License-Identifier: Apache-2.0
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE NumericUnderscores #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RecordWildCards #-}

{-# OPTIONS_GHC -fplugin=Protocols.Plugin #-}
{-# LANGUAGE FlexibleInstances #-}
module Bittide.Instances.Hitl.FmcClock where

import Clash.Prelude
import Clash.Explicit.Prelude (orReset, noReset)

import Data.Maybe (fromMaybe, isJust)
import Language.Haskell.TH (runIO)
import System.FilePath

import Protocols
import Protocols.Wishbone

import VexRiscv

import Clash.Annotations.TH (makeTopEntity)
import Clash.Cores.UART (ValidBaud)
import Clash.Cores.Xilinx.Ila (IlaConfig(..), Depth(..), ila, ilaConfig)
import Clash.Xilinx.ClockGen (clockWizardDifferential)

import Bittide.ClockControl
import Bittide.ClockControl.Registers (dataCountsWb)
import Bittide.Counter (domainDiffCounter)
import Bittide.DoubleBufferedRam
import Bittide.Hitl (HitlTests, testsFromEnum, hitlVio, singleFpga)
import Bittide.ProcessingElement
import Bittide.ProcessingElement.Util (memBlobsFromElf)
import Bittide.SharedTypes (ByteOrder(BigEndian))
import Bittide.Wishbone

import Bittide.Instances.Domains
import Bittide.Instances.Hitl.FincFdec (TestState(..), Test(..), testStateToDoneSuccess)
import Project.FilePath

import Clash.Cores.Xilinx.GTH (ibufds_gte3, gthCore)
import Clash.Explicit.Reset.Extra (Asserted(..), xpmResetSynchronizer)


onChange :: (HiddenClockResetEnable dom, Eq a, NFDataX a) => Signal dom a -> Signal dom Bool
onChange x = (Just <$> x) ./=. register Nothing (Just <$> x)

fmcClockRiscv ::
forall dom .
( HiddenClockResetEnable dom
, 1 <= DomainPeriod dom
, ValidBaud dom 921600 ) =>
"sclBs" ::: BiSignalIn 'PullUp dom 1 ->
"sdaIn" ::: Signal dom Bit ->
"datacounts" ::: Vec 1 (Signal dom (DataCount 32)) ->
"USB_UART_TX" ::: Signal dom Bit ->
"testSelect" ::: Signal dom (Maybe Test) ->
( "sclBs" ::: BiSignalOut 'PullUp dom 1
, "sdaOut" ::: Signal dom Bit
, "muxSelect" ::: BitVector 3
, "clockInitDone" ::: Signal dom Bool
, "testResult" ::: Signal dom TestState
, "USB_UART_RX" ::: Signal dom Bit
)
fmcClockRiscv sclBs sdaIn dataCounts uartRx testSelect =
( writeToBiSignal sclBs sclOut
, fromMaybe 1 <$> sdaOut
, 0b100
, clockInitDoneO
, testResultO
, uartTx
)
where
(_, (i2cOut, controlReg, uartTx)) =
circuitFn (((i2cIn, Just <$> testSelect, uartRx), pure (JtagIn low low low)), (pure (), pure (), pure ()))

Circuit circuitFn = circuit $ \((i2cIn, statusRegIn, uartRx), jtag) -> do
[timeBus, i2cBus, controlRegBus, statusRegBus, dataCountsBus, uartBus, dummyBus] <- processingElement @dom peConfig -< jtag
(uartTx, _uartStatus) <- uartWb d16 d16 (SNat @921600) -< (uartBus, uartRx)
i2cOut <- i2cWb -< (i2cBus, i2cIn)
dummyWb -< dummyBus
timeWb -< timeBus
statusRegWb Nothing -< (statusRegIn, statusRegBus)
controlReg <- controlRegWb (False, Busy) -< controlRegBus
dataCountsWb dataCounts -< dataCountsBus
idC -< (i2cOut, controlReg, uartTx)

(sclOut, sdaOut) = unbundle i2cOut
(clockInitDoneO, testResultO) = unbundle controlReg

sclIn = readFromBiSignal sclBs
i2cIn :: Signal dom (Bit, Bit)
i2cIn = bundle (sclIn, fromMaybe <$> sdaIn <*> sdaOut)

dummyWb :: NFDataX a => Circuit (Wishbone dom 'Standard aw a) ()
dummyWb = Circuit $ const (pure emptyWishboneS2M, ())

(iMem, dMem) = $(do
root <- runIO $ findParentContaining "cabal.project"
let
elfDir = root </> firmwareBinariesDir "riscv32imc-unknown-none-elf" Release
elfPath = elfDir </> "fmc-clock"
iSize = 128 * 1024 -- 128 KiB
dSize = 64 * 1024 -- 64 KiB
memBlobsFromElf BigEndian (Just iSize, Just dSize) elfPath Nothing)

{-
MSBs Device
0b1000 Instruction memory
0b0100 Data memory
0b0001 Memory mapped time component
0b0010 Memory mapped I2C core
0b0011 Memory mapped control register
0b0101 Memory mapped status register
0b0110 Memory mapped datacounts
0b0111 Memory mapped UART core
0b0000 Memory mapped dummy device

Dummy device is needed because the total number of devices cannot be equal to a power
of 2. The dummy device must then be mapped to the zero-address.
-}
peConfig =
PeConfig
(0b1000 :> 0b0100 :> 0b0001 :> 0b0010 :> 0b0011 :> 0b0101 :> 0b0110 :> 0b0111 :> (0b0000 :: Unsigned 4) :> Nil)
(Reloadable $ Blob iMem)
(Reloadable $ Blob dMem)

fmcClockTests ::
"SYSCLK_125" ::: DiffClock Ext125 ->
"FMC_HPC_GBTCLK1_M2C" ::: DiffClock Ext200 ->
"sclBs" ::: BiSignalIn 'PullUp Basic125 1 ->
"sdaIn" ::: Signal Basic125 Bit ->
"USB_UART_TX" ::: Signal Basic125 Bit ->
( "sclBs" ::: BiSignalOut 'PullUp Basic125 1
, "sdaOut" ::: Signal Basic125 Bit
, "muxSelect" ::: BitVector 3
, "" :::
( "done" ::: Signal Basic125 Bool
, "success" ::: Signal Basic125 Bool
)
, "USB_UART_RX" ::: Signal Basic125 Bit
)
fmcClockTests sysClkDiff fmcClkDiff sclBsIn sdaIn uartIn =
fmcClockIla `hwSeqX`
(sclBsOut, sdaOut, muxSelect, (testDone, testSuccess), uartOut)
where
(sysClk, sysRst :: Reset Basic125) = clockWizardDifferential sysClkDiff noReset

(sclBsOut, sdaOut, muxSelect, clockInitDone, testResult, uartOut) =
withClockResetEnable sysClk sysRst enableGen $
fmcClockRiscv sclBsIn sdaIn (domainDiff :> Nil) uartIn testInput

fmcClk = ibufds_gte3 fmcClkDiff :: Clock Ext200

( _gthtxn_out
, _gthtxp_out
, txClock::Clock GthTx
, _gtwiz_userclk_rx_usrclk2_out::Clock GthRx
, _gtwiz_userdata_rx_out
, _gtwiz_reset_tx_done_out
, _gtwiz_reset_rx_done_out
, xpmResetSynchronizer Asserted txClock txClock . unsafeFromActiveLow . fmap unpack -> txClkRst
) =
gthCore
"X0Y10" "clk0" (pure 0) (pure 0)
sysClk
gthRst noReset noReset noReset noReset (pure 0) (pure 0)
sysClk fmcClk

gthRst =
sysRst `orReset`
unsafeFromActiveLow clockInitDone
testRst =
sysRst `orReset`
unsafeFromActiveLow clockInitDone `orReset`
unsafeFromActiveLow testStarted

(domainDiff, dcActive) =
unbundle $ domainDiffCounter txClock txClkRst sysClk testRst

testStarted = isJust <$> testInput
(testDone, testSuccess) = unbundle $ testStateToDoneSuccess <$> testResult

testInput :: Signal Basic125 (Maybe Test)
testInput =
hitlVio
FDec
sysClk
testDone
testSuccess

capture :: Signal Basic125 Bool
capture =
withClockResetEnable sysClk sysRst enableGen $
onChange $ bundle
( domainDiff
, testInput
, testDone
, testSuccess
, clockInitDone
)

fmcClockIla :: Signal Basic125 ()
fmcClockIla = setName @"fmcClockIla" $ ila
(ilaConfig $
"trigger_0"
:> "capture_0"
:> "probe_testInput"
:> "probe_testDone"
:> "probe_testSuccess"
:> "probe_clockInitDone"
:> "probe_testRst"
:> "probe_txLockRst"
:> "probe_domainDiffActive"
:> "probe_domainDiff"
:> Nil
) { depth = D32768 }
sysClk
testStarted
capture
-- Debug signals
testInput
testDone
testSuccess
clockInitDone
(unsafeToActiveHigh testRst)
(unsafeToActiveHigh $ xpmResetSynchronizer Asserted txClock sysClk txClkRst)
dcActive
domainDiff
{-# NOINLINE fmcClockTests #-}
makeTopEntity 'fmcClockTests

tests :: HitlTests Test
tests = testsFromEnum (singleFpga maxBound)
2 changes: 2 additions & 0 deletions bittide-instances/src/Bittide/Instances/Hitl/Tests.hs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import Data.Aeson (ToJSON)

import qualified Bittide.Instances.Hitl.BoardTest as BoardTest
import qualified Bittide.Instances.Hitl.FincFdec as FincFdec
import qualified Bittide.Instances.Hitl.FmcClock as FmcClock
import qualified Bittide.Instances.Hitl.FullMeshHwCc as FullMeshHwCc
import qualified Bittide.Instances.Hitl.FullMeshSwCc as FullMeshSwCc
import qualified Bittide.Instances.Hitl.HwCcTopologies as HwCcTopologies
Expand Down Expand Up @@ -47,6 +48,7 @@ hitlTests =
knownType 'BoardTest.boardTestExtended BoardTest.testsExtended
, knownType 'BoardTest.boardTestSimple BoardTest.testsSimple
, knownType 'FincFdec.fincFdecTests FincFdec.tests
, knownType 'FmcClock.fmcClockTests FmcClock.tests
, knownType 'FullMeshHwCc.fullMeshHwCcTest FullMeshHwCc.tests
, knownType 'FullMeshHwCc.fullMeshHwCcWithRiscvTest FullMeshHwCc.tests
, knownType 'FullMeshSwCc.fullMeshSwCcTest FullMeshSwCc.tests
Expand Down
Loading
Loading