diff --git a/src/main/scala/uk/ac/soton/ecs/can/config/CanCoreConfiguration.scala b/src/main/scala/uk/ac/soton/ecs/can/config/CanCoreConfiguration.scala
index c6acc2b6bcdd19f3a27f2bccdf56923396dc9eee..26fb9e30a7046ea7809df5d9e830e96d6292a690 100644
--- a/src/main/scala/uk/ac/soton/ecs/can/config/CanCoreConfiguration.scala
+++ b/src/main/scala/uk/ac/soton/ecs/can/config/CanCoreConfiguration.scala
@@ -8,8 +8,6 @@ case class CanCoreConfiguration(
     programMemoryWords: Int,
     dataMemoryWords: Int,
     syncReadMemory: Boolean,
-    regAfterBlockInitializer: Boolean,
-    regBetweenRounds: Boolean,
-    regAfterAdder: Boolean,
+    registerFileWords: Int,
     quarterRoundType: Int
 )
diff --git a/src/main/scala/uk/ac/soton/ecs/can/core/CanCore.scala b/src/main/scala/uk/ac/soton/ecs/can/core/CanCore.scala
index 25705dfe07033c68a38a58381f943c3439815d3f..7c903e975b20487153154efa9e4683989d1814a2 100644
--- a/src/main/scala/uk/ac/soton/ecs/can/core/CanCore.scala
+++ b/src/main/scala/uk/ac/soton/ecs/can/core/CanCore.scala
@@ -4,6 +4,96 @@
 package uk.ac.soton.ecs.can.core
 
 import chisel3._
+import chisel3.util.log2Ceil
+import uk.ac.soton.ecs.can.types._
 import uk.ac.soton.ecs.can.config.CanCoreConfiguration
 
-class CanCore(implicit cfg: CanCoreConfiguration) extends MultiIOModule {}
+class CanCore(implicit cfg: CanCoreConfiguration) extends MultiIOModule {
+
+  //////////////////// Calculated parameters ////////////////////
+
+  private val programMemoryAddressWidth = log2Ceil(cfg.programMemoryWords)
+  private val programMemoryDataWidth = (new CanCoreControlWord).getWidth
+  private val dataMemoryAddressWidth = log2Ceil(cfg.dataMemoryWords)
+  private val dataMemoryDataWidth = 512
+
+  //////////////////// Ports ////////////////////
+
+  val io = IO(new Bundle {
+    val programMemory = new Bundle {
+      val read =
+        new MemoryReadIO(programMemoryAddressWidth, programMemoryDataWidth)
+      val write =
+        new MemoryWriteIO(programMemoryAddressWidth, programMemoryDataWidth)
+    }
+    val dataMemory = new Bundle {
+      val take = Input(Bool())
+      val read =
+        new MemoryReadIO(dataMemoryAddressWidth, dataMemoryDataWidth)
+      val write =
+        new MemoryWriteIO(dataMemoryAddressWidth, dataMemoryDataWidth)
+    }
+  })
+
+  //////////////////// Modules ////////////////////
+
+  private val programMemory = Module(new ProgramMemory)
+  private val dataMemory = Module(new DataMemory)
+  private val registerFile = Module(new RegisterFile)
+  private val alu = Module(new ALU)
+
+  //////////////////// Control Paths ////////////////////
+
+  private val ctrl = programMemory.cw.asTypeOf(new CanCoreControlWord)
+
+  programMemory.br.abs := ctrl.absoluteBranch
+  programMemory.br.rel := ctrl.relativeBranch
+  programMemory.br.addr := ctrl.immediate
+
+  dataMemory.read.addr := Mux(
+    io.dataMemory.take,
+    io.dataMemory.read.addr,
+    ctrl.dataMemoryReadAddress
+  )
+  dataMemory.write.en := Mux(
+    io.dataMemory.take,
+    io.dataMemory.write.en,
+    ctrl.dataMemoryWriteEnable
+  )
+  dataMemory.write.addr := Mux(
+    io.dataMemory.take,
+    io.dataMemory.write.addr,
+    ctrl.dataMemoryWriteAddress
+  )
+
+  registerFile.read(0).addr := ctrl.registerFileReadAddress(0)
+  registerFile.read(1).addr := ctrl.registerFileReadAddress(1)
+
+  registerFile.write.en := ctrl.registerFileWriteEnable
+  registerFile.write.addr := ctrl.registerFileWriteAddress
+
+  alu.fillConstant := ctrl.fillConstant
+  alu.incrementBlockCount := ctrl.incrementBlockCount
+  alu.f := ctrl.aluFunction
+
+  //////////////////// Data Paths ////////////////////
+
+  programMemory.read <> io.programMemory.read
+  programMemory.write <> io.programMemory.write
+
+  io.dataMemory.read.data := dataMemory.read.data
+  dataMemory.write.data := Mux(
+    io.dataMemory.take,
+    io.dataMemory.write.data,
+    alu.y
+  )
+
+  alu.a := registerFile.read(0).data
+  alu.b := registerFile.read(1).data
+  registerFile.write.data := Mux(
+    ctrl.registerFileWriteFrom,
+    dataMemory.read.data,
+    alu.y
+  )
+
+}
diff --git a/src/main/scala/uk/ac/soton/ecs/can/core/RegisterFile.scala b/src/main/scala/uk/ac/soton/ecs/can/core/RegisterFile.scala
new file mode 100644
index 0000000000000000000000000000000000000000..dc29fb905e929d6240c80d21bd0f91c5f6d033d8
--- /dev/null
+++ b/src/main/scala/uk/ac/soton/ecs/can/core/RegisterFile.scala
@@ -0,0 +1,25 @@
+// 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._
+import uk.ac.soton.ecs.can.types._
+import uk.ac.soton.ecs.can.config.CanCoreConfiguration
+
+class RegisterFile(implicit cfg: CanCoreConfiguration) extends MultiIOModule {
+  private val addrWidth = log2Ceil(cfg.registerFileWords)
+
+  val read = IO(Vec(2, new MemoryReadIO(addrWidth, 512)))
+  val write = IO(new MemoryWriteIO(addrWidth, 512))
+
+  private val reg = Reg(Vec(cfg.registerFileWords, UInt(512.W)))
+
+  read(0).data := reg(read(0).addr)
+  read(1).data := reg(read(1).addr)
+
+  when(write.en) {
+    reg(write.addr) := write.data
+  }
+}
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 63439d15ac00daefdbdd6122b4c81ae6f1d28785..0ccc8e55c8245d70776569ce2278b61cb080c692 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
@@ -10,16 +10,21 @@ import uk.ac.soton.ecs.can.config.CanCoreConfiguration
 class CanCoreControlWord(implicit val cfg: CanCoreConfiguration)
     extends Bundle {
   private val dataMemoryAddressWidth = log2Ceil(cfg.dataMemoryWords)
+  private val registerFileAddressWidth = log2Ceil(cfg.registerFileWords)
 
   val immediate = UInt(cfg.immediateWidth.W)
   val absoluteBranch = Bool()
   val relativeBranch = Bool()
 
-  val dataMemoryReadEnable = Bool()
   val dataMemoryReadAddress = UInt(dataMemoryAddressWidth.W)
   val dataMemoryWriteEnable = Bool()
   val dataMemoryWriteAddress = UInt(dataMemoryAddressWidth.W)
 
+  val registerFileReadAddress = Vec(2, UInt(registerFileAddressWidth.W))
+  val registerFileWriteFrom = Bool()
+  val registerFileWriteEnable = Bool()
+  val registerFileWriteAddress = UInt(registerFileAddressWidth.W)
+
   val fillConstant = Bool()
   val incrementBlockCount = Bool()
   val aluFunction = UInt(CanCoreALUFunction.requiredWidth.W)