{-|
Module      : Ice40.I2c
Description : Ice40 I2C hard IP primitive
Copyright   : (c) David Cox, 2021-2024
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 :: forall (dom :: Domain).
String
-> String
-> Clock dom
-> Signal dom Bool
-> Signal dom Bool
-> Signal dom Bit
-> Signal dom Bit
-> Signal dom Bit
-> Signal dom Bit
-> Signal dom Bit
-> Signal dom Bit
-> Signal dom Bit
-> Signal dom Bit
-> Signal dom Bit
-> Signal dom Bit
-> Signal dom Bit
-> Signal dom Bit
-> Signal dom Bit
-> Signal dom Bit
-> Signal dom Bit
-> Signal dom Bit
-> Signal dom Bit
-> Signal dom Bit
-> Unbundled dom (BitVector 8, Bool, Bit, Bit, Bit, Bit, Bit, Bit)
i2cPrim !String
_ !String
_ !Clock dom
_ !Signal dom Bool
_ !Signal dom Bool
_ !Signal dom Bit
_ !Signal dom Bit
_ !Signal dom Bit
_ !Signal dom Bit
_ !Signal dom Bit
_ !Signal dom Bit
_ !Signal dom Bit
_ !Signal dom Bit
_ !Signal dom Bit
_ !Signal dom Bit
_ !Signal dom Bit
_ !Signal dom Bit
_ !Signal dom Bit
_ !Signal dom Bit
_ !Signal dom Bit
_ !Signal dom Bit
_ !Signal dom Bit
_ !Signal dom Bit
_
  = Signal dom (BitVector 8, Bool, Bit, Bit, Bit, Bit, Bit, Bit)
-> Unbundled dom (BitVector 8, Bool, Bit, Bit, Bit, Bit, Bit, Bit)
forall a (dom :: Domain).
Bundle a =>
Signal dom a -> Unbundled dom a
forall (dom :: Domain).
Signal dom (BitVector 8, Bool, Bit, Bit, Bit, Bit, Bit, Bit)
-> Unbundled dom (BitVector 8, Bool, Bit, Bit, Bit, Bit, Bit, Bit)
unbundle (Signal dom (BitVector 8, Bool, Bit, Bit, Bit, Bit, Bit, Bit)
 -> Unbundled dom (BitVector 8, Bool, Bit, Bit, Bit, Bit, Bit, Bit))
-> Signal dom (BitVector 8, Bool, Bit, Bit, Bit, Bit, Bit, Bit)
-> Unbundled dom (BitVector 8, Bool, Bit, Bit, Bit, Bit, Bit, Bit)
forall a b. (a -> b) -> a -> b
$ (BitVector 8, Bool, Bit, Bit, Bit, Bit, Bit, Bit)
-> Signal dom (BitVector 8, Bool, Bit, Bit, Bit, Bit, Bit, Bit)
forall a. a -> Signal dom a
forall (f :: Type -> Type) a. Applicative f => a -> f a
pure ( BitVector 8
0
                    , Bool
False
                    , Bit
0
                    , Bit
0
                    , Bit
0
                    , Bit
0
                    , Bit
0
                    , Bit
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 :: forall (dom :: Domain).
HiddenClock dom =>
String
-> String
-> Signal dom Bool
-> Signal dom Bool
-> Signal dom (BitVector 8)
-> Signal dom (BitVector 8)
-> Signal dom Bit
-> Signal dom Bit
-> Unbundled dom (BitVector 8, Bool, Bit, Bit, Bit, Bit, Bit, Bit)
i2c 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 =
  String
-> String
-> Clock dom
-> Signal dom Bool
-> Signal dom Bool
-> Signal dom Bit
-> Signal dom Bit
-> Signal dom Bit
-> Signal dom Bit
-> Signal dom Bit
-> Signal dom Bit
-> Signal dom Bit
-> Signal dom Bit
-> Signal dom Bit
-> Signal dom Bit
-> Signal dom Bit
-> Signal dom Bit
-> Signal dom Bit
-> Signal dom Bit
-> Signal dom Bit
-> Signal dom Bit
-> Signal dom Bit
-> Signal dom Bit
-> Unbundled dom (BitVector 8, Bool, Bit, Bit, Bit, Bit, Bit, Bit)
forall (dom :: Domain).
String
-> String
-> Clock dom
-> Signal dom Bool
-> Signal dom Bool
-> Signal dom Bit
-> Signal dom Bit
-> Signal dom Bit
-> Signal dom Bit
-> Signal dom Bit
-> Signal dom Bit
-> Signal dom Bit
-> Signal dom Bit
-> Signal dom Bit
-> Signal dom Bit
-> Signal dom Bit
-> Signal dom Bit
-> Signal dom Bit
-> Signal dom Bit
-> Signal dom Bit
-> Signal dom Bit
-> Signal dom Bit
-> Signal dom Bit
-> Unbundled dom (BitVector 8, Bool, Bit, Bit, Bit, Bit, Bit, Bit)
i2cPrim String
initAddr
          String
busAddr
          Clock dom
forall (dom :: Domain). HiddenClock dom => Clock dom
hasClock
          Signal dom Bool
sbrwi
          Signal dom Bool
sbstbi
          (Index 8 -> Signal dom (BitVector 8) -> Signal dom Bit
forall (n :: Nat) (dom :: Domain).
KnownNat n =>
Index n -> Signal dom (BitVector n) -> Signal dom Bit
bitAt Index 8
7 Signal dom (BitVector 8)
sbadri)
          (Index 8 -> Signal dom (BitVector 8) -> Signal dom Bit
forall (n :: Nat) (dom :: Domain).
KnownNat n =>
Index n -> Signal dom (BitVector n) -> Signal dom Bit
bitAt Index 8
6 Signal dom (BitVector 8)
sbadri)
          (Index 8 -> Signal dom (BitVector 8) -> Signal dom Bit
forall (n :: Nat) (dom :: Domain).
KnownNat n =>
Index n -> Signal dom (BitVector n) -> Signal dom Bit
bitAt Index 8
5 Signal dom (BitVector 8)
sbadri)
          (Index 8 -> Signal dom (BitVector 8) -> Signal dom Bit
forall (n :: Nat) (dom :: Domain).
KnownNat n =>
Index n -> Signal dom (BitVector n) -> Signal dom Bit
bitAt Index 8
4 Signal dom (BitVector 8)
sbadri)
          (Index 8 -> Signal dom (BitVector 8) -> Signal dom Bit
forall (n :: Nat) (dom :: Domain).
KnownNat n =>
Index n -> Signal dom (BitVector n) -> Signal dom Bit
bitAt Index 8
3 Signal dom (BitVector 8)
sbadri)
          (Index 8 -> Signal dom (BitVector 8) -> Signal dom Bit
forall (n :: Nat) (dom :: Domain).
KnownNat n =>
Index n -> Signal dom (BitVector n) -> Signal dom Bit
bitAt Index 8
2 Signal dom (BitVector 8)
sbadri)
          (Index 8 -> Signal dom (BitVector 8) -> Signal dom Bit
forall (n :: Nat) (dom :: Domain).
KnownNat n =>
Index n -> Signal dom (BitVector n) -> Signal dom Bit
bitAt Index 8
1 Signal dom (BitVector 8)
sbadri)
          (Index 8 -> Signal dom (BitVector 8) -> Signal dom Bit
forall (n :: Nat) (dom :: Domain).
KnownNat n =>
Index n -> Signal dom (BitVector n) -> Signal dom Bit
bitAt Index 8
0 Signal dom (BitVector 8)
sbadri)
          (Index 8 -> Signal dom (BitVector 8) -> Signal dom Bit
forall (n :: Nat) (dom :: Domain).
KnownNat n =>
Index n -> Signal dom (BitVector n) -> Signal dom Bit
bitAt Index 8
7 Signal dom (BitVector 8)
sbdati)
          (Index 8 -> Signal dom (BitVector 8) -> Signal dom Bit
forall (n :: Nat) (dom :: Domain).
KnownNat n =>
Index n -> Signal dom (BitVector n) -> Signal dom Bit
bitAt Index 8
6 Signal dom (BitVector 8)
sbdati)
          (Index 8 -> Signal dom (BitVector 8) -> Signal dom Bit
forall (n :: Nat) (dom :: Domain).
KnownNat n =>
Index n -> Signal dom (BitVector n) -> Signal dom Bit
bitAt Index 8
5 Signal dom (BitVector 8)
sbdati)
          (Index 8 -> Signal dom (BitVector 8) -> Signal dom Bit
forall (n :: Nat) (dom :: Domain).
KnownNat n =>
Index n -> Signal dom (BitVector n) -> Signal dom Bit
bitAt Index 8
4 Signal dom (BitVector 8)
sbdati)
          (Index 8 -> Signal dom (BitVector 8) -> Signal dom Bit
forall (n :: Nat) (dom :: Domain).
KnownNat n =>
Index n -> Signal dom (BitVector n) -> Signal dom Bit
bitAt Index 8
3 Signal dom (BitVector 8)
sbdati)
          (Index 8 -> Signal dom (BitVector 8) -> Signal dom Bit
forall (n :: Nat) (dom :: Domain).
KnownNat n =>
Index n -> Signal dom (BitVector n) -> Signal dom Bit
bitAt Index 8
2 Signal dom (BitVector 8)
sbdati)
          (Index 8 -> Signal dom (BitVector 8) -> Signal dom Bit
forall (n :: Nat) (dom :: Domain).
KnownNat n =>
Index n -> Signal dom (BitVector n) -> Signal dom Bit
bitAt Index 8
1 Signal dom (BitVector 8)
sbdati)
          (Index 8 -> Signal dom (BitVector 8) -> Signal dom Bit
forall (n :: Nat) (dom :: Domain).
KnownNat n =>
Index n -> Signal dom (BitVector n) -> Signal dom Bit
bitAt Index 8
0 Signal dom (BitVector 8)
sbdati)
          Signal dom Bit
scli
          Signal dom Bit
sdai

bitAt :: KnownNat n => Index n -> Signal dom (BitVector n) -> Signal dom Bit
bitAt :: forall (n :: Nat) (dom :: Domain).
KnownNat n =>
Index n -> Signal dom (BitVector n) -> Signal dom Bit
bitAt Index n
n = (BitVector n -> Bit) -> Signal dom (BitVector n) -> Signal dom Bit
forall a b. (a -> b) -> Signal dom a -> Signal dom b
forall (f :: Type -> Type) a b. Functor f => (a -> b) -> f a -> f b
fmap (BitVector n -> Index n -> Bit
forall a i. (BitPack a, Enum i) => a -> i -> Bit
! Index n
n)