1 from nmigen
import Array
, Module
, Signal
2 from nmigen
.lib
.coding
import Encoder
4 from CamEntry
import CamEntry
6 # Content Addressable Memory (CAM)
7 # The purpose of this module is to quickly look up whether an entry exists
8 # given a certain key and return the mapped data.
9 # This module when given a key will search for the given key
10 # in all internal entries and output whether a match was found or not.
11 # If an entry is found the data will be returned and data_hit is HIGH,
12 # if it is not LOW is asserted on data_hit. When given a write
13 # command it will write the given key and data into the given cam entry index.
14 # Entry managment should be performed one level above this block as lookup is
19 # key_size: (bit count) The size of the key
20 # data_size: (bit count) The size of the data
21 # cam_size: (entry count) The number of entries int he CAM
22 def __init__(self
, key_size
, data_size
, cam_size
):
24 self
.cam_size
= cam_size
25 self
.entry_array
= Array(CamEntry(key_size
, data_size
) \
26 for x
in range(cam_size
))
27 self
.encoder_input
= Signal(cam_size
)
30 self
.command
= Signal(2) # 00 => NA 01 => Read 10 => Write 11 => Search
31 self
.address
= Signal(max=cam_size
) # address of CAM Entry to write/read
32 self
.key_in
= Signal(key_size
) # The key to search for or to be written
33 self
.data_in
= Signal(key_size
) # The data to be written
36 self
.data_hit
= Signal(1) # Denotes a key data pair was stored at key_in
37 self
.data_out
= Signal(data_size
) # The data mapped to by key_in
39 def get_fragment(self
, platform
=None):
42 m
.d
.submodules
.encoder
= encoder
= Encoder(self
.cam_size
)
44 # Set the key value for every CamEntry
45 for index
in range(self
.cam_size
):
46 with m
.If(self
.command
== 3):
48 self
.entry_array
[index
].write
.eq(0),
49 self
.entry_array
[index
].key_in
.eq(self
.key_in
),
50 self
.entry_array
[index
].data_in
.eq(self
.data_in
),
51 self
.encoder_input
[index
].eq(self
.entry_array
[index
].match
)
54 with m
.Switch(self
.command
):
59 self
.data_out
.eq(self
.entry_array
[self
.address
].data
)
65 self
.entry_array
[self
.address
].write
.eq(1),
66 self
.entry_array
[self
.address
].key_in
.eq(self
.key_in
),
67 self
.entry_array
[self
.address
].data
.eq(self
.data_in
)
71 m
.d
.sync
+= encoder
.i
.eq(self
.encoder_input
)
72 with m
.If(encoder
.n
== 0):
75 self
.data_out
.eq(self
.entry_array
[encoder
.o
].data
)
78 m
.d
.sync
+= self
.data_hit
.eq(1)