Adding Reset. Cleaning Logic for CAM. Still needs tests
authorDaniel Benusovich <flyingmonkeys1996@gmail.com>
Mon, 25 Feb 2019 07:10:02 +0000 (23:10 -0800)
committerDaniel Benusovich <flyingmonkeys1996@gmail.com>
Mon, 25 Feb 2019 07:10:02 +0000 (23:10 -0800)
TLB/src/Cam.py
TLB/test/test_cam.py

index 42b7f028b1bda677faf7c9dbb04b1a3abf90090d..30783cea94786f73ab347bfb30d7985064c882f9 100644 (file)
@@ -1,5 +1,5 @@
 from nmigen import Array, Module, Signal
-from nmigen.lib.coding import Encoder
+from nmigen.lib.coding import Encoder, Decoder
 from nmigen.compat.fhdl.structure import ClockDomain
 
 from CamEntry import CamEntry
@@ -14,6 +14,10 @@ from CamEntry import CamEntry
 # command it will write the given key and data into the given cam entry index.
 # Entry managment should be performed one level above this block as lookup is 
 # performed within.
+# Notes:
+# The search, write, and reset operations take one clock cycle to complete.
+# Attempting a read before reading the search result will cause 
+# the read to be ignored.
 class Cam():
     
     # Arguments:
@@ -27,7 +31,9 @@ class Cam():
                             for x in range(cam_size))
 
         # Input
-        self.command = Signal(2) # 00 => NA 01 => Read 10 => Write 11 => Search
+        # 000 => NA 001 => Read 010 => Write 011 => Search
+        # 100 => Reset 101, 110, 111 => Reserved
+        self.command = Signal(3) 
         self.address = Signal(max=cam_size) # address of CAM Entry to write/read
         self.key_in = Signal(key_size) # The key to search for or to be written
         self.data_in = Signal(key_size) # The data to be written
@@ -39,54 +45,61 @@ class Cam():
     def elaborate(self, platform=None):
         m = Module()
         
+        
+        # Encoder is used to selecting what data is output when searching
         m.submodules.encoder = encoder = Encoder(self.cam_size)
-        m.submodules += self.entry_array
+        # Decoder is used to select which entry will be written to
+        m.submodules.decoder = decoder = Decoder(self.cam_size)
+        # Don't forget to add all entries to the submodule list
+        entry_array = self.entry_array
+        m.submodules += entry_array
+        
+        # Decoder logic
+        m.d.comb += [
+            decoder.i.eq(self.address),
+            decoder.n.eq(0)
+        ]
         
         # Set the key value for every CamEntry
         for index in range(self.cam_size):
             with m.Switch(self.command):
-                # Read and Search both read from the CamEntry
-                with m.Case("-1"):
-                    m.d.comb += self.entry_array[index].command.eq(1)
+                # Read from a single entry
+                with m.Case("0-1"):
+                    m.d.comb += entry_array[index].command.eq(1)
+                    # Only read if an encoder value is not ready
+                    with m.If(decoder.o[index] & encoder.n):
+                        m.d.comb += self.data_out.eq(entry_array[index].data)
                 # Write only to one entry
-                with m.Case("10"):
-                    with m.If(self.address == index):
-                        m.d.comb += self.entry_array[index].command.eq(2)
+                with m.Case("010"):
+                    # Address is decoded and selects which 
+                    # entry will be written to
+                    with m.If(decoder.o[index]):
+                        m.d.comb += entry_array[index].command.eq(2)
                     with m.Else():
-                        m.d.comb += self.entry_array[index].command.eq(0)
-                # NA
+                        m.d.comb += entry_array[index].command.eq(0)
+                # Search all entries
+                with m.Case("011"):
+                    m.d.comb += entry_array[index].command.eq(1)
+                # Reset
+                with m.Case("100"):
+                    m.d.comb += entry_array[index].command.eq(3)
+                # NA / Reserved
                 with m.Case():
-                    m.d.comb += self.entry_array[index].command.eq(0)
+                    m.d.comb += entry_array[index].command.eq(0)
  
             m.d.comb += [
-                   self.entry_array[index].key_in.eq(self.key_in),
-                   self.entry_array[index].data_in.eq(self.data_in),
-                   encoder.i[index].eq(self.entry_array[index].match)
+                   entry_array[index].key_in.eq(self.key_in),
+                   entry_array[index].data_in.eq(self.data_in),
+                   encoder.i[index].eq(entry_array[index].match)
             ]
         
+        # Process out data based on encoder address
+        with m.If(encoder.n == 0):
+            m.d.comb += [
+                self.data_hit.eq(1),
+                self.data_out.eq(entry_array[encoder.o].data)
+            ]
+        with m.Else():
+            m.d.comb += self.data_hit.eq(0)        
               
-        with m.Switch(self.command):
-            # Read
-            with m.Case("01"):
-                m.d.comb += [
-                    self.data_hit.eq(0),
-                    self.data_out.eq(self.entry_array[self.address].data)
-                ]
-            # Write
-            with m.Case("10"):
-                m.d.comb += [
-                    self.data_hit.eq(0),
-                    self.entry_array[self.address].key_in.eq(self.key_in),
-                    self.entry_array[self.address].data_in.eq(self.data_in)
-                ]
-            # NA / Searching
-            with m.Case():
-                with m.If(encoder.n == 0):
-                    m.d.comb += [
-                        self.data_hit.eq(1),
-                        self.data_out.eq(self.entry_array[encoder.o].data)
-                    ]
-                with m.Else():
-                    m.d.comb += self.data_hit.eq(0)
-                
         return m
index c5141a932f53f4d7f5201859d0bab864562ddd56..2e05863408f59830066a2c932fa4dbb482ee0f15 100644 (file)
@@ -79,7 +79,17 @@ def testbench(dut):
     data_hit = 1
     yield from set_cam(dut, command, address, key, data)
     yield
-    yield from check_all(dut, data_hit, data, 0, 0)     
+    yield from check_all(dut, data_hit, data, 0, 0)
+    
+    # Reset 
+    command = 4
+    address = 0
+    key = 0
+    data = 0
+    data_hit = 0
+    yield from set_cam(dut, command, address, key, data)
+    yield
+    yield from check_all(dut, data_hit, data, 0, 0)      
     
     yield