package Decoder where -- IMaybe creates separate ports for the valid bit and payload of a Maybe -- at synthesis boundaries. -- It deliberately does *not* derive Bits so that it isn't unexpectedly -- packed or unpacked at synthesis boundaries. interface IMaybe a = iValid :: Bool iValue :: a deriving(Eq) iMaybe :: Maybe a -> IMaybe a iMaybe ma = IMaybe { iValid = isValid ma; iValue = validValue ma } data Command = DoBar (Bit 2) (Maybe Bool) | DoBaz (UInt 5) (Int 7) deriving(Eq, Bits) interface BarCtrl = bar_1 :: Bit 2 bar_2 :: IMaybe Bool interface BazCtrl = baz_1 :: UInt 5 baz_2 :: Int 7 interface CtrlOut = bar :: IMaybe BarCtrl baz :: IMaybe BazCtrl interface Decoder = cmdIn :: Command -> Action {-# always_enabled #-} ctrlOut :: CtrlOut {-# verilog mkDecoder { noReady } #-} mkDecoder :: Module Decoder mkDecoder = module cmdWire <- mkBypassWire interface cmdIn = cmdWire._write ctrlOut = case cmdWire of DoBar bar_1 bar_2 -> interface CtrlOut bar = iMaybe $ Valid $ interface BarCtrl bar_1 = bar_1 bar_2 = iMaybe bar_2 baz = iMaybe Invalid DoBaz baz_1 baz_2 -> interface CtrlOut bar = iMaybe Invalid baz = iMaybe $ Valid $ interface BazCtrl baz_1 = baz_1 baz_2 = baz_2