--- /dev/null
+from nmigen import Array, Module, Signal
+from nmigen.lib.coding import Decoder
+
+class RegisterFile():
+ """ Register File
+
+ The purpose of this module is to represent a bank of registers.
+
+ Usage:
+ To Write: Set the address line to the desired register in the file, set
+ write_enable HIGH, and wait one cycle
+ To Read: Set the address line to the desired register in the file, set
+ write_enable LOW, and wait one cycle.
+ """
+
+ def __init__(self, data_size, file_size):
+ """ Arguments:
+ * data_size: (bit count) The number of bits in one register
+ * cam_size: (entry count) the number of registers in this file
+ """
+
+ # Internal
+ self.register_array = Array(Signal(data_size) for x in range(file_size))
+
+ # Input
+ self.enable = Signal(1)
+ self.write_enable = Signal(1)
+ self.address = Signal(max=file_size)
+ self.data_i = Signal(data_size)
+
+ # Output
+ self.valid = Signal(1)
+ self.data_o = Signal(data_size)
+
+ def elaborate(self, platform=None):
+ m = Module()
+
+ with m.If(self.enable):
+ # Write Logic
+ with m.If(self.write_enable):
+ m.d.sync += [
+ self.valid.eq(0),
+ self.data_o.eq(0),
+ self.register_array[self.address].eq(self.data_i)
+ ]
+ # Read Logic
+ with m.Else():
+ m.d.sync += [
+ self.valid.eq(1),
+ self.data_o.eq(self.register_array[self.address])
+ ]
+ # Invalidate results when not enabled
+ with m.Else():
+ m.d.sync += [
+ self.valid.eq(0),
+ self.data_o.eq(0)
+ ]
+
+ return m
\ No newline at end of file
--- /dev/null
+import sys
+sys.path.append("../src")
+sys.path.append("../../TestUtil")
+
+from nmigen.compat.sim import run_simulation
+
+from RegisterFile import RegisterFile
+
+from test_helper import assert_eq, assert_ne, assert_op
+
+def setRegisterFile(dut, e, we, a, di):
+ yield dut.enable.eq(e)
+ yield dut.write_enable.eq(we)
+ yield dut.address.eq(a)
+ yield dut.data_i.eq(di)
+ yield
+
+# Checks the address output of the Cam
+# Arguments:
+# dut: The Cam being tested
+# v (Valid): If the output is valid or not
+# op (Operation): (0 => ==), (1 => !=)
+def check_valid(dut, v, op):
+ out_v = yield dut.valid
+ assert_op("Valid", out_v, v, op)
+
+# Checks the address output of the Cam
+# Arguments:
+# dut: The Cam being tested
+# do (Data Out): The current output data
+# op (Operation): (0 => ==), (1 => !=)
+def check_data(dut, do, op):
+ out_do = yield dut.data_o
+ assert_op("Data Out", out_do, do, op)
+
+# Checks the address output of the Cam
+# Arguments:
+# dut: The Cam being tested
+# v (Valid): If the output is valid or not
+# do (Data Out): The current output data
+# v_op (Operation): Operation for the valid assertion (0 => ==), (1 => !=)
+# do_op (Operation): Operation for the data assertion (0 => ==), (1 => !=)
+def check_all(dut, v, do, v_op, do_op):
+ yield from check_valid(dut, v, v_op)
+ yield from check_data(dut, do, do_op)
+
+def testbench(dut):
+ # Test write 0
+ enable = 1
+ write_enable = 1
+ address = 0
+ data = 1
+ valid = 0
+ yield from setRegisterFile(dut, enable, write_enable, address, data)
+ yield
+ yield from check_all(dut, valid, 0, 0, 0)
+
+ # Test read 0
+ enable = 1
+ write_enable = 0
+ address = 0
+ data = 1
+ valid = 1
+ yield from setRegisterFile(dut, enable, write_enable, address, data)
+ yield
+ yield from check_all(dut, valid, data, 0, 0)
+
+ # Test write 3
+ enable = 1
+ write_enable = 1
+ address = 3
+ data = 5
+ valid = 0
+ yield from setRegisterFile(dut, enable, write_enable, address, data)
+ yield
+ yield from check_all(dut, valid, 0, 0, 0)
+
+ # Test read 3
+ enable = 1
+ write_enable = 0
+ address = 3
+ data = 5
+ valid = 1
+ yield from setRegisterFile(dut, enable, write_enable, address, data)
+ yield
+ yield from check_all(dut, valid, data, 0, 0)
+
+ # Test read 0
+ enable = 1
+ write_enable = 0
+ address = 0
+ data = 1
+ valid = 1
+ yield from setRegisterFile(dut, enable, write_enable, address, data)
+ yield
+ yield from check_all(dut, valid, data, 0, 0)
+
+ # Test overwrite 0
+ enable = 1
+ write_enable = 1
+ address = 0
+ data = 6
+ valid = 0
+ yield from setRegisterFile(dut, enable, write_enable, address, data)
+ yield
+ yield from check_all(dut, valid, 0, 0, 0)
+
+ # Test read 0
+ enable = 1
+ write_enable = 0
+ address = 0
+ data = 6
+ valid = 1
+ yield from setRegisterFile(dut, enable, write_enable, address, data)
+ yield
+ yield from check_all(dut, valid, data, 0, 0)
+
+
+if __name__ == "__main__":
+ dut = RegisterFile(4, 4)
+ run_simulation(dut, testbench(dut), vcd_name="Waveforms/test_register_file.vcd")
+ print("RegisterFile Unit Test Success")
\ No newline at end of file