1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130
|
//
// Copyright 2018 Ettus Research, A National Instruments Company
//
// SPDX-License-Identifier: LGPL-3.0-or-later
//
// Module: axis_ctrl_crossbar_nxn
// Description:
// This module implements a 2-dimentional (2d) mesh network (mesh) crossbar
// for AXIS-CTRL traffic. Supports mesh and torus topologies.
// It uses AXI-Stream for all of its links.
// The torus topology, routing algorithms and the router architecture is
// described in README.md in this directory.
// Parameters:
// - WIDTH: Width of the AXI-Stream data bus
// - NPORTS: Number of ports (maximum 1024)
// - TOPOLOGY: Is this a mesh (MESH) or a torus (TORUS) topology
// - INGRESS_BUFF_SIZE: log2 of the ingress terminal buffer size (in words)
// - ROUTER_BUFF_SIZE: log2 of the ingress inter-router buffer size (in words)
// - ROUTING_ALLOC: Algorithm to allocate routing paths between routers.
// * WORMHOLE: Allocate route as soon as first word in pkt arrives
// * CUT-THROUGH: Allocate route only after the full pkt arrives
// - SWITCH_ALLOC: Algorithm to allocate the switch
// * PRIO: Priority based. Priority: Y-dim > X-dim > Term
// * ROUND-ROBIN: Round robin input port allocation
// - DEADLOCK_TIMEOUT: Number of cycles to wait until a deadlock is detected
// Signals:
// - s_axis_*: Slave port for router (flattened)
// - m_axis_*: Master port for router (flattened)
//
module axis_ctrl_crossbar_nxn #(
parameter WIDTH = 32,
parameter NPORTS = 10,
parameter TOPOLOGY = "TORUS",
parameter INGRESS_BUFF_SIZE = 5,
parameter ROUTER_BUFF_SIZE = 5,
parameter ROUTING_ALLOC = "WORMHOLE",
parameter SWITCH_ALLOC = "PRIO",
parameter DEADLOCK_TIMEOUT = 16384
) (
input wire clk,
input wire reset,
// Inputs
input wire [(NPORTS*WIDTH)-1:0] s_axis_tdata,
input wire [NPORTS-1:0] s_axis_tlast,
input wire [NPORTS-1:0] s_axis_tvalid,
output wire [NPORTS-1:0] s_axis_tready,
// Output
output wire [(NPORTS*WIDTH)-1:0] m_axis_tdata,
output wire [NPORTS-1:0] m_axis_tlast,
output wire [NPORTS-1:0] m_axis_tvalid,
input wire [NPORTS-1:0] m_axis_tready,
// Deadlock alert
output wire deadlock_detected
);
function integer csqrt_max1024;
input integer value;
integer i;
begin
csqrt_max1024 = 1;
for (i = 1; i <= 32; i = i + 1) // sqrt(1024) = 32
csqrt_max1024 = csqrt_max1024 + (i*i < value ? 1 : 0);
end
endfunction
localparam integer DIM_SIZE = csqrt_max1024(NPORTS);
wire [(DIM_SIZE*DIM_SIZE*WIDTH)-1:0] i_tdata, o_tdata ;
wire [DIM_SIZE*DIM_SIZE-1:0] i_tlast, o_tlast ;
wire [DIM_SIZE*DIM_SIZE-1:0] i_tvalid, o_tvalid;
wire [DIM_SIZE*DIM_SIZE-1:0] i_tready, o_tready;
// axis_ctrl_crossbar_2d_mesh needs to scale up in squares
// i.e. 4, 9, 16, 25, ... but NPORTS can be any number, so
// instantiate the next highest square number of ports and
// terminate the rest.
axis_ctrl_crossbar_2d_mesh #(
.WIDTH (WIDTH),
.DIM_SIZE (DIM_SIZE),
.TOPOLOGY (TOPOLOGY),
.INGRESS_BUFF_SIZE(INGRESS_BUFF_SIZE),
.ROUTER_BUFF_SIZE (ROUTER_BUFF_SIZE),
.ROUTING_ALLOC (ROUTING_ALLOC),
.SWITCH_ALLOC (SWITCH_ALLOC),
.DEADLOCK_TIMEOUT (DEADLOCK_TIMEOUT)
) router_dut_i (
.clk (clk),
.reset (reset),
.s_axis_tdata (i_tdata),
.s_axis_tlast (i_tlast),
.s_axis_tvalid (i_tvalid),
.s_axis_tready (i_tready),
.m_axis_tdata (o_tdata),
.m_axis_tlast (o_tlast),
.m_axis_tvalid (o_tvalid),
.m_axis_tready (o_tready),
.deadlock_detected(deadlock_detected)
);
// Connect the bottom NPORTS to the IO
assign i_tdata[(NPORTS*WIDTH)-1:0] = s_axis_tdata;
assign i_tlast[NPORTS-1:0] = s_axis_tlast;
assign i_tvalid[NPORTS-1:0] = s_axis_tvalid;
assign s_axis_tready = i_tready[NPORTS-1:0];
assign m_axis_tdata = o_tdata[(NPORTS*WIDTH)-1:0];
assign m_axis_tlast = o_tlast[NPORTS-1:0];
assign m_axis_tvalid = o_tvalid[NPORTS-1:0];
assign o_tready[NPORTS-1:0] = m_axis_tready;
// Terminate the rest
genvar i;
generate for (i = NPORTS; i < (DIM_SIZE*DIM_SIZE); i = i + 1) begin: ports
axis_port_terminator #(.DATA_W(WIDTH)) term_i (
.clk (clk),
.reset (reset),
.s_axis_tdata (o_tdata[(i*WIDTH)+:WIDTH]),
.s_axis_tlast (o_tlast[i]),
.s_axis_tvalid(o_tvalid[i]),
.s_axis_tready(o_tready[i]),
.m_axis_tdata (i_tdata[(i*WIDTH)+:WIDTH]),
.m_axis_tlast (i_tlast[i]),
.m_axis_tvalid(i_tvalid[i]),
.m_axis_tready(i_tready[i]),
.pkts_dropped ()
);
end endgenerate
endmodule
|