Forwarding-table request arbiter – openenoc_forwarding_table_arb_mux
Arbitrates multiple lookup and learning clients onto a shared forwarding table.
Source: openenoc_forwarding_table_arb_mux.sv.
Parameters
Name |
Default value |
Allowed values |
Description |
|---|---|---|---|
|
|
2..32 |
Number of upstream clients on each channel and width of every port bitmap; all connected interfaces must use this value. |
Signals
Interface ports contain channels in both directions. The table identifies the selected modport or stream role; member directions follow that interface.
Name |
Type |
Direction / role |
Description |
|---|---|---|---|
|
|
input |
Clock for this component or interface domain. |
|
|
input |
Active-high reset; suppresses requests and acknowledgements and clears pending work, ownership, captured payloads, and arbitration priority. |
|
|
bidirectional (slv) |
Per-port destination lookup clients. |
|
|
bidirectional (slv) |
Per-port source-learning clients. |
|
|
bidirectional (mst) |
Shared forwarding-table lookup channel. |
|
|
bidirectional (mst) |
Shared forwarding-table learning channel. |
Architecture and operation
NUM_OF_INTERFACES sets the number of s_lookup_if and s_learning_if
clients. m_lookup_if and m_learning_if connect the shared table.
Lookup and learning have independent round-robin arbiters.
Each client may have one outstanding request on each channel. A low-to-high
transition of req captures its MAC address and, for learning, its port
bitmap. Capture works while another client owns the downstream channel.
Pending requests from different clients are retained separately. A client
cannot queue a second request on the same channel before its first completes.
Each idle channel searches its pending clients in circular order, starting
at its current priority position. Reset initializes that position to client
zero. Launching a request advances it to the client after the winner, wrapping
after NUM_OF_INTERFACES - 1. Empty positions are skipped. A request
captured during an interval becomes eligible after that interval’s ending
edge; selection does not bypass the captured pending state.
A downstream request is a registered one-cycle pulse. Its selected MAC and learning bitmap come from the captured payload, and its client identity is retained until acknowledgement. Only one transaction may be outstanding on each downstream channel. Even with queued work, the next request is launched after the current response has released ownership; it is not issued in the response interval.
An upstream request held through acknowledgement is one transaction. Changing its payload after the first active interval does not replace the snapshot. Another request requires a sampled low interval followed by a new assertion. A new request may coincide with the previous acknowledgement after such a low interval; the new payload is queued separately from the completing operation.
The downstream acknowledgement is routed to the recorded owner in the same
interval, without an additional response register. A lookup bitmap is passed
to that owner with its acknowledgement; all other lookup clients receive
ack = 0 and bitmap zero. Learning returns only the acknowledgement.
The module does not interpret MAC matches or bitmap contents.
Lookup and learning keep independent priority positions, pending requests, and active owners. Both downstream request pulses may therefore occur together, and waiting on one response does not hold the other arbiter. The shared Forwarding table – openenoc_forwarding_table still applies its own fixed CPU/lookup/learning service priority; independent arbitration does not make table accesses simultaneous.
Asserting rst suppresses both downstream request pulses and upstream
acknowledgements. The clocked reset clears queued work, active ownership,
payload snapshots, and both priority positions. Cancelled requests receive no
completion. Reset is coordinated with the clients and downstream table so
that abandoned responses are discarded before new work starts.
Functional scenarios
The examples use NUM_OF_INTERFACES = 4 and a 10 ns clock period.
A0 through A5 are distinct MAC addresses. Port bitmaps show all four
bits in port order [3:0]. 0b0001, 0b0010, 0b0100, and 0b1000
select ports 0 through 3; 0b1111 is the default bitmap.
The downstream forwarding table has four entries. Initially it contains
enabled mappings A0/0b0001, A1/0b0010, A2/0b0100, and A3/0b1000
at indices 0 through 3. Learning allocation starts at entry zero.
The first two scenarios use managed mode; the final two use unmanaged mode.
All examples start after reset and initial table setup, except for the reset
explicitly shown in the final scenario.
A numbered tick marks a clock interval. Inputs are sampled at its ending
rising edge. x marks payload values that are irrelevant outside their
request or response interval. Upstream lookup bitmaps are shown as zero
outside their owning acknowledgement, matching the module’s output gating.
Round-robin order wraps across the client array
Client 2 first issues a lookup for A2 in tick 1. Its response in
tick 5 completes that request. The next priority position is now client 3.
In tick 6, all four clients submit new lookup requests:
Client |
MAC key |
Response bitmap |
Service order |
|---|---|---|---|
0 |
|
|
2 |
1 |
|
|
3 |
2 |
|
|
4 |
3 |
|
|
1 |
The burst is served in order 3, 0, 1, 2. Each response reaches only the client whose request was forwarded. The one-cycle source pulses remain pending while earlier transactions use the table channel.
Round-robin lookup service wraps from client 3 to client 0
Captured pulses and a request held through acknowledgement
The first lookup waits while the shared table serves higher-priority CPU reads. During that wait, two more clients submit requests:
Client |
First request tick |
Captured MAC key |
Request behavior |
|---|---|---|---|
0 |
1 |
|
One-cycle pulse; completes with 0b0001 |
1 |
4 |
|
One-cycle pulse while client 0 is active; completes with 0b0010 |
2 |
5 |
|
Holds req through acknowledgement; completes with 0b0100 |
Client 2 changes its live mac_addr to A3 in tick 6 while
keeping req high. Its downstream request still carries A2,
and its returned bitmap is 0b0100. Client 1’s pulse is also retained
even though its source payload is no longer meaningful while it waits.
The responses arrive in ticks 11, 15, and 19, respectively. The held
request produces one downstream transaction and one acknowledgement.
Queued pulses and a held request retain their first captured MAC
Independent lookup and learning arbitration
Four requests arrive together in tick 1. CPU table access is idle:
Channel |
Client |
MAC key |
Bitmap |
|---|---|---|---|
Lookup |
0 |
|
Returns |
Lookup |
3 |
|
Returns |
Learning |
1 |
|
Stores |
Learning |
2 |
|
Stores |
Both arbiters launch their first request in tick 3. The table completes lookup client 0 in tick 5 and learning client 1 in tick 7. The next lookup request is already launched in tick 7, while the learning acknowledgement belongs to its previous owner. The next learning request follows in tick 9. Separate priority positions produce lookup order 0, 3 and learning order 1, 2.
Each MAC and learning bitmap remains associated with its captured client. The table’s sequential service completes the remaining lookup in tick 9 and learning request in tick 11; acknowledgements are routed independently.
Lookup and learning keep independent owners and request order
Reset cancels active and queued requests
Initially the requests are:
Channel |
Client |
Request tick |
Payload |
|---|---|---|---|
Lookup |
0 |
1 |
|
Lookup |
1 |
2 |
|
Learning |
2 |
1 |
|
The first lookup and learning requests reach the table in tick 3; the second lookup remains queued. Reset is asserted in ticks 4 and 5 for the clients, arbiter, and table. None of those requests receives a completion or is replayed after reset.
Client 3 issues a fresh lookup for A3 in tick 7. It is forwarded
in tick 9 and acknowledged in tick 11. The bitmap is 0b1111 because
the coordinated table reset has also cleared the initial entries.
Reset discards active and queued requests before a fresh lookup
Verification
The test suite is in dv/core/openenoc_forwarding_table_arb_mux/.
Testbench
This suite validates openenoc_forwarding_table_arb_mux as a stand-alone module. The real
forwarding table, forwarding engines and Ethernet datapath are not instantiated. Cocotb drives
all lookup and learning masters directly and models the two forwarding-table slave interfaces
with independently variable response delays.
The module contains two independent round-robin arbiters:
all per-port lookup interfaces share one downstream lookup interface;
all per-port learning interfaces share one downstream learning interface.
Every source can have one outstanding request per channel. The arbiter captures the one-cycle request and its payload, queues simultaneous requests, keeps the selected owner until the slave acknowledges the transaction, and returns the response only to that owner. Lookup and learning may be active concurrently.
Coverage
The TestFactory matrix combines three arrival patterns, four slave timing profiles and three channel selections:
Dimension |
Values |
|---|---|
Request arrival |
consecutive source requests, request during an active transaction, all ports simultaneously |
Slave response delay |
minimum, alternating short/long, deterministic random, long |
Active channels |
lookup only, learning only, lookup and learning concurrently |
Additional directed tests cover:
independent completion timing between lookup and learning;
new requests arriving on the same edge as a slave acknowledge;
requests held until acknowledge producing exactly one transaction;
repeatable randomized arrivals and variable response delays;
reset while transactions are active and queued.
The scoreboard checks every captured request, payload snapshot, downstream request strobe, round-robin selection, registered owner, acknowledge target and lookup bitmap. Inactive payloads are deliberately overwritten after request capture so that using live source data instead of the saved request is detected.
Parameter sweep
The pytest runner sweeps NUM_OF_INTERFACES over 2, 4, 5, 8 and 32 ports. The five-port
configuration checks round-robin pointer wrap for a port count that is not a power of two.