""" Content Addressable Memory (CAM)
The purpose of this module is to quickly look up whether an
- entry exists given a certain key and return the mapped data.
- This module when given a key will search for the given key
- in all internal entries and output whether a match was found or not.
- If an entry is found the data will be returned and data_hit is HIGH,
- if it is not LOW is asserted on data_hit. When given a write
- 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
+ entry exists given a data key.
+ This module will search for the given data in all internal entries
+ and output whether a single or multiple match was found.
+ If an single entry is found the address be returned and single_match
+ is set HIGH. If multiple entries are found the lowest address is
+ returned and multiple_match is set HIGH. If neither single_match or
+ multiple_match are HIGH this implies no match was found. To write
+ to the CAM set the address bus to the desired entry and set write_enable
+ HIGH. 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. Performing a read immediately after a search will cause
- the read to be ignored.
+ The read and write operations take one clock cycle to complete.
+ Currently the read_warning line is present for interfacing but
+ is not necessary for this design. This module is capable of writing
+ in the first cycle, reading on the second, and output the correct
+ address on the third.
"""
def __init__(self, data_size, cam_size):
self.cam_size = cam_size
self.encoder = AddressEncoder(cam_size)
self.decoder = Decoder(cam_size)
- self.entry_array = Array(CamEntry(data_size) \
- for x in range(cam_size))
+ self.entry_array = Array(CamEntry(data_size) for x in range(cam_size))
self.vector_assembler = VectorAssembler(cam_size)
# Input
def elaborate(self, platform=None):
m = Module()
- # Encoder checks for multiple matches
+ # AddressEncoder for match types and output address
m.submodules.AddressEncoder = self.encoder
# Decoder is used to select which entry will be written to
m.submodules.Decoder = self.decoder
self.decoder.n.eq(0)
]
- # XXX change name of write_enable interface to write_enable_n ?
- wen = Signal(reset_less=True)
- m.d.comb += wen.eq(~self.write_enable)
-
with m.If(self.enable):
# Set the key value for every CamEntry
for index in range(self.cam_size):
- # Read Operation
- with m.If(wen):
- m.d.comb += entry_array[index].command.eq(1)
-
# Write Operation
- with m.Else():
+ with m.If(self.write_enable):
with m.If(self.decoder.o[index]):
m.d.comb += entry_array[index].command.eq(2)
with m.Else():
m.d.comb += entry_array[index].command.eq(0)
+ # Read Operation
+ with m.Else():
+ m.d.comb += entry_array[index].command.eq(1)
+
# Send data input to all entries
m.d.comb += entry_array[index].data_in.eq(self.data_in)
- #Send all entry matches to encoder
- m.d.comb += self.vector_assembler.input[index].eq(entry_array[index].match)
+ # Send all entry matches to encoder
+ ematch = entry_array[index].match
+ m.d.comb += self.vector_assembler.i[index].eq(ematch)
# Give input to and accept output from encoder module
m.d.comb += [