----------------------------------------------------------------------
-- A node that outputs true whenever there is a rising edge
-- on its input stream.
----------------------------------------------------------------------
node RisingEdge( X : bool ) returns ( Y : bool );
let
  Y = false -> X and not pre X;
tel

----------------------------------------------------------------------
-- A node that outputs true whenever there is a falling edge
-- on its input stream.
----------------------------------------------------------------------
node FallingEdge( X : bool ) returns ( Y : bool );
let
 Y = false -> not X  and pre(X);
tel

----------------------------------------------------------------------
-- This node has the same behaviour as the FallingEdge node above. 
-- It just has a different implementation, using RisingEdge.
----------------------------------------------------------------------
node FallingEdge2( X : bool ) returns ( Y : bool );
let
  Y = RisingEdge(not X);
tel

----------------------------------------------------------------------
-- A synchronous observer that checks whether the two implementations 
-- of the falling edge are equal. 
--
-- Convince yourself that the implementations are equivalent:
-- 1) Simulate it using luke. 
-- 2) Draw a truth table.
-- 3) Prove it using "luke ---node ReqEdge edge.lus --verify".
--
-- Try to make other implementations of FallingEdge and check them 
-- too.
----------------------------------------------------------------------
node ReqEdge(X: bool) returns(OK: bool);
let
  OK = FallingEdge(X) = FallingEdge2(X);
tel