Skip to content

Instantly share code, notes, and snippets.

@Ravenslofty
Created April 1, 2019 22:13
Show Gist options
  • Select an option

  • Save Ravenslofty/dd73ec8336901ec7163afaddf0f0ac63 to your computer and use it in GitHub Desktop.

Select an option

Save Ravenslofty/dd73ec8336901ec7163afaddf0f0ac63 to your computer and use it in GitHub Desktop.
#!/usr/bin/env python3
from migen import Array, Cat, Module, Signal
from migen import sim
from migen.fhdl import verilog
# 74LS153 dual 4:1 multiplexer
class IC74153(Module):
def __init__(self):
self.table0 = Array(Signal() for a in range(4))
self.table1 = Array(Signal() for a in range(4))
self.select = Signal(2)
self.disable = Signal(2)
self.out = Signal(2)
###
x0 = self.table0[self.select]
x1 = self.table1[self.select]
self.comb += self.out[0].eq(x0 & ~self.disable[0])
self.comb += self.out[1].eq(x1 & ~self.disable[1])
# 74LS182 carry generator
class IC74182(Module):
def __init__(self):
self.cin = Signal()
self.pin = Array(Signal() for a in range(4)) # Inverted
self.gin = Array(Signal() for a in range(4)) # Inverted
self.carry = Array(Signal() for a in range(3))
self.prop = Signal() # Inverted
self.gen = Signal() # Inverted
###
self.comb += self.carry[0].eq((self.cin & self.pin[0]) | self.gin[0])
self.comb += self.carry[1].eq((self.carry[0] & self.pin[1]) | self.gin[1])
self.comb += self.carry[2].eq((self.carry[1] & self.pin[2]) | self.gin[2])
self.comb += self.prop.eq(~(self.pin[0] & self.pin[1] & self.pin[2] & self.pin[3]))
self.comb += self.gen.eq(~(self.gin[3] |
(self.gin[2] & self.pin[3]) |
(self.gin[1] & self.pin[3] & self.pin[2]) |
(self.gin[0] & self.pin[3] & self.pin[2] & self.pin[1])))
# 74LS86 quad XOR gate
class IC7486(Module):
def __init__(self):
self.i = Array(Signal(2) for a in range(4))
self.o = Array(Signal() for a in range(4))
###
for i in range(4):
self.comb += self.o[i].eq(self.i[i][0] ^ self.i[i][1])
class ALUSlice(Module):
def __init__(self):
self.table0 = Array(Signal() for a in range(4))
self.table1 = Array(Signal() for a in range(4))
self.a = Array(Signal() for a in range(4))
self.b = Array(Signal() for a in range(4))
self.cin = Signal()
self.f = Array(Signal() for a in range(4))
self.prop = Signal()
self.gen = Signal()
###
mux_a = IC74153()
mux_b = IC74153()
mux_c = IC74153()
mux_d = IC74153()
carry = IC74182()
xor = IC7486()
self.submodules += mux_a, mux_b, mux_c, mux_d, carry, xor
for i, mux in enumerate({mux_a, mux_b, mux_c, mux_d}):
for x in range(4):
self.comb += mux.table0[x].eq(self.table0[x])
self.comb += mux.table1[x].eq(self.table1[x])
self.comb += mux.select.eq(Cat(self.a[i], self.b[i]))
self.comb += mux.disable.eq(0)
self.comb += carry.pin[i].eq(mux.out[0])
self.comb += carry.gin[i].eq(mux.out[1])
self.comb += xor.i[i][0].eq(0)#self.cin if i == 0 else carry.carry[i - 1])
self.comb += xor.i[i][1].eq(mux.out[1])
self.comb += self.f[i].eq(xor.o[i])
self.comb += carry.cin.eq(self.cin)
self.comb += self.prop.eq(carry.prop)
self.comb += self.gen.eq(carry.gen)
alu_slice = ALUSlice()
def test_func(pt, gt, ok):
# Propagate table
for i in range(4):
yield alu_slice.table0[i].eq(pt[i])
# Generate table
for i in range(4):
yield alu_slice.table1[i].eq(gt[i])
# Carry
yield alu_slice.cin.eq(0)
for a in range(16):
yield alu_slice.a[0].eq(a & 1 == 1)
yield alu_slice.a[1].eq(a & 2 == 2)
yield alu_slice.a[2].eq(a & 4 == 4)
yield alu_slice.a[3].eq(a & 8 == 8)
for b in range(16):
yield alu_slice.b[0].eq(b & 1 == 1)
yield alu_slice.b[1].eq(b & 2 == 2)
yield alu_slice.b[2].eq(b & 4 == 4)
yield alu_slice.b[3].eq(b & 8 == 8)
yield
f = yield alu_slice.f
x = 0
x |= 1 if f[0] == True else 0
x |= 2 if f[1] == True else 0
x |= 4 if f[2] == True else 0
x |= 8 if f[3] == True else 0
if not ok(a, b, x):
print("A = {}, B = {}, X = {}".format(a, b, x))
assert False
def test_and():
pt = (0, 0, 0, 0)
gt = (0, 0, 0, 1)
f = lambda a, b, x: a & b == x
yield from test_func(pt, gt, f)
print("AND is OK")
def test_or():
pt = (0, 0, 0, 0)
gt = (0, 1, 1, 1)
f = lambda a, b, x: a | b == x
yield from test_func(pt, gt, f)
print("OR is OK")
def test_xor():
pt = (0, 0, 0, 0)
gt = (0, 1, 1, 0)
f = lambda a, b, x: a ^ b == x
yield from test_func(pt, gt, f)
print("XOR is OK")
def test_add():
pt = (1, 0, 0, 1)
gt = (1, 1, 1, 0)
f = lambda a, b, x: a + b == x
yield from test_func(pt, gt, f)
print("ADD is OK")
def test():
yield from test_and()
yield from test_or()
yield from test_xor()
yield from test_add()
if __name__ == "__main__":
sim.run_simulation(alu_slice, test())
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment