adding test on migen pinmux
[pinmux.git] / src / migen / safeinmux.py
1 from functools import reduce
2 from math import log
3 from migen.fhdl.module import Module
4 from migen.fhdl.structure import Mux, Signal, Array, Constant, If, Case
5 from migen.fhdl import verilog
6 from migen.sim.core import run_simulation
7
8 def orop(x1, x2):
9 return x1 | x2
10
11 class SafeInputMux(Module):
12 def __init__(self, inwidth):
13 wlog = int(log(inwidth, 2))
14 self.inputs = Array()
15 for i in range(inwidth):
16 self.inputs.append(Signal(1, name_override="input_{}".format(i)))
17 self.output = Signal(name_override="output")
18 self.selector = Signal(max=inwidth + 1)
19 self.io = set(self.inputs) | set([self.output, self.selector])
20 sel_r = Signal(max=inwidth + 1)
21 sel25 = Signal(max=1<<inwidth)
22 zero = Constant(0)
23 muxes = []
24 for i in range(len(self.inputs)):
25 x = Constant(1<<i, inwidth)
26 choose = Signal()
27 choose.eq(self.selector & x)
28 muxes.append(Mux(self.selector & x, self.inputs[i], zero))
29 mux = self.output.eq(reduce(orop, muxes))
30 self.comb += mux
31 self.sync += sel_r.eq(self.selector)
32
33 d = {}
34 x = 1
35 for i in range(inwidth):
36 d[i] = (sel25.eq(x << i),)
37
38 self.sync += If(self.selector != sel_r,
39 sel25.eq(0),
40 ).Else(
41 Case(sel_r, d)
42 )
43
44 class Blinker(Module):
45 def __init__(self, led, maxperiod1, maxperiod2, select):
46 self.counter = Signal(max=maxperiod1 + 1)
47 self.period1 = Signal(max=maxperiod1 + 1)
48 self.period2 = Signal(max=maxperiod2 + 1)
49 self.selector = Signal(max=select + 1)
50 self.period = Signal(max=maxperiod1 + 1)
51 self.comb += self.period.eq(Mux(self.selector,
52 self.period1, self.period2))
53 self.comb += self.period1.eq(maxperiod1)
54 self.comb += self.period2.eq(maxperiod2)
55 self.sync += If(self.counter == 0,
56 led.eq(~led),
57 self.counter.eq(self.period)
58 ).Else(
59 self.counter.eq(self.counter - 1)
60 )
61 self.led = led
62
63
64 def tb(dut):
65 swap = 0
66 for val in [0, 1]:
67 for i in range(4):
68 yield dut.inputs[i].eq(val)
69 for sel in [0,1,2,3]:
70 yield dut.selector.eq(sel)
71 yield # run one more clock
72 yield
73 s = ''
74 ins = []
75 for x in range(len(dut.inputs)):
76 ins.append((yield dut.inputs[x]))
77 for x in range(len(dut.inputs)):
78 s += ("{0} ".format(ins[x]))
79 sel = (yield dut.selector)
80 out = (yield dut.output)
81 yield
82 print("{0} out={1} sel={2}".format(s, out, sel))
83
84 print ("%d %d" % (out, ins[sel]))
85 #assert out == ins[sel]
86
87
88 if __name__ == '__main__':
89 mux = SafeInputMux(4)
90 print(verilog.convert(mux, mux.io))
91
92 mux = SafeInputMux(4)
93 run_simulation(mux, tb(mux), vcd_name="safeinputmux.vcd")