Skip to content

Instantly share code, notes, and snippets.

@imakin
Last active February 3, 2017 10:53
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save imakin/8f27561331f2ce695bf37be7ee566f5c to your computer and use it in GitHub Desktop.
Save imakin/8f27561331f2ce695bf37be7ee566f5c to your computer and use it in GitHub Desktop.
JKFF simulator
#!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
)
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()
@imakin
Copy link
Author

imakin commented Jan 30, 2017

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment