diff --git a/src/finn/custom_op/__init__.py b/src/finn/custom_op/__init__.py
index ab6e03bee65b8bf5c4041dd8021b1a561e7673d2..4ae7b9ebffaab6ca6be04b8d73f647b2db22dc78 100644
--- a/src/finn/custom_op/__init__.py
+++ b/src/finn/custom_op/__init__.py
@@ -56,8 +56,15 @@ class CustomOp(ABC):
                     ret = ret.decode("utf-8")
                 return ret
             else:
-                # not set, return default value
-                return def_val
+                if req:
+                    raise Exception(
+                        """Required attribute %s unspecified in
+                    a %s node"""
+                        % (name, self.onnx_node.op_type)
+                    )
+                else:
+                    # not set, return default value
+                    return def_val
         except KeyError:
             raise AttributeError("Op has no such attribute: " + name)
 
diff --git a/tests/fpgadataflow/test_fpgadataflow_channelwise_ops.py b/tests/fpgadataflow/test_fpgadataflow_channelwise_ops.py
index 6a69d8180a4a9825a83b419666bbccb9f203a7d8..2ed352e28981552b186bb778b94dcbc07471e14b 100644
--- a/tests/fpgadataflow/test_fpgadataflow_channelwise_ops.py
+++ b/tests/fpgadataflow/test_fpgadataflow_channelwise_ops.py
@@ -48,7 +48,7 @@ from finn.transformation.fpgadataflow.replace_verilog_relpaths import (
 )
 
 
-def make_modelwrapper(C, pe, idt, odt, func, vecs):
+def make_modelwrapper(C, pe, idt, odt, pdt, func, vecs):
     NumChannels = C.shape[0]
 
     inp = helper.make_tensor_value_info("inp", TensorProto.FLOAT, vecs + [NumChannels])
@@ -69,9 +69,10 @@ def make_modelwrapper(C, pe, idt, odt, func, vecs):
         PE=pe,
         inputDataType=idt.name,
         outputDataType=odt.name,
+        paramDataType=pdt.name,
         numInputVectors=vecs,
     )
-    graph = helper.make_graph(nodes=[node], name="graph", inputs=[inp], outputs=[outp],)
+    graph = helper.make_graph(nodes=[node], name="graph", inputs=[inp], outputs=[outp])
 
     model = helper.make_model(graph, producer_name="model")
     model = ModelWrapper(model)
@@ -88,6 +89,8 @@ def make_modelwrapper(C, pe, idt, odt, func, vecs):
 @pytest.mark.parametrize("act", [DataType.INT8])
 # input datatype
 @pytest.mark.parametrize("idt", [DataType.INT4])
+# param datatype
+@pytest.mark.parametrize("pdt", [DataType.INT4])
 # folding, -1 is maximum possible
 @pytest.mark.parametrize("nf", [-1, 2])
 # number of input features
@@ -100,19 +103,20 @@ def make_modelwrapper(C, pe, idt, odt, func, vecs):
 @pytest.mark.parametrize("exec_mode", ["cppsim", "rtlsim"])
 @pytest.mark.vivado
 @pytest.mark.slow
-def test_fpgadataflow_addmul(idt, act, nf, ich, func, vecs, exec_mode):
+def test_fpgadataflow_channelwise_ops(idt, act, pdt, nf, ich, func, vecs, exec_mode):
     if nf == -1:
         nf = ich
     pe = ich // nf
     assert ich % pe == 0
 
-    # generate input data
+    # generate input and param data
     x = gen_finn_dt_tensor(idt, tuple(vecs + [ich]))
+    # C = np.random.randint(idt.min(), idt.max() + 1, ich).astype(np.float32)
+    C = gen_finn_dt_tensor(pdt, (ich))
 
     odt = act
-    C = np.random.randint(idt.min(), idt.max() + 1, ich).astype(np.float32)
 
-    model = make_modelwrapper(C, pe, idt, odt, func, vecs)
+    model = make_modelwrapper(C, pe, idt, odt, pdt, func, vecs)
 
     if exec_mode == "cppsim":
         model = model.transform(PrepareCppSim())