Summary ->

Modules Description
Input FIFOs decouple ingress from switching (elastic buffering)
XY routers independently decide each flit's exit port (one-hot output)
Switch allocator (previewed; full details in Part 2) arbitrates conflicts
Crossbar muxes the data to the selected outputs
Pop logic drains the FIFOs only when flits are accepted downstream (backpressure)

XY Router - Combinational Routing

The xy_router.v module is the simplest building block. It performs one job: decide which output port a flit should go to, given the flit's destination coordinates and the router's own coordinates.

module xy_router #(
    parameter COORD_WIDTH = 1
)(
    input  wire [COORD_WIDTH-1:0] curr_x, curr_y, dest_x, dest_y,
    output reg  [4:0]             out_port_req
);

Inputs:

Output:

Port Encoding:

Local (destination reached)  = 5'b00001
North                        = 5'b00010
South                        = 5'b00100
East                         = 5'b01000
West                         = 5'b10000

Routing Algorithm (XY order):

The logic is a simple priority chain:

always @(*) begin
    if      (dest_x > curr_x) out_port_req = PORT_EAST;
    else if (dest_x < curr_x) out_port_req = PORT_WEST;
    else if (dest_y > curr_y) out_port_req = PORT_SOUTH;
    else if (dest_y < curr_y) out_port_req = PORT_NORTH;
    else                      out_port_req = PORT_LOCAL;
end

Example: If a flit arrives at router (0,0) destined for (1,1):