diff --git a/src/main/scala/uk/ac/soton/ecs/can/core/ALU.scala b/src/main/scala/uk/ac/soton/ecs/can/core/ALU.scala
new file mode 100644
index 0000000000000000000000000000000000000000..58cca3449abaa472c2e77ebce366f4aaf671ebba
--- /dev/null
+++ b/src/main/scala/uk/ac/soton/ecs/can/core/ALU.scala
@@ -0,0 +1,48 @@
+// SPDX-FileCopyrightText: 2021 Minyong Li <ml10g20@soton.ac.uk>
+// SPDX-License-Identifier: CERN-OHL-W-2.0
+
+package uk.ac.soton.ecs.can.core
+
+import chisel3._
+import chisel3.util.MuxLookup
+import uk.ac.soton.ecs.can.config.CanCoreConfiguration
+import uk.ac.soton.ecs.can.types.CanCoreALUFunction
+
+class ALU(implicit cfg: CanCoreConfiguration) extends MultiIOModule {
+  val fillConstant = IO(Input(Bool()))
+  val incrementBlockCount = IO(Input(Bool()))
+  val f = IO(Input(UInt(CanCoreALUFunction.requiredWidth.W)))
+  val a = IO(Input(UInt(512.W)))
+  val b = IO(Input(UInt(512.W)))
+  val y = IO(Output(UInt(512.W)))
+
+  private val blockInitializer = Module(new BlockInitializer)
+  private val columnarRound = Module(new ColumnarRound)
+  private val diagonalRound = Module(new DiagonalRound)
+  private val adder = Module(new Adder)
+  private val xorer = Module(new Xorer)
+
+  // Module inputs
+  blockInitializer.fillConstants := fillConstant
+  blockInitializer.incrementBlockCount := incrementBlockCount
+  blockInitializer.in := a
+  columnarRound.in := a
+  diagonalRound.in := a
+  adder.lhs := a
+  adder.rhs := b
+  xorer.lhs := a
+  xorer.rhs := b
+
+  // Module selection and outputs
+  y := MuxLookup(
+    f,
+    0.U(512.W),
+    Array(
+      CanCoreALUFunction.blockInitialize.U -> blockInitializer.out,
+      CanCoreALUFunction.columnarRound.U -> columnarRound.out,
+      CanCoreALUFunction.diagonalRound.U -> diagonalRound.out,
+      CanCoreALUFunction.add.U -> adder.out,
+      CanCoreALUFunction.xor.U -> xorer.out
+    )
+  )
+}
diff --git a/src/main/scala/uk/ac/soton/ecs/can/types/CanCoreALUFunction.scala b/src/main/scala/uk/ac/soton/ecs/can/types/CanCoreALUFunction.scala
new file mode 100644
index 0000000000000000000000000000000000000000..d756df43af81f19140e0b0da1aeed939af805ad0
--- /dev/null
+++ b/src/main/scala/uk/ac/soton/ecs/can/types/CanCoreALUFunction.scala
@@ -0,0 +1,13 @@
+package uk.ac.soton.ecs.can.types
+
+import chisel3.util.log2Ceil
+
+case object CanCoreALUFunction {
+  val blockInitialize = 1
+  val columnarRound = 2
+  val diagonalRound = 3
+  val add = 4
+  val xor = 5
+
+  def requiredWidth = log2Ceil(xor)
+}
diff --git a/src/main/scala/uk/ac/soton/ecs/can/types/CanCoreControlWord.scala b/src/main/scala/uk/ac/soton/ecs/can/types/CanCoreControlWord.scala
index 19ee395fc3540c6e13e174ae02b369db9ec6de47..63439d15ac00daefdbdd6122b4c81ae6f1d28785 100644
--- a/src/main/scala/uk/ac/soton/ecs/can/types/CanCoreControlWord.scala
+++ b/src/main/scala/uk/ac/soton/ecs/can/types/CanCoreControlWord.scala
@@ -9,19 +9,18 @@ import uk.ac.soton.ecs.can.config.CanCoreConfiguration
 
 class CanCoreControlWord(implicit val cfg: CanCoreConfiguration)
     extends Bundle {
-  private val dataMemoryAddrWidth = log2Ceil(cfg.dataMemoryWords)
+  private val dataMemoryAddressWidth = log2Ceil(cfg.dataMemoryWords)
 
   val immediate = UInt(cfg.immediateWidth.W)
   val absoluteBranch = Bool()
   val relativeBranch = Bool()
-  val dataMemoryReadAddress = Vec(2, UInt(dataMemoryAddrWidth.W))
+
+  val dataMemoryReadEnable = Bool()
+  val dataMemoryReadAddress = UInt(dataMemoryAddressWidth.W)
   val dataMemoryWriteEnable = Bool()
-  val dataMemoryWriteAddress = UInt(dataMemoryAddrWidth.W)
-  val fillConstants = Bool()
+  val dataMemoryWriteAddress = UInt(dataMemoryAddressWidth.W)
+
+  val fillConstant = Bool()
   val incrementBlockCount = Bool()
-  val roundLoop = Bool()
-  val addFrom = Bool()
-  val xorFrom = Bool()
-  val writeBackFromInit = Bool()
-  val writeBackFromRound = Bool()
+  val aluFunction = UInt(CanCoreALUFunction.requiredWidth.W)
 }