Created
April 1, 2019 22:13
-
-
Save Ravenslofty/dd73ec8336901ec7163afaddf0f0ac63 to your computer and use it in GitHub Desktop.
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
| #!/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