create MultiPriorityPicker which can mutually-exclusively select M outputs from
[nmutil.git] / src / nmutil / latch.py
1 from nmigen.compat.sim import run_simulation
2 from nmigen.cli import verilog, rtlil
3 from nmigen import Signal, Module, Const, Elaboratable
4
5 """ jk latch
6
7 module jk(q,q1,j,k,c);
8 output q,q1;
9 input j,k,c;
10 reg q,q1;
11 initial begin q=1'b0; q1=1'b1; end
12 always @ (posedge c)
13 begin
14 case({j,k})
15 {1'b0,1'b0}:begin q=q; q1=q1; end
16 {1'b0,1'b1}: begin q=1'b0; q1=1'b1; end
17 {1'b1,1'b0}:begin q=1'b1; q1=1'b0; end
18 {1'b1,1'b1}: begin q=~q; q1=~q1; end
19 endcase
20 end
21 endmodule
22 """
23
24 def latchregister(m, incoming, outgoing, settrue, name=None):
25 reg = Signal.like(incoming, name=name) # make reg same as input. reset OK.
26 with m.If(settrue):
27 m.d.sync += reg.eq(incoming) # latch input into register
28 m.d.comb += outgoing.eq(incoming) # return input (combinatorial)
29 with m.Else():
30 m.d.comb += outgoing.eq(reg) # return input (combinatorial)
31
32 def mkname(prefix, suffix):
33 if suffix is None:
34 return prefix
35 return "%s_%s" % (prefix, suffix)
36
37 class SRLatch(Elaboratable):
38 def __init__(self, sync=True, llen=1, name=None):
39 self.sync = sync
40 self.llen = llen
41 s_n, r_n = mkname("s", name), mkname("r", name)
42 q_n, qn_n = mkname("q", name), mkname("qn", name)
43 qlq_n = mkname("qlq", name)
44 self.s = Signal(llen, name=s_n, reset=0)
45 self.r = Signal(llen, name=r_n, reset=(1<<llen)-1) # defaults to off
46 self.q = Signal(llen, name=q_n, reset_less=True)
47 self.qn = Signal(llen, name=qn_n, reset_less=True)
48 self.qlq = Signal(llen, name=qlq_n, reset_less=True)
49
50 def elaborate(self, platform):
51 m = Module()
52 q_int = Signal(self.llen)
53
54 m.d.sync += q_int.eq((q_int & ~self.r) | self.s)
55 if self.sync:
56 m.d.comb += self.q.eq(q_int)
57 else:
58 m.d.comb += self.q.eq((q_int & ~self.r) | self.s)
59 m.d.comb += self.qn.eq(~self.q)
60 m.d.comb += self.qlq.eq(self.q | q_int) # useful output
61
62 return m
63
64 def ports(self):
65 return self.s, self.r, self.q, self.qn
66
67
68 def sr_sim(dut):
69 yield dut.s.eq(0)
70 yield dut.r.eq(0)
71 yield
72 yield
73 yield
74 yield dut.s.eq(1)
75 yield
76 yield
77 yield
78 yield dut.s.eq(0)
79 yield
80 yield
81 yield
82 yield dut.r.eq(1)
83 yield
84 yield
85 yield
86 yield dut.r.eq(0)
87 yield
88 yield
89 yield
90
91 def test_sr():
92 dut = SRLatch(llen=4)
93 vl = rtlil.convert(dut, ports=dut.ports())
94 with open("test_srlatch.il", "w") as f:
95 f.write(vl)
96
97 run_simulation(dut, sr_sim(dut), vcd_name='test_srlatch.vcd')
98
99 dut = SRLatch(sync=False, llen=4)
100 vl = rtlil.convert(dut, ports=dut.ports())
101 with open("test_srlatch_async.il", "w") as f:
102 f.write(vl)
103
104 run_simulation(dut, sr_sim(dut), vcd_name='test_srlatch_async.vcd')
105
106 if __name__ == '__main__':
107 test_sr()