add docs
[nmutil.git] / src / nmutil / latch.py
index 7d6a1efe22c881585a626e397590337186f6ef1b..f4c03ab9f5784f7c1365bc3c8454c12fc6e95140 100644 (file)
@@ -1,6 +1,13 @@
+"""
+    This work is funded through NLnet under Grant 2019-02-012
+
+    License: LGPLv3+
+
+
+"""
 from nmigen.compat.sim import run_simulation
 from nmigen.cli import verilog, rtlil
-from nmigen import Record, Signal, Module, Const, Elaboratable
+from nmigen import Record, Signal, Module, Const, Elaboratable, Mux
 
 """ jk latch
 
@@ -21,47 +28,59 @@ always @ (posedge c)
 endmodule
 """
 
+
 def latchregister(m, incoming, outgoing, settrue, name=None):
+    """latchregister
+
+    based on a conditon, "settrue", incoming data will be "latched"
+    into a register and passed out on "outgoing".
+
+    * if "settrue" is ASSERTED, outgoing is COMBINATORIALLY equal to incoming
+    * on the same cycle that settrue is DEASSERTED, outgoing REMAINS
+      equal (indefinitely) to the incoming value
+    """
     # make reg same as input. reset OK.
     if isinstance(incoming, Record):
         reg = Record.like(incoming, name=name)
     else:
         reg = Signal.like(incoming, name=name)
+    m.d.comb += outgoing.eq(Mux(settrue, incoming, reg))
     with m.If(settrue): # pass in some kind of expression/condition here
         m.d.sync += reg.eq(incoming)      # latch input into register
-        m.d.comb += outgoing.eq(incoming) # return input (combinatorial)
-    with m.Else():
-        m.d.comb += outgoing.eq(reg) # return input (combinatorial)
+    return reg
+
 
 def mkname(prefix, suffix):
     if suffix is None:
         return prefix
     return "%s_%s" % (prefix, suffix)
 
+
 class SRLatch(Elaboratable):
     def __init__(self, sync=True, llen=1, name=None):
         self.sync = sync
         self.llen = llen
         s_n, r_n = mkname("s", name), mkname("r", name)
         q_n, qn_n = mkname("q", name), mkname("qn", name)
+        qint = mkname("qint", name)
         qlq_n = mkname("qlq", name)
         self.s = Signal(llen, name=s_n, reset=0)
         self.r = Signal(llen, name=r_n, reset=(1<<llen)-1) # defaults to off
         self.q = Signal(llen, name=q_n, reset_less=True)
         self.qn = Signal(llen, name=qn_n, reset_less=True)
         self.qlq = Signal(llen, name=qlq_n, reset_less=True)
+        self.q_int = Signal(llen, name=qint, reset_less=True)
 
     def elaborate(self, platform):
         m = Module()
-        q_int = Signal(self.llen)
 
-        m.d.sync += q_int.eq((q_int & ~self.r) | self.s)
+        m.d.sync += self.q_int.eq((self.q_int & ~self.r) | self.s)
         if self.sync:
-            m.d.comb += self.q.eq(q_int)
+            m.d.comb += self.q.eq(self.q_int)
         else:
-            m.d.comb += self.q.eq((q_int & ~self.r) | self.s)
+            m.d.comb += self.q.eq((self.q_int & ~self.r) | self.s)
         m.d.comb += self.qn.eq(~self.q)
-        m.d.comb += self.qlq.eq(self.q | q_int) # useful output
+        m.d.comb += self.qlq.eq(self.q | self.q_int) # useful output
 
         return m