333 lines
9.4 KiB
Systemverilog
333 lines
9.4 KiB
Systemverilog
// this module is at local device side, use to handle local device credit based flow control
|
|
module local_port_couple_module
|
|
import rvh_noc_pkg::*;
|
|
#(
|
|
parameter VC_NUM_OUTPORT = 2,
|
|
parameter VC_NUM_OUTPORT_IDX_W = VC_NUM_OUTPORT > 1 ? $clog2(VC_NUM_OUTPORT) : 1,
|
|
parameter VC_DEPTH_OUTPORT = 2,
|
|
parameter VC_DEPTH_OUTPORT_COUNTER_W = $clog2(VC_DEPTH_OUTPORT + 1),
|
|
|
|
// for local ports, always OUTPUT_TO_L
|
|
parameter OUTPUT_TO_N = 0,
|
|
parameter OUTPUT_TO_S = 0,
|
|
parameter OUTPUT_TO_E = 0,
|
|
parameter OUTPUT_TO_W = 0,
|
|
parameter OUTPUT_TO_L = 1
|
|
)
|
|
(
|
|
// input vc head to calculate next routing
|
|
input logic [NodeID_X_Width-1:0] node_id_x_tgt_i,
|
|
input logic [NodeID_Y_Width-1:0] node_id_y_tgt_i,
|
|
`ifdef ALLOW_SAME_ROUTER_L2L_TRANSFER
|
|
input logic [NodeID_Device_Port_Width-1:0] device_port_tgt_i,
|
|
`endif
|
|
|
|
// input this hop xy addr
|
|
input logic [NodeID_X_Width-1:0] node_id_x_src_i,
|
|
input logic [NodeID_Y_Width-1:0] node_id_y_src_i,
|
|
|
|
// output look ahead routing result
|
|
output io_port_t look_ahead_routing_o,
|
|
|
|
// free credit in from router
|
|
input logic tx_lcrd_v_i,
|
|
input logic [VC_ID_NUM_MAX_W-1:0] tx_lcrd_id_i,
|
|
|
|
// consume credit
|
|
input logic flit_vld_i,
|
|
input logic [QoS_Value_Width-1:0] flit_qos_value_i,
|
|
output logic free_credit_vld_o,
|
|
output logic [VC_ID_NUM_MAX_W-1:0] free_credit_vc_id_o,
|
|
|
|
input logic clk,
|
|
input logic rstn
|
|
);
|
|
|
|
logic [VC_NUM_OUTPORT-1:0][VC_DEPTH_OUTPORT_COUNTER_W-1:0] vc_credit_counter;
|
|
logic [VC_NUM_OUTPORT-1:0] vc_credit_counter_non_zero;
|
|
logic [VC_NUM_OUTPORT-QOS_VC_NUM_PER_INPUT-1:0] vc_allocate_common_vc_grt_oh;
|
|
|
|
localparam GRT_IDX_W = VC_NUM_OUTPORT-QOS_VC_NUM_PER_INPUT > 1 ? $clog2(VC_NUM_OUTPORT-QOS_VC_NUM_PER_INPUT) : 1;
|
|
logic [GRT_IDX_W-1:0] vc_allocate_common_vc_grt_idx;
|
|
|
|
`ifdef COMMON_QOS_EXTRA_RT_VC
|
|
logic [QOS_VC_NUM_PER_INPUT-1:0] vc_allocate_rt_vc_grt_oh;
|
|
logic [$clog2(QOS_VC_NUM_PER_INPUT)-1:0] vc_allocate_rt_vc_grt_idx;
|
|
`else
|
|
logic [1-1:0] vc_allocate_rt_vc_grt_oh;
|
|
logic [$clog2(1)-1:0] vc_allocate_rt_vc_grt_idx;
|
|
`endif
|
|
|
|
logic [VC_NUM_OUTPORT_IDX_W-1:0] preferred_vc_id;
|
|
|
|
// to send flit buffer
|
|
logic flit_buffer_head_rt_vc_en;
|
|
|
|
logic free_credit_vld;
|
|
logic flit_buffer_dequeue_vld;
|
|
|
|
logic consume_vc_credit_vld;
|
|
logic [VC_NUM_OUTPORT_IDX_W-1:0] consume_vc_credit_vc_id;
|
|
|
|
|
|
// 1st phase: calculate look ahead routing
|
|
local_port_look_adead_routing
|
|
local_port_look_adead_routing_u
|
|
(
|
|
.node_id_x_tgt_i (node_id_x_tgt_i ),
|
|
.node_id_y_tgt_i (node_id_y_tgt_i ),
|
|
`ifdef ALLOW_SAME_ROUTER_L2L_TRANSFER
|
|
.device_port_tgt_i (device_port_tgt_i),
|
|
`endif
|
|
.node_id_x_src_i (node_id_x_src_i ),
|
|
.node_id_y_src_i (node_id_y_src_i ),
|
|
.look_ahead_routing_o ( look_ahead_routing_o)
|
|
);
|
|
|
|
// 2nd phase: choose input vc
|
|
|
|
assign flit_buffer_head_rt_vc_en = QOS_VC_NUM_PER_INPUT && (flit_qos_value_i == '1);
|
|
|
|
assign free_credit_vld = (
|
|
`ifdef COMMON_QOS_EXTRA_RT_VC
|
|
(flit_buffer_head_rt_vc_en & (|(vc_credit_counter_non_zero[QOS_VC_NUM_PER_INPUT-1:0]))) |
|
|
`endif
|
|
(~flit_buffer_head_rt_vc_en & (|(vc_credit_counter_non_zero[VC_NUM_OUTPORT-1:QOS_VC_NUM_PER_INPUT])))
|
|
);
|
|
|
|
assign free_credit_vld_o = free_credit_vld;
|
|
assign free_credit_vc_id_o = VC_ID_NUM_MAX_W'(consume_vc_credit_vc_id);
|
|
|
|
assign flit_buffer_dequeue_vld = flit_vld_i & // head valid
|
|
free_credit_vld; // vc not empty
|
|
|
|
// rr for vc allocation
|
|
generate
|
|
for(genvar i = 0; i < VC_NUM_OUTPORT; i++) begin: gen_vc_credit_counter_non_zero
|
|
assign vc_credit_counter_non_zero[i] = ~(vc_credit_counter[i] == '0);
|
|
end
|
|
endgenerate
|
|
|
|
one_hot_rr_arb #(
|
|
.N_INPUT (VC_NUM_OUTPORT-QOS_VC_NUM_PER_INPUT)
|
|
)
|
|
vc_allocate_common_vc_rr_arb_u
|
|
(
|
|
.req_i (vc_credit_counter_non_zero[VC_NUM_OUTPORT-1:QOS_VC_NUM_PER_INPUT] ),
|
|
.update_i (|(vc_credit_counter_non_zero[VC_NUM_OUTPORT-1:QOS_VC_NUM_PER_INPUT])),
|
|
.grt_o (vc_allocate_common_vc_grt_oh ),
|
|
.grt_idx_o (vc_allocate_common_vc_grt_idx ),
|
|
|
|
.rstn (rstn ),
|
|
.clk (clk )
|
|
);
|
|
|
|
`ifdef COMMON_QOS_EXTRA_RT_VC
|
|
generate
|
|
if(QOS_VC_NUM_PER_INPUT > 1) begin: gen_vc_allocate_rt_vc_rr_arb_u
|
|
one_hot_rr_arb #(
|
|
.N_INPUT (QOS_VC_NUM_PER_INPUT)
|
|
)
|
|
vc_allocate_rt_vc_rr_arb_u
|
|
(
|
|
.req_i (vc_credit_counter_non_zero[QOS_VC_NUM_PER_INPUT-1:0] ),
|
|
.update_i (|(vc_credit_counter_non_zero[QOS_VC_NUM_PER_INPUT-1:0])),
|
|
.grt_o (vc_allocate_rt_vc_grt_oh ),
|
|
.grt_idx_o (vc_allocate_rt_vc_grt_idx ),
|
|
|
|
.rstn (rstn ),
|
|
.clk (clk )
|
|
);
|
|
end else begin
|
|
assign vc_allocate_rt_vc_grt_oh = vc_credit_counter_non_zero[0];
|
|
assign vc_allocate_rt_vc_grt_idx = '0;
|
|
end
|
|
endgenerate
|
|
`else
|
|
assign vc_allocate_rt_vc_grt_oh = '0;
|
|
assign vc_allocate_rt_vc_grt_idx = '0;
|
|
`endif
|
|
|
|
// credit counter
|
|
assign consume_vc_credit_vld = flit_buffer_dequeue_vld;
|
|
assign consume_vc_credit_vc_id = flit_buffer_head_rt_vc_en ? vc_allocate_rt_vc_grt_idx :
|
|
vc_credit_counter_non_zero[preferred_vc_id] ? preferred_vc_id :
|
|
vc_allocate_common_vc_grt_idx+QOS_VC_NUM_PER_INPUT;
|
|
|
|
output_port_vc_credit_counter
|
|
#(
|
|
.VC_NUM (VC_NUM_OUTPORT ),
|
|
.VC_DEPTH (VC_DEPTH_OUTPORT )
|
|
)
|
|
output_port_vc_credit_counter_u (
|
|
.free_vc_credit_vld_i (tx_lcrd_v_i ),
|
|
.free_vc_credit_vc_id_i (tx_lcrd_id_i[VC_NUM_OUTPORT_IDX_W-1:0] ),
|
|
.consume_vc_credit_vld_i (consume_vc_credit_vld ),
|
|
.consume_vc_credit_vc_id_i (consume_vc_credit_vc_id ),
|
|
.vc_credit_counter_o (vc_credit_counter ),
|
|
.clk (clk ),
|
|
.rstn (rstn )
|
|
);
|
|
|
|
|
|
// select preferred vc id for different output ports
|
|
// to N vc:
|
|
// vc0
|
|
generate
|
|
|
|
if(OUTPUT_TO_N) begin: gen_output_to_n // output to N, next hop input is S
|
|
always_comb begin
|
|
preferred_vc_id = '0;
|
|
unique case(look_ahead_routing_o)
|
|
S: begin
|
|
preferred_vc_id = 0;
|
|
end
|
|
L0: begin
|
|
preferred_vc_id = 1;
|
|
end
|
|
`ifdef LOCAL_PORT_NUM_2
|
|
L1: begin
|
|
preferred_vc_id = 2;
|
|
end
|
|
`endif
|
|
`ifdef LOCAL_PORT_NUM_3
|
|
L2: begin
|
|
preferred_vc_id = 3;
|
|
end
|
|
`endif
|
|
`ifdef LOCAL_PORT_NUM_4
|
|
L3: begin
|
|
preferred_vc_id = 4;
|
|
end
|
|
`endif
|
|
default: begin
|
|
end
|
|
endcase
|
|
preferred_vc_id = preferred_vc_id + QOS_VC_NUM_PER_INPUT;
|
|
end
|
|
end
|
|
|
|
if(OUTPUT_TO_S) begin: gen_output_to_s // output to S, next hop input is N
|
|
always_comb begin
|
|
preferred_vc_id = '0;
|
|
unique case(look_ahead_routing_o)
|
|
N: begin
|
|
preferred_vc_id = 0;
|
|
end
|
|
L0: begin
|
|
preferred_vc_id = 1;
|
|
end
|
|
`ifdef LOCAL_PORT_NUM_2
|
|
L1: begin
|
|
preferred_vc_id = 2;
|
|
end
|
|
`endif
|
|
`ifdef LOCAL_PORT_NUM_3
|
|
L2: begin
|
|
preferred_vc_id = 3;
|
|
end
|
|
`endif
|
|
`ifdef LOCAL_PORT_NUM_4
|
|
L3: begin
|
|
preferred_vc_id = 4;
|
|
end
|
|
`endif
|
|
default: begin
|
|
end
|
|
endcase
|
|
preferred_vc_id = preferred_vc_id + QOS_VC_NUM_PER_INPUT;
|
|
end
|
|
end
|
|
|
|
if(OUTPUT_TO_E) begin: gen_output_to_e // output to E, next hop input is W
|
|
always_comb begin
|
|
preferred_vc_id = '0;
|
|
unique case(look_ahead_routing_o)
|
|
N: begin
|
|
preferred_vc_id = 0;
|
|
end
|
|
S: begin
|
|
preferred_vc_id = 1;
|
|
end
|
|
W: begin
|
|
preferred_vc_id = 2;
|
|
end
|
|
L0: begin
|
|
preferred_vc_id = 3;
|
|
end
|
|
`ifdef LOCAL_PORT_NUM_2
|
|
L1: begin
|
|
preferred_vc_id = 4;
|
|
end
|
|
`endif
|
|
`ifdef LOCAL_PORT_NUM_3
|
|
L2: begin
|
|
preferred_vc_id = 5;
|
|
end
|
|
`endif
|
|
`ifdef LOCAL_PORT_NUM_4
|
|
L3: begin
|
|
preferred_vc_id = 6;
|
|
end
|
|
`endif
|
|
default: begin
|
|
end
|
|
endcase
|
|
preferred_vc_id = preferred_vc_id + QOS_VC_NUM_PER_INPUT;
|
|
end
|
|
end
|
|
|
|
if(OUTPUT_TO_W) begin: gen_output_to_w // output to W, next hop input is E
|
|
always_comb begin
|
|
preferred_vc_id = '0;
|
|
unique case(look_ahead_routing_o)
|
|
N: begin
|
|
preferred_vc_id = 0;
|
|
end
|
|
S: begin
|
|
preferred_vc_id = 1;
|
|
end
|
|
E: begin
|
|
preferred_vc_id = 2;
|
|
end
|
|
L0: begin
|
|
preferred_vc_id = 3;
|
|
end
|
|
`ifdef LOCAL_PORT_NUM_2
|
|
L1: begin
|
|
preferred_vc_id = 4;
|
|
end
|
|
`endif
|
|
`ifdef LOCAL_PORT_NUM_3
|
|
L2: begin
|
|
preferred_vc_id = 5;
|
|
end
|
|
`endif
|
|
`ifdef LOCAL_PORT_NUM_4
|
|
L3: begin
|
|
preferred_vc_id = 6;
|
|
end
|
|
`endif
|
|
default: begin
|
|
end
|
|
endcase
|
|
preferred_vc_id = preferred_vc_id + QOS_VC_NUM_PER_INPUT;
|
|
end
|
|
end
|
|
|
|
if(OUTPUT_TO_L) begin: gen_output_to_l // output to L, no next hop
|
|
always_comb begin
|
|
preferred_vc_id = '0;
|
|
unique case(look_ahead_routing_o) // assume all local port have 1 vc
|
|
default: begin
|
|
preferred_vc_id = '0;
|
|
end
|
|
endcase
|
|
preferred_vc_id = preferred_vc_id + QOS_VC_NUM_PER_INPUT;
|
|
end
|
|
end
|
|
|
|
endgenerate
|
|
|
|
endmodule
|