diff --git a/src/main/scala/uk/ac/soton/ecs/can/core/DataMemory.scala b/src/main/scala/uk/ac/soton/ecs/can/core/DataMemory.scala
new file mode 100644
index 0000000000000000000000000000000000000000..ad0b08daf55d58d842201342e758ae68a0f9846e
--- /dev/null
+++ b/src/main/scala/uk/ac/soton/ecs/can/core/DataMemory.scala
@@ -0,0 +1,25 @@
+package uk.ac.soton.ecs.can.core
+
+import chisel3._
+
+class DataMemory(addrWidth: Int, dataWidth: Int, size: Int) extends Module {
+  val io = IO(new Bundle {
+    val read = new Bundle {
+      val addr = Input(UInt(addrWidth.W))
+      val data = Output(UInt(dataWidth.W))
+    }
+    val write = new Bundle {
+      val en = Input(Bool())
+      val addr = Input(UInt(addrWidth.W))
+      val data = Input(UInt(dataWidth.W))
+    }
+  })
+
+  val mem = SyncReadMem(size, UInt(dataWidth.W))
+
+  io.read.data := mem(io.read.addr)
+
+  when(io.write.en) {
+    mem(io.write.addr) := io.write.data
+  }
+}
diff --git a/src/test/scala/uk/ac/soton/ecs/can/core/DataMemoryTest.scala b/src/test/scala/uk/ac/soton/ecs/can/core/DataMemoryTest.scala
new file mode 100644
index 0000000000000000000000000000000000000000..7b7d0dd8068b1edd7f74f9c341bc7b194851f507
--- /dev/null
+++ b/src/test/scala/uk/ac/soton/ecs/can/core/DataMemoryTest.scala
@@ -0,0 +1,51 @@
+package uk.ac.soton.ecs.can.core
+
+import org.scalatest._
+import chiseltest._
+import chisel3._
+
+class DataMemoryTest extends FlatSpec with ChiselScalatestTester {
+  private val addrWidth = 8
+  private val dataWidth = 16
+  private val size = 32
+
+  it should "store some values" in {
+    test(new DataMemory(addrWidth, dataWidth, size)) { c =>
+      c.io.write.addr.poke("h01".U(addrWidth.W))
+      c.io.write.data.poke("h1234".U(dataWidth.W))
+      c.io.write.en.poke(true.B)
+      c.clock.step(2)
+      c.io.write.en.poke(false.B)
+      c.io.read.addr.poke("h01".U(addrWidth.W))
+      c.clock.step(2)
+      c.io.read.data.expect("h1234".U(dataWidth.W))
+
+      c.io.write.addr.poke("h0a".U(addrWidth.W))
+      c.io.write.data.poke("hfefe".U(dataWidth.W))
+      c.io.write.en.poke(true.B)
+      c.clock.step(2)
+      c.io.write.en.poke(false.B)
+      c.io.read.addr.poke("h0a".U(addrWidth.W))
+      c.clock.step(2)
+      c.io.read.data.expect("hfefe".U(dataWidth.W))
+    }
+  }
+
+  it should "not write without write enable" in {
+    test(new DataMemory(addrWidth, dataWidth, size)) { c =>
+      c.io.write.addr.poke("h06".U(addrWidth.W))
+      c.io.write.data.poke("hcafe".U(dataWidth.W))
+      c.io.write.en.poke(true.B)
+      c.clock.step(2)
+      c.io.write.en.poke(false.B)
+      c.io.read.addr.poke("h06".U(addrWidth.W))
+      c.clock.step(2)
+      c.io.read.data.expect("hcafe".U(dataWidth.W))
+
+      c.io.write.data.poke("hefac".U(dataWidth.W))
+      c.clock.step(8)
+      c.io.read.data.expect("hcafe".U(dataWidth.W))
+    }
+  }
+
+}