packages feed

ice40-prim-0.2.0.0: src/Ice40/I2c.hs

{-|
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)