ice40-prim-0.2.0.0: src/Ice40/IO.hs
{-|
Module : Ice40.IO
Description : Ice40 IO hard IP primitives
Copyright : (c) David Cox, 2021
License : BSD 3-Clause
Maintainer : standardsemiconductor@gmail.com
IO hard IP primitive from [Lattice Ice Technology Library](https://github.com/standardsemiconductor/VELDT-info/blob/master/SBTICETechnologyLibrary201708.pdf)
-}
module Ice40.IO where
import Clash.Prelude
import Clash.Annotations.Primitive
import Data.String.Interpolate (i)
import Data.String.Interpolate.Util (unindent)
{-# ANN ioPrim (InlinePrimitive [Verilog] $ unindent [i|
[ { "BlackBox" :
{ "name" : "Ice40.IO.ioPrim"
, "kind" : "Declaration"
, "type" :
"ioPrim
:: BitVector 6 -- ARG[0] pinType
-> Bit -- ARG[1] pullup
-> Bit -- ARG[2] negTrigger
-> String -- ARG[3] ioStandard
-> Signal domIn Bit -- ARG[4] latchInputValue
-> Signal domEn Bit -- ARG[5] clockEnable
-> Clock domIn -- ARG[6] inputClk
-> Clock domOut -- ARG[7] outputClk
-> Signal domOut Bit -- ARG[8] outputEnable
-> Signal domOut Bit -- ARG[9] dOut0
-> Signal domOut Bit -- ARG[10] dOut1
-> ( Signal domPin Bit -- packagePin
, Signal domIn Bit -- dIn0
, Signal domIn Bit -- dIn1
)"
, "template" :
"//SB_IO begin
wire ~GENSYM[package_pin][0];
wire ~GENSYM[d_in_0][1];
wire ~GENSYM[d_in_1][2];
SB_IO #(
.PIN_TYPE ( ~ARG[0] ),
.PULLUP ( ~ARG[1] ),
.NEG_TRIGGER ( ~ARG[2] ),
.IO_STANDARD ( ~ARG[3] )
) ~GENSYM[sb_io_inst][3] (
.PACKAGE_PIN ( ~SYM[0] ),
.LATCH_INPUT_VALUE( ~ARG[4] ),
.CLOCK_ENABLE ( ~ARG[5] ),
.INPUT_CLK ( ~ARG[6] ),
.OUTPUT_CLK ( ~ARG[7] ),
.OUTPUT_ENABLE ( ~ARG[8] ),
.D_OUT_0 ( ~ARG[9] ),
.D_OUT_1 ( ~ARG[10] ),
.D_IN_0 ( ~SYM[1] ),
.D_IN_1 ( ~SYM[2] )
);
assign ~RESULT = { ~SYM[0], ~SYM[1], ~SYM[2] };
//SB_IO end"
}
}
]
|]) #-}
-- | IO primitive, see io for wrapper
{-# NOINLINE ioPrim #-}
ioPrim
:: BitVector 6 -- ^ pinType
-> Bit -- ^ pullup
-> Bit -- ^ negTrigger
-> String -- ^ ioStandard
-> Signal domIn Bit -- ^ latchInputValue
-> Signal domEn Bit -- ^ clockEnable
-> Clock domIn -- ^ inputClk
-> Clock domOut -- ^ outputClk
-> Signal domOut Bit -- ^ outputEnable
-> Signal domOut Bit -- ^ dOut0
-> Signal domOut Bit -- ^ dOut1
-> ( Signal domPin Bit -- packagePin
, Signal domIn Bit -- dIn0
, Signal domIn Bit -- dIn1
) -- ^ (packagePin, dIn0, dIn1)
ioPrim !_ !_ !_ !_ !_ !_ !_ !_ !_ !_ !_ = (pure 0, pure 0, pure 0)
-- | Input pin configuration parameter
data PinInput = PinInput -- ^ Simple Input pin dIn0
| PinInputLatch -- ^ Disables Internal data changes on the physical input pin by latching the value
| PinInputRegistered -- ^ Input data is registered in input cell
| PinInputRegisteredLatch -- ^ Disables internal data changes on the physical input pin by latching the value on the input register
| PinInputDDR -- ^ Input DDR data is clocked out on rising and falling clock edges. Use the dIn0 and dIn1 pins for DDR operation
deriving stock (Generic, Show, Read, Eq)
deriving anyclass NFDataX
fromPinInput :: PinInput -> BitVector 2
fromPinInput = \case
PinInput -> 0b01
PinInputLatch -> 0b11
PinInputRegistered -> 0b00
PinInputRegisteredLatch -> 0b10
PinInputDDR -> 0b00
-- | Output pin configuration parameter
data PinOutput = PinNoOutput -- ^Disables the output function
| PinOutput -- ^ Simple output pin (no enable)
| PinOutputTristate -- ^ The output pin may be tristated using the enable
| PinOutputEnableRegistered -- ^ The output pin may be tristated using a registered enable signal
| PinOutputRegistered -- ^ Output registered (no enable)
| PinOutputRegisteredEnable -- ^ Output registered with enable (the enable is not registered)
| PinOutputRegisteredEnableRegistered -- ^ Output registered and enable registered
| PinOutputDDR -- ^ Output DDR data is clocked out on rising and falling clock edges
| PinOutputDDREnable -- ^ Output data is clocked out on rising and falling clock edges
| PinOutputDDREnableRegistered -- ^ Output DDR data with registered enable signal
| PinOutputRegisteredInverted -- ^ Output registered signal is inverted
| PinOutputRegisteredEnableInverted -- ^ Output signal is registered and inverted (no enable function)
| PinOutputRegisteredEnableRegisteredInverted -- ^ Output signal is registered and inverted, the enable/tristate control is registered
deriving stock (Generic, Show, Read, Eq)
deriving anyclass NFDataX
fromPinOutput :: PinOutput -> BitVector 4
fromPinOutput = \case
PinNoOutput -> 0b0000
PinOutput -> 0b0110
PinOutputTristate -> 0b1010
PinOutputEnableRegistered -> 0b1110
PinOutputRegistered -> 0b0101
PinOutputRegisteredEnable -> 0b1001
PinOutputRegisteredEnableRegistered -> 0b1101
PinOutputDDR -> 0b0100
PinOutputDDREnable -> 0b1000
PinOutputDDREnableRegistered -> 0b1100
PinOutputRegisteredInverted -> 0b0111
PinOutputRegisteredEnableInverted -> 0b1011
PinOutputRegisteredEnableRegisteredInverted -> 0b1111
-- | Input-Output Standards
data IOStandard = SBLVCMOS
| SBLVDSINPUT
deriving (Generic, Show, Read, Eq)
fromIOStandard :: IOStandard -> String
fromIOStandard = \case
SBLVCMOS -> "SB_LVCMOS"
SBLVDSINPUT -> "SB_LVDS_INPUT"
-- | IO primitive
io
:: PinInput
-> PinOutput
-> Bit -- ^ pullUp
-> Bit -- ^ negTrigger
-> IOStandard
-> Signal domIn Bit -- ^ latchInputValue
-> Signal domEn Bit -- ^ clockEnable
-> Clock domIn -- ^ inputClk
-> Clock domOut -- ^ outputClk
-> Signal domOut Bit -- ^ outputEnable
-> Signal domOut Bit -- ^ dOut0
-> Signal domOut Bit -- ^ dOut1
-> ( Signal domPin Bit -- packagePin
, Signal domIn Bit -- dIn0
, Signal domIn Bit -- dIn1
) -- ^ (packagePin, dIn0, dIn1)
io pinInput pinOutput pullUp negTrigger ioStandard
= ioPrim
(fromPinOutput pinOutput ++# fromPinInput pinInput)
pullUp
negTrigger
(fromIOStandard ioStandard)