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

work.globals

Provides project-specific constants and types such as HOTRIO_ADDR_WIDTH_C, HOTRIO_PAYLOAD_WIDTH_C, payload_array_t, array_slv8 etc.

Detailed portlist

scheduler_rxclk_istd_logicrstn_istd_logicen_istd_logicfirst_slave_addr_istd_logic_vector(hotrio_addr_width_c -...broadcast_addr_istd_logic_vector(hotrio_addr_width_c -...addr_update_istd_logicrx_valid_istd_logicrx_addr_istd_logic_vector(hotrio_addr_width_c -...rx_payload_istd_logic_vector(hotrio_payload_width_c...rx_payload_arr_opayload_array_t(0 tonum_slaves_g - 1)rx_payload_valid_arr_ostd_logic_vector(num_slaves_g - 1 downto 0)invalid_addr_pulse_ostd_logic

Generics

Name

Description

Type

Default

num_slaves_g

choose the number of slave addresses and the number of payload output ports to be generated

positive range 1 to 64

3

history_depth_g

choose the depth of que memory for each slave

positive range 1 to 64

3

Input signals


IN ports

Name

Description

Type

clk_i

system clock of the design

std_logic

rstn_i

active low reset, synchronous to `clk_i`

std_logic

en_i

module enable. when not asserted, the fsm is forced to ``idle``

std_logic

first_slave_addr_i

base address used to generate the internal contiguous slave address table

std_logic_vector(hotrio_addr_width_c - 1 downto 0)

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.

std_logic_vector(hotrio_addr_width_c - 1 downto 0)

addr_update_i

rising-edge detected request to reload the internal address table

std_logic

rx_valid_i

indicates that ``rx_addr_i`` and ``rx_payload_i`` contain a decoded incoming packet.

std_logic

rx_addr_i

address field from the incoming decoded packet

std_logic_vector(hotrio_addr_width_c - 1 downto 0)

rx_payload_i

payload field from the incoming decoded packet

std_logic_vector(hotrio_payload_width_c - 1 downto 0)

Output signals


OUT ports

Name

Description

Type

rx_payload_arr_o

latest stored payload for each slave

payload_array_t(0 to num_slaves_g - 1)

rx_payload_valid_arr_o

one-cycle valid pulse vector

std_logic_vector(num_slaves_g - 1 downto 0)

invalid_addr_pulse_o

optional debug -- indicates address other than the configured address is received

std_logic

Generics

Generic

Type / Range

Default

Description

NUM_SLAVES_G

positive range 1 to 256

3

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.

HISTORY_DEPTH_G

positive range 1 to 256

3

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_G

Use 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_C width. The system should ensure that first_slave_addr_i and NUM_SLAVES_G do not create unintended address wraparound.

HISTORY_DEPTH_G

Use this generic to configure how many recent payloads are stored per slave. A value of 1 stores 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_s is set to IDLE.

  • 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_s is cleared to all 0.

  • invalid_addr_pulse_s is cleared to 0.

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_s vector to mark which history entries contain valid data.

  • A fresh_hist_s vector to mark the newest entry for that slave.

  • A wr_ptr_s value 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_ADDR when 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) through slave_addrs_s(NUM_SLAVES_G - 1).

  • Clears payload_hist_s.

  • Clears valid_hist_s.

  • Clears fresh_hist_s.

  • Resets all entries of wr_ptr_s to 0.

  • 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:

  1. Rising edge of addr_reset_i.

  2. Rising edge of addr_update_i.

  3. 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:

  1. Check whether rx_addr_latch_s equals broadcast_addr_i.

  2. If not broadcast, compare rx_addr_latch_s against every entry in slave_addrs_s.

  3. If a slave match is found, store the matched index and proceed to STORE_UNICAST.

  4. 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_s into the selected history entry.

  • Sets the corresponding valid_hist_s bit.

  • Sets the corresponding fresh_hist_s bit.

  • 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_s into payload_hist_s(i)(wr_ptr_s(i)).

  • Sets the matching valid_hist_s bit.

  • Sets the matching fresh_hist_s bit.

  • 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_s for 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_UNICAST asserts one bit.

  • STORE_BROADCAST asserts 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.