summaryrefslogtreecommitdiff
path: root/hdl/core/alu.py
diff options
context:
space:
mode:
Diffstat (limited to 'hdl/core/alu.py')
-rw-r--r--hdl/core/alu.py195
1 files changed, 114 insertions, 81 deletions
diff --git a/hdl/core/alu.py b/hdl/core/alu.py
index 049c8af..d9858b1 100644
--- a/hdl/core/alu.py
+++ b/hdl/core/alu.py
@@ -2,7 +2,8 @@ from amaranth import *
from amaranth.sim import Simulator, Settle, Delay
from enum import Enum, unique
-from hdl.utils import cmd, DubbleBuff
+from hdl.utils import cmd, step, sim
+from hdl.lib.in_out_buff import InOutBuff
@unique
class AluOpCodes(Enum):
@@ -17,12 +18,10 @@ class AluOpCodes(Enum):
lleft = 8
lright = 9
aright = 10
- set_bit = 11
- clear_bit = 12
- umult = 13
- smult = 14
- udiv = 15
- sdiv = 16
+ umult = 11
+ smult = 12
+ # udiv = 13
+ # sdiv = 14
class ALU(Elaboratable):
def __init__(self, **kargs):
@@ -37,14 +36,13 @@ class ALU(Elaboratable):
self.overflow = Signal(1, reset_less=True)
self.zero = Signal(1, reset_less=True)
self.neg = Signal(1, reset_less=True)
- self.odd = Signal(1, reset_less=True)
self.out = Signal(32, reset_less=True)
self.sim = kargs["sim"] if "sim" in kargs else None
ports_in = [self.in1, self.in2, self.op, self.c_in]
- ports_out = [self.c_in, self.out, self.c_out, self.overflow, self.zero, self.neg, self.odd]
+ ports_out = [self.c_in, self.out, self.c_out, self.overflow, self.zero, self.neg]
self.ports = {'in': ports_in, 'out': ports_out}
def elaborate(self, platform=None):
@@ -66,7 +64,7 @@ class ALU(Elaboratable):
m.d.comb += self.tmp.eq(self.in1 - self.in2)
with m.Case(AluOpCodes.subc.value):
- m.d.comb += self.tmp.eq(self.in1 + (~self.in2 + self.c_in))
+ m.d.comb += self.tmp.eq(self.in1 + ~self.in2 + self.c_in)
with m.Case(AluOpCodes.bit_and.value):
m.d.comb += self.tmp.eq(Cat(self.in1 & self.in2, 0))
@@ -93,12 +91,6 @@ class ALU(Elaboratable):
m.d.comb += tmp2.eq(Cat(0, self.in1).as_signed() >> self.in2[0:5])
m.d.comb += self.tmp.eq(Cat(tmp2[1:33], tmp2[0])) # move shifted bit to carry bit
- with m.Case(AluOpCodes.set_bit.value):
- m.d.comb += self.tmp.eq(Cat(self.in1 | (1 << self.in2[0:5]), 0))
-
- with m.Case(AluOpCodes.clear_bit.value):
- m.d.comb += self.tmp.eq(Cat(self.in1 & ~(1 << self.in2[0:5]), 0))
-
with m.Case(AluOpCodes.umult.value):
m.d.comb += self.tmp.eq(Cat(self.in1[0:16] * self.in2[0:16], 0))
@@ -122,148 +114,189 @@ class ALU(Elaboratable):
m.d.comb += self.out.eq(self.tmp[0:32])
m.d.comb += self.neg.eq(self.out[31])
m.d.comb += self.zero.eq(self.out == 0)
- m.d.comb += self.odd.eq(self.out.xor()) # 1 if odd number of bits, 0 if even
return m
-def test_alu(filename="alu.vcd"):
- dut = ALU(sim=True)
-
- def proc1():
- def sub_proc(val1, val2, c_in=0):
- yield dut.in1.eq(val1)
- yield dut.in2.eq(val2)
- yield dut.c_in.eq(c_in)
- yield
- yield Settle()
+def sub_proc(dut, val1, val2, c_in=0):
+ yield dut.in1.eq(val1)
+ yield dut.in2.eq(val2)
+ yield dut.c_in.eq(c_in)
+ yield
+ yield Settle()
- # test addition
+# test addition
+def test_alu_add():
+ dut = ALU(sim=True)
+ def proc():
yield dut.op.eq(AluOpCodes.add.value)
- yield from sub_proc(27, 13)
+ yield from sub_proc(dut, 27, 13)
out = yield dut.out
assert 27 + 13 == (out), f'ERROR: {out} != {27 + 13}'
+ sim(dut, proc)
- # test addition with carry
+# test addition with carry
+def test_alu_addc():
+ dut = ALU(sim=True)
+ def proc():
yield dut.op.eq(AluOpCodes.addc.value)
- yield from sub_proc(11, 43, 1)
+ yield from sub_proc(dut, 11, 43, 1)
out = yield dut.out.as_signed()
assert 11 + 43 + 1 == out, f'ERROR: {out} != {11 + 43 + 1}'
+ sim(dut, proc)
- # test subtraction
+# test subtraction
+def test_alu_sub():
+ dut = ALU(sim=True)
+ def proc():
yield dut.op.eq(AluOpCodes.sub.value)
- yield from sub_proc(25, 13)
+ yield from sub_proc(dut, 25, 13)
out = yield dut.out
assert 25 - 13 == out, f'ERROR: {out} != {25 - 13}'
+ sim(dut, proc)
- # test subtraction with carry
+# test subtraction with carry
+def test_alu_subc_0():
+ dut = ALU(sim=True)
+ def proc():
yield dut.op.eq(AluOpCodes.subc.value)
- yield from sub_proc(25, -13, 0)
+ yield from sub_proc(dut, 25, -13, 0)
out = yield dut.out.as_signed()
assert 25 + 13 -1 +0 == out, f'ERROR: {out} != {25 + 13 -1 +0}'
+ sim(dut, proc)
- # test subtraction with carry
+# test subtraction with carry
+def test_alu_subc_1():
+ dut = ALU(sim=True)
+ def proc():
yield dut.op.eq(AluOpCodes.subc.value)
- yield from sub_proc(25, -13, 1)
+ yield from sub_proc(dut, 25, -13, 1)
out = yield dut.out.as_signed()
assert 25 + 13 -1 +1 == out, f'ERROR: {out} != {25 + 13 -1 +1}'
+ sim(dut, proc)
- # test binary and
+# test binary and
+def test_alu_and():
+ dut = ALU(sim=True)
+ def proc():
yield dut.op.eq(AluOpCodes.bit_and.value)
- yield from sub_proc(0b10101011, 0b01010101)
+ yield from sub_proc(dut, 0b10101011, 0b01010101)
out = yield dut.out
assert 0b00000001 == out, f'ERROR: {out} != {0b00000001}'
+ sim(dut, proc)
- # test binary or
+# test binary or
+def test_alu_or():
+ dut = ALU(sim=True)
+ def proc():
yield dut.op.eq(AluOpCodes.bit_or.value)
- yield from sub_proc(0b10101011, 0b01000101)
+ yield from sub_proc(dut, 0b10101011, 0b01000101)
out = yield dut.out
assert 0b11101111 == out, f'ERROR: {out} != {0b11101111}'
+ sim(dut, proc)
- # test binary nor
+# test binary nor
+def test_alu_nor():
+ dut = ALU(sim=True)
+ def proc():
yield dut.op.eq(AluOpCodes.bit_nor.value)
- yield from sub_proc(0b10001011, 0b01000101)
+ yield from sub_proc(dut, 0b10001011, 0b01000101)
out = yield dut.out
assert 0b11111111111111111111111100110000 == out, f'ERROR: {bin(out)} != {bin(0b11111111111111111111111100110000)}'
+ sim(dut, proc)
- # test binary xor
+# test binary xor
+def test_alu_xor():
+ dut = ALU(sim=True)
+ def proc():
yield dut.op.eq(AluOpCodes.bit_xor.value)
- yield from sub_proc(0b10001011, 0b01000101)
+ yield from sub_proc(dut, 0b10001011, 0b01000101)
out = yield dut.out
assert 0b11001110 == out, f'ERROR: {out} != {0b11001110}'
+ sim(dut, proc)
- # test logical shift left
+# test logical shift left
+def test_alu_logic_shift_left():
+ dut = ALU(sim=True)
+ def proc():
yield dut.op.eq(AluOpCodes.lleft.value)
- yield from sub_proc(0b10001011, 25) # shift left by 5
+ yield from sub_proc(dut, 0b10001011, 25) # shift left by 5
out = yield dut.out
assert 0b00010110000000000000000000000000 == out, f'ERROR: {bin(out)} != {bin(0b00010110000000000000000000000000)}'
out = yield dut.c_out
assert 1 == out, f'ERROR: {out} != {1}'
+ sim(dut, proc)
- # test logical shift right
+# test logical shift right
+def test_alu_logic_shift_right():
+ dut = ALU(sim=True)
+ def proc():
yield dut.op.eq(AluOpCodes.lright.value)
- yield from sub_proc(0b10001011, 4) # shift right by 5
+ yield from sub_proc(dut, 0b10001011, 4) # shift right by 5
out = yield dut.out
assert 0b1000 == out, f'ERROR: {bin(out)} != {bin(0b1000)}'
out = yield dut.c_out
assert 1 == out, f'ERROR: {out} != {1}'
+ sim(dut, proc)
- # test aligned shift right
+# test arithmetic shift right
+def test_alu_arith_shift_right():
+ dut = ALU(sim=True)
+ def proc():
yield dut.op.eq(AluOpCodes.aright.value)
- yield from sub_proc(0x80001234, 4) # shift right by 4
+ yield from sub_proc(dut, 0x80001234, 4) # shift right by 4
out = yield dut.out
assert 0xF8000123 == out, f'ERROR: {out} != {0xF8000123}'
out = yield dut.c_out
assert 0 == out, f'ERROR: {out} != {0}'
+ sim(dut, proc)
- # test unsigned overflow
+# test unsigned overflow
+def test_alu_unsigned_overflow():
+ dut = ALU(sim=True)
+ def proc():
yield dut.op.eq(AluOpCodes.add.value)
- yield from sub_proc(0xFFFFFFFF, 1) # add 1 to 0xFFFFFFFF
+ yield from sub_proc(dut, 0xFFFFFFFF, 1) # add 1 to 0xFFFFFFFF
out = yield dut.overflow
assert out == 1, f'ERROR: {out} != {1}'
out = yield dut.c_out
assert out == 1, f'ERROR: {out} != {1}'
+ sim(dut, proc)
- # test unsigned underflow
+# test unsigned underflow
+def test_alu_unsigned_underflow():
+ dut = ALU(sim=True)
+ def proc():
yield dut.op.eq(AluOpCodes.add.value)
- yield from sub_proc(0, -1) # subtract 1 from 0
+ yield from sub_proc(dut, 0, -1) # subtract 1 from 0
out = yield dut.overflow
assert out == 1, f'ERROR: {out} != {1}'
out = yield dut.c_out
assert out == 0, f'ERROR: {out} != {0}'
+ sim(dut, proc)
- # test zero
- yield dut.op.eq(AluOpCodes.add.value)
- yield from sub_proc(0, 0) # add 0 to 0
- out = yield dut.zero
- assert out == 1, f'ERROR: {out} != {1}'
-
- # test zero
+# test zero
+def test_alu_zero_0():
+ dut = ALU(sim=True)
+ def proc():
yield dut.op.eq(AluOpCodes.add.value)
- yield from sub_proc(0, 1) # add 0 to 0
+ yield from sub_proc(dut, 0, 1) # add 0 to 0
out = yield dut.zero
assert out == 0, f'ERROR: {out} != {0}'
+ sim(dut, proc)
- # test odd
- yield dut.op.eq(AluOpCodes.add.value)
- yield from sub_proc(0, 0xAAAAAAAA) # add 0 to 0
- out = yield dut.odd
- assert out == 0, f'ERROR: {out} != {0}'
-
- # test odd
+# test zero
+def test_alu_zero_1():
+ dut = ALU(sim=True)
+ def proc():
yield dut.op.eq(AluOpCodes.add.value)
- yield from sub_proc(0, 0xAAAAAAAB) # add 0 to 0
- out = yield dut.odd
+ yield from sub_proc(dut, 0, 0) # add 0 to 0
+ out = yield dut.zero
assert out == 1, f'ERROR: {out} != {1}'
-
+ sim(dut, proc)
- sim = Simulator(dut)
- sim.add_clock(1e-6)
- sim.add_sync_process(proc1)
-
- with sim.write_vcd(filename):
- sim.run()
+
if __name__ == '__main__':
- hdl = DubbleBuff(ALU())
- cmd(hdl, test_alu)
+ hdl = InOutBuff(ALU())
+ cmd(hdl)