From ed27ead19924af2bc25f014a30e328d1d03b6664 Mon Sep 17 00:00:00 2001 From: t-wallet Date: Tue, 27 Aug 2024 14:05:16 +0200 Subject: [PATCH 1/3] Add RGMII core Co-authored-by: Jasmijn Bookelmann Co-authored-by: Cato van Ojen Co-authored-by: MatthijsMu <93450301+MatthijsMu@users.noreply.github.com> Co-authored-by: Jasper Laumen <96011116+JLaumen@users.noreply.github.com> Co-authored-by: Mart Koster <30956441+Akribes@users.noreply.github.com> Co-authored-by: Bryan Rinders Co-authored-by: Daan Weessies Co-authored-by: Rowan Goemans Co-authored-by: syberant --- CHANGELOG.md | 1 + clash-cores.cabal | 2 + nix/nixpkgs.nix | 4 + nix/sources.json | 18 +++- src/Clash/Cores/Rgmii.hs | 216 +++++++++++++++++++++++++++++++++++++++ 5 files changed, 238 insertions(+), 3 deletions(-) create mode 100644 src/Clash/Cores/Rgmii.hs diff --git a/CHANGELOG.md b/CHANGELOG.md index cac4dfa..4a13770 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,3 +6,4 @@ * Add Lattice Semi SB_IO primitive * Add UART core * Add CRC core +* Add RGMII core diff --git a/clash-cores.cabal b/clash-cores.cabal index 163b805..9656082 100644 --- a/clash-cores.cabal +++ b/clash-cores.cabal @@ -108,6 +108,7 @@ common basic-config build-depends: base >= 4.10 && < 5, clash-prelude, + clash-protocols, constraints, containers >=0.5 && <0.8, ghc-typelits-extra >= 0.3.2, @@ -133,6 +134,7 @@ library Clash.Cores.LineCoding8b10b Clash.Cores.LineCoding8b10b.Decoder Clash.Cores.LineCoding8b10b.Encoder + Clash.Cores.Rgmii Clash.Cores.SPI Clash.Cores.UART Clash.Cores.Xilinx.BlockRam diff --git a/nix/nixpkgs.nix b/nix/nixpkgs.nix index 884d8a5..5620725 100644 --- a/nix/nixpkgs.nix +++ b/nix/nixpkgs.nix @@ -30,6 +30,10 @@ let self.callCabal2nix "doctest-parallel" sources.doctest-parallel {}; clash-prelude = self.callCabal2nix "clash-prelude" (sources.clash-compiler + "/clash-prelude") {}; + clash-protocols-base = + self.callCabal2nix "clash-protocols-base" (sources.clash-protocols + "/clash-protocols-base") {}; + clash-protocols = + self.callCabal2nix "clash-protocols" (sources.clash-protocols + "/clash-protocols") {}; clash-lib = self.callCabal2nix "clash-lib" (sources.clash-compiler + "/clash-lib") {}; clash-ghc = diff --git a/nix/sources.json b/nix/sources.json index 613a609..03eefe7 100644 --- a/nix/sources.json +++ b/nix/sources.json @@ -5,13 +5,25 @@ "homepage": "https://clash-lang.org/", "owner": "clash-lang", "repo": "clash-compiler", - "rev": "aba55fed9f45711c8336935721a43d243f7f78c1", - "sha256": "1hrzp8g189v46qfr9ds7w6w0yj5w8y4im1pa3lf5vjx3z64v26qv", + "rev": "f946617561565440d82f67747acb2486f6526a66", + "sha256": "0924xzzwzrpjb1yid9mvy2imxwrzyxfdmkd2l1wfrsdwgrc53dpg", "type": "tarball", - "url": "https://github.com/clash-lang/clash-compiler/archive/aba55fed9f45711c8336935721a43d243f7f78c1.tar.gz", + "url": "https://github.com/clash-lang/clash-compiler/archive/f946617561565440d82f67747acb2486f6526a66.tar.gz", "url_template": "https://github.com///archive/.tar.gz", "version": "1.8.1" }, + "clash-protocols": { + "branch": "packetstream", + "description": "a battery-included library for dataflow protocols", + "homepage": null, + "owner": "clash-lang", + "repo": "clash-protocols", + "rev": "b893b1b22e8157c1352295fa115e3f9c01fcaf5c", + "sha256": "0v21bzmg0p2fdzkvri9wvzhbg79zjxmp4zg53h3fb1rlcxnmxq9r", + "type": "tarball", + "url": "https://github.com/clash-lang/clash-protocols/archive/b893b1b22e8157c1352295fa115e3f9c01fcaf5c.tar.gz", + "url_template": "https://github.com///archive/.tar.gz" + }, "doctest-parallel": { "branch": "main", "description": "Test interactive Haskell examples", diff --git a/src/Clash/Cores/Rgmii.hs b/src/Clash/Cores/Rgmii.hs new file mode 100644 index 0000000..e3c6c06 --- /dev/null +++ b/src/Clash/Cores/Rgmii.hs @@ -0,0 +1,216 @@ +{-# LANGUAGE RankNTypes #-} +{-# LANGUAGE RecordWildCards #-} + +{- | +Module : Clash.Cores.Rgmii +Description : Functions and types to connect an RGMII PHY to a packet stream interface. + +To keep this module generic, users will have to provide their own "primitive" functions: + + 1. delay functions to set to the proper amount of delay (which can be different for RX and TX); + 2. iddr function to turn a single DDR (Double Data Rate) signal into 2 non-DDR signals; + 3. oddr function to turn two non-DDR signals into a single DDR signal. + +Note that Clash models a DDR signal as being twice as fast, thus both facilitating +and requiring type-level separation between the two "clock domains". +-} +module Clash.Cores.Rgmii ( + RgmiiRxChannel (..), + RgmiiTxChannel (..), + rgmiiReceiver, + rgmiiSender, + unsafeRgmiiRxC, + rgmiiTxC, +) where + +import Clash.Prelude + +import Protocols +import Protocols.PacketStream + +import Data.Maybe (isJust) + +-- | RX channel from the RGMII PHY +data RgmiiRxChannel dom domDDR = RgmiiRxChannel + { rgmiiRxClk :: "rx_clk" ::: Clock dom + , rgmiiRxCtl :: "rx_ctl" ::: Signal domDDR Bit + , rgmiiRxData :: "rx_data" ::: Signal domDDR (BitVector 4) + } + +instance Protocol (RgmiiRxChannel dom domDDR) where + type Fwd (RgmiiRxChannel dom domDDR) = RgmiiRxChannel dom domDDR + type Bwd (RgmiiRxChannel dom domDDR) = Signal dom () + +-- | TX channel to the RGMII PHY +data RgmiiTxChannel domDDR = RgmiiTxChannel + { rgmiiTxClk :: "tx_clk" ::: Signal domDDR Bit + , rgmiiTxCtl :: "tx_ctl" ::: Signal domDDR Bit + , rgmiiTxData :: "tx_data" ::: Signal domDDR (BitVector 4) + } + +instance Protocol (RgmiiTxChannel domDDR) where + type Fwd (RgmiiTxChannel domDDR) = RgmiiTxChannel domDDR + type Bwd (RgmiiTxChannel domDDR) = Signal domDDR () + +-- | RGMII receiver. +rgmiiReceiver :: + forall dom domDDR. + (DomainPeriod dom ~ (*) 2 (DomainPeriod domDDR)) => + (KnownDomain dom) => + -- | RX channel from the RGMII PHY + RgmiiRxChannel dom domDDR -> + -- | RX delay function + (forall a. Signal domDDR a -> Signal domDDR a) -> + -- | iddr function + ( forall a. + (NFDataX a, BitPack a) => + Clock dom -> + Reset dom -> + Signal domDDR a -> + Signal dom (a, a) + ) -> + -- | (Error bit, Received data) + Signal dom (Bool, Maybe (BitVector 8)) +rgmiiReceiver RgmiiRxChannel{..} rxdelay iddr = bundle (ethRxErr, ethRxData) + where + ethRxCtl :: Signal dom (Bool, Bool) + ethRxCtl = iddr rgmiiRxClk resetGen (rxdelay (bitToBool <$> rgmiiRxCtl)) + + -- The RXCTL signal at the falling edge is the XOR of RXDV and RXERR + -- meaning that RXERR is the XOR of it and RXDV. + -- See RGMII interface documentation. + ethRxDv, ethRxErr :: Signal dom Bool + (ethRxDv, ethRxErr) = unbundle ((\(dv, err) -> (dv, dv `xor` err)) <$> ethRxCtl) + + -- LSB first! See RGMII interface documentation. + ethRxData1, ethRxData2 :: Signal dom (BitVector 4) + (ethRxData2, ethRxData1) = unbundle $ iddr rgmiiRxClk resetGen (rxdelay rgmiiRxData) + + ethRxData :: Signal dom (Maybe (BitVector 8)) + ethRxData = + (\(dv, dat) -> if dv then Just dat else Nothing) + <$> bundle (ethRxDv, liftA2 (++#) ethRxData1 ethRxData2) + +-- | RGMII sender. Does not consider transmission error. +rgmiiSender :: + forall dom domDDR. + (DomainPeriod dom ~ (*) 2 (DomainPeriod domDDR)) => + Clock dom -> + Reset dom -> + -- | TX delay function + (forall a. Signal domDDR a -> Signal domDDR a) -> + -- | oddr function + ( forall a. + (NFDataX a, BitPack a) => + Clock dom -> + Reset dom -> + Signal dom a -> + Signal dom a -> + Signal domDDR a + ) -> + -- | Maybe the byte we have to send + Signal dom (Maybe (BitVector 8)) -> + -- | Error signal indicating whether the current packet is corrupt + Signal dom Bool -> + -- | TX channel to the RGMII PHY + RgmiiTxChannel domDDR +rgmiiSender txClk rst txdelay oddr input err = channel + where + txEn, txErr :: Signal dom Bit + txEn = boolToBit . isJust <$> input + txErr = fmap boolToBit err + + ethTxData1, ethTxData2 :: Signal dom (BitVector 4) + (ethTxData1, ethTxData2) = unbundle $ maybe (undefined, undefined) split <$> input + + -- The TXCTL signal at the falling edge is the XOR of TXEN and TXERR + -- meaning that TXERR is the XOR of it and TXEN. + -- See RGMII interface documentation. + txCtl :: Signal domDDR Bit + txCtl = oddr txClk rst txEn (liftA2 xor txEn txErr) + + -- LSB first! See RGMII interface documentation. + txData :: Signal domDDR (BitVector 4) + txData = oddr txClk rst ethTxData2 ethTxData1 + + channel = + RgmiiTxChannel + { rgmiiTxClk = txdelay (oddr txClk rst (pure 1) (pure 0)) + , rgmiiTxCtl = txdelay txCtl + , rgmiiTxData = txdelay txData + } + +{- | +Circuit that adapts an `RgmiiRxChannel` to a `PacketStream`. Forwards data +from the RGMII receiver with one clock cycle latency so that we can properly +mark the last transfer of a packet: if we received valid data from the RGMII +receiver in the last clock cycle and the data in the current clock cycle is +invalid, we set `_last`. If the RGMII receiver gives an error, we set `_abort`. + +__UNSAFE__: ignores backpressure, because the RGMII PHY is unable to handle that. +-} +unsafeRgmiiRxC :: + forall dom domDDR. + (HiddenClockResetEnable dom) => + (DomainPeriod dom ~ (*) 2 (DomainPeriod domDDR)) => + -- | RX delay function + (forall a. Signal domDDR a -> Signal domDDR a) -> + -- | iddr function + ( forall a. + (NFDataX a, BitPack a) => + Clock dom -> + Reset dom -> + Signal domDDR a -> + Signal dom (a, a) + ) -> + Circuit (RgmiiRxChannel dom domDDR) (PacketStream dom 1 ()) +unsafeRgmiiRxC rxDelay iddr = fromSignals ckt + where + ckt (fwdIn, _) = (pure (), fwdOut) + where + (rxErr, rxData) = unbundle (rgmiiReceiver fwdIn rxDelay iddr) + lastRxErr = register False rxErr + lastRxData = register Nothing rxData + + fwdOut = go <$> bundle (rxData, lastRxData, lastRxErr) + + go (currData, lastData, lastErr) = + ( \byte -> + PacketStreamM2S + { _data = singleton byte + , _last = case currData of + Nothing -> Just 0 + Just _ -> Nothing + , _meta = () + , _abort = lastErr + } + ) + <$> lastData + +{- | +Circuit that adapts a `PacketStream` to an `RgmiiTxChannel`. +Never asserts backpressure. +-} +rgmiiTxC :: + forall dom domDDR. + (HiddenClockResetEnable dom) => + (DomainPeriod dom ~ (*) 2 (DomainPeriod domDDR)) => + -- | TX delay function + (forall a. Signal domDDR a -> Signal domDDR a) -> + -- | oddr function + ( forall a. + (NFDataX a, BitPack a) => + Clock dom -> + Reset dom -> + Signal dom a -> + Signal dom a -> + Signal domDDR a + ) -> + Circuit (PacketStream dom 1 ()) (RgmiiTxChannel domDDR) +rgmiiTxC txDelay oddr = fromSignals ckt + where + ckt (fwdIn, _) = (pure (PacketStreamS2M True), fwdOut) + where + input = fmap (head . _data) <$> fwdIn + err = maybe False _abort <$> fwdIn + fwdOut = rgmiiSender hasClock hasReset txDelay oddr input err From 8c1d5fcb3262072fbaab4e5a4ed02276ae9649cd Mon Sep 17 00:00:00 2001 From: t-wallet Date: Tue, 3 Sep 2024 09:18:29 +0200 Subject: [PATCH 2/3] Style changes --- clash-cores.cabal | 2 +- src/Clash/Cores/{ => Ethernet}/Rgmii.hs | 90 +++++++++++++------------ 2 files changed, 49 insertions(+), 43 deletions(-) rename src/Clash/Cores/{ => Ethernet}/Rgmii.hs (71%) diff --git a/clash-cores.cabal b/clash-cores.cabal index 9656082..97f93d8 100644 --- a/clash-cores.cabal +++ b/clash-cores.cabal @@ -127,6 +127,7 @@ library Clash.Cores.Crc Clash.Cores.Crc.Internal Clash.Cores.Crc.Catalog + Clash.Cores.Ethernet.Rgmii Clash.Cores.LatticeSemi.ECP5.Blackboxes.IO Clash.Cores.LatticeSemi.ECP5.IO Clash.Cores.LatticeSemi.ICE40.Blackboxes.IO @@ -134,7 +135,6 @@ library Clash.Cores.LineCoding8b10b Clash.Cores.LineCoding8b10b.Decoder Clash.Cores.LineCoding8b10b.Encoder - Clash.Cores.Rgmii Clash.Cores.SPI Clash.Cores.UART Clash.Cores.Xilinx.BlockRam diff --git a/src/Clash/Cores/Rgmii.hs b/src/Clash/Cores/Ethernet/Rgmii.hs similarity index 71% rename from src/Clash/Cores/Rgmii.hs rename to src/Clash/Cores/Ethernet/Rgmii.hs index e3c6c06..d9e3fab 100644 --- a/src/Clash/Cores/Rgmii.hs +++ b/src/Clash/Cores/Ethernet/Rgmii.hs @@ -14,11 +14,11 @@ To keep this module generic, users will have to provide their own "primitive" fu Note that Clash models a DDR signal as being twice as fast, thus both facilitating and requiring type-level separation between the two "clock domains". -} -module Clash.Cores.Rgmii ( +module Clash.Cores.Ethernet.Rgmii ( RgmiiRxChannel (..), RgmiiTxChannel (..), rgmiiReceiver, - rgmiiSender, + rgmiiTransmitter, unsafeRgmiiRxC, rgmiiTxC, ) where @@ -31,42 +31,42 @@ import Protocols.PacketStream import Data.Maybe (isJust) -- | RX channel from the RGMII PHY -data RgmiiRxChannel dom domDDR = RgmiiRxChannel +data RgmiiRxChannel dom ddrDom = RgmiiRxChannel { rgmiiRxClk :: "rx_clk" ::: Clock dom - , rgmiiRxCtl :: "rx_ctl" ::: Signal domDDR Bit - , rgmiiRxData :: "rx_data" ::: Signal domDDR (BitVector 4) + , rgmiiRxCtl :: "rx_ctl" ::: Signal ddrDom Bit + , rgmiiRxData :: "rx_data" ::: Signal ddrDom (BitVector 4) } -instance Protocol (RgmiiRxChannel dom domDDR) where - type Fwd (RgmiiRxChannel dom domDDR) = RgmiiRxChannel dom domDDR - type Bwd (RgmiiRxChannel dom domDDR) = Signal dom () +instance Protocol (RgmiiRxChannel dom ddrDom) where + type Fwd (RgmiiRxChannel dom ddrDom) = RgmiiRxChannel dom ddrDom + type Bwd (RgmiiRxChannel dom ddrDom) = Signal dom () -- | TX channel to the RGMII PHY -data RgmiiTxChannel domDDR = RgmiiTxChannel - { rgmiiTxClk :: "tx_clk" ::: Signal domDDR Bit - , rgmiiTxCtl :: "tx_ctl" ::: Signal domDDR Bit - , rgmiiTxData :: "tx_data" ::: Signal domDDR (BitVector 4) +data RgmiiTxChannel ddrDom = RgmiiTxChannel + { rgmiiTxClk :: "tx_clk" ::: Signal ddrDom Bit + , rgmiiTxCtl :: "tx_ctl" ::: Signal ddrDom Bit + , rgmiiTxData :: "tx_data" ::: Signal ddrDom (BitVector 4) } -instance Protocol (RgmiiTxChannel domDDR) where - type Fwd (RgmiiTxChannel domDDR) = RgmiiTxChannel domDDR - type Bwd (RgmiiTxChannel domDDR) = Signal domDDR () +instance Protocol (RgmiiTxChannel ddrDom) where + type Fwd (RgmiiTxChannel ddrDom) = RgmiiTxChannel ddrDom + type Bwd (RgmiiTxChannel ddrDom) = Signal ddrDom () -- | RGMII receiver. rgmiiReceiver :: - forall dom domDDR. - (DomainPeriod dom ~ (*) 2 (DomainPeriod domDDR)) => + forall dom ddrDom. + (DomainPeriod dom ~ 2 * DomainPeriod ddrDom) => (KnownDomain dom) => -- | RX channel from the RGMII PHY - RgmiiRxChannel dom domDDR -> + RgmiiRxChannel dom ddrDom -> -- | RX delay function - (forall a. Signal domDDR a -> Signal domDDR a) -> + (forall a. Signal ddrDom a -> Signal ddrDom a) -> -- | iddr function ( forall a. (NFDataX a, BitPack a) => Clock dom -> Reset dom -> - Signal domDDR a -> + Signal ddrDom a -> Signal dom (a, a) ) -> -- | (Error bit, Received data) @@ -91,14 +91,14 @@ rgmiiReceiver RgmiiRxChannel{..} rxdelay iddr = bundle (ethRxErr, ethRxData) (\(dv, dat) -> if dv then Just dat else Nothing) <$> bundle (ethRxDv, liftA2 (++#) ethRxData1 ethRxData2) --- | RGMII sender. Does not consider transmission error. -rgmiiSender :: - forall dom domDDR. - (DomainPeriod dom ~ (*) 2 (DomainPeriod domDDR)) => +-- | RGMII transmitter. Does not consider transmission error. +rgmiiTransmitter :: + forall dom ddrDom. + (DomainPeriod dom ~ 2 * DomainPeriod ddrDom) => Clock dom -> Reset dom -> -- | TX delay function - (forall a. Signal domDDR a -> Signal domDDR a) -> + (forall a. Signal ddrDom a -> Signal ddrDom a) -> -- | oddr function ( forall a. (NFDataX a, BitPack a) => @@ -106,31 +106,37 @@ rgmiiSender :: Reset dom -> Signal dom a -> Signal dom a -> - Signal domDDR a + Signal ddrDom a ) -> -- | Maybe the byte we have to send Signal dom (Maybe (BitVector 8)) -> -- | Error signal indicating whether the current packet is corrupt Signal dom Bool -> -- | TX channel to the RGMII PHY - RgmiiTxChannel domDDR -rgmiiSender txClk rst txdelay oddr input err = channel + RgmiiTxChannel ddrDom +rgmiiTransmitter txClk rst txdelay oddr input err = channel where txEn, txErr :: Signal dom Bit txEn = boolToBit . isJust <$> input txErr = fmap boolToBit err ethTxData1, ethTxData2 :: Signal dom (BitVector 4) - (ethTxData1, ethTxData2) = unbundle $ maybe (undefined, undefined) split <$> input + (ethTxData1, ethTxData2) = unbundle $ + maybe + ( deepErrorX "rgmiiTransmitter: undefined Ethernet TX data 1" + , deepErrorX "rgmiiTransmitter: undefined Ethernet TX data 2" + ) + split + <$> input -- The TXCTL signal at the falling edge is the XOR of TXEN and TXERR -- meaning that TXERR is the XOR of it and TXEN. -- See RGMII interface documentation. - txCtl :: Signal domDDR Bit + txCtl :: Signal ddrDom Bit txCtl = oddr txClk rst txEn (liftA2 xor txEn txErr) -- LSB first! See RGMII interface documentation. - txData :: Signal domDDR (BitVector 4) + txData :: Signal ddrDom (BitVector 4) txData = oddr txClk rst ethTxData2 ethTxData1 channel = @@ -150,20 +156,20 @@ invalid, we set `_last`. If the RGMII receiver gives an error, we set `_abort`. __UNSAFE__: ignores backpressure, because the RGMII PHY is unable to handle that. -} unsafeRgmiiRxC :: - forall dom domDDR. + forall dom ddrDom. (HiddenClockResetEnable dom) => - (DomainPeriod dom ~ (*) 2 (DomainPeriod domDDR)) => + (DomainPeriod dom ~ 2 * DomainPeriod ddrDom) => -- | RX delay function - (forall a. Signal domDDR a -> Signal domDDR a) -> + (forall a. Signal ddrDom a -> Signal ddrDom a) -> -- | iddr function ( forall a. (NFDataX a, BitPack a) => Clock dom -> Reset dom -> - Signal domDDR a -> + Signal ddrDom a -> Signal dom (a, a) ) -> - Circuit (RgmiiRxChannel dom domDDR) (PacketStream dom 1 ()) + Circuit (RgmiiRxChannel dom ddrDom) (PacketStream dom 1 ()) unsafeRgmiiRxC rxDelay iddr = fromSignals ckt where ckt (fwdIn, _) = (pure (), fwdOut) @@ -192,11 +198,11 @@ Circuit that adapts a `PacketStream` to an `RgmiiTxChannel`. Never asserts backpressure. -} rgmiiTxC :: - forall dom domDDR. + forall dom ddrDom. (HiddenClockResetEnable dom) => - (DomainPeriod dom ~ (*) 2 (DomainPeriod domDDR)) => + (DomainPeriod dom ~ 2 * DomainPeriod ddrDom) => -- | TX delay function - (forall a. Signal domDDR a -> Signal domDDR a) -> + (forall a. Signal ddrDom a -> Signal ddrDom a) -> -- | oddr function ( forall a. (NFDataX a, BitPack a) => @@ -204,13 +210,13 @@ rgmiiTxC :: Reset dom -> Signal dom a -> Signal dom a -> - Signal domDDR a + Signal ddrDom a ) -> - Circuit (PacketStream dom 1 ()) (RgmiiTxChannel domDDR) + Circuit (PacketStream dom 1 ()) (RgmiiTxChannel ddrDom) rgmiiTxC txDelay oddr = fromSignals ckt where ckt (fwdIn, _) = (pure (PacketStreamS2M True), fwdOut) where input = fmap (head . _data) <$> fwdIn err = maybe False _abort <$> fwdIn - fwdOut = rgmiiSender hasClock hasReset txDelay oddr input err + fwdOut = rgmiiTransmitter hasClock hasReset txDelay oddr input err From 948d9e5ec6d4cc0c52dab06f2d5d464836b9296d Mon Sep 17 00:00:00 2001 From: t-wallet Date: Fri, 6 Sep 2024 10:29:55 +0200 Subject: [PATCH 3/3] Rename ddrDom to domDdr --- src/Clash/Cores/Ethernet/Rgmii.hs | 70 +++++++++++++++---------------- 1 file changed, 35 insertions(+), 35 deletions(-) diff --git a/src/Clash/Cores/Ethernet/Rgmii.hs b/src/Clash/Cores/Ethernet/Rgmii.hs index d9e3fab..e3b9e45 100644 --- a/src/Clash/Cores/Ethernet/Rgmii.hs +++ b/src/Clash/Cores/Ethernet/Rgmii.hs @@ -31,42 +31,42 @@ import Protocols.PacketStream import Data.Maybe (isJust) -- | RX channel from the RGMII PHY -data RgmiiRxChannel dom ddrDom = RgmiiRxChannel +data RgmiiRxChannel dom domDdr = RgmiiRxChannel { rgmiiRxClk :: "rx_clk" ::: Clock dom - , rgmiiRxCtl :: "rx_ctl" ::: Signal ddrDom Bit - , rgmiiRxData :: "rx_data" ::: Signal ddrDom (BitVector 4) + , rgmiiRxCtl :: "rx_ctl" ::: Signal domDdr Bit + , rgmiiRxData :: "rx_data" ::: Signal domDdr (BitVector 4) } -instance Protocol (RgmiiRxChannel dom ddrDom) where - type Fwd (RgmiiRxChannel dom ddrDom) = RgmiiRxChannel dom ddrDom - type Bwd (RgmiiRxChannel dom ddrDom) = Signal dom () +instance Protocol (RgmiiRxChannel dom domDdr) where + type Fwd (RgmiiRxChannel dom domDdr) = RgmiiRxChannel dom domDdr + type Bwd (RgmiiRxChannel dom domDdr) = Signal dom () -- | TX channel to the RGMII PHY -data RgmiiTxChannel ddrDom = RgmiiTxChannel - { rgmiiTxClk :: "tx_clk" ::: Signal ddrDom Bit - , rgmiiTxCtl :: "tx_ctl" ::: Signal ddrDom Bit - , rgmiiTxData :: "tx_data" ::: Signal ddrDom (BitVector 4) +data RgmiiTxChannel domDdr = RgmiiTxChannel + { rgmiiTxClk :: "tx_clk" ::: Signal domDdr Bit + , rgmiiTxCtl :: "tx_ctl" ::: Signal domDdr Bit + , rgmiiTxData :: "tx_data" ::: Signal domDdr (BitVector 4) } -instance Protocol (RgmiiTxChannel ddrDom) where - type Fwd (RgmiiTxChannel ddrDom) = RgmiiTxChannel ddrDom - type Bwd (RgmiiTxChannel ddrDom) = Signal ddrDom () +instance Protocol (RgmiiTxChannel domDdr) where + type Fwd (RgmiiTxChannel domDdr) = RgmiiTxChannel domDdr + type Bwd (RgmiiTxChannel domDdr) = Signal domDdr () -- | RGMII receiver. rgmiiReceiver :: - forall dom ddrDom. - (DomainPeriod dom ~ 2 * DomainPeriod ddrDom) => + forall dom domDdr. + (DomainPeriod dom ~ 2 * DomainPeriod domDdr) => (KnownDomain dom) => -- | RX channel from the RGMII PHY - RgmiiRxChannel dom ddrDom -> + RgmiiRxChannel dom domDdr -> -- | RX delay function - (forall a. Signal ddrDom a -> Signal ddrDom a) -> + (forall a. Signal domDdr a -> Signal domDdr a) -> -- | iddr function ( forall a. (NFDataX a, BitPack a) => Clock dom -> Reset dom -> - Signal ddrDom a -> + Signal domDdr a -> Signal dom (a, a) ) -> -- | (Error bit, Received data) @@ -93,12 +93,12 @@ rgmiiReceiver RgmiiRxChannel{..} rxdelay iddr = bundle (ethRxErr, ethRxData) -- | RGMII transmitter. Does not consider transmission error. rgmiiTransmitter :: - forall dom ddrDom. - (DomainPeriod dom ~ 2 * DomainPeriod ddrDom) => + forall dom domDdr. + (DomainPeriod dom ~ 2 * DomainPeriod domDdr) => Clock dom -> Reset dom -> -- | TX delay function - (forall a. Signal ddrDom a -> Signal ddrDom a) -> + (forall a. Signal domDdr a -> Signal domDdr a) -> -- | oddr function ( forall a. (NFDataX a, BitPack a) => @@ -106,14 +106,14 @@ rgmiiTransmitter :: Reset dom -> Signal dom a -> Signal dom a -> - Signal ddrDom a + Signal domDdr a ) -> -- | Maybe the byte we have to send Signal dom (Maybe (BitVector 8)) -> -- | Error signal indicating whether the current packet is corrupt Signal dom Bool -> -- | TX channel to the RGMII PHY - RgmiiTxChannel ddrDom + RgmiiTxChannel domDdr rgmiiTransmitter txClk rst txdelay oddr input err = channel where txEn, txErr :: Signal dom Bit @@ -132,11 +132,11 @@ rgmiiTransmitter txClk rst txdelay oddr input err = channel -- The TXCTL signal at the falling edge is the XOR of TXEN and TXERR -- meaning that TXERR is the XOR of it and TXEN. -- See RGMII interface documentation. - txCtl :: Signal ddrDom Bit + txCtl :: Signal domDdr Bit txCtl = oddr txClk rst txEn (liftA2 xor txEn txErr) -- LSB first! See RGMII interface documentation. - txData :: Signal ddrDom (BitVector 4) + txData :: Signal domDdr (BitVector 4) txData = oddr txClk rst ethTxData2 ethTxData1 channel = @@ -156,20 +156,20 @@ invalid, we set `_last`. If the RGMII receiver gives an error, we set `_abort`. __UNSAFE__: ignores backpressure, because the RGMII PHY is unable to handle that. -} unsafeRgmiiRxC :: - forall dom ddrDom. + forall dom domDdr. (HiddenClockResetEnable dom) => - (DomainPeriod dom ~ 2 * DomainPeriod ddrDom) => + (DomainPeriod dom ~ 2 * DomainPeriod domDdr) => -- | RX delay function - (forall a. Signal ddrDom a -> Signal ddrDom a) -> + (forall a. Signal domDdr a -> Signal domDdr a) -> -- | iddr function ( forall a. (NFDataX a, BitPack a) => Clock dom -> Reset dom -> - Signal ddrDom a -> + Signal domDdr a -> Signal dom (a, a) ) -> - Circuit (RgmiiRxChannel dom ddrDom) (PacketStream dom 1 ()) + Circuit (RgmiiRxChannel dom domDdr) (PacketStream dom 1 ()) unsafeRgmiiRxC rxDelay iddr = fromSignals ckt where ckt (fwdIn, _) = (pure (), fwdOut) @@ -198,11 +198,11 @@ Circuit that adapts a `PacketStream` to an `RgmiiTxChannel`. Never asserts backpressure. -} rgmiiTxC :: - forall dom ddrDom. + forall dom domDdr. (HiddenClockResetEnable dom) => - (DomainPeriod dom ~ 2 * DomainPeriod ddrDom) => + (DomainPeriod dom ~ 2 * DomainPeriod domDdr) => -- | TX delay function - (forall a. Signal ddrDom a -> Signal ddrDom a) -> + (forall a. Signal domDdr a -> Signal domDdr a) -> -- | oddr function ( forall a. (NFDataX a, BitPack a) => @@ -210,9 +210,9 @@ rgmiiTxC :: Reset dom -> Signal dom a -> Signal dom a -> - Signal ddrDom a + Signal domDdr a ) -> - Circuit (PacketStream dom 1 ()) (RgmiiTxChannel ddrDom) + Circuit (PacketStream dom 1 ()) (RgmiiTxChannel domDdr) rgmiiTxC txDelay oddr = fromSignals ckt where ckt (fwdIn, _) = (pure (PacketStreamS2M True), fwdOut)