alu_done = Signal(reset_less=True)
m.d.comb += alu_done.eq(self.counter == 1)
- # in a sequential ALU, valid_o rises when the ALU is done
- # and falls when acknowledged by ready_i
- valid_o = Signal()
- with m.If(alu_done):
- m.d.sync += valid_o.eq(1)
- with m.Elif(self.n.ready_i):
- m.d.sync += valid_o.eq(0)
-
# select handshake handling according to ALU type
with m.If(go_now):
# with a combinatorial, no-delay ALU, just pass through
# ready_o responds to valid_i, but only if the ALU is idle
m.d.comb += self.p.ready_o.eq(self.p.valid_i & alu_idle)
# select the internally generated valid_o, above
- m.d.comb += self.n.valid_o.eq(valid_o)
+ m.d.comb += self.n.valid_o.eq(alu_done)
# hold the ALU result until ready_o is asserted
alu_r = Signal(self.width)
# MUL, to take 5 instructions
with m.If(self.op.insn_type == InternalOp.OP_MUL_L64):
m.d.sync += self.counter.eq(5)
- # SHIFT to take 7
+ # SHIFT to take 1, straight away
with m.Elif(self.op.insn_type == InternalOp.OP_SHR):
- m.d.sync += self.counter.eq(7)
- # ADD/SUB to take 2, straight away
+ m.d.sync += self.counter.eq(1)
+ # ADD/SUB to take 3
with m.Elif(self.op.insn_type == InternalOp.OP_ADD):
m.d.sync += self.counter.eq(3)
# others to take no delay
with m.Else():
m.d.comb += go_now.eq(1)
- with m.Else():
- # decrement the counter while the ALU is not idle
+ with m.Elif(~alu_done | self.n.ready_i):
+ # decrement the counter while the ALU is neither idle nor finished
m.d.sync += self.counter.eq(self.counter - 1)
# choose between zero-delay output, or registered
return list(self)
def run_op(dut, a, b, op, inv_a=0):
+ from nmigen.back.pysim import Settle
yield dut.a.eq(a)
yield dut.b.eq(b)
yield dut.op.insn_type.eq(op)
yield dut.op.invert_a.eq(inv_a)
yield dut.n.ready_i.eq(0)
yield dut.p.valid_i.eq(1)
- yield
# if valid_o rose on the very first cycle, it is a
# zero-delay ALU
+ yield Settle()
vld = yield dut.n.valid_o
if vld:
# special case for zero-delay ALU
yield
return result
+ yield
+
# wait for the ALU to accept our input data
while True:
rdy = yield dut.p.ready_o
# wait for the ALU to present the output data
while True:
+ yield Settle()
vld = yield dut.n.valid_o
if vld:
break
print ("alu_sim sub", result)
assert (result == 2)
+ result = yield from run_op(dut, 13, 2, InternalOp.OP_SHR)
+ print ("alu_sim shr", result)
+ assert (result == 3)
+
def test_alu():
alu = ALU(width=16)