module Lava.SequentialCircuits where

import Lava

----------------------------------------------------------------
-- Sequential Circuits

edge :: Signal Bool -> Signal Bool
edge inp :: Signal Bool
inp = Signal Bool
change
  where
    inp' :: Signal Bool
inp'   = Signal Bool -> Signal Bool -> Signal Bool
forall a. Generic a => a -> a -> a
delay Signal Bool
low Signal Bool
inp
    change :: Signal Bool
change = (Signal Bool, Signal Bool) -> Signal Bool
xor2 (Signal Bool
inp, Signal Bool
inp')

toggle :: Signal Bool -> Signal Bool
toggle change :: Signal Bool
change = Signal Bool
out
  where
    out' :: Signal Bool
out' = Signal Bool -> Signal Bool -> Signal Bool
forall a. Generic a => a -> a -> a
delay Signal Bool
low Signal Bool
out
    out :: Signal Bool
out  = (Signal Bool, Signal Bool) -> Signal Bool
xor2 (Signal Bool
change, Signal Bool
out')

delayClk :: b -> (Signal Bool, b) -> b
delayClk init :: b
init (clk :: Signal Bool
clk, inp :: b
inp) = b
out
  where
    out :: b
out = b -> b -> b
forall a. Generic a => a -> a -> a
delay b
init b
val
    val :: b
val = (Signal Bool, (b, b)) -> b
forall a. Choice a => (Signal Bool, (a, a)) -> a
mux (Signal Bool
clk, (b
out, b
inp))

delayN :: a -> t -> t -> t
delayN 0 init :: t
init inp :: t
inp = t
inp
delayN n :: a
n init :: t
init inp :: t
inp = t
out
  where
    out :: t
out  = t -> t -> t
forall a. Generic a => a -> a -> a
delay t
init t
rest
    rest :: t
rest = a -> t -> t -> t
delayN (a
na -> a -> a
forall a. Num a => a -> a -> a
-1) t
init t
inp

always :: Signal Bool -> Signal Bool
always inp :: Signal Bool
inp = Signal Bool
ok
  where
    sofar :: Signal Bool
sofar = Signal Bool -> Signal Bool -> Signal Bool
forall a. Generic a => a -> a -> a
delay Signal Bool
high Signal Bool
ok
    ok :: Signal Bool
ok    = (Signal Bool, Signal Bool) -> Signal Bool
and2 (Signal Bool
inp, Signal Bool
sofar)

constant :: a -> Signal Bool
constant x :: a
x = Signal Bool
ok
  where
    init :: Signal Bool
init = Signal Bool -> Signal Bool -> Signal Bool
forall a. Generic a => a -> a -> a
delay Signal Bool
high Signal Bool
low
    same :: Signal Bool
same = a
x a -> a -> Signal Bool
forall a. Generic a => a -> a -> Signal Bool
<==> a -> a -> a
forall a. Generic a => a -> a -> a
delay a
forall a. Constructive a => a
zero a
x
    ok :: Signal Bool
ok   = Signal Bool -> Signal Bool
always (Signal Bool
init Signal Bool -> Signal Bool -> Signal Bool
<|> Signal Bool
same)

puls :: a -> () -> Signal Bool
puls n :: a
n () = Signal Bool
out
  where
    out :: Signal Bool
out  = a -> Signal Bool -> Signal Bool -> Signal Bool
forall a t. (Eq a, Num a, Generic t) => a -> t -> t -> t
delayN (a
na -> a -> a
forall a. Num a => a -> a -> a
-1) Signal Bool
low Signal Bool
last
    last :: Signal Bool
last = Signal Bool -> Signal Bool -> Signal Bool
forall a. Generic a => a -> a -> a
delay Signal Bool
high Signal Bool
out

outputList :: t b -> () -> b
outputList sigs :: t b
sigs () = b
out
  where
    out :: b
out = (b -> b -> b) -> b -> t b -> b
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr b -> b -> b
forall a. Generic a => a -> a -> a
(|->) b
out t b
sigs

rowSeq :: ((a, b) -> (a, a)) -> b -> a
rowSeq circ :: (a, b) -> (a, a)
circ inp :: b
inp = a
out
  where
    carryIn :: a
carryIn         = a -> a -> a
forall a. Generic a => a -> a -> a
delay a
forall a. Constructive a => a
zero a
carryOut
    (out :: a
out, carryOut :: a
carryOut) = (a, b) -> (a, a)
circ (a
carryIn, b
inp)

rowSeqReset :: ((a, b) -> (a, a)) -> (Signal Bool, b) -> a
rowSeqReset circ :: (a, b) -> (a, a)
circ (reset :: Signal Bool
reset,inp :: b
inp) = a
out
  where
    carryIn :: a
carryIn         = a -> a -> a
forall a. Generic a => a -> a -> a
delay a
forall a. Constructive a => a
zero a
carry
    carry :: a
carry           = (Signal Bool, (a, a)) -> a
forall a. Choice a => (Signal Bool, (a, a)) -> a
mux (Signal Bool
reset, (a
carryOut, a
forall a. Constructive a => a
zero))
    (out :: a
out, carryOut :: a
carryOut) = (a, b) -> (a, a)
circ (a
carryIn, b
inp)

rowSeqPeriod :: a -> ((a, b) -> (a, a)) -> b -> a
rowSeqPeriod n :: a
n circ :: (a, b) -> (a, a)
circ inp :: b
inp = a
out
  where
    reset :: Signal Bool
reset = a -> () -> Signal Bool
forall a. (Eq a, Num a) => a -> () -> Signal Bool
puls a
n ()
    out :: a
out   = ((a, b) -> (a, a)) -> (Signal Bool, b) -> a
forall a b a.
(Constructive a, Choice a) =>
((a, b) -> (a, a)) -> (Signal Bool, b) -> a
rowSeqReset (a, b) -> (a, a)
circ (Signal Bool
reset, b
inp)

----------------------------------------------------------------
-- the end.