module CLaSH.Prelude.Synchronizer
(
dualFlipFlopSynchronizer
, asyncFIFOSynchronizer
)
where
import Data.Bits (complement, shiftR, xor)
import GHC.TypeLits (type (+))
import CLaSH.Class.BitPack (boolToBV)
import CLaSH.Prelude.BitIndex (slice)
import CLaSH.Prelude.Mealy (mealyB')
import CLaSH.Prelude.RAM (asyncRam')
import CLaSH.Promoted.Nat (SNat, powSNat, subSNat)
import CLaSH.Promoted.Nat.Literals (d0, d1, d2)
import CLaSH.Signal ((.&&.), not1)
import CLaSH.Signal.Explicit (Signal', SClock, register',
unsafeSynchronizer)
import CLaSH.Sized.BitVector (BitVector, (++#))
dualFlipFlopSynchronizer :: SClock clk1
-> SClock clk2
-> a
-> Signal' clk1 a
-> Signal' clk2 a
dualFlipFlopSynchronizer clk1 clk2 i = register' clk2 i
. register' clk2 i
. unsafeSynchronizer clk1 clk2
fifoMem :: _
=> SClock wclk
-> SClock rclk
-> SNat addrSize
-> Signal' wclk (BitVector addrSize)
-> Signal' rclk (BitVector addrSize)
-> Signal' wclk Bool
-> Signal' wclk Bool
-> Signal' wclk a
-> Signal' rclk a
fifoMem wclk rclk addrSize waddr raddr winc wfull wdata =
asyncRam' wclk rclk
(d2 `powSNat` addrSize)
waddr raddr
(winc .&&. not1 wfull)
wdata
ptrCompareT :: _
=> SNat addrSize
-> (BitVector (addrSize + 1) -> BitVector (addrSize + 1) -> Bool)
-> (BitVector (addrSize + 1), BitVector (addrSize + 1), Bool)
-> (BitVector (addrSize + 1), Bool)
-> ((BitVector (addrSize + 1), BitVector (addrSize + 1), Bool)
,(Bool, BitVector addrSize, BitVector (addrSize + 1)))
ptrCompareT addrSize flagGen (bin,ptr,flag) (s_ptr,inc) = ((bin',ptr',flag')
,(flag,addr,ptr))
where
bin' = bin + boolToBV (inc && not flag)
ptr' = (bin' `shiftR` 1) `xor` bin'
addr = slice (addrSize `subSNat` d1) d0 bin
flag' = flagGen ptr' s_ptr
isFull :: _
=> SNat addrSize
-> BitVector (addrSize + 1)
-> BitVector (addrSize + 1)
-> Bool
isFull addrSize ptr s_ptr =
ptr == (complement (slice addrSize (addrSize `subSNat` d1) s_ptr) ++#
slice (addrSize `subSNat` d2) d0 s_ptr)
asyncFIFOSynchronizer :: _
=> SNat addrSize
-> SClock wclk
-> SClock rclk
-> Signal' wclk a
-> Signal' wclk Bool
-> Signal' rclk Bool
-> (Signal' rclk a, Signal' rclk Bool, Signal' wclk Bool)
asyncFIFOSynchronizer addrSize wclk rclk wdata winc rinc = (rdata,rempty,wfull)
where
s_rptr = dualFlipFlopSynchronizer rclk wclk 0 rptr
s_wptr = dualFlipFlopSynchronizer wclk rclk 0 wptr
rdata = fifoMem wclk rclk addrSize waddr raddr winc wfull wdata
(rempty,raddr,rptr) = mealyB' rclk (ptrCompareT addrSize (==)) (0,0,True)
(s_wptr,rinc)
(wfull,waddr,wptr) = mealyB' wclk (ptrCompareT addrSize (isFull addrSize))
(0,0,False) (s_rptr,winc)