add migen safe input mux
authorLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Thu, 29 Mar 2018 13:08:13 +0000 (14:08 +0100)
committerLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Thu, 29 Mar 2018 13:08:13 +0000 (14:08 +0100)
src/migen/safeinmux.py [new file with mode: 0644]

diff --git a/src/migen/safeinmux.py b/src/migen/safeinmux.py
new file mode 100644 (file)
index 0000000..75d10e7
--- /dev/null
@@ -0,0 +1,85 @@
+from functools import reduce
+from math import log
+from migen.fhdl.module import Module
+from migen.fhdl.structure import Mux, Signal, Array, Constant, If, Case
+from migen.fhdl import verilog
+from migen.sim.core import run_simulation
+
+def orop(x1, x2):
+    return x1 | x2
+
+class SafeInputMux(Module):
+    def __init__(self, inwidth):
+        wlog = int(log(inwidth, 2))
+        self.inputs = Array()
+        for i in range(inwidth):
+            self.inputs.append(Signal(1, name_override="input_{}".format(i)))
+        self.output = Signal(name_override="output")
+        self.selector = Signal(max=inwidth + 1)
+        self.io = set(self.inputs) | set([self.output, self.selector]) 
+        sel_r = Signal(max=inwidth + 1)
+        sel25 = Signal(max=1<<inwidth + 1)
+        zero = Constant(0, wlog)
+        muxes = []
+        for i in range(len(self.inputs)):
+            x = Constant(1<<i, inwidth)
+            choose = Signal()
+            choose.eq(self.selector & x)
+            muxes.append(Mux(self.selector & x, self.inputs[i], zero))
+        mux = self.output.eq(reduce(orop, muxes))
+        self.comb += mux
+        self.sync += sel_r.eq(self.selector)
+
+        d = {}
+        x = 1
+        for i in range(inwidth):
+            d[i] = (sel25.eq(x << i),)
+
+        self.sync += If(self.selector != sel_r,
+                        sel25.eq(0),
+                        ).Else(
+                            Case(sel_r, d)
+                        )
+
+class Blinker(Module):
+    def __init__(self, led, maxperiod1, maxperiod2, select):
+        self.counter = Signal(max=maxperiod1 + 1)
+        self.period1 = Signal(max=maxperiod1 + 1)
+        self.period2 = Signal(max=maxperiod2 + 1)
+        self.selector = Signal(max=select + 1)
+        self.period = Signal(max=maxperiod1 + 1)
+        self.comb += self.period.eq(Mux(self.selector,
+                                        self.period1, self.period2))
+        self.comb += self.period1.eq(maxperiod1)
+        self.comb += self.period2.eq(maxperiod2)
+        self.sync += If(self.counter == 0,
+                        led.eq(~led),
+                        self.counter.eq(self.period)
+                        ).Else(
+                            self.counter.eq(self.counter - 1)
+        )
+        self.led = led
+
+
+def tb(dut):
+    swap = 0
+    for val in [0, 1]:
+        for i in range(4):
+            yield dut.inputs[i].eq(val)
+            for sel in [0,1,2,3]:
+                yield dut.selector.eq(sel)
+                yield # run one more clock
+                s = ''
+                for x in range(len(dut.inputs)):
+                    s += ("{0} ".format((yield dut.inputs[x])))
+                print("{0} out={1} sel={2}".format(s, (yield dut.output),
+                                                (yield dut.selector)))
+                yield
+
+
+if __name__ == '__main__':
+    mux = SafeInputMux(4)
+    print(verilog.convert(mux, mux.io))
+
+    mux = SafeInputMux(4)
+    run_simulation(mux, tb(mux), vcd_name="safeinputmux.vcd")