1 # SPDX-License-Identifier: LGPL-3-or-later
3 This work is funded through NLnet under Grant 2019-02-012
9 from nmigen
.compat
.sim
import run_simulation
10 from nmigen
.cli
import verilog
, rtlil
11 from nmigen
import Record
, Signal
, Module
, Const
, Elaboratable
, Mux
15 module jk(q,q1,j,k,c);
19 initial begin q=1'b0; q1=1'b1; end
23 {1'b0,1'b0}:begin q=q; q1=q1; end
24 {1'b0,1'b1}: begin q=1'b0; q1=1'b1; end
25 {1'b1,1'b0}:begin q=1'b1; q1=1'b0; end
26 {1'b1,1'b1}: begin q=~q; q1=~q1; end
33 def latchregister(m
, incoming
, outgoing
, settrue
, name
=None):
36 based on a conditon, "settrue", incoming data will be "latched"
37 into a register and passed out on "outgoing".
39 * if "settrue" is ASSERTED, outgoing is COMBINATORIALLY equal to incoming
40 * on the same cycle that settrue is DEASSERTED, outgoing REMAINS
41 equal (indefinitely) to the incoming value
43 # make reg same as input. reset OK.
44 if isinstance(incoming
, Record
):
45 reg
= Record
.like(incoming
, name
=name
)
47 reg
= Signal
.like(incoming
, name
=name
)
48 m
.d
.comb
+= outgoing
.eq(Mux(settrue
, incoming
, reg
))
49 with m
.If(settrue
): # pass in some kind of expression/condition here
50 m
.d
.sync
+= reg
.eq(incoming
) # latch input into register
54 def mkname(prefix
, suffix
):
57 return "%s_%s" % (prefix
, suffix
)
60 class SRLatch(Elaboratable
):
61 def __init__(self
, sync
=True, llen
=1, name
=None):
64 s_n
, r_n
= mkname("s", name
), mkname("r", name
)
65 q_n
, qn_n
= mkname("q", name
), mkname("qn", name
)
66 qint
= mkname("qint", name
)
67 qlq_n
= mkname("qlq", name
)
68 self
.s
= Signal(llen
, name
=s_n
, reset
=0)
69 self
.r
= Signal(llen
, name
=r_n
, reset
=(1 << llen
)-1) # defaults to off
70 self
.q
= Signal(llen
, name
=q_n
, reset_less
=True)
71 self
.qn
= Signal(llen
, name
=qn_n
, reset_less
=True)
72 self
.qlq
= Signal(llen
, name
=qlq_n
, reset_less
=True)
73 self
.q_int
= Signal(llen
, name
=qint
, reset_less
=True)
75 def elaborate(self
, platform
):
78 next_o
= Signal(self
.llen
, reset_less
=True)
79 m
.d
.comb
+= next_o
.eq((self
.q_int
& ~self
.r
) | self
.s
)
80 m
.d
.sync
+= self
.q_int
.eq(next_o
)
82 m
.d
.comb
+= self
.q
.eq(self
.q_int
)
84 m
.d
.comb
+= self
.q
.eq(next_o
)
85 m
.d
.comb
+= self
.qn
.eq(~self
.q
)
86 m
.d
.comb
+= self
.qlq
.eq(self
.q | self
.q_int
) # useful output
91 return self
.s
, self
.r
, self
.q
, self
.qn
119 dut
= SRLatch(llen
=4)
120 vl
= rtlil
.convert(dut
, ports
=dut
.ports())
121 with
open("test_srlatch.il", "w") as f
:
124 run_simulation(dut
, sr_sim(dut
), vcd_name
='test_srlatch.vcd')
126 dut
= SRLatch(sync
=False, llen
=4)
127 vl
= rtlil
.convert(dut
, ports
=dut
.ports())
128 with
open("test_srlatch_async.il", "w") as f
:
131 run_simulation(dut
, sr_sim(dut
), vcd_name
='test_srlatch_async.vcd')
134 if __name__
== '__main__':