module Hardware.KansasLava.FIFO where
import Control.Concurrent
import Control.Monad
import Data.Maybe as Maybe
import Data.Sized.Arith as Arith
import Data.Sized.Ix as X
import Data.Word
import Data.Sized.Unsigned
import Language.KansasLava
import System.IO
resetable :: forall a c. (Clock c, Rep a) => Signal c Bool -> a -> Signal c a -> Signal c a
resetable rst val x = mux rst (x,pureS val)
fifoFE :: forall c a counter ix sig .
(Size counter
, Size ix
, counter ~ ADD ix X1
, Rep a
, Rep counter
, Rep ix
, Num counter
, Num ix
, Clock c
, sig ~ Signal c
)
=> Witness ix
-> Signal c Bool
-> Patch (sig (Enabled a)) (sig (Enabled (ix,a)) :> sig Bool)
(sig Ack) (sig Ready :> sig counter)
fifoFE w rst = ackToReadyBridge $$ fifoFE' w rst where
fifoFE' Witness rst ~(inp,mem_ready :> dec_by) = (toReady inp_ready, wr :> inp_done0)
where
inp_try0 :: Signal c Bool
inp_try0 = inp_ready `and2` isEnabled inp
wr :: Signal c (Enabled (ix,a))
wr = packEnabled (inp_try0)
(pack (wr_addr,enabledVal inp))
inp_done0 :: Signal c Bool
inp_done0 = isEnabled wr `and2` fromReady mem_ready
wr_addr :: Signal c ix
wr_addr = resetable rst 0
$ register 0
$ mux inp_done0 (wr_addr,loopingIncS wr_addr)
in_counter0 :: Signal c counter
in_counter0 = resetable rst 0
$ in_counter1
+ (unsigned) inp_done0
dec_by
in_counter1 :: Signal c counter
in_counter1 = register 0 in_counter0
inp_ready :: Signal c Bool
inp_ready = (in_counter1 .<. fromIntegral (size (error "witness" :: ix)))
`and2`
(bitNot rst)
`and2`
(fromReady mem_ready)
fifoBE :: forall a c counter ix sig .
(Size counter
, Size ix
, counter ~ ADD ix X1
, Rep a
, Rep counter
, Rep ix
, Num counter
, Num ix
, Clock c
, sig ~ Signal c
)
=> Witness ix
-> Signal c Bool
-> Patch (sig (Enabled a) :> sig counter) (sig (Enabled a))
(sig (Enabled ix) :> sig Bool) (sig Ack)
fifoBE Witness rst (mem_rd :> inc_by, out_ready) =
let
rd_addr0 :: Signal c ix
rd_addr0 = resetable rst 0
$ mux out_done0 (rd_addr1,loopingIncS rd_addr1)
rd_addr1 = register 0
$ rd_addr0
out_done0 :: Signal c Bool
out_done0 = fromAck out_ready `and2` (isEnabled out)
out :: Signal c (Enabled a)
out = packEnabled ((out_counter1 .>. 0) `and2` bitNot rst `and2` isEnabled mem_rd) (enabledVal mem_rd)
out_counter0 :: Signal c counter
out_counter0 = resetable rst 0
$ out_counter1
+ inc_by
(unsigned) out_done0
out_counter1 = register 0 out_counter0
in
(enabledS rd_addr0 :> out_done0, out)
fifoMem :: forall a c1 c2 counter ix sig1 sig2 .
(Size counter
, Size ix
, counter ~ ADD ix X1
, Rep a
, Rep counter
, Rep ix
, Num counter
, Num ix
, Clock c1
, Clock c2
, sig1 ~ Signal c1
, sig2 ~ Signal c2
, c1 ~ c2
)
=> Witness ix
-> Patch (sig1 (Enabled (ix,a)) :> sig1 Bool) (sig2 (Enabled a) :> sig2 counter)
(sig1 Ready :> sig1 counter) (sig2 (Enabled ix) :> sig2 Bool)
fifoMem Witness ~(~(wr_in :> wr_in_done),~(rd_addr :> sent)) = (toReady high :> dec_fe,mem_val :> inc_be)
where
mem_val = packEnabled (register False (isEnabled rd_addr))
$ syncRead (writeMemory wr_in)
(enabledVal rd_addr)
dec_fe = (unsigned) sent
inc_be = (unsigned) $ register False $ register False $ wr_in_done
fifoCounter :: forall counter . (Num counter, Rep counter) => Seq Bool -> Seq Bool -> Seq Bool -> Seq counter
fifoCounter rst inc dec = counter1
where
counter0 :: Seq counter
counter0 = resetable rst 0
$ counter1
+ (unsigned) inc
(unsigned) dec
counter1 = register 0 counter0
fifoCounter' :: forall counter . (Num counter, Rep counter) => Seq Bool -> Seq counter -> Seq counter -> Seq counter
fifoCounter' rst inc dec = counter1
where
counter0 :: Seq counter
counter0 = resetable rst 0
$ counter1
+ inc
dec
counter1 = register 0 counter0
fifo :: forall a c counter ix .
(Size counter
, Size ix
, counter ~ ADD ix X1
, Rep a
, Rep counter
, Rep ix
, Num counter
, Num ix
, Clock c
)
=> Witness ix
-> Signal c Bool
-> Patch (Signal c (Enabled a)) (Signal c (Enabled a))
(Signal c Ack) (Signal c Ack)
fifo w_ix rst = fifo_patch
where
fifo_patch = fifoFE w_ix rst $$ fifoMem w_ix $$ fifoBE w_ix rst
mulBy :: forall x sz c . (Clock c, Size sz, Num sz, Num x, Rep x) => Witness sz -> Signal c Bool -> Signal c x
mulBy Witness trig = mux trig (pureS 0,pureS $ fromIntegral $ size (error "witness" :: sz))
divBy :: forall x sz c . (Clock c, Size sz, Num sz, Rep sz, Num x, Rep x) => Witness sz -> Signal c Bool -> Signal c Bool -> Signal c x
divBy Witness rst trig = mux issue (0,1)
where
issue = trig .&&. (counter1 .==. (pureS $ fromIntegral (size (error "witness" :: sz) 1)))
counter0 :: Signal c sz
counter0 = cASE [ (rst,0)
, (trig,counter1 + 1)
] counter1
counter1 :: Signal c sz
counter1 = register 0
$ mux issue (counter0,0)