diff options
Diffstat (limited to 'fpga/usrp3/lib/rfnoc/crossbar/axis_ctrl_crossbar_nxn.v')
| -rw-r--r-- | fpga/usrp3/lib/rfnoc/crossbar/axis_ctrl_crossbar_nxn.v | 130 |
1 files changed, 130 insertions, 0 deletions
diff --git a/fpga/usrp3/lib/rfnoc/crossbar/axis_ctrl_crossbar_nxn.v b/fpga/usrp3/lib/rfnoc/crossbar/axis_ctrl_crossbar_nxn.v new file mode 100644 index 000000000..6de082b4c --- /dev/null +++ b/fpga/usrp3/lib/rfnoc/crossbar/axis_ctrl_crossbar_nxn.v @@ -0,0 +1,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 |
