module input_port_vc import rvh_noc_pkg::*; #( parameter type flit_payload_t = logic[256-1:0], parameter VC_NUM = 1, parameter VC_NUM_IDX_W = VC_NUM > 1 ? $clog2(VC_NUM) : 1, parameter VC_DEPTH = 1, `ifdef RETURN_CREDIT_AT_SA_STAGE parameter VC_BUFFER_DEPTH = VC_DEPTH + 1, // need one more slot to handle push and pop at the same cycle when the fifo is full `else parameter VC_BUFFER_DEPTH = VC_DEPTH, `endif parameter VC_BUFFER_DEPTH_IDX_W = VC_BUFFER_DEPTH > 1 ? $clog2(VC_BUFFER_DEPTH) : 1 `ifdef VC_DATA_USE_DUAL_PORT_RAM , parameter VC_DPRAM_DEPTH = VC_NUM * VC_BUFFER_DEPTH, parameter VC_DPRAM_DEPTH_IDX_W = VC_DPRAM_DEPTH > 1 ? $clog2(VC_DPRAM_DEPTH) : 1 `endif ) ( // input from input port input logic flit_v_i, input flit_payload_t flit_i, input flit_dec_t flit_dec_i, input logic [VC_NUM_IDX_W-1:0] flit_vc_id_i, // free vc credit sent to sender output logic lcrd_v_o, output logic [VC_ID_NUM_MAX_W-1:0] lcrd_id_o, // output ctrl to local allocate output logic [VC_NUM-1:0] vc_ctrl_head_vld_o, output flit_dec_t [VC_NUM-1:0] vc_ctrl_head_o, // output data to switch traversal output flit_payload_t [VC_NUM-1:0] vc_data_head_o, // input pop flit ctrl fifo (comes from SA stage) input logic inport_read_enable_sa_stage_i, input logic [VC_NUM_IDX_W-1:0] inport_read_vc_id_sa_stage_i, // use local sa result instead of vc assignment `ifdef VC_DATA_USE_DUAL_PORT_RAM input dpram_used_idx_t inport_read_dpram_idx_i, `endif // input pop flit ctrl fifo (comes from ST stage) input logic inport_read_enable_st_stage_i, input logic [VC_NUM_IDX_W-1:0] inport_read_vc_id_st_stage_i, input logic clk, input logic rstn ); genvar i; logic [VC_NUM-1:0] vc_data_tail_we; flit_payload_t vc_data_din; logic [VC_NUM-1:0] vc_data_enqueue_rdy; logic [VC_NUM-1:0] vc_ctrl_tail_we; flit_dec_t vc_ctrl_din; logic [VC_NUM-1:0] vc_ctrl_enqueue_rdy; logic [VC_NUM-1:0] vc_data_head_vld; flit_payload_t [VC_NUM-1:0] vc_data_head; logic [VC_NUM-1:0] vc_data_head_dequeue_vld; logic [VC_NUM-1:0] vc_ctrl_head_vld; flit_dec_t [VC_NUM-1:0] vc_ctrl_head; logic [VC_NUM-1:0] vc_ctrl_head_dequeue_vld; `ifdef VC_DATA_USE_DUAL_PORT_RAM logic [VC_NUM-1:0][VC_BUFFER_DEPTH_IDX_W-1:0] vc_data_freelist_deq_per_vc_idx; logic [VC_BUFFER_DEPTH_IDX_W-1:0] vc_data_freelist_deq_per_vc_idx_sel; logic [VC_NUM-1:0] vc_data_freelist_deq_rdy; logic [VC_NUM-1:0][VC_DPRAM_DEPTH_IDX_W-1:0] vc_data_freelist_deq_dpram_idx; logic [VC_DPRAM_DEPTH_IDX_W-1:0] vc_data_freelist_deq_dpram_idx_sel; logic [VC_NUM-1:0] vc_data_freelist_deq_vld; logic [VC_BUFFER_DEPTH_IDX_W-1:0] vc_data_freelist_enq_per_vc_idx; `endif // enqueue always_comb begin vc_data_tail_we = '0; vc_ctrl_tail_we = '0; if(flit_v_i) begin vc_data_tail_we[flit_vc_id_i] = 1'b1; vc_ctrl_tail_we[flit_vc_id_i] = 1'b1; end end assign vc_data_din = flit_i; assign vc_ctrl_din.tgt_id = flit_dec_i.tgt_id; assign vc_ctrl_din.src_id = flit_dec_i.src_id; `ifdef ENABLE_TXN_ID assign vc_ctrl_din.txn_id = flit_dec_i.txn_id; `endif assign vc_ctrl_din.look_ahead_routing = flit_dec_i.look_ahead_routing; `ifdef USE_QOS_VALUE assign vc_ctrl_din.qos_value = flit_dec_i.qos_value; `endif `ifdef VC_DATA_USE_DUAL_PORT_RAM assign vc_ctrl_din.dpram_used_idx.dpram_idx = {{(VC_DPRAM_DEPTH_MAX_W-VC_DPRAM_DEPTH_IDX_W){1'b0}}, vc_data_freelist_deq_dpram_idx_sel}; assign vc_ctrl_din.dpram_used_idx.per_vc_idx = {{(VC_BUFFER_DEPTH_MAX_W-VC_BUFFER_DEPTH_IDX_W){1'b0}}, vc_data_freelist_deq_per_vc_idx_sel}; `endif // dequeue // ctrl dequeue at SA stage always_comb begin vc_ctrl_head_dequeue_vld = '0; vc_ctrl_head_dequeue_vld[inport_read_vc_id_sa_stage_i] = inport_read_enable_sa_stage_i; end // data dequeue at ST stage always_comb begin vc_data_head_dequeue_vld = '0; vc_data_head_dequeue_vld[inport_read_vc_id_st_stage_i] = inport_read_enable_st_stage_i; end // fifo module `ifdef VC_DATA_USE_DUAL_PORT_RAM generate for(i = 0; i < VC_NUM; i++) begin: gen_vc_data_freelist_deq_dpram_idx assign vc_data_freelist_deq_dpram_idx[i] = VC_BUFFER_DEPTH * i + vc_data_freelist_deq_per_vc_idx[i]; end endgenerate assign vc_data_freelist_deq_vld = vc_data_tail_we; onehot_mux #( .SOURCE_COUNT(VC_NUM ), .DATA_WIDTH (VC_DPRAM_DEPTH_IDX_W ) ) onehot_mux_vc_data_freelist_deq_dpram_idx_sel_u ( .sel_i (vc_data_tail_we ), .data_i (vc_data_freelist_deq_dpram_idx ), .data_o (vc_data_freelist_deq_dpram_idx_sel ) ); onehot_mux #( .SOURCE_COUNT(VC_NUM ), .DATA_WIDTH (VC_BUFFER_DEPTH_IDX_W ) ) onehot_mux_vc_data_freelist_deq_per_vc_idx_sel_u ( .sel_i (vc_data_tail_we ), .data_i (vc_data_freelist_deq_per_vc_idx ), .data_o (vc_data_freelist_deq_per_vc_idx_sel ) ); assign vc_data_freelist_enq_per_vc_idx = inport_read_dpram_idx_i.per_vc_idx[VC_BUFFER_DEPTH_IDX_W-1:0]; // free list generate for(i = 0; i < VC_NUM; i++) begin: gen_vc_data_freelist freelist #( .ENTRY_COUNT (VC_BUFFER_DEPTH) ) VC_DATA_FREELIST_U ( .enq_vld_i (vc_ctrl_head_dequeue_vld [i] ), .enq_tag_i (vc_data_freelist_enq_per_vc_idx ), .deq_vld_i (vc_data_freelist_deq_vld [i] ), .deq_tag_o (vc_data_freelist_deq_per_vc_idx [i] ), .deq_rdy_o (vc_data_freelist_deq_rdy [i] ), .flush_i ('0 ), .clk (clk ), .rst (~rstn ) ); end endgenerate // dpram simple_dual_one_clock #( .ADDR_BITS (VC_DPRAM_DEPTH_IDX_W), .DATA_BITS ($bits(flit_payload_t)) ) VC_DATA_DPRAM_U ( .clk (clk ), .ena (flit_v_i ), // in flit write .enb (inport_read_enable_sa_stage_i ), // out flit read .wea (flit_v_i ), .addra (vc_data_freelist_deq_dpram_idx_sel ), .addrb (inport_read_dpram_idx_i.dpram_idx[VC_DPRAM_DEPTH_IDX_W-1:0] ), .dia (vc_data_din ), .dob (vc_data_head_o [0] ) ); `else generate for(i = 0; i < VC_NUM; i++) begin: gen_vc_data_fifo mp_fifo #( .payload_t (flit_payload_t), .ENQUEUE_WIDTH (1), .DEQUEUE_WIDTH (1), .DEPTH (VC_BUFFER_DEPTH), .MUST_TAKEN_ALL (1) ) VC_DATA_U ( // Enqueue .enqueue_vld_i (vc_data_tail_we [i] ), .enqueue_payload_i (vc_data_din ), .enqueue_rdy_o (vc_data_enqueue_rdy [i] ), // Dequeue .dequeue_vld_o (vc_data_head_vld [i] ), .dequeue_payload_o (vc_data_head [i] ), .dequeue_rdy_i (vc_data_head_dequeue_vld [i] ), .flush_i (1'b0 ), .clk (clk), .rst (~rstn) ); assign vc_data_head_o [i] = vc_data_head [i]; end endgenerate `endif generate for(i = 0; i < VC_NUM; i++) begin: gen_vc_ctrl_fifo mp_fifo #( .payload_t (flit_dec_t), .ENQUEUE_WIDTH (1), .DEQUEUE_WIDTH (1), .DEPTH (VC_DEPTH), .MUST_TAKEN_ALL (1) ) VC_CTRL_U ( // Enqueue .enqueue_vld_i (vc_ctrl_tail_we [i] ), .enqueue_payload_i (vc_ctrl_din ), .enqueue_rdy_o (vc_ctrl_enqueue_rdy [i] ), // Dequeue .dequeue_vld_o (vc_ctrl_head_vld [i] ), .dequeue_payload_o (vc_ctrl_head [i] ), .dequeue_rdy_i (vc_ctrl_head_dequeue_vld [i] ), .flush_i (1'b0 ), .clk (clk), .rst (~rstn) ); assign vc_ctrl_head_vld_o [i] = vc_ctrl_head_vld[i]; assign vc_ctrl_head_o [i] = vc_ctrl_head [i]; end endgenerate // free vc credit sent to sender `ifdef RETURN_CREDIT_AT_SA_STAGE assign lcrd_v_o = inport_read_enable_sa_stage_i; assign lcrd_id_o = {{(VC_ID_NUM_MAX_W-VC_NUM_IDX_W){1'b0}}, inport_read_vc_id_sa_stage_i}; `else assign lcrd_v_o = inport_read_enable_st_stage_i; assign lcrd_id_o = {{(VC_ID_NUM_MAX_W-VC_NUM_IDX_W){1'b0}}, inport_read_vc_id_st_stage_i}; `endif `ifndef SYNTHESIS `ifdef COMMON_QOS_EXTRA_RT_VC // assert property(@(posedge clk)disable iff(~rstn) (flit_v_i == 1'b1) |-> (((flit_vc_id_i < QOS_VC_NUM_PER_INPUT) && (flit_dec_i.qos_value == 15)))) // else $error("noc_input_port: flit with highest QoS value goes into common VC, txn_id: 0x%x, vc_id: %d, flit_v_i=%d", flit_dec_i.txn_id, flit_vc_id_i, flit_v_i); // assert property(@(posedge clk)disable iff(~rstn) (flit_v_i == 1'b1) |-> (((flit_vc_id_i >= QOS_VC_NUM_PER_INPUT) && (flit_dec_i.qos_value < 15)))) // else begin $display("noc_input_port: flit with lower QoS value goes into rt VC, txn_id: 0x%x, vc_id: %d, flit_v_i=%d", flit_dec_i.txn_id, flit_vc_id_i, flit_v_i); $fatal(); end generate for(i = 0; i < QOS_VC_NUM_PER_INPUT; i++) begin assert property(@(posedge clk)disable iff(~rstn) (vc_ctrl_head_vld[i]) |-> (vc_ctrl_head[i].qos_value == 15)) `ifdef ENABLE_TXN_ID else $fatal("noc_input_vc: rt VC has flit with lower QoS value, txn_id: 0x%x", vc_ctrl_head[i].txn_id); `else else $fatal("noc_input_vc: rt VC has flit with lower QoS value"); `endif end for(i = QOS_VC_NUM_PER_INPUT; i < VC_NUM; i++) begin assert property(@(posedge clk)disable iff(~rstn) (vc_ctrl_head_vld[i]) |-> (vc_ctrl_head[i].qos_value != 15)) `ifdef ENABLE_TXN_ID else $fatal("noc_input_vc: common VC has flit with highest QoS value, txn_id: 0x%x", vc_ctrl_head[i].txn_id); `else else $fatal("noc_input_vc: common VC has flit with highest QoS value"); `endif end endgenerate `endif `endif endmodule