add a multi-input stb/ack module
authorLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Mon, 11 Mar 2019 08:42:21 +0000 (08:42 +0000)
committerLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Mon, 11 Mar 2019 08:42:21 +0000 (08:42 +0000)
to be used for acknowledging and passing on multiple inputs once all ready

src/add/nmigen_add_experiment.py
src/add/test_syncops.py [new file with mode: 0644]

index 121f61b22ab54654bd7147bf8972a524699a362b..542b18218a1f1dab0a1870b6e3b9ea1d753cc027 100644 (file)
@@ -2,7 +2,7 @@
 # Copyright (C) Jonathan P Dawson 2013
 # 2013-12-12
 
-from nmigen import Module, Signal, Cat, Mux, Array
+from nmigen import Module, Signal, Cat, Mux, Array, Const
 from nmigen.lib.coding import PriorityEncoder
 from nmigen.cli import main, verilog
 
@@ -26,6 +26,36 @@ class FPState(FPBase):
             setattr(self, k, v)
 
 
+class FPGetSyncOpsMod:
+    def __init__(self, width, num_ops=2):
+        self.width = width
+        self.num_ops = num_ops
+        inops = []
+        outops = []
+        for i in range(num_ops):
+            inops.append(Signal(width, reset_less=True))
+            outops.append(Signal(width, reset_less=True))
+        self.in_op = inops
+        self.out_op = outops
+        self.stb = Signal(num_ops)
+        self.ack = Signal()
+        self.out_decode = Signal(reset_less=True)
+
+    def elaborate(self, platform):
+        m = Module()
+        stb = Signal(reset_less=True)
+        m.d.comb += stb.eq(self.stb == Const(-1, (self.num_ops, False)))
+        m.d.comb += self.out_decode.eq(self.ack & stb)
+        with m.If(self.out_decode):
+            for i in range(self.num_ops):
+                m.d.comb += [
+                        self.out_op[i].eq(self.in_op[i]),
+                ]
+        return m
+
+    def ports(self):
+        return self.in_op + self.out_op + [self.stb, self.ack]
+
 class FPGetOpMod:
     def __init__(self, width):
         self.in_op = FPOp(width)
diff --git a/src/add/test_syncops.py b/src/add/test_syncops.py
new file mode 100644 (file)
index 0000000..c413322
--- /dev/null
@@ -0,0 +1,48 @@
+from random import randint
+from nmigen import Module, Signal
+from nmigen.compat.sim import run_simulation
+from nmigen.cli import verilog
+
+from nmigen_add_experiment import FPGetSyncOpsMod
+
+
+def testbench(dut):
+    stb = yield dut.stb
+    assert stb == 0
+    ack = yield dut.ack
+    assert ack == 0
+
+    yield dut.in_op[0].eq(5)
+    yield dut.stb.eq(0b01)
+    yield dut.ack.eq(1)
+    yield
+    yield
+    decode = yield dut.out_decode
+    assert decode == 0
+
+    op0 = yield dut.out_op[0]
+    op1 = yield dut.out_op[1]
+    assert op0 == 0 and op1 == 0
+
+    yield dut.in_op[1].eq(6)
+    yield dut.stb.eq(0b11)
+    yield
+    yield
+
+    op0 = yield dut.out_op[0]
+    op1 = yield dut.out_op[1]
+    assert op0 == 5 and op1 == 6
+
+    yield dut.ack.eq(0)
+    yield
+
+    op0 = yield dut.out_op[0]
+    op1 = yield dut.out_op[1]
+    assert op0 == 0 and op1 == 0
+
+if __name__ == '__main__':
+    dut = FPGetSyncOpsMod(width=32)
+    run_simulation(dut, testbench(dut), vcd_name="test_getsyncops.vcd")
+    vl = verilog.convert(dut, ports=dut.ports())
+    with open("test_getsyncops.v", "w") as f:
+        f.write(vl)