Scheduler RX
Overview
Scheduler_rx is a HotRIO receive-side scheduler and packet decoder. It accepts decoded incoming packets, checks whether each packet is addressed to one of the configured slave addresses or to a broadcast address, and stores the received payload into per-slave history buffers.
The module provides the latest payload per slave on rx_payload_arr_o and
generates one-cycle valid pulses on rx_payload_valid_arr_o whenever a
payload is stored. Invalid packet addresses are reported with a one-cycle pulse
on invalid_addr_pulse_o.
The design supports:
Configurable number of slave addresses.
Configurable payload history depth per slave.
Sequential address table generation from a base address.
Unicast packet decoding and storage.
Broadcast packet decoding and storage to all slaves.
Address table reload using update or reset pulses.
Invalid-address detection for debug and diagnostics.
scheduler_rx is interfaced to the HotRIO master Rx which receives packets from a group of addressed HotRIO slave endpoints. The module converts a
stream of decoded packet fields into structured per-slave payload outputs.
It typically does the following functions :
Receiving slave-specific status or measurement payloads.
Maintaining the latest received payload for each slave.
Keeping a short circular history of recently received payloads per slave.
Applying a broadcast payload update to all slave entries.
Detecting packets whose address does not belong to the configured address map.
The module is designed to sit after the HotRIO master Rx. The HotRIO master Rx
asserts rx_valid_i with rx_addr_i and rx_payload_i. The scheduler
latches the packet, decodes the address, stores the payload, and then returns to
waiting for the next packet.
Source Dependencies
The design uses the following packages:
Package |
Purpose |
|---|---|
|
Provides project-specific constants and types such as
|
Detailed portlist
Generics
Name |
Description |
Type |
Default |
|---|---|---|---|
num_slaves_g | choose the number of slave addresses and the number of payload output ports to be generated |
|
|
history_depth_g | choose the depth of que memory for each slave |
|
|
Input signals
IN ports
Name |
Description |
Type |
|---|---|---|
clk_i | system clock of the design |
|
rstn_i | active low reset, synchronous to `clk_i` |
|
en_i | module enable. when not asserted, the fsm is forced to ``idle`` |
|
first_slave_addr_i | base address used to generate the internal contiguous slave address table |
|
broadcast_addr_i | address value that identifies a broadcast packet. if the latched receive address equals this value, the payload is stored for every slave. |
|
addr_update_i | rising-edge detected request to reload the internal address table |
|
rx_valid_i | indicates that ``rx_addr_i`` and ``rx_payload_i`` contain a decoded incoming packet. |
|
rx_addr_i | address field from the incoming decoded packet |
|
rx_payload_i | payload field from the incoming decoded packet |
|
Output signals
OUT ports
Name |
Description |
Type |
|---|---|---|
rx_payload_arr_o | latest stored payload for each slave |
|
rx_payload_valid_arr_o | one-cycle valid pulse vector |
|
invalid_addr_pulse_o | optional debug -- indicates address other than the configured address is received |
|
Generics
Generic |
Type / Range |
Default |
Description |
|---|---|---|---|
|
|
|
Defines the number of slave addresses handled by the scheduler. This generic sizes the address table, output payload array, output valid vector, match index range, write-pointer array, and internal history storage. |
|
|
|
Defines how many received payload entries are retained internally for each slave. Each slave has an independent circular history buffer and an independent write pointer. |
Generic Use Cases
NUM_SLAVES_GUse this generic to match the number of slave endpoints in the receive address map. For example, if the system has eight slaves addressed sequentially from a base address, set
NUM_SLAVES_G => 8.The internal address table is generated as:
slave_addrs_s(i) = first_slave_addr_i + i
Address generation uses unsigned arithmetic at
HOTRIO_ADDR_WIDTH_Cwidth. The system should ensure thatfirst_slave_addr_iandNUM_SLAVES_Gdo not create unintended address wraparound.HISTORY_DEPTH_GUse this generic to configure how many recent payloads are stored per slave. A value of
1stores only the most recent payload in the internal history. Larger values create a per-slave circular buffer.The current entity exposes only the latest payload per slave through
rx_payload_arr_o. The history buffers are internal to this implementation. They are useful for future extensions, debug visibility, or additional interfaces that may expose historical payload entries.
Internal Architecture
Reset Behavior
When rstn_i = '0' on a rising clock edge:
fsm_sis set toIDLE.The generated slave address table is cleared.
Payload history, valid history, and fresh history are cleared.
All per-slave write pointers are reset to
0.Latest payload outputs are cleared.
Output valid pulses and invalid-address pulse are deasserted.
Packet latches are cleared.
Match state is cleared.
Address update and address reset edge-detection registers are cleared.
Enable Behavior
At the beginning of every enabled clock cycle outside reset:
rx_payload_valid_arr_sis cleared to all0.invalid_addr_pulse_sis cleared to0.
This makes the receive valid outputs and invalid-address output behave as single-cycle pulses.
When en_i is not asserted:
The FSM is forced to
IDLE.Payload history, valid history, fresh history, and write pointers are cleared.
Latest payload outputs are cleared.
Match state is cleared.
Address Table Generation
The address table is generated in the LOAD_ADDR state:
for i in 0 to NUM_SLAVES_G-1 loop
slave_addrs_s(i) <= std_logic_vector(
unsigned(first_slave_addr_i) +
to_unsigned(i, HOTRIO_ADDR_WIDTH_C)
);
end loop;
After the table is generated, the module clears receive history and returns to
packet-waiting operation through the WAIT_PACKET state.
Payload History Model
Each slave has an independent circular history buffer:
payload_hist_s(slave_index)(history_index)
Each slave also has:
A
valid_hist_svector to mark which history entries contain valid data.A
fresh_hist_svector to mark the newest entry for that slave.A
wr_ptr_svalue to select the next history entry to overwrite.
On each unicast store, only the matched slave history is updated. On each broadcast store, every slave history is updated with the broadcast payload.
Circular Write Pointer
For each slave, the write pointer advances after a payload is stored:
0 -> 1 -> 2 -> ... -> HISTORY_DEPTH_G - 1 -> 0
The pointer wraps to 0 after the final history entry. Each slave has an
independent pointer, so one active slave does not disturb the history position
of other slaves.
Finite State Machine
IDLE State
The IDLE state is the inactive starting point of the receive scheduler.
Actions performed:
No packet is decoded.
No payload is stored.
The FSM advances to
LOAD_ADDRwhen the module is enabled.
This state prevents packet processing before the address table has been initialized.
LOAD_ADDR State
The LOAD_ADDR state builds the internal slave address table using
first_slave_addr_i as the base address. It also clears all receive history
and output payload storage.
Actions performed:
Generates
slave_addrs_s(0)throughslave_addrs_s(NUM_SLAVES_G - 1).Clears
payload_hist_s.Clears
valid_hist_s.Clears
fresh_hist_s.Resets all entries of
wr_ptr_sto0.Clears
rx_payload_arr_s.Clears match state.
Advances to
WAIT_PACKET.
This state is entered after IDLE and when either addr_update_i or
addr_reset_i is detected in WAIT_PACKET.
WAIT_PACKET State
The WAIT_PACKET state is the normal idle-running state. The scheduler waits
for either an address-table reload request or a valid received packet.
Priority order in WAIT_PACKET:
Rising edge of
addr_reset_i.Rising edge of
addr_update_i.rx_valid_i = '1'.
If addr_reset_i or addr_update_i has a rising edge, the FSM moves to
LOAD_ADDR. If rx_valid_i is asserted, the module latches the incoming
address and payload:
rx_addr_latch_s <= rx_addr_i;
rx_payload_latch_s <= rx_payload_i;
fsm_s <= DECODE_ADDR;
The latched values are used in later FSM states. This gives a stable packet view during address decoding and storage.
DECODE_ADDR State
The DECODE_ADDR state classifies the latched address.
The decode order is:
Check whether
rx_addr_latch_sequalsbroadcast_addr_i.If not broadcast, compare
rx_addr_latch_sagainst every entry inslave_addrs_s.If a slave match is found, store the matched index and proceed to
STORE_UNICAST.If no match is found, proceed to
ERROR_ADDR.
Broadcast has priority over unicast matching. If the broadcast address is equal to one of the generated slave addresses, the packet is treated as broadcast.
The unicast search loop is:
match_found_v := '0';
match_idx_v := 0;
for i in 0 to NUM_SLAVES_G-1 loop
if rx_addr_latch_s = slave_addrs_s(i) then
match_found_v := '1';
match_idx_v := i;
end if;
end loop;
If duplicate addresses exist in slave_addrs_s, the final matching index in
the loop is selected. A correctly configured system should avoid duplicate
slave addresses.
STORE_UNICAST State
The STORE_UNICAST state stores the latched payload for the matched slave.
Actions performed for match_idx_s:
Clears all
fresh_hist_s(match_idx_s)entries.Reads the current write pointer for the matched slave.
Writes
rx_payload_latch_sinto the selected history entry.Sets the corresponding
valid_hist_sbit.Sets the corresponding
fresh_hist_sbit.Updates
rx_payload_arr_s(match_idx_s)with the latest payload.Pulses
rx_payload_valid_arr_s(match_idx_s).Advances the matched slave write pointer with wraparound.
Returns to
WAIT_PACKET.
Only the matched slave is updated. Other slave histories and latest payloads are left unchanged.
STORE_BROADCAST State
The STORE_BROADCAST state stores the latched payload into every slave entry.
For each slave i:
Clears all
fresh_hist_s(i)entries.Reads
wr_ptr_s(i).Writes
rx_payload_latch_sintopayload_hist_s(i)(wr_ptr_s(i)).Sets the matching
valid_hist_sbit.Sets the matching
fresh_hist_sbit.Updates
rx_payload_arr_s(i)with the broadcast payload.Pulses
rx_payload_valid_arr_s(i).Advances
wr_ptr_s(i)with wraparound.
After all slaves are updated, the FSM returns to WAIT_PACKET.
ERROR_ADDR State
The ERROR_ADDR state handles packets whose address is neither the broadcast
address nor a configured slave address.
Actions performed:
Asserts
invalid_addr_pulse_sfor one clock cycle.Returns to
WAIT_PACKET.
No payload history or latest payload output is modified in this state.
Output Behavior
Latest Payload Outputs
rx_payload_arr_o reflects rx_payload_arr_s, which stores the latest
payload received for each slave.
For a unicast packet:
Only the matched slave payload output is updated.
Only the matched valid bit pulses.
For a broadcast packet:
Every slave payload output is updated with the broadcast payload.
Every valid bit pulses.
Payload Valid Pulses
rx_payload_valid_arr_o is cleared to all zeros at the beginning of each
non-reset clock cycle. It is then asserted only in store states:
STORE_UNICASTasserts one bit.STORE_BROADCASTasserts all bits.
This output should be treated as a pulse notification that a latest payload entry was updated.
Invalid Address Pulse
invalid_addr_pulse_o is also cleared at the beginning of each non-reset
clock cycle. It is asserted in ERROR_ADDR for one cycle when an unmatched
packet address is detected.
Address Reload Behavior
Address reload requests are detected using sampled previous values:
if (addr_update_old_s = '0' and addr_update_i = '1') then
fsm_s <= LOAD_ADDR;
The edge-history registers are updated at the end of each non-reset clock cycle:
addr_update_old_s <= addr_update_i;
The current implementation checks these edges only in WAIT_PACKET. For
reliable address reload behavior, assert addr_update_i
while the scheduler is enabled and waiting for packets.