diff --git a/include/aidge/aidge.hpp b/include/aidge/aidge.hpp
index 32e96ac2886c4956888f0657dbcbced00d76ee78..6088cf31c91cdd1b939bb4508850a9d0f798e5d2 100644
--- a/include/aidge/aidge.hpp
+++ b/include/aidge/aidge.hpp
@@ -52,6 +52,7 @@
 #include "aidge/operator/GenericOperator.hpp"
 #include "aidge/operator/GlobalAveragePooling.hpp"
 #include "aidge/operator/GridSample.hpp"
+#include "aidge/operator/Heaviside.hpp"
 #include "aidge/operator/MatMul.hpp"
 #include "aidge/operator/MaxPooling.hpp"
 #include "aidge/operator/MetaOperator.hpp"
diff --git a/include/aidge/operator/Heaviside.hpp b/include/aidge/operator/Heaviside.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..65c7f341a1c5aa12eeada2165e459cc1c933e327
--- /dev/null
+++ b/include/aidge/operator/Heaviside.hpp
@@ -0,0 +1,107 @@
+/********************************************************************************
+ * Copyright (c) 2024 CEA-List
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ ********************************************************************************/
+
+#ifndef AIDGE_CORE_OPERATOR_HEAVISIDE_H_
+#define AIDGE_CORE_OPERATOR_HEAVISIDE_H_
+
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "aidge/backend/OperatorImpl.hpp"
+#include "aidge/graph/Node.hpp"
+#include "aidge/operator/Operator.hpp"
+#include "aidge/operator/OperatorTensor.hpp"
+#include "aidge/utils/Registrar.hpp"
+#include "aidge/utils/StaticAttributes.hpp"
+#include "aidge/utils/Types.h"
+
+namespace Aidge {
+enum class HeavisideAttr { 
+    /**
+     * @brief The value used in the output tensor when the input is 0.
+     */
+    Value 
+};
+
+class Heaviside_Op
+    : public OperatorTensor,
+      public Registrable<
+          Heaviside_Op,
+          std::string,
+          std::function<std::shared_ptr<OperatorImpl>(const Heaviside_Op &)>> {
+  private:
+    using Attributes_ = StaticAttributes<HeavisideAttr, float>;
+    template <HeavisideAttr e>
+    using attr = typename Attributes_::template attr<e>;
+    const std::shared_ptr<Attributes_> mAttributes;
+
+  public:
+    static const std::string Type;
+
+    /*
+     * Compute the Heaviside step function for each element of the first input.
+     * Heaviside step function is defined as :
+     *
+     * \f[
+     * heaviside(input, values) = \begin{cases}
+     *     0      & \text{if input }  < 0 \\
+     *     values & \text{if input }  = 0 \\
+     *     1      & \text{if input }  > 0
+     * \end{cases}
+     * \f]
+     * */
+    Heaviside_Op(float value);
+
+    Heaviside_Op(const Heaviside_Op &op);
+
+    std::shared_ptr<Operator> clone() const override;
+
+    void setBackend(const std::string &name, DeviceIdx_t device = 0) override;
+
+    std::set<std::string> getAvailableBackends() const override;
+
+    static const std::vector<std::string> getInputsName() {
+        return {"data_input", "data_values"};
+    }
+
+    static const std::vector<std::string> getOutputsName() {
+        return {"output"};
+    }
+
+    inline std::shared_ptr<Attributes> attributes() const override {
+        return mAttributes;
+    }
+    inline float &value() const {
+        return mAttributes->template getAttr<HeavisideAttr::Value>();
+    }
+};
+
+/**
+ * @brief Create a Heaviside node.
+ *
+ * Initializes a Heaviside node that computes the Heaviside step function for each element 
+ * of the input tensor, using the specified value for inputs equal to zero.
+ *
+ * @param value The value used in the output tensor when the input is 0.
+ * @param name  Optional. The name of the node.
+ * 
+ * @return A shared pointer to a Node representing the Heaviside operation.
+ */
+std::shared_ptr<Node> Heaviside(float value, const std::string &name = "");
+} // namespace Aidge
+
+namespace {
+template <>
+const char *const EnumStrings<Aidge::HeavisideAttr>::data[] = {"value"};
+}
+
+#endif /* AIDGE_CORE_OPERATOR_HEAVISIDE_H_ */
diff --git a/python_binding/operator/pybind_Heaviside.cpp b/python_binding/operator/pybind_Heaviside.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..cbc2502aac018927c544a57f343a6305ee2bd86f
--- /dev/null
+++ b/python_binding/operator/pybind_Heaviside.cpp
@@ -0,0 +1,56 @@
+/********************************************************************************
+ * Copyright (c) 2024 CEA-List
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ ********************************************************************************/
+
+#include <pybind11/pybind11.h>
+
+#include "aidge/operator/Heaviside.hpp"
+#include "aidge/operator/OperatorTensor.hpp"
+
+namespace py = pybind11;
+
+namespace Aidge {
+
+void init_Heaviside(py::module &m) {
+    py::class_<Heaviside_Op, std::shared_ptr<Heaviside_Op>, OperatorTensor>(
+        m,
+        "HeavisideOp",
+        py::multiple_inheritance(),
+         R"mydelimiter(
+          Initialize an Heaviside node. This node will compute a heaviside step function 
+          on each element of the input tensor.
+          heaviside(input, values) = { 0  if input < 0 
+                                     { values if input == 0
+                                     { 1 if input > 0
+
+          :param value : The value use for the output tensor when input is 0.
+          :type value : float
+          :param name : Name of the node.
+          )mydelimiter")
+        .def(py::init<float>(), py::arg("value"))
+        .def_static("get_inputs_name", &Heaviside_Op::getInputsName)
+        .def_static("get_outputs_name", &Heaviside_Op::getOutputsName)
+        .def_readonly_static("Type", &Heaviside_Op::Type);
+
+    declare_registrable<Heaviside_Op>(m, "HeavisideOp");
+    m.def("Heaviside", &Heaviside, py::arg("value"), py::arg("name") = "",
+            R"mydelimiter(
+          Initialize an Heaviside node. This node will compute a heaviside step function 
+          on each element of the input tensor.
+          heaviside(input, values) = { 0  if input < 0 
+                                     { values if input == 0
+                                     { 1 if input > 0
+
+          :param value : The value use for the output tensor when input is 0.
+          :type value : float
+          :param name : Name of the node.
+          )mydelimiter");
+}
+} // namespace Aidge
diff --git a/python_binding/pybind_core.cpp b/python_binding/pybind_core.cpp
index 2730f8e0b2ebb048c88bf8af6a80f906dcea499e..02f4b732c39ef5cbc1755eb314d32c25c96d01fd 100644
--- a/python_binding/pybind_core.cpp
+++ b/python_binding/pybind_core.cpp
@@ -48,6 +48,7 @@ void init_Gather(py::module&);
 void init_GenericOperator(py::module&);
 void init_GlobalAveragePooling(py::module&);
 void init_GridSample(py::module&);
+void init_Heaviside(py::module&);
 void init_Identity(py::module&);
 void init_LeakyReLU(py::module&);
 void init_MatMul(py::module&);
@@ -137,6 +138,7 @@ void init_Aidge(py::module& m) {
     init_GenericOperator(m);
     init_GlobalAveragePooling(m);
     init_GridSample(m);
+    init_Heaviside(m);
     init_Identity(m);
     init_LeakyReLU(m);
     init_MatMul(m);
diff --git a/src/operator/Heaviside.cpp b/src/operator/Heaviside.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..9ecb3b436d8312ef479d6bc0592cfe372235fa25
--- /dev/null
+++ b/src/operator/Heaviside.cpp
@@ -0,0 +1,64 @@
+/********************************************************************************
+ * Copyright (c) 2024 CEA-List
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ ********************************************************************************/
+
+#include <cstddef>   // std::size_t
+#include <memory>
+#include <stdexcept> // std::runtime_error
+#include <string>
+#include <vector>
+
+#include "aidge/backend/OperatorImpl.hpp"
+#include "aidge/data/Tensor.hpp"
+#include "aidge/operator/Heaviside.hpp"
+#include "aidge/utils/ErrorHandling.hpp"
+#include "aidge/utils/Types.h"
+
+namespace Aidge {
+// ----------------------------------------------------------- Heaviside_Op
+// class
+
+const std::string Heaviside_Op::Type = "Heaviside";
+
+Heaviside_Op::Heaviside_Op(float value)
+    : OperatorTensor(Type, {InputCategory::Data}, 1),
+      mAttributes(
+          std::make_shared<Attributes_>(attr<HeavisideAttr::Value>(value))) {}
+
+Heaviside_Op::Heaviside_Op(const Heaviside_Op &op)
+    : OperatorTensor(op), mAttributes(op.mAttributes) {
+    if (op.mImpl) {
+        SET_IMPL_MACRO(Heaviside_Op, *this, op.backend());
+    } else {
+        mImpl = nullptr;
+    }
+}
+
+std::shared_ptr<Aidge::Operator> Aidge::Heaviside_Op::clone() const {
+    return std::make_shared<Heaviside_Op>(*this);
+}
+
+void Heaviside_Op::setBackend(const std::string &name, DeviceIdx_t device) {
+    SET_IMPL_MACRO(Heaviside_Op, *this, name);
+    mOutputs[0]->setBackend(name, device);
+}
+
+std::set<std::string> Aidge::Heaviside_Op::getAvailableBackends() const {
+    return Registrar<Heaviside_Op>::getKeys();
+}
+
+// --------------------------------------------------------------- Free
+// functions
+
+NodePtr Heaviside(float value, const std::string &name) {
+    return std::make_shared<Node>(std::make_shared<Heaviside_Op>(value), name);
+}
+
+} // namespace Aidge
diff --git a/unit_tests/operator/Test_Heaviside_Op.cpp b/unit_tests/operator/Test_Heaviside_Op.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..d53268d1213730dc6202193d26b0531e781518f7
--- /dev/null
+++ b/unit_tests/operator/Test_Heaviside_Op.cpp
@@ -0,0 +1,70 @@
+/********************************************************************************
+ * Copyright (c) 2024 CEA-List
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ ********************************************************************************/
+
+#include <catch2/catch_test_macros.hpp>
+#include <catch2/generators/catch_generators_random.hpp>
+#include <cstddef> // std::size_t
+#include <memory>
+#include <random>  // std::mt19937, std::uniform_int_distribution
+#include <vector>
+
+#include "aidge/data/Tensor.hpp"
+#include "aidge/operator/Heaviside.hpp"
+#include "aidge/operator/OperatorTensor.hpp"
+
+namespace Aidge {
+
+TEST_CASE("[core/operator] Heaviside_Op(forwardDims)",
+          "[Heaviside][forwardDims]") {
+
+    constexpr std::uint16_t NBTRIALS = 10;
+
+    // Create a random number generator
+    auto rd = Catch::Generators::Detail::getSeed;
+    std::mt19937 gen(rd());
+    std::uniform_int_distribution<std::size_t> dimsDist(1, 10);
+    std::uniform_int_distribution<std::size_t> nbDimsDist(1, 5);
+
+    // Create Heaviside Operator
+    std::shared_ptr<Node> myHeaviside = Heaviside(0.5);
+    auto op =
+        std::static_pointer_cast<OperatorTensor>(myHeaviside->getOperator());
+
+    // input_0
+    std::shared_ptr<Tensor> T0 = std::make_shared<Tensor>();
+    op->associateInput(0, T0);
+
+    SECTION("Scalar") {
+        // input 0
+        T0->resize({});
+
+        REQUIRE_NOTHROW(op->forwardDims());
+        REQUIRE((op->getOutput(0)->dims() == std::vector<std::size_t>()));
+    }
+
+    SECTION("+1-D Tensor") {
+
+        for (std::uint16_t trial = 0; trial < NBTRIALS; ++trial) {
+
+            const std::size_t nb_dims = nbDimsDist(gen);
+            std::vector<std::size_t> dims(nb_dims);
+
+            for (std::size_t i = 0; i < nb_dims; ++i) {
+                dims[i] = dimsDist(gen);
+            }
+            T0->resize(dims);
+
+            REQUIRE_NOTHROW(op->forwardDims());
+            REQUIRE((op->getOutput(0)->dims()) == dims);
+        }
+    }
+}
+} // namespace Aidge