Last active
February 3, 2017 10:53
-
-
Save imakin/8f27561331f2ce695bf37be7ee566f5c to your computer and use it in GitHub Desktop.
JKFF simulator
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!python3 | |
class Device(object): | |
def clock(self): | |
raise NotImplemented("unimplemented clock method") | |
class Terminal(Device): | |
""" | |
wired object for any devices | |
Members: | |
connections: all connected Terminal/wire object array | |
value: boolean value True(High/Set), False=(Low/Reset) | |
usage: as boolean value | |
""" | |
connections = [] | |
value = True | |
label = "" | |
def __init__(self, label="", connections_init = False): | |
""" | |
label is optional information | |
connections_init is an array to be put in connections | |
""" | |
self.connections = [] | |
self.label = label | |
if connections_init: | |
self.connections = connections_init | |
self.value = False | |
def add_connection(self, terminal): | |
if terminal not in self.connections: | |
if terminal is not self: | |
self.connections.append(terminal) | |
for t in terminal.connections: | |
if not(t in self.connections): | |
if t is not self: | |
self.connections.append(t) | |
if self not in terminal.connections: | |
if terminal is not self: | |
terminal.connections.append(self) | |
#~ print(self.connections) | |
def clock(self): | |
for c in self.connections: | |
c.value = self.value | |
def __bool__(self): | |
self.clock() | |
return self.value | |
class AND(Device): | |
""" | |
Terminals: | |
a | |
b | |
output | |
inputs: | |
[a,b] | |
outputs: | |
[output] | |
""" | |
a = None | |
b = None | |
inputs = [] | |
output = None | |
outputs = [] | |
def __init__(self): | |
self.a = Terminal() | |
self.b = Terminal() | |
self.output = Terminal() | |
self.inputs = [self.a,self.b] | |
self.outputs = [self.output] | |
def clock(self): | |
self.output.value = (self.a.value and self.b.value) | |
self.output.clock() | |
def __bool__(self): | |
self.clock() | |
return bool(self.output.value) | |
class NAND(AND): | |
def __init__(self): | |
super().__init__() | |
def clock(self): | |
super().clock() | |
self.output.value = not self.output.value | |
self.output.clock() | |
def __bool__(self): | |
self.clock() | |
return bool(self.output.value) | |
class AND3(AND): | |
c = None | |
def __init__(self): | |
super().__init__() | |
self.c = Terminal() | |
self.inputs.append(self.c) | |
def clock(self): | |
try: | |
bool(self.a) | |
except TypeError as e: | |
print("HAI", self.a, self.a.value) | |
self.output.value = (bool(self.a) and bool(self.b) and bool(self.c)) | |
self.output.clock() | |
def __bool__(self): | |
self.clock() | |
return bool(self.output.value) | |
class NAND3(AND3): | |
def __init__(self): | |
super().__init__() | |
def clock(self): | |
super().clock() | |
self.output.value = not self.output.value | |
self.output.clock() | |
def __bool__(self): | |
self.clock() | |
return bool(self.output.value) | |
class NOT(Device): | |
a = None | |
output = None | |
inputs = [] | |
outputs = [] | |
def __init__(self): | |
self.a = Terminal() | |
self.output = Terminal() | |
self.inputs = [self.a] | |
self.outputs = [self.output] | |
def clock(self): | |
self.output.value = not (self.a.value) | |
self.output.clock() | |
def __bool__(self): | |
self.output.value = not (self.a.value) | |
return bool(self.output.value) | |
class JKFF(Device): | |
j = None | |
k = None | |
clk = None | |
q = None | |
qn= None | |
inputs = [] | |
outputs = [] | |
def __init__(self): | |
""" | |
n0 n2 n4 n6 | |
n1 n3 n5 n7 | |
nt | |
""" | |
self.j = Terminal("j") | |
self.k = Terminal("k") | |
self.clk = Terminal("clk") | |
self.q = Terminal("q") | |
self.qn = Terminal("not q") | |
self.inputs = [self.j, self.k, self.clk] | |
self.outputs = [self.q, self.qn] | |
self.n0 = NAND3() | |
self.n1 = NAND3() | |
self.n2 = NAND() | |
self.n3 = NAND() | |
self.n4 = NAND() | |
self.n5 = NAND() | |
self.n6 = NAND() | |
self.n7 = NAND() | |
self.nt = NOT() | |
self.gates = [ | |
self.n0, | |
self.n1, | |
self.n2, | |
self.n3, | |
self.n4, | |
self.n5, | |
self.n6, | |
self.n7, | |
self.nt, | |
] | |
self.nt.a.add_connection(self.clk) | |
self.n0.a.add_connection(self.j) | |
self.n0.b.add_connection(self.qn) | |
self.n0.c.add_connection(self.clk) | |
self.n1.a.add_connection(self.clk) | |
self.n1.b.add_connection(self.q) | |
self.n1.c.add_connection(self.k) | |
self.n2.a.add_connection(self.n0.output) | |
self.n2.b.add_connection(self.n3.output) | |
self.n3.a.add_connection(self.n2.output) | |
self.n3.b.add_connection(self.n1.output) | |
self.n4.a.add_connection(self.n2.output) | |
self.n4.b.add_connection(self.nt.output) | |
self.n5.a.add_connection(self.nt.output) | |
self.n5.b.add_connection(self.n3.output) | |
self.n6.a.add_connection(self.n4.output) | |
self.n6.b.add_connection(self.n7.output) | |
self.n7.a.add_connection(self.n6.output) | |
self.n7.b.add_connection(self.n5.output) | |
self.n6.output.add_connection(self.q) | |
self.n7.output.add_connection(self.qn) | |
def clock(self, half=False, half_value=None): | |
""" | |
clock the JKFF, | |
if half is False or unset, will be full-clocked | |
if half is True, will only clock to value half_value(True/False) | |
if half_value is None, clk will be valued to its connections[0] value | |
""" | |
if not half: | |
#clock start-High | |
self.j.clock() | |
self.k.clock() | |
self.clk.value = True | |
self.clk.clock() | |
for gate in self.gates: | |
gate.clock() | |
self.clk.value = False | |
self.clk.clock() | |
for gate in self.gates: | |
gate.clock() | |
self.q.clock() | |
self.qn.clock() | |
else: | |
if (half_value is not None): | |
self.clk.value = half_value | |
else: | |
self.clk.value = ( | |
self.clk.connections[0].value | |
) | |
if self.clk.value: | |
self.j.clock() | |
self.k.clock() | |
self.clk.clock() | |
for gate in self.gates: | |
gate.clock() | |
if self.clk.value==False: | |
self.q.clock() | |
self.qn.clock() | |
def __bool__(self): | |
return self.q.value | |
def __int__(self): | |
return int(self.q.value==True) | |
class Counter4Synch(Device): | |
counter = 0 | |
def __init__(self): | |
self.counter = 0 | |
self.jkff0 = JKFF() | |
self.jkff1 = JKFF() | |
self.jkff2 = JKFF() | |
self.jkff3 = JKFF() | |
self.n2 = AND() | |
self.n3 = AND3() | |
self.jkff0.clk.add_connection(self.jkff1.clk) | |
self.jkff0.clk.add_connection(self.jkff2.clk) | |
self.jkff0.clk.add_connection(self.jkff3.clk) | |
self.jkff0.j.add_connection(self.jkff0.k) | |
self.n2.a.add_connection(self.jkff0.q) | |
self.n2.b.add_connection(self.jkff1.q) | |
self.n3.a.add_connection(self.jkff0.q) | |
self.n3.b.add_connection(self.jkff1.q) | |
self.n3.c.add_connection(self.jkff2.q) | |
self.jkff0.q.add_connection(self.jkff1.j) | |
self.jkff0.q.add_connection(self.jkff1.k) | |
self.n2.output.add_connection(self.jkff2.j) | |
self.n2.output.add_connection(self.jkff2.k) | |
self.n3.output.add_connection(self.jkff3.j) | |
self.n3.output.add_connection(self.jkff3.k) | |
self.jkff0.j.value = True | |
self.jkff0.k.value = True | |
def clock(self): | |
self.jkff3.clock(half=False) | |
self.jkff2.clock(half=False) | |
self.jkff1.clock(half=False) | |
self.jkff0.clock(half=False) | |
self.n2.clock() | |
self.n3.clock() | |
self.counter = ( | |
int(self.jkff3)<<3 | | |
int(self.jkff2)<<2 | | |
int(self.jkff1)<<1 | | |
int(self.jkff0)<<0 | |
) | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import unittest | |
from device import * | |
class DeviceTest(unittest.TestCase): | |
def test_terminal(self): | |
na = NAND() | |
nb = NAND() | |
c = Terminal("c") | |
na.a.add_connection(c) | |
self.assertEqual(nb.a.connections,[]) | |
def test_ff_one(self): | |
print("test J terminal") | |
jkff = JKFF() | |
print("test set state") | |
jkff.j.value = True | |
jkff.k.value = False | |
jkff.clock() | |
self.assertTrue(jkff.q) | |
self.assertFalse(jkff.qn) | |
print("test togle state") | |
jkff.j.value = True | |
jkff.k.value = True | |
jkff.clock(False) | |
self.assertFalse(jkff.q) | |
self.assertTrue(jkff.qn) | |
jkff.clock(False) | |
self.assertTrue(jkff.q) | |
self.assertFalse(jkff.qn) | |
jkff.clock(False) | |
self.assertFalse(jkff.q) | |
self.assertTrue(jkff.qn) | |
def test_ff_8bit_asynch(self): | |
jkffs = [JKFF() for x in range(0,8)] | |
for x in range(0,8): | |
jkffs[x].j.value = True | |
jkffs[x].k.value = True | |
if x>0: | |
jkffs[x].clk.add_connection( | |
jkffs[x-1].q | |
) | |
jkffs[0].clock() | |
def test_ff_synch(self): | |
jkff0 = JKFF() | |
jkff1 = JKFF() | |
jkff2 = JKFF() | |
jkff3 = JKFF() | |
n2 = AND() | |
n3 = AND3() | |
jkff0.clk.add_connection(jkff1.clk) | |
jkff0.clk.add_connection(jkff2.clk) | |
jkff0.clk.add_connection(jkff3.clk) | |
jkff0.j.add_connection(jkff0.k) | |
n2.a.add_connection(jkff0.q) | |
n2.b.add_connection(jkff1.q) | |
n3.a.add_connection(jkff0.q) | |
n3.b.add_connection(jkff1.q) | |
n3.c.add_connection(jkff2.q) | |
jkff0.q.add_connection(jkff1.j) | |
jkff0.q.add_connection(jkff1.k) | |
n2.output.add_connection(jkff2.j) | |
n2.output.add_connection(jkff2.k) | |
n3.output.add_connection(jkff3.j) | |
n3.output.add_connection(jkff3.k) | |
jkff0.j.value = True | |
jkff0.k.value = True | |
first = True | |
jkff3.clock(half=False) | |
jkff2.clock(half=False) | |
jkff1.clock(half=False) | |
jkff0.clock(half=False) | |
n2.clock() | |
n3.clock() | |
self.assertEqual(jkff3.q.value, True) | |
self.assertEqual(jkff2.q.value, True) | |
self.assertEqual(jkff1.q.value, True) | |
self.assertEqual(jkff0.q.value, True) | |
#~ print(jkff3.q.value, jkff2.q.value, jkff1.q.value, jkff0.q.value) | |
jkff3.clock(half=False) | |
jkff2.clock(half=False) | |
jkff1.clock(half=False) | |
jkff0.clock(half=False) | |
n2.clock() | |
n3.clock() | |
self.assertEqual(jkff3.q.value, False) | |
self.assertEqual(jkff2.q.value, False) | |
self.assertEqual(jkff1.q.value, False) | |
self.assertEqual(jkff0.q.value, False) | |
#~ print(jkff3.q.value, jkff2.q.value, jkff1.q.value, jkff0.q.value) | |
jkff3.clock(half=False) | |
jkff2.clock(half=False) | |
jkff1.clock(half=False) | |
jkff0.clock(half=False) | |
n2.clock() | |
n3.clock() | |
self.assertEqual(jkff3.q.value, False) | |
self.assertEqual(jkff2.q.value, False) | |
self.assertEqual(jkff1.q.value, False) | |
self.assertEqual(jkff0.q.value, True) | |
#~ print(jkff3.q.value, jkff2.q.value, jkff1.q.value, jkff0.q.value) | |
jkff3.clock(half=False) | |
jkff2.clock(half=False) | |
jkff1.clock(half=False) | |
jkff0.clock(half=False) | |
n2.clock() | |
n3.clock() | |
self.assertEqual(jkff3.q.value, False) | |
self.assertEqual(jkff2.q.value, False) | |
self.assertEqual(jkff1.q.value, True) | |
self.assertEqual(jkff0.q.value, False) | |
#~ print(jkff3.q.value, jkff2.q.value, jkff1.q.value, jkff0.q.value) | |
jkff3.clock(half=False) | |
jkff2.clock(half=False) | |
jkff1.clock(half=False) | |
jkff0.clock(half=False) | |
n2.clock() | |
n3.clock() | |
self.assertEqual(jkff3.q.value, False) | |
self.assertEqual(jkff2.q.value, False) | |
self.assertEqual(jkff1.q.value, True) | |
self.assertEqual(jkff0.q.value, True) | |
#~ print(jkff3.q.value, jkff2.q.value, jkff1.q.value, jkff0.q.value) | |
jkff3.clock(half=False) | |
jkff2.clock(half=False) | |
jkff1.clock(half=False) | |
jkff0.clock(half=False) | |
n2.clock() | |
n3.clock() | |
self.assertEqual(jkff3.q.value, False) | |
self.assertEqual(jkff2.q.value, True) | |
self.assertEqual(jkff1.q.value, False) | |
self.assertEqual(jkff0.q.value, False) | |
#~ print(jkff3.q.value, jkff2.q.value, jkff1.q.value, jkff0.q.value) | |
jkff3.clock(half=False) | |
jkff2.clock(half=False) | |
jkff1.clock(half=False) | |
jkff0.clock(half=False) | |
n2.clock() | |
n3.clock() | |
self.assertEqual(jkff3.q.value, False) | |
self.assertEqual(jkff2.q.value, True) | |
self.assertEqual(jkff1.q.value, False) | |
self.assertEqual(jkff0.q.value, True) | |
#~ print(jkff3.q.value, jkff2.q.value, jkff1.q.value, jkff0.q.value) | |
def test_counter(self): | |
c = Counter4Synch() | |
while (c.counter!=8): | |
c.clock() | |
self.assertEqual(c.counter,8) | |
if __name__=='__main__': | |
unittest.main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
http://www.falstad.com/circuit/e-jkff.html