Add RegisterFile class for usage in the TLB.
authorDaniel Benusovich <flyingmonkeys1996@gmail.com>
Tue, 12 Mar 2019 02:51:25 +0000 (19:51 -0700)
committerDaniel Benusovich <flyingmonkeys1996@gmail.com>
Tue, 12 Mar 2019 02:51:25 +0000 (19:51 -0700)
TLB/src/RegisterFile.py [new file with mode: 0644]
TLB/test/test_register_file.py [new file with mode: 0644]

diff --git a/TLB/src/RegisterFile.py b/TLB/src/RegisterFile.py
new file mode 100644 (file)
index 0000000..5fd691c
--- /dev/null
@@ -0,0 +1,59 @@
+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
diff --git a/TLB/test/test_register_file.py b/TLB/test/test_register_file.py
new file mode 100644 (file)
index 0000000..ee8b172
--- /dev/null
@@ -0,0 +1,122 @@
+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