diff --git a/tests/fpgadataflow/test_fpgadataflow_ip_stitch.py b/tests/fpgadataflow/test_fpgadataflow_ip_stitch.py
new file mode 100644
index 0000000000000000000000000000000000000000..248f18770023b9dad289d776b6dae00d99367a91
--- /dev/null
+++ b/tests/fpgadataflow/test_fpgadataflow_ip_stitch.py
@@ -0,0 +1,112 @@
+import numpy as np
+from onnx import TensorProto, helper
+
+from finn.core.datatype import DataType
+from finn.core.modelwrapper import ModelWrapper
+from finn.core.utils import calculate_signed_dot_prod_range, gen_finn_dt_tensor
+from finn.transformation.fpgadataflow.codegen_ipgen import CodeGen_ipgen
+from finn.transformation.fpgadataflow.codegen_ipstitch import CodeGen_ipstitch
+from finn.transformation.fpgadataflow.hlssynth_ipgen import HLSSynth_IPGen
+from finn.transformation.general import GiveUniqueNodeNames
+
+
+def create_two_fc_model():
+    # create a model with two StreamingFCLayer instances
+    wdt = DataType.INT2
+    idt = DataType.INT2
+    odt = DataType.INT2
+    act = DataType.INT2
+    m = 4
+    tdt = DataType.INT32
+    actval = odt.min()
+    no_act = 0
+    binary_xnor_mode = 0
+
+    inp = helper.make_tensor_value_info("inp", TensorProto.FLOAT, [1, m])
+    mid = helper.make_tensor_value_info("mid", TensorProto.FLOAT, [1, m])
+    outp = helper.make_tensor_value_info("outp", TensorProto.FLOAT, [1, m])
+
+    fc0 = helper.make_node(
+        "StreamingFCLayer_Batch",
+        ["inp", "w0", "t0"],
+        ["mid"],
+        domain="finn",
+        backend="fpgadataflow",
+        resType="ap_resource_lut()",
+        MW=m,
+        MH=m,
+        SIMD=1,
+        PE=1,
+        inputDataType=idt.name,
+        weightDataType=wdt.name,
+        outputDataType=odt.name,
+        ActVal=actval,
+        binaryXnorMode=binary_xnor_mode,
+        noActivation=no_act,
+    )
+
+    fc1 = helper.make_node(
+        "StreamingFCLayer_Batch",
+        ["mid", "w1", "t1"],
+        ["outp"],
+        domain="finn",
+        backend="fpgadataflow",
+        resType="ap_resource_lut()",
+        MW=m,
+        MH=m,
+        SIMD=1,
+        PE=1,
+        inputDataType=idt.name,
+        weightDataType=wdt.name,
+        outputDataType=odt.name,
+        ActVal=actval,
+        binaryXnorMode=binary_xnor_mode,
+        noActivation=no_act,
+    )
+
+    graph = helper.make_graph(
+        nodes=[fc0, fc1],
+        name="fclayer_graph",
+        inputs=[inp],
+        outputs=[outp],
+        value_info=[mid],
+    )
+
+    model = helper.make_model(graph, producer_name="fclayer-model")
+    model = ModelWrapper(model)
+
+    model.set_tensor_datatype("inp", idt)
+    model.set_tensor_datatype("mid", idt)
+    model.set_tensor_datatype("outp", odt)
+    model.set_tensor_datatype("w0", wdt)
+    model.set_tensor_datatype("w1", wdt)
+
+    # generate weights
+    w0 = gen_finn_dt_tensor(wdt, (m, m))
+    w1 = gen_finn_dt_tensor(wdt, (m, m))
+    model.set_initializer("w0", w0)
+    model.set_initializer("w1", w1)
+
+    # generate thresholds
+    (min, max) = calculate_signed_dot_prod_range(idt, wdt, m)
+    n_steps = act.get_num_possible_values() - 1
+    t0 = np.random.randint(min, max - 1, (m, n_steps)).astype(np.float32)
+    t1 = np.random.randint(min, max - 1, (m, n_steps)).astype(np.float32)
+    # provide non-decreasing thresholds
+    t0 = np.sort(t0, axis=1)
+    t1 = np.sort(t1, axis=1)
+
+    model.set_initializer("t0", t0)
+    model.set_initializer("t1", t1)
+    model.set_tensor_datatype("t0", tdt)
+    model.set_tensor_datatype("t1", tdt)
+    return model
+
+
+def test_fpgadataflow_ip_stitch():
+    model = create_two_fc_model()
+    model = model.transform(GiveUniqueNodeNames())
+    model = model.transform(CodeGen_ipgen("xc7z020clg400-1", 5))
+    model = model.transform(HLSSynth_IPGen())
+    model = model.transform(CodeGen_ipstitch("xc7z020clg400-1"))
+    model.save("stitching-test.onnx")