ice40-prim (empty) → 0.1.0.0
raw patch · 14 files changed
+1573/−0 lines, 14 filesdep +Cabaldep +basedep +clash-preludesetup-changed
Dependencies added: Cabal, base, clash-prelude, ghc-typelits-extra, ghc-typelits-knownnat, ghc-typelits-natnormalise, interpolate
Files
- CHANGELOG.md +5/−0
- LICENSE +29/−0
- README.md +74/−0
- Setup.hs +2/−0
- ice40-prim.cabal +89/−0
- src/Ice40/Clock.hs +36/−0
- src/Ice40/I2c.hs +231/−0
- src/Ice40/IO.hs +173/−0
- src/Ice40/Led.hs +140/−0
- src/Ice40/Mac.hs +187/−0
- src/Ice40/Osc.hs +130/−0
- src/Ice40/Rgb.hs +95/−0
- src/Ice40/Spi.hs +285/−0
- src/Ice40/Spram.hs +97/−0
+ CHANGELOG.md view
@@ -0,0 +1,5 @@+# Revision history for ice40-prim++## 0.1.0.0 -- 2021-02-15++* First version.
+ LICENSE view
@@ -0,0 +1,29 @@+BSD 3-Clause License++Copyright (c) 2020, dopamane+All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are met:++1. Redistributions of source code must retain the above copyright notice, this+ list of conditions and the following disclaimer.++2. Redistributions in binary form must reproduce the above copyright notice,+ this list of conditions and the following disclaimer in the documentation+ and/or other materials provided with the distribution.++3. Neither the name of the copyright holder nor the names of its+ contributors may be used to endorse or promote products derived from+ this software without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ README.md view
@@ -0,0 +1,74 @@+# ice40-prim+++Lattice iCE40 Primitive IP+## Supported IP Modules+* [Ice40.Spram](https://github.com/standardsemiconductor/ice40-prim/blob/main/src/Ice40/Spram.hs) - For more information see the [iCE40 SPRAM Usage Guide](https://github.com/standardsemiconductor/VELDT-info/blob/master/FPGA-TN-02022-1-2-iCE40-SPRAM-Usage-Guide.pdf)+ * sysMem Single Port RAM Memory (SPRAM)+ * Each block of SPRAM is 16k x 16 (256 kbits)+ * 16-bit data width with nibble mast control+ * Cascadable design for deeper/wider SPRAM+ * Three power modes, standby, sleep, and power off++* [Ice40.Mac](https://github.com/standardsemiconductor/ice40-prim/blob/main/src/Ice40/Mac.hs) - For more information see the [DSP Function Usage Guide PDF](https://github.com/standardsemiconductor/VELDT-info/blob/master/DSPFunctionUsageGuideforICE40Devices.pdf)+ * 16-bit x 16-bit Multiplier, or two independent 8-bit x 8-bit multipliers+ * Optional independent pipeline control on input Register, Output Register, and Intermediate Register for faster clock performance+ * 32-bit accumulator, or two independent 16-bit accumulators+ * 32-bit, or two independent 16-bit adder/subtractor functions, registered or asynchronous+ * Cascadable to create wider accumulator blocks++* [Ice40.Osc](https://github.com/standardsemiconductor/ice40-prim/blob/main/src/Ice40/Osc.hs)+ * on-chip oscillator+ * Low-power low frequency oscillator of 10 kHz+ * High frequency oscillator configurable to 48 Mhz, 24 Mhz, 12 Mhz, or 6 Mhz+ * See also [Ice40.Clock](https://github.com/standardsemiconductor/ice40-prim/blob/main/src/Ice40/Clock.hs) for clock domains and reset++* [Ice40.Rgb](https://github.com/standardsemiconductor/ice40-prim/blob/main/src/Ice40/Rgb.hs) - For more information see the [iCE40 LED Driver Usage Guide](https://github.com/standardsemiconductor/VELDT-info/blob/master/ICE40LEDDriverUsageGuide.pdf)+ * RGB High Current Drive I/O Pins+ * Provides sinking current to an LED connecting to the positive supply+ * Three outputs designed to drive the RGB LEDs+ * RGB drive current is user programmable from 4mA to 24mA, in increments of 4mA++* [Ice40.Led](https://github.com/standardsemiconductor/ice40-prim/blob/main/src/Ice40/Led.hs) - For more information see the [iCE40 LED Driver Usage Guide PDF](https://github.com/standardsemiconductor/VELDT-info/blob/master/ICE40LEDDriverUsageGuide.pdf)+ * LED PWM IP+ * Provide easier usage of RGB high current drivers+ * Provides flexibility for user to dynamically change the modulation width of each of the RGB LED driver+ * User can dynamically change ON and OFF-time durations+ * Ability to turn LEDs on and off gradually with breath-on and breath-off time++* [Ice40.Spi](https://github.com/standardsemiconductor/ice40-prim/blob/main/src/Ice40/Spi.hs) - For more information see the [Advanced SPI and I2C Usage Guide PDF](https://github.com/standardsemiconductor/VELDT-info/blob/master/AdvancediCE40SPII2CHardenedIPUsageGuide.pdf)+ * User SPI IP+ * Configurable Boss and Worker modes+ * Full-Duplex data transfer+ * Mode fault error flag with CPU interrupt capability+ * Double-buffered data register+ * Serial clock with programmable polarity and phase+ * LSB First or MSB First data transfer++* [Ice40.IO](https://github.com/standardsemiconductor/ice40-prim/blob/main/src/Ice40/IO.hs)+ * sysIO++* [Ice40.I2c](https://github.com/standardsemiconductor/ice40-prim/blob/main/src/Ice40/I2c.hs) - For more information see the [Advanced SPI and I2C Usage Guide PDF](https://github.com/standardsemiconductor/VELDT-info/blob/master/AdvancediCE40SPII2CHardenedIPUsageGuide.pdf)+ * User I2C IP+ * Boss and Worker operation+ * 7-bit and 10-bit addressing+ * Multi-master arbitration support+ * Clock stretching+ * Up to 400 kHz data transfer speed+ * General Call support+ * Optionally delaying input or output data, or both+ * Optional filter on SCL input++## Lattice Documentation++[iCE40 UltraPlus Family Data Sheet PDF](https://github.com/standardsemiconductor/VELDT-info/blob/master/FPGA-DS-02008-1-9-iCE40-UltraPlus-Family-Data-Sheet.pdf)++[iCE Technology Library PDF](https://github.com/standardsemiconductor/VELDT-info/blob/master/SBTICETechnologyLibrary201708.pdf)++[Advanced SPI and I2C Usage Guide PDF](https://github.com/standardsemiconductor/VELDT-info/blob/master/AdvancediCE40SPII2CHardenedIPUsageGuide.pdf)++[iCE40 LED Driver Usage Guide PDF](https://github.com/standardsemiconductor/VELDT-info/blob/master/ICE40LEDDriverUsageGuide.pdf)++[iCE40 SPRAM Usage Guide](https://github.com/standardsemiconductor/VELDT-info/blob/master/FPGA-TN-02022-1-2-iCE40-SPRAM-Usage-Guide.pdf)++[DSP Function Usage Guide PDF](https://github.com/standardsemiconductor/VELDT-info/blob/master/DSPFunctionUsageGuideforICE40Devices.pdf)
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ ice40-prim.cabal view
@@ -0,0 +1,89 @@+cabal-version: >=1.10+name: ice40-prim+version: 0.1.0.0+synopsis: Lattice iCE40 Primitive IP+description: Clash primitives to instantiate Lattice Semiconductor's iCE40 FPGA hard IP+bug-reports: https://github.com/standardsemiconductor/ice40-prim/issues+license: BSD3+license-file: LICENSE+author: dopamane+maintainer: dopamane <standard.semiconductor@gmail.com>+copyright: Copyright (c) 2020-2021 David Cox+category: Hardware+build-type: Simple+extra-source-files: CHANGELOG.md, README.md++source-repository head+ type: git+ location: git://github.com/standardsemiconductor/ice40-prim.git+ +library+ exposed-modules: Ice40.Clock,+ Ice40.Led,+ Ice40.Mac,+ Ice40.Osc,+ Ice40.Spram,+ Ice40.Rgb,+ Ice40.Spi,+ Ice40.I2c,+ Ice40.IO+ hs-source-dirs: src+ build-depends: base >=4.12 && <4.15,+ Cabal,+ interpolate,+ clash-prelude >=1.2.5 && <1.4,+ ghc-typelits-natnormalise,+ ghc-typelits-extra,+ ghc-typelits-knownnat+ ghc-options:+ -Wall -Wcompat+ -haddock++ -- Plugins to support type-level constraint solving on naturals+ -fplugin GHC.TypeLits.Extra.Solver+ -fplugin GHC.TypeLits.Normalise+ -fplugin GHC.TypeLits.KnownNat.Solver++ -- Worker wrappers introduce unstable names for functions that might+ -- have blackboxes attached for them. You can disable this,+ -- but be sure to add a no-specialize pragma to every function+ -- with a blackbox.+ -fno-worker-wrapper+ default-language: Haskell2010+ default-extensions:+ BangPatterns+ BinaryLiterals+ ConstraintKinds+ DataKinds+ DefaultSignatures+ DeriveAnyClass+ DeriveDataTypeable+ DeriveFoldable+ DeriveFunctor+ DeriveGeneric+ DeriveLift+ DeriveTraversable+ DerivingStrategies+ InstanceSigs+ KindSignatures+ LambdaCase+ NoStarIsType+ MagicHash+ PolyKinds+ RankNTypes+ RecordWildCards+ ScopedTypeVariables+ StandaloneDeriving+ TupleSections+ TypeApplications+ TypeFamilies+ TypeOperators+ ViewPatterns+ + -- TemplateHaskell is used to support convenience functions such as+ -- 'listToVecTH' and 'bLit'.+ TemplateHaskell+ QuasiQuotes++ -- Prelude isn't imported by default as Clash offers Clash.Prelude+ NoImplicitPrelude
+ src/Ice40/Clock.hs view
@@ -0,0 +1,36 @@+{-|+Module : Ice40.Clock+Description : Ice40 Clock domains+Copyright : (c) David Cox, 2021+License : BSD 3-Clause+Maintainer : standardsemiconductor@gmail.com++Commonly used clock domains with ice40 IP+-}++{-# OPTIONS_GHC -fno-warn-orphans #-}+module Ice40.Clock+ ( vLattice10kHz+ , Lattice10kHz+ , vLattice48Mhz+ , vLattice24Mhz+ , vLattice12Mhz+ , vLattice6Mhz+ , Lattice48Mhz+ , Lattice24Mhz+ , Lattice12Mhz+ , Lattice6Mhz+ , latticeRst+ ) where++import Clash.Prelude++createDomain vXilinxSystem{vName="Lattice10kHz", vPeriod=100000000}+createDomain vXilinxSystem{vName="Lattice48Mhz", vPeriod=20833}+createDomain vXilinxSystem{vName="Lattice24Mhz", vPeriod=41666}+createDomain vXilinxSystem{vName="Lattice12Mhz", vPeriod=83333}+createDomain vXilinxSystem{vName="Lattice6Mhz", vPeriod=166660}++-- | Lattice reset signal, always inactive+latticeRst :: KnownDomain dom => Reset dom+latticeRst = unsafeFromHighPolarity $ pure False
+ src/Ice40/I2c.hs view
@@ -0,0 +1,231 @@+{-|+Module : Ice40.I2c+Description : Ice40 I2C hard IP primitive+Copyright : (c) David Cox, 2021+License : BSD 3-Clause+Maintainer : standardsemiconductor@gmail.com++I2C hard IP primitive from Lattice Ice Technology Library https://github.com/standardsemiconductor/VELDT-info/blob/master/SBTICETechnologyLibrary201708.pdf+-}+module Ice40.I2c ( i2c ) where++import Clash.Prelude+import Clash.Annotations.Primitive+import Data.String.Interpolate (i)+import Data.String.Interpolate.Util (unindent)++{-# ANN i2cPrim (InlinePrimitive [Verilog] $ unindent [i|+ [ { "BlackBox" :+ { "name" : "Ice40.I2c.i2cPrim"+ , "kind" : "Declaration"+ , "type" :+ "i2cPrim+ :: String -- ARG[0] initAddr+ -> String -- ARG[1] busAddr+ -> Clock dom -- ARG[2] sbclki+ -> Signal dom Bool -- ARG[3] sbrwi+ -> Signal dom Bool -- ARG[4] sbstbi+ -> Signal dom Bit -- ARG[5] sbadri7+ -> Signal dom Bit -- ARG[6] sbadri6+ -> Signal dom Bit -- ARG[7] sbadri5+ -> Signal dom Bit -- ARG[8] sbadri4+ -> Signal dom Bit -- ARG[9] sbadri3+ -> Signal dom Bit -- ARG[10] sbadri2+ -> Signal dom Bit -- ARG[11] sbadri1+ -> Signal dom Bit -- ARG[12] sbadri0+ -> Signal dom Bit -- ARG[13] sbdati7+ -> Signal dom Bit -- ARG[14] sbdati6+ -> Signal dom Bit -- ARG[15] sbdati5+ -> Signal dom Bit -- ARG[16] sbdati4+ -> Signal dom Bit -- ARG[17] sbdati3+ -> Signal dom Bit -- ARG[18] sbdati2+ -> Signal dom Bit -- ARG[19] sbdati1+ -> Signal dom Bit -- ARG[20] sbdati0+ -> Signal dom Bit -- ARG[21] scli+ -> Signal dom Bit -- ARG[22] sdai+ -> Unbundled dom+ ( BitVector 8 -- sbdato+ , Bool -- sbacko+ , Bit -- i2cirq+ , Bit -- i2cwkup+ , Bit -- sclo+ , Bit -- scloe+ , Bit -- sdao+ , Bit -- sdaoe+ )"+ , "template" :+ "//SB_I2C begin+ wire ~GENSYM[sbdato7][0];+ wire ~GENSYM[sbdato6][1];+ wire ~GENSYM[sbdato5][2];+ wire ~GENSYM[sbdato4][3];+ wire ~GENSYM[sbdato3][4];+ wire ~GENSYM[sbdato2][5];+ wire ~GENSYM[sbdato1][6];+ wire ~GENSYM[sbdato0][7];+ wire ~GENSYM[sbacko][8];+ wire ~GENSYM[i2cirq][9];+ wire ~GENSYM[i2cwkup][10];+ wire ~GENSYM[sclo][11];+ wire ~GENSYM[scloe][12];+ wire ~GENSYM[sdao][13];+ wire ~GENSYM[sdaoe][14];++ SB_I2C #(+ .I2C_SLAVE_INIT_ADDR ( ~ARG[0] ),+ .BUS_ADDR74 ( ~ARG[1] )+ ) ~GENSYM[sb_i2c_inst][15] (+ .SBCLKI ( ~ARG[2] ),+ .SBRWI ( ~ARG[3] ),+ .SBSTBI ( ~ARG[4] ),+ .SBADRI7 ( ~ARG[5] ),+ .SBADRI6 ( ~ARG[6] ),+ .SBADRI5 ( ~ARG[7] ),+ .SBADRI4 ( ~ARG[8] ),+ .SBADRI3 ( ~ARG[9] ),+ .SBADRI2 ( ~ARG[10] ),+ .SBADRI1 ( ~ARG[11] ),+ .SBADRI0 ( ~ARG[12] ),+ .SBDATI7 ( ~ARG[13] ),+ .SBDATI6 ( ~ARG[14] ),+ .SBDATI5 ( ~ARG[15] ),+ .SBDATI4 ( ~ARG[16] ),+ .SBDATI3 ( ~ARG[17] ),+ .SBDATI2 ( ~ARG[18] ),+ .SBDATI1 ( ~ARG[19] ),+ .SBDATI0 ( ~ARG[20] ),+ .SCLI ( ~ARG[21] ),+ .SDAI ( ~ARG[22] ),+ .SBDATO7 ( ~SYM[0] ),+ .SBDATO6 ( ~SYM[1] ),+ .SBDATO5 ( ~SYM[2] ),+ .SBDATO4 ( ~SYM[3] ),+ .SBDATO3 ( ~SYM[4] ),+ .SBDATO2 ( ~SYM[5] ),+ .SBDATO1 ( ~SYM[6] ),+ .SBDATO0 ( ~SYM[7] ),+ .SBACKO ( ~SYM[8] ),+ .I2CIRQ ( ~SYM[9] ),+ .I2CWKUP ( ~SYM[10] ),+ .SCLO ( ~SYM[11] ),+ .SCLOE ( ~SYM[12] ),+ .SDAO ( ~SYM[13] ),+ .SDAOE ( ~SYM[14] )+ );++ assign ~RESULT = { ~SYM[0] // sbdato7+ , ~SYM[1] // sbdato6+ , ~SYM[2] // sbdato5+ , ~SYM[3] // sbdato4+ , ~SYM[4] // sbdato3+ , ~SYM[5] // sbdato2+ , ~SYM[6] // sbdato1+ , ~SYM[7] // sbdato0+ , ~SYM[8] // sbacko+ , ~SYM[9] // i2cirq+ , ~SYM[10] // i2cwkup+ , ~SYM[11] // sclo+ , ~SYM[12] // scloe+ , ~SYM[13] // sdao+ , ~SYM[14] // sdaoe+ };+ //SB_I2C end"+ }+ }+ ]+ |]) #-}++{-# NOINLINE i2cPrim #-}+i2cPrim+ :: String -- ARG[0] initAddr+ -> String -- ARG[1] busAddr+ -> Clock dom -- ARG[2] sbclki+ -> Signal dom Bool -- ARG[3] sbrwi+ -> Signal dom Bool -- ARG[4] sbstbi+ -> Signal dom Bit -- ARG[5] sbadri7+ -> Signal dom Bit -- ARG[6] sbadri6+ -> Signal dom Bit -- ARG[7] sbadri5+ -> Signal dom Bit -- ARG[8] sbadri4+ -> Signal dom Bit -- ARG[9] sbadri3+ -> Signal dom Bit -- ARG[10] sbadri2+ -> Signal dom Bit -- ARG[11] sbadri1+ -> Signal dom Bit -- ARG[12] sbadri0+ -> Signal dom Bit -- ARG[13] sbdati7+ -> Signal dom Bit -- ARG[14] sbdati6+ -> Signal dom Bit -- ARG[15] sbdati5+ -> Signal dom Bit -- ARG[16] sbdati4+ -> Signal dom Bit -- ARG[17] sbdati3+ -> Signal dom Bit -- ARG[18] sbdati2+ -> Signal dom Bit -- ARG[19] sbdati1+ -> Signal dom Bit -- ARG[20] sbdati0+ -> Signal dom Bit -- ARG[21] scli+ -> Signal dom Bit -- ARG[22] sdai+ -> Unbundled dom+ ( BitVector 8 -- sbdato+ , Bool -- sbacko+ , Bit -- i2cirq+ , Bit -- i2cwkup+ , Bit -- sclo+ , Bit -- scloe+ , Bit -- sdao+ , Bit -- sdaoe+ )+i2cPrim !_ !_ !_ !_ !_ !_ !_ !_ !_ !_ !_ !_ !_ !_ !_ !_ !_ !_ !_ !_ !_ !_ !_+ = unbundle $ pure ( 0+ , False+ , 0+ , 0+ , 0+ , 0+ , 0+ , 0+ )++-- | I2C primitive wrapper+i2c+ :: HiddenClock dom+ => String -- ^ initAddr+ -> String -- ^ busAddr+ -> Signal dom Bool -- ^ sbrwi+ -> Signal dom Bool -- ^ sbstbi+ -> Signal dom (BitVector 8) -- ^ sbadri+ -> Signal dom (BitVector 8) -- ^ sbdati+ -> Signal dom Bit -- ^ scli+ -> Signal dom Bit -- ^ sdai+ -> Unbundled dom+ ( BitVector 8 -- sbdato+ , Bool -- sbacko+ , Bit -- i2cirq+ , Bit -- i2cwkup+ , Bit -- sclo+ , Bit -- scloe+ , Bit -- sdao+ , Bit -- sdaoe+ ) -- ^ (sbdato, sbacko, i2cirq, i2cwkup, sclo, scloe, sdao, sdaoe)+i2c initAddr busAddr sbrwi sbstbi sbadri sbdati scli sdai =+ i2cPrim initAddr+ busAddr+ hasClock+ sbrwi+ sbstbi+ (bitAt 7 sbadri)+ (bitAt 6 sbadri)+ (bitAt 5 sbadri)+ (bitAt 4 sbadri)+ (bitAt 3 sbadri)+ (bitAt 2 sbadri)+ (bitAt 1 sbadri)+ (bitAt 0 sbadri)+ (bitAt 7 sbdati)+ (bitAt 6 sbdati)+ (bitAt 5 sbdati)+ (bitAt 4 sbdati)+ (bitAt 3 sbdati)+ (bitAt 2 sbdati)+ (bitAt 1 sbdati)+ (bitAt 0 sbdati)+ scli+ sdai++bitAt :: KnownNat n => Index n -> Signal dom (BitVector n) -> Signal dom Bit+bitAt n = fmap (!n)
+ src/Ice40/IO.hs view
@@ -0,0 +1,173 @@+{-|+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)+
+ src/Ice40/Led.hs view
@@ -0,0 +1,140 @@+{-|+Module : Ice40.Led+Description : LED Ice40 hard IP primitive+Copyright : (c) David Cox, 2021+License : BSD 3-Clause+Maintainer : standardsemiconductor@gmail.com++LED hard IP primitive from Lattice Ice Technology Library https://github.com/standardsemiconductor/VELDT-info/blob/master/SBTICETechnologyLibrary201708.pdf+-}+module Ice40.Led ( led ) where++import Clash.Prelude+import Clash.Annotations.Primitive+import Data.String.Interpolate (i)+import Data.String.Interpolate.Util (unindent)++{-# ANN ledPrim (InlinePrimitive [Verilog] $ unindent [i|+ [ { "BlackBox" :+ { "name" : "Ice40.Led.ledPrim"+ , "kind" : "Declaration"+ , "type" :+ "ledPrim+ :: Signal dom Bit -- ARG[0] leddcs+ -> Clock dom -- ARG[1] leddclk+ -> Signal dom Bit -- ARG[2] ledddat7+ -> Signal dom Bit -- ARG[3] ledddat6+ -> Signal dom Bit -- ARG[4] ledddat5+ -> Signal dom Bit -- ARG[5] ledddat4+ -> Signal dom Bit -- ARG[6] ledddat3+ -> Signal dom Bit -- ARG[7] ledddat2+ -> Signal dom Bit -- ARG[8] ledddat1+ -> Signal dom Bit -- ARG[9] ledddat0+ -> Signal dom Bit -- ARG[10] leddaddr3+ -> Signal dom Bit -- ARG[11] leddaddr2+ -> Signal dom Bit -- ARG[12] leddaddr1+ -> Signal dom Bit -- ARG[13] leddaddr0+ -> Signal dom Bool -- ARG[14] leddden+ -> Signal dom Bool -- ARG[15] leddexe+ -> Unbundled dom ( Bit -- pwmOut0+ , Bit -- pwmOut1+ , Bit -- pwmOut2+ , Bool -- leddon+ )"+ , "template" :+ "//SB_LEDDA_IP begin+ wire ~GENSYM[pwmOut0][0];+ wire ~GENSYM[pwmOut1][1];+ wire ~GENSYM[pwmOut2][2];+ wire ~GENSYM[leddon][3];++ SB_LEDDA_IP SB_LEDDA_IP_INST (+ .LEDDCS ( ~ARG[0] ),+ .LEDDCLK ( ~ARG[1] ),+ .LEDDDAT7 ( ~ARG[2] ),+ .LEDDDAT6 ( ~ARG[3] ),+ .LEDDDAT5 ( ~ARG[4] ),+ .LEDDDAT4 ( ~ARG[5] ),+ .LEDDDAT3 ( ~ARG[6] ),+ .LEDDDAT2 ( ~ARG[7] ),+ .LEDDDAT1 ( ~ARG[8] ),+ .LEDDDAT0 ( ~ARG[9] ),+ .LEDDADDR3 ( ~ARG[10] ),+ .LEDDADDR2 ( ~ARG[11] ),+ .LEDDADDR1 ( ~ARG[12] ),+ .LEDDADDR0 ( ~ARG[13] ),+ .LEDDDEN ( ~ARG[14] ),+ .LEDDEXE ( ~ARG[15] ),++ .PWMOUT0 ( ~SYM[0] ),+ .PWMOUT1 ( ~SYM[1] ),+ .PWMOUT2 ( ~SYM[2] ),+ .LEDDON ( ~SYM[3] )+ );++ assign ~RESULT = {~SYM[0], ~SYM[1], ~SYM[2], ~SYM[3]};+ //SB_LEDDA_IP end"+ }+ }+ ]+ |]) #-}++{-# NOINLINE ledPrim #-}+ledPrim+ :: Signal dom Bit -- ARG[0] leddcs - CS to write LEDD IP registers+ -> Clock dom -- ARG[1] leddclk - Clock to write LEDD IP registers+ -> Signal dom Bit -- ARG[2] ledddat7 - bit 7 data to write into the LEDD IP registers+ -> Signal dom Bit -- ARG[3] ledddat6 - bit 6 data to write into the LEDD IP registers+ -> Signal dom Bit -- ARG[4] ledddat5 - bit 5 data to write into the LEDD IP registers+ -> Signal dom Bit -- ARG[5] ledddat4 - bit 4 data to write into the LEDD IP registers+ -> Signal dom Bit -- ARG[6] ledddat3 - bit 3 data to write into the LEDD IP registers+ -> Signal dom Bit -- ARG[7] ledddat2+ -> Signal dom Bit -- ARG[8] ledddat1+ -> Signal dom Bit -- ARG[9] ledddat0+ -> Signal dom Bit -- ARG[10] leddaddr3+ -> Signal dom Bit -- ARG[11] leddaddr2+ -> Signal dom Bit -- ARG[12] leddaddr1+ -> Signal dom Bit -- ARG[13] leddaddr0+ -> Signal dom Bool -- ARG[14] leddden+ -> Signal dom Bool -- ARG[15] leddexe+ -> Unbundled dom ( Bit -- pwmOut0+ , Bit -- pwmOut1+ , Bit -- pwmOut2+ , Bool -- leddon+ )+ledPrim !_ !_ !_ !_ !_ !_ !_ !_ !_ !_ !_ !_ !_ !_ !_ !_ = (pure 0, pure 0, pure 0, pure False)++-- | SB_LEDDA_IP primitive generates the RGB PWM outputs for the RGB LED drivers. The IP contains registers that are programmed in byte the SCI bus interface signals.+led+ :: HiddenClock dom+ => Signal dom Bit -- ^ cs - CS to write LEDD IP registers+ -> Signal dom (BitVector 8) -- ^ dat - data to write into the LEDD IP registers+ -> Signal dom (BitVector 4) -- ^ addr - LEDD IP register address+ -> Signal dom Bool -- ^ en - data enable input to indicate data and address are stable+ -> Signal dom Bool -- ^ exe - enable to IP to run the blinking sequence. When it is LOW, the sequence stops at the nearest OFF state+ -> Unbundled dom ( Bit + , Bit + , Bit + , Bool+ ) -- ^ (pwmOut0, pwmOut1, pwmOut2, LED on indicator)+led cs dat addr en exe = (pwmOut0, pwmOut1, pwmOut2, on)+ where+ (pwmOut0, pwmOut1, pwmOut2, on) = ledPrim cs+ hasClock+ (bitAt 7 dat)+ (bitAt 6 dat)+ (bitAt 5 dat)+ (bitAt 4 dat)+ (bitAt 3 dat)+ (bitAt 2 dat)+ (bitAt 1 dat)+ (bitAt 0 dat)+ (bitAt 3 addr)+ (bitAt 2 addr)+ (bitAt 1 addr)+ (bitAt 0 addr)+ en+ exe++bitAt :: KnownNat n => Index n -> Signal dom (BitVector n) -> Signal dom Bit+bitAt n = fmap (!n)
+ src/Ice40/Mac.hs view
@@ -0,0 +1,187 @@+{-|+Module : Ice40.Mac+Description : Ice40 Multiply-Accumulate (DSP) hard IP primitive+Copyright : (c) David Cox, 2021+License : BSD 3-Clause+Maintainer : standardsemiconductor@gmail.com++Mac hard IP primitive from Lattice Ice Technology Library https://github.com/standardsemiconductor/VELDT-info/blob/master/SBTICETechnologyLibrary201708.pdf+-}+module Ice40.Mac ( macPrim ) where++import Clash.Prelude+import Clash.Annotations.Primitive+import Data.String.Interpolate (i)+import Data.String.Interpolate.Util (unindent)++{-# ANN macPrim (InlinePrimitive [Verilog] $ unindent [i|+ [ { "BlackBox" :+ { "name" : "Ice40.Mac.macPrim"+ , "kind" : "Declaration"+ , "type" :+ "macPrim+ :: Bit -- ARG[0] negTrigger+ -> Bit -- ARG[1] aReg+ -> Bit -- ARG[2] bReg+ -> Bit -- ARG[3] cReg+ -> Bit -- ARG[4] dReg+ -> Bit -- ARG[5] top8x8MultReg+ -> Bit -- ARG[6] bot8x8MultReg+ -> Bit -- ARG[7] pipeline16x16MultReg1+ -> Bit -- ARG[8] pipeline16x16MultReg2+ -> BitVector 2 -- ARG[9] topOutputSelect+ -> BitVector 2 -- ARG[10] topAddSubLowerInput+ -> Bit -- ARG[11] topAddSubUpperInput+ -> BitVector 2 -- ARG[12] topAddSubCarrySelect+ -> BitVector 2 -- ARG[13] botOutputSelect+ -> BitVector 2 -- ARG[14] botAddSubLowerInput+ -> Bit -- ARG[15] botAddSubUpperInput+ -> BitVector 2 -- ARG[16] botAddSubCarrySelect+ -> Bit -- ARG[17] mode8x8+ -> Bit -- ARG[18] aSigned+ -> Bit -- ARG[19] bSigned+ -> Clock dom -- ARG[20] clk+ -> Signal dom Bit -- ARG[21] ce+ -> Signal dom (BitVector 16) -- ARG[22] c+ -> Signal dom (BitVector 16) -- ARG[23] a+ -> Signal dom (BitVector 16) -- ARG[24] b+ -> Signal dom (BitVector 16) -- ARG[25] d+ -> Signal dom Bit -- ARG[26] irsttop+ -> Signal dom Bit -- ARG[27] irstbot+ -> Signal dom Bit -- ARG[28] orsttop+ -> Signal dom Bit -- ARG[29] orstbot+ -> Signal dom Bit -- ARG[30] ahold+ -> Signal dom Bit -- ARG[31] bhold+ -> Signal dom Bit -- ARG[32] chold+ -> Signal dom Bit -- ARG[33] dhold+ -> Signal dom Bit -- ARG[34] oholdtop+ -> Signal dom Bit -- ARG[35] oholdbot+ -> Signal dom Bit -- ARG[36] addsubtop+ -> Signal dom Bit -- ARG[37] addsubbot+ -> Signal dom Bit -- ARG[38] oloadtop+ -> Signal dom Bit -- ARG[39] oloadbot+ -> Signal dom Bit -- ARG[40] accumci+ -> Signal dom Bit -- ARG[41] signextin+ -> Signal dom Bit -- ARG[42] ci+ -> ( Signal dom (BitVector 32) -- o[31:0]+ , Signal dom Bit -- co+ , Signal dom Bit -- accumco+ , Signal dom Bit -- signextout+ )"+ , "template" :+ "//SB_MAC16 begin+ wire [31:0] ~GENSYM[o][0];+ wire ~GENSYM[co][1];+ wire ~GENSYM[accumco][2];+ wire ~GENSYM[signextout][3];++ SB_MAC16 #(+ .NEG_TRIGGER(~ARG[0]),+ .C_REG(~ARG[3]),+ .A_REG(~ARG[1]),+ .B_REG(~ARG[2]),+ .D_REG(~ARG[4]),+ .TOP_8x8_MULT_REG(~ARG[5]),+ .BOT_8x8_MULT_REG(~ARG[6]),+ .PIPELINE_16x16_MULT_REG1(~ARG[7]),+ .PIPELINE_16x16_MULT_REG2(~ARG[8]),+ .TOPOUTPUT_SELECT(~ARG[9]),+ .TOPADDSUB_LOWERINPUT(~ARG[10]),+ .TOPADDSUB_UPPERINPUT(~ARG[11]),+ .TOPADDSUB_CARRYSELECT(~ARG[12]),+ .BOTOUTPUT_SELECT(~ARG[13]),+ .BOTADDSUB_LOWERINPUT(~ARG[14]),+ .BOTADDSUB_UPPERINPUT(~ARG[15]),+ .BOTADDSUB_CARRYSELECT(~ARG[16]),+ .MODE_8x8(~ARG[17]),+ .A_SIGNED(~ARG[18]),+ .B_SIGNED(~ARG[19])+ ) ~GENSYM[sb_mac16_inst][4] (+ .CLK(~ARG[20]),+ .CE(~ARG[21]),+ .C(~ARG[22]),+ .A(~ARG[23]),+ .B(~ARG[24]),+ .D(~ARG[25]),+ .AHOLD(~ARG[30]),+ .BHOLD(~ARG[31]),+ .CHOLD(~ARG[32]),+ .DHOLD(~ARG[33]),+ .IRSTTOP(~ARG[26]),+ .IRSTBOT(~ARG[27]),+ .ORSTTOP(~ARG[28]),+ .ORSTBOT(~ARG[29]),+ .OLOADTOP(~ARG[38]),+ .OLOADBOT(~ARG[39]),+ .ADDSUBTOP(~ARG[36]),+ .ADDSUBBOT(~ARG[37]),+ .OHOLDTOP(~ARG[34]),+ .OHOLDBOT(~ARG[35]),+ .CI(~ARG[42]),+ .ACCUMCI(~ARG[40]),+ .SIGNEXTIN(~ARG[41]),+ .O(~SYM[0]),+ .CO(~SYM[1]),+ .ACCUMCO(~SYM[2]),+ .SIGNEXTOUT(~SYM[3])+ );++ assign ~RESULT = { ~SYM[0], ~SYM[1], ~SYM[2], ~SYM[3] };+ // SB_MAC16 end"+ }+ }+ ]+ |]) #-}++-- | Multiply-Accumulate primitive+{-# NOINLINE macPrim #-}+macPrim+ :: Bit -- ^ negTrigger+ -> Bit -- ^ aReg+ -> Bit -- ^ bReg+ -> Bit -- ^ cReg+ -> Bit -- ^ dReg+ -> Bit -- ^ top8x8MultReg+ -> Bit -- ^ bot8x8MultReg+ -> Bit -- ^ pipeline16x16MultReg1+ -> Bit -- ^ pipeline16x16MultReg2+ -> BitVector 2 -- ^ topOutputSelect+ -> BitVector 2 -- ^ topAddSubLowerInput+ -> Bit -- ^ topAddSubUpperInput+ -> BitVector 2 -- ^ topAddSubCarrySelect+ -> BitVector 2 -- ^ botOutputSelect+ -> BitVector 2 -- ^ botAddSubLowerInput+ -> Bit -- ^ botAddSubUpperInput+ -> BitVector 2 -- ^ botAddSubCarrySelect+ -> Bit -- ^ mode8x8+ -> Bit -- ^ aSigned+ -> Bit -- ^ bSigned+ -> Clock dom -- ^ clk+ -> Signal dom Bit -- ^ ce+ -> Signal dom (BitVector 16) -- ^ c+ -> Signal dom (BitVector 16) -- ^ a+ -> Signal dom (BitVector 16) -- ^ b+ -> Signal dom (BitVector 16) -- ^ d+ -> Signal dom Bit -- ^ irsttop+ -> Signal dom Bit -- ^ irstbot+ -> Signal dom Bit -- ^ orsttop+ -> Signal dom Bit -- ^ orstbot+ -> Signal dom Bit -- ^ ahold+ -> Signal dom Bit -- ^ bhold+ -> Signal dom Bit -- ^ chold+ -> Signal dom Bit -- ^ dhold+ -> Signal dom Bit -- ^ oholdtop+ -> Signal dom Bit -- ^ oholdbot+ -> Signal dom Bit -- ^ addsubtop+ -> Signal dom Bit -- ^ addsubbot+ -> Signal dom Bit -- ^ oloadtop+ -> Signal dom Bit -- ^ oloadbot+ -> Signal dom Bit -- ^ accumci+ -> Signal dom Bit -- ^ signextin+ -> Signal dom Bit -- ^ ci+ -> ( Signal dom (BitVector 32) -- o[31:0]+ , Signal dom Bit -- co+ , Signal dom Bit -- accumco+ , Signal dom Bit -- signextout+ ) -- ^ (o[31:0], co, accumco, signextout)+macPrim !_ !_ !_ !_ !_ !_ !_ !_ !_ !_ !_ !_ !_ !_ !_ !_ !_ !_ !_ !_ !_ !_ !_ !_ !_ !_ !_ !_ !_ !_ !_ !_ !_ !_ !_ !_ !_ !_ !_ !_ !_ !_ !_ = (0, 0, 0, 0)
+ src/Ice40/Osc.hs view
@@ -0,0 +1,130 @@+{-|+Module : Ice40.Osc+Description : Ice40 oscillator hard IP primitives+Copyright : (c) David Cox, 2021+License : BSD 3-Clause+Maintainer : standardsemiconductor@gmail.com++LFOSC and HFOSC hard IP primitive from Lattice Ice Technology Library https://github.com/standardsemiconductor/VELDT-info/blob/master/SBTICETechnologyLibrary201708.pdf+-}+module Ice40.Osc+ ( lf10kHz+ , hf48Mhz+ , hf24Mhz+ , hf12Mhz+ , hf6Mhz+ ) where++import Clash.Prelude+import Clash.Signal.Internal+import Clash.Annotations.Primitive+import Data.String.Interpolate (i)+import Data.String.Interpolate.Util (unindent)+import Ice40.Clock++------------------------------+-- Low Frequency Oscillator --+------------------------------++{-# ANN lf10kHz (InlinePrimitive [Verilog] $ unindent [i|+ [ { "BlackBox" :+ { "name" : "Ice40.Osc.lf10kHz"+ , "kind" : "Declaration"+ , "type" :+ "lf10kHz+ :: Signal dom Bool -- ARG[0] clkLfPu+ -> Signal dom Bool -- ARG[1] clkLfEn+ -> Clock Lattice10kHz"+ , "template" :+ "//SB_LFOSC begin+ SB_LFOSC ~GENSYM[sb_lfosc_inst][0] ( + .CLKLFEN (~ARG[0]),+ .CLKLFPU (~ARG[1]), + .CLKLF (~RESULT)+ );+ //SB_LFOSC end"+ }+ }+ ]+ |]) #-}++-- | Low frequency oscillator 10 kHz+{-# NOINLINE lf10kHz #-}+lf10kHz+ :: Signal dom Bool -- ^ CLKLFPU - Power up the LFOSC circuit. After power up, oscillator output will be stable after 100us. Active High.+ -> Signal dom Bool -- ^ CLKLFEN - Enable the clock output. Enable should be low for the 100us power up period. Active High.+ -> Clock Lattice10kHz -- ^ LF Oscillator output+lf10kHz !_ !_ = Clock SSymbol++-------------------------------+-- High Frequency Oscillator --+-------------------------------+-- | SB_HFOSC primitive generates 48MHz nominal clock frequency within +/-10% variation, with user programmable divider value of 1, 2, 4, and 8. the HFOSC can drive either the global clock network or fabric routes directly based on the clock network selection.++{-# ANN hfPrim (InlinePrimitive [Verilog] $ unindent [i|+ [ { "BlackBox" :+ { "name" : "Ice40.Osc.hfPrim"+ , "kind" : "Declaration"+ , "type" :+ "hfPrim+ :: KnownDomain dom -- ARG[0]+ => KnownDomain dom' -- ARG[1]+ => String -- ARG[2] clkhfdiv+ -> Signal dom Bool -- ARG[3] clkhfen+ -> Signal dom Bool -- ARG[4] clkhfpu+ -> Clock dom' -- clkhf"+ , "template" :+ "//SB_HFOSC begin+ SB_HFOSC #( .CLKHF_DIV(~ARG[2]) ) sb_hfosc_inst (+ .CLKHFEN (~ARG[3]),+ .CLKHFPU (~ARG[4]),+ .CLKHF (~RESULT)+ ); + //SB_HFOSC end"+ }+ }+ ]+ |]) #-}++{-# NOINLINE hfPrim #-}+hfPrim+ :: KnownDomain dom -- ARG[0]+ => KnownDomain dom' -- ARG[1]+ => String -- ARG[2] clkhfdiv+ -> Signal dom Bool -- ARG[3] clkhfen+ -> Signal dom Bool -- ARG[4] clkhfpu+ -> Clock dom' -- clkhf"+hfPrim !_ !_ !_ = Clock SSymbol++-- | High frequency oscillator 48 Mhz+hf48Mhz+ :: KnownDomain dom+ => Signal dom Bool -- ^ CLKHFEN Enable the clock output. Enable should be low for the 100us power up period. Active High.+ -> Signal dom Bool -- ^ CLKHFPU Power up the HFOSC circuit. After power up, oscillator output will be stable after 100us. Active High.+ -> Clock Lattice48Mhz -- ^ HF Oscillator output+hf48Mhz = hfPrim "0b00"++-- | High frequency oscillator 24 Mhz+hf24Mhz+ :: KnownDomain dom+ => Signal dom Bool -- ^ CLKHFEN Enable the clock output. Enable should be low for the 100us power up period. Active High.+ -> Signal dom Bool -- ^ CLKHFPU Power up the HFOSC circuit. After power up, oscillator output will be stable after 100us. Active High.+ -> Clock Lattice24Mhz -- ^ HF Oscillator output+hf24Mhz = hfPrim "0b01"++-- | High frequency oscillator 12 Mhz+hf12Mhz+ :: KnownDomain dom+ => Signal dom Bool -- ^ CLKHFEN Enable the clock output. Enable should be low for the 100us power up period. Active High.+ -> Signal dom Bool -- ^ CLKHFPU Power up the HFOSC circuit. After power up, oscillator output will be stable after 100us. Active High.+ -> Clock Lattice12Mhz -- ^ HF Oscillator output+hf12Mhz = hfPrim "0b10"++-- | High frequency oscillator 6 Mhz+hf6Mhz+ :: KnownDomain dom+ => Signal dom Bool -- ^ CLKHFEN Enable the clock output. Enable should be low for the 100us power up period. Active High.+ -> Signal dom Bool -- ^ CLKHFPU Power up the HFOSC circuit. After power up, oscillator output will be stable after 100us. Active High.+ -> Clock Lattice6Mhz -- ^ HF Oscillator output+hf6Mhz = hfPrim "0b11"+
+ src/Ice40/Rgb.hs view
@@ -0,0 +1,95 @@+{-|+Module : Ice40.Rgb+Description : Ice40 RGB hard IP primitive+Copyright : (c) David Cox, 2021+License : BSD 3-Clause+Maintainer : standardsemiconductor@gmail.com++RGB hard IP primitive from Lattice Ice Technology Library https://github.com/standardsemiconductor/VELDT-info/blob/master/SBTICETechnologyLibrary201708.pdf+-}+module Ice40.Rgb where++import Clash.Prelude+import Clash.Annotations.Primitive+import Data.String.Interpolate (i)+import Data.String.Interpolate.Util (unindent)++{-# ANN rgbPrim (InlinePrimitive [Verilog] $ unindent [i|+ [ { "BlackBox" :+ { "name" : "Ice40.Rgb.rgbPrim"+ , "kind" : "Declaration"+ , "type" :+ "rgbPrim+ :: String -- currentMode ARG[0]+ -> String -- rgb0Current ARG[1]+ -> String -- rgb1Current ARG[2]+ -> String -- rgb2Current ARG[3]+ -> Signal dom Bit -- curren ARG[4]+ -> Signal dom Bit -- rgbleden ARG[5]+ -> Signal dom Bit -- rgb0Pwm ARG[6]+ -> Signal dom Bit -- rgb1Pwm ARG[7]+ -> Signal dom Bit -- rgb2Pwm ARG[8]+ -> Signal dom ( Bit -- rgb0+ , Bit -- rgb1+ , Bit -- rgb2+ )"+ , "template" :+ "//SB_RGBA_DRV begin+ wire ~GENSYM[rgb0][0];+ wire ~GENSYM[rgb1][1];+ wire ~GENSYM[rgb2][2];++ SB_RGBA_DRV #(+ .CURRENT_MODE ( ~ARG[0] ),+ .RGB0_CURRENT ( ~ARG[1] ),+ .RGB1_CURRENT ( ~ARG[2] ),+ .RGB2_CURRENT ( ~ARG[3] )+ ) ~GENSYM[rgba_drv_inst][3] (+ .CURREN ( ~ARG[4] ),+ .RGBLEDEN ( ~ARG[5] ),+ .RGB0PWM ( ~ARG[6] ),+ .RGB1PWM ( ~ARG[7] ),+ .RGB2PWM ( ~ARG[8] ),+ .RGB0 ( ~SYM[0] ),+ .RGB1 ( ~SYM[1] ),+ .RGB2 ( ~SYM[2] )+ );+ + assign ~RESULT = {~SYM[0], ~SYM[1], ~SYM[2]};+ //SB_RGBA_DRV end"+ }+ } + ]+ |]) #-}++-- | SB_RGBA_DRV primitive is the RGB LED drive module which contains 3 +-- dedicated open drain I/O pins for RGB LED outputs. Each of the RGB LED +-- output is bonded out together with an SB_IO_OD primitive to +-- the package pin. User can either use SB_RGB_DRV primitive or the +-- SB_IO_OD primitive to drive the package pin, but not both.+-- +-- The primitive allows configuration of each of the 3 RGB LED +-- outputs individually. When the RGBx_CURRENT parameter of RGBx output is +-- set to "0b000000", then SB_IO_OD can be used to drive +-- the package pin. "0b000001" = 4mA for Full Mode; 2mA for +-- Half Mode. "0b000011" = 8mA for Full Mode; 4mA for Half Mode. +-- "0b000111" = 12mA for Full Mode; 6mA for Half Mode. +-- "0b001111" = 16mA for Full Mode; 8mA for Half Mode. +-- "0b011111" = 20mA for Full Mode; 10mA for Half Mode. +-- "0b111111" = 24mA for Full Mode; 12mA for Half Mode.+{-# NOINLINE rgbPrim #-}+rgbPrim+ :: String -- ^ currentMode - Parameter values: "0b0" = Full Current Mode (Default), "0b1" = Half Current Mode.+ -> String -- ^ rgb0Current+ -> String -- ^ rgb1Current+ -> String -- ^ rgb2Current+ -> Signal dom Bit -- ^ curren - enable the mixed signal control block to supply reference current to the IR drivers. When it is not enabled (CURREN=0), no current is supplied, and the IR drivers are powered down. Enabling the mixed signal control block takes 100us to reach a stable reference current value.+ -> Signal dom Bit -- ^ rgbleden - enable the SB_RGB_DRV primitive. Active High.+ -> Signal dom Bit -- ^ rgb0Pwm - input data to drive RGB0 LED pin. This input is usually driven from the SB_LEDD_IP.+ -> Signal dom Bit -- ^ rgb1Pwm - input data to drive RGB1 LED pin. This input is usually driven from the SB_LEDD_IP.+ -> Signal dom Bit -- ^ rgb2Pwm - input data to drive RGB2 LED pin. This input is usually driven from teh SB_LEDD_IP.+ -> Signal dom ( Bit+ , Bit+ , Bit+ ) -- ^ (RGB0 LED output, RGB1 LED output, RGB2 LED output)+rgbPrim !_ !_ !_ !_ !_ !_ !_ !_ !_ = pure (0, 0, 0)
+ src/Ice40/Spi.hs view
@@ -0,0 +1,285 @@+{-|+Module : Ice40.Spi+Description : Ice40 SPI hard IP primitive+Copyright : (c) David Cox, 2021+License : BSD 3-Clause+Maintainer : standardsemiconductor@gmail.com++SPI hard IP primitive from Lattice Ice Technology Library https://github.com/standardsemiconductor/VELDT-info/blob/master/SBTICETechnologyLibrary201708.pdf+-}+module Ice40.Spi ( spi ) where++import Clash.Prelude+import Clash.Annotations.Primitive+import Data.String.Interpolate (i)+import Data.String.Interpolate.Util (unindent)+ +-- | spi primitive wrapper+spi+ :: HiddenClock dom+ => String -- ^ busAddr+ -> Signal dom Bool -- ^ sbrwi+ -> Signal dom Bool -- ^ sbstbi+ -> Signal dom (BitVector 8) -- ^ sbadri+ -> Signal dom (BitVector 8) -- ^ sbdati+ -> Signal dom Bit -- ^ bi+ -> Signal dom Bit -- ^ wi+ -> Signal dom Bit -- ^ wcki+ -> Signal dom Bit -- ^ wcsni+ -> Unbundled dom + ( BitVector 8 -- sbdato+ , Bool -- sbacko+ , Bit -- spiirq+ , Bit -- spiwkup+ , Bit -- wo+ , Bit -- woe+ , Bit -- bo+ , Bit -- boe+ , Bit -- wcko+ , Bit -- wckoe+ , BitVector 4 -- bcsno+ , BitVector 4 -- bcsnoe+ ) -- ^ (sbdato, sbacko, spiirq, spiwkup, wo, woe, bo, boe, wcko, wckoe, bcsno, bcsnoe)+spi busAddr sbrwi sbstbi sbadri sbdati bi wi wcki wcsni =+ spiPrim busAddr+ hasClock+ sbrwi+ sbstbi+ (bitAt 7 sbadri)+ (bitAt 6 sbadri)+ (bitAt 5 sbadri)+ (bitAt 4 sbadri)+ (bitAt 3 sbadri)+ (bitAt 2 sbadri)+ (bitAt 1 sbadri)+ (bitAt 0 sbadri)+ (bitAt 7 sbdati)+ (bitAt 6 sbdati)+ (bitAt 5 sbdati)+ (bitAt 4 sbdati)+ (bitAt 3 sbdati)+ (bitAt 2 sbdati)+ (bitAt 1 sbdati)+ (bitAt 0 sbdati)+ bi+ wi+ wcki+ wcsni++bitAt :: KnownNat n => Index n -> Signal dom (BitVector n) -> Signal dom Bit+bitAt n = fmap (!n)++{-# ANN spiPrim (InlinePrimitive [Verilog] $ unindent [i|+ [ { "BlackBox" :+ { "name" : "Ice40.Spi.spiPrim"+ , "kind" : "Declaration"+ , "type" :+ "spiPrim+ :: String -- ARG[0] busAddr+ -> Clock dom -- ARG[1] sbclki+ -> Signal dom Bool -- ARG[2] sbrwi+ -> Signal dom Bool -- ARG[3] sbstbi+ -> Signal dom Bit -- ARG[4] sbadri7+ -> Signal dom Bit -- ARG[5] sbadri6+ -> Signal dom Bit -- ARG[6] sbadri5+ -> Signal dom Bit -- ARG[7] sbadri4+ -> Signal dom Bit -- ARG[8] sbadri3+ -> Signal dom Bit -- ARG[9] sbadri2+ -> Signal dom Bit -- ARG[10] sbadri1+ -> Signal dom Bit -- ARG[11] sbadri0+ -> Signal dom Bit -- ARG[12] sbdati7+ -> Signal dom Bit -- ARG[13] sbdati6+ -> Signal dom Bit -- ARG[14] sbdati5+ -> Signal dom Bit -- ARG[15] sbdati4+ -> Signal dom Bit -- ARG[16] sbdati3+ -> Signal dom Bit -- ARG[17] sbdati2+ -> Signal dom Bit -- ARG[18] sbdati1+ -> Signal dom Bit -- ARG[19] sbdati0+ -> Signal dom Bit -- ARG[20] bi+ -> Signal dom Bit -- ARG[21] wi+ -> Signal dom Bit -- ARG[22] wcki+ -> Signal dom Bit -- ARG[23] wcsni+ -> Unbundled dom + ( BitVector 8 -- sbdato+ , Bool -- sbacko+ , Bit -- spiirq+ , Bit -- spiwkup+ , Bit -- wo+ , Bit -- woe+ , Bit -- bo+ , Bit -- boe+ , Bit -- wcko+ , Bit -- wckoe+ , BitVector 4 -- bcsno+ , BitVector 4 -- bcsnoe+ )"+ , "template" :+ "//SB_SPI begin+ wire ~GENSYM[sbdato7][0];+ wire ~GENSYM[sbdato6][1];+ wire ~GENSYM[sbdato5][2];+ wire ~GENSYM[sbdato4][3];+ wire ~GENSYM[sbdato3][4];+ wire ~GENSYM[sbdato2][5];+ wire ~GENSYM[sbdato1][6];+ wire ~GENSYM[sbdato0][7];+ wire ~GENSYM[sbacko][8];+ wire ~GENSYM[irq][9];+ wire ~GENSYM[wkup][10];+ wire ~GENSYM[wo][11];+ wire ~GENSYM[woe][12];+ wire ~GENSYM[bo][13];+ wire ~GENSYM[boe][14];+ wire ~GENSYM[wcko][15];+ wire ~GENSYM[wckoe][16];+ wire ~GENSYM[bcsno3][17];+ wire ~GENSYM[bcsno2][18];+ wire ~GENSYM[bcsno1][19];+ wire ~GENSYM[bcsno0][20];+ wire ~GENSYM[bcsnoe3][21];+ wire ~GENSYM[bcsnoe2][22];+ wire ~GENSYM[bcsnoe1][23];+ wire ~GENSYM[bcsnoe0][24];++ SB_SPI #(+ .BUS_ADDR74( ~ARG[0] )+ ) ~GENSYM[sb_spi_inst][25] (+ .SBCLKI ( ~ARG[1] ),+ .SBRWI ( ~ARG[2] ),+ .SBSTBI ( ~ARG[3] ),+ .SBADRI7 ( ~ARG[4] ),+ .SBADRI6 ( ~ARG[5] ),+ .SBADRI5 ( ~ARG[6] ),+ .SBADRI4 ( ~ARG[7] ),+ .SBADRI3 ( ~ARG[8] ),+ .SBADRI2 ( ~ARG[9] ),+ .SBADRI1 ( ~ARG[10] ),+ .SBADRI0 ( ~ARG[11] ),+ .SBDATI7 ( ~ARG[12] ),+ .SBDATI6 ( ~ARG[13] ),+ .SBDATI5 ( ~ARG[14] ),+ .SBDATI4 ( ~ARG[15] ),+ .SBDATI3 ( ~ARG[16] ),+ .SBDATI2 ( ~ARG[17] ),+ .SBDATI1 ( ~ARG[18] ),+ .SBDATI0 ( ~ARG[19] ),+ .MI ( ~ARG[20] ),+ .SI ( ~ARG[21] ),+ .SCKI ( ~ARG[22] ),+ .SCSNI ( ~ARG[23] ),++ .SBDATO7 ( ~SYM[0] ),+ .SBDATO6 ( ~SYM[1] ),+ .SBDATO5 ( ~SYM[2] ),+ .SBDATO4 ( ~SYM[3] ),+ .SBDATO3 ( ~SYM[4] ),+ .SBDATO2 ( ~SYM[5] ),+ .SBDATO1 ( ~SYM[6] ),+ .SBDATO0 ( ~SYM[7] ),+ .SBACKO ( ~SYM[8] ),+ .SPIIRQ ( ~SYM[9] ),+ .SPIWKUP ( ~SYM[10] ),+ .SO ( ~SYM[11] ),+ .SOE ( ~SYM[12] ),+ .MO ( ~SYM[13] ),+ .MOE ( ~SYM[14] ),+ .SCKO ( ~SYM[15] ),+ .SCKOE ( ~SYM[16] ),+ .MCSNO3 ( ~SYM[17] ),+ .MCSNO2 ( ~SYM[18] ),+ .MCSNO1 ( ~SYM[19] ),+ .MCSNO0 ( ~SYM[20] ),+ .MCSNOE3 ( ~SYM[21] ),+ .MCSNOE2 ( ~SYM[22] ),+ .MCSNOE1 ( ~SYM[23] ),+ .MCSNOE0 ( ~SYM[24] )+ );++ assign ~RESULT = { ~SYM[0] // sbdato7+ , ~SYM[1] // sbdato6+ , ~SYM[2] // sbdato5+ , ~SYM[3] // sbdato4+ , ~SYM[4] // sbdato3+ , ~SYM[5] // sbdato2+ , ~SYM[6] // sbdato1+ , ~SYM[7] // sbdato0+ , ~SYM[8] // sbacko+ , ~SYM[9] // spiirq+ , ~SYM[10] // spiwkup+ , ~SYM[11] // wo+ , ~SYM[12] // woe+ , ~SYM[13] // bo+ , ~SYM[14] // boe+ , ~SYM[15] // wcko+ , ~SYM[16] // wckoe+ , ~SYM[17] // bcsno3+ , ~SYM[18] // bcsno2+ , ~SYM[19] // bcsno1+ , ~SYM[20] // bcsno0+ , ~SYM[21] // bcsnoe3+ , ~SYM[22] // bcsnoe2+ , ~SYM[23] // bcsnoe1+ , ~SYM[24] // bcsnoe0+ };+ // SB_SPI end"+ }+ }+ ]+ |]) #-}++{-# NOINLINE spiPrim #-}+spiPrim+ :: String -- ARG[0] busAddr+ -> Clock dom -- ARG[1] sbclki+ -> Signal dom Bool -- ARG[2] sbrwi+ -> Signal dom Bool -- ARG[3] sbstbi+ -> Signal dom Bit -- ARG[4] sbadri7+ -> Signal dom Bit -- ARG[5] sbadri6+ -> Signal dom Bit -- ARG[6] sbadri5+ -> Signal dom Bit -- ARG[7] sbadri4+ -> Signal dom Bit -- ARG[8] sbadri3+ -> Signal dom Bit -- ARG[9] sbadri2+ -> Signal dom Bit -- ARG[10] sbadri1+ -> Signal dom Bit -- ARG[11] sbadri0+ -> Signal dom Bit -- ARG[12] sbdati7+ -> Signal dom Bit -- ARG[13] sbdati6+ -> Signal dom Bit -- ARG[14] sbdati5+ -> Signal dom Bit -- ARG[15] sbdati4+ -> Signal dom Bit -- ARG[16] sbdati3+ -> Signal dom Bit -- ARG[17] sbdati2+ -> Signal dom Bit -- ARG[18] sbdati1+ -> Signal dom Bit -- ARG[19] sbdati0+ -> Signal dom Bit -- ARG[20] bi+ -> Signal dom Bit -- ARG[21] wi+ -> Signal dom Bit -- ARG[22] wcki+ -> Signal dom Bit -- ARG[23] wcsni+ -> Unbundled dom + ( BitVector 8 -- sbdato+ , Bool -- sbacko+ , Bit -- spiirq+ , Bit -- spiwkup+ , Bit -- wo+ , Bit -- woe+ , Bit -- bo+ , Bit -- boe+ , Bit -- wcko+ , Bit -- wckoe+ , BitVector 4 -- bcsno+ , BitVector 4 -- bcsnoe+ )+spiPrim !_ !_ !_ !_ !_ !_ !_ !_ !_ !_ !_ !_ !_ !_ !_ !_ !_ !_ !_ !_ !_ !_ !_ !_+ = unbundle $ pure ( 0 -- sbdato+ , False -- sbacko+ , 0 -- spiirq+ , 0 -- spiwkup+ , 0 -- wo+ , 0 -- woe+ , 0 -- bo+ , 0 -- boe+ , 0 -- wcko+ , 0 -- wckoe+ , 0 -- bcsno+ , 0 -- bcsnoe+ )++
+ src/Ice40/Spram.hs view
@@ -0,0 +1,97 @@+{-|+Module : Ice40.Spram+Description : Ice40 single-port RAM hard IP primitive+Copyright : (c) David Cox, 2021+License : BSD 3-Clause+Maintainer : standardsemiconductor@gmail.com++SPRAM hard IP primitive from Lattice Ice Technology Library https://github.com/standardsemiconductor/VELDT-info/blob/master/SBTICETechnologyLibrary201708.pdf+-}+module Ice40.Spram ( spramPrim ) where++import Clash.Prelude+import Clash.Annotations.Primitive+import Data.String.Interpolate (i)+import Data.String.Interpolate.Util (unindent)++{-# ANN spramPrim (InlinePrimitive [Verilog] $ unindent [i|+ [ { "BlackBox" :+ { "name" : "Ice40.Spram.spramPrim"+ , "kind" : "Declaration"+ , "type" :+ "spramPrim+ :: KnownDomain dom -- ARG[0] + => Clock dom -- ARG[1] clock+ -> Signal dom (BitVector 14) -- ARG[2] address+ -> Signal dom (BitVector 16) -- ARG[3] dataIn+ -> Signal dom (BitVector 4) -- ARG[4] maskWrEn+ -> Signal dom Bit -- ARG[5] wrEN+ -> Signal dom Bit -- ARG[6] chipSelect+ -> Signal dom Bit -- ARG[7] standBy+ -> Signal dom Bit -- ARG[8] sleep+ -> Signal dom Bit -- ARG[9] powerOff+ -> Signal dom (BitVector 16) -- dataOut"+ , "template" :+ "//SB_SPRAM begin+ SB_SPRAM256KA ~GENSYM[sb_spram_inst][0] (+ .ADDRESS (~ARG[2]),+ .DATAIN (~ARG[3]),+ .MASKWREN (~ARG[4]),+ .WREN (~ARG[5]),+ .CHIPSELECT(~ARG[6]),+ .CLOCK (~ARG[1]),+ .STANDBY (~ARG[7]),+ .SLEEP (~ARG[8]),+ .POWEROFF (~ARG[9]),+ .DATAOUT (~RESULT)+ );+ //SB_SPRAM end"+ }+ }+ ]+ |]) #-}++data Nyb = Nyb3 | Nyb2 | Nyb1 | Nyb0++-- | Single port RAM primitive+{-# NOINLINE spramPrim #-}+spramPrim+ :: KnownDomain dom -- ARG[0] + => Clock dom -- ^ clock+ -> Signal dom (BitVector 14) -- ^ address+ -> Signal dom (BitVector 16) -- ^ dataIn+ -> Signal dom (BitVector 4) -- ^ maskWrEn+ -> Signal dom Bit -- ^ wrEN+ -> Signal dom Bit -- ^ chipSelect+ -> Signal dom Bit -- ^ standBy+ -> Signal dom Bit -- ^ sleep+ -> Signal dom Bit -- ^ powerOff+ -> Signal dom (BitVector 16) -- ^ dataOut+spramPrim clock address dataIn maskWrEn wrEn chipSelect !_ !_ !_+ = concat4 <$> nyb3 <*> nyb2 <*> nyb1 <*> nyb0+ where+ addressU = unpack <$> address+ concat4 a b c d = a ++# b ++# c ++# d+ ramEn = toEnable $ bitToBool <$> chipSelect+ nybRam = withClock clock $ withEnable ramEn (blockRamPow2 (repeat 0) addressU)+ nyb3 = nybRam wrM3+ nyb2 = nybRam wrM2+ nyb1 = nybRam wrM1+ nyb0 = nybRam wrM0+ wrM3 = writeGuard Nyb3 <$> dataIn <*> addressU <*> wrEn <*> maskWrEn+ wrM2 = writeGuard Nyb2 <$> dataIn <*> addressU <*> wrEn <*> maskWrEn+ wrM1 = writeGuard Nyb1 <$> dataIn <*> addressU <*> wrEn <*> maskWrEn+ wrM0 = writeGuard Nyb0 <$> dataIn <*> addressU <*> wrEn <*> maskWrEn+ nybSlice = \case+ Nyb3 -> slice d15 d12+ Nyb2 -> slice d11 d8+ Nyb1 -> slice d7 d4+ Nyb0 -> slice d3 d0+ nybMask = \case+ Nyb3 -> (!(3 :: Index 4))+ Nyb2 -> (!(2 :: Index 4))+ Nyb1 -> (!(1 :: Index 4))+ Nyb0 -> (!(0 :: Index 4))+ writeGuard n dIn addr en mask+ | bitToBool en && (not.bitToBool) (nybMask n mask) = Just (addr, nybSlice n dIn)+ | otherwise = Nothing