// Copyright 2021 ETH Zurich and University of Bologna. // Solderpad Hardware License, Version 0.51, see LICENSE for details. // SPDX-License-Identifier: SHL-0.51 // TCDM Shim // Description: Converts propper handshaking (ready/valid) to TCDM signaling // Author: Florian Zaruba <zarubaf@iis.ee.ethz.ch> module tcdm_shim import mempool_pkg::address_map_t; import cf_math_pkg::idx_width; #( parameter int unsigned AddrWidth = 32 , parameter int unsigned DataWidth = 32 , parameter int unsigned MaxOutStandingReads = 8 , parameter int unsigned NrTCDM = 2 , parameter int unsigned NrSoC = 1 , parameter int unsigned NumRules = 1 , // Routing rules localparam int unsigned StrbWidth = DataWidth/8 , localparam int unsigned NumOutput = NrTCDM + NrSoC, localparam int unsigned MetaIdWidth = idx_width(MaxOutStandingReads) ) ( input logic clk_i, input logic rst_ni, // to TCDM output logic [NrTCDM-1:0] tcdm_req_valid_o, output logic [NrTCDM-1:0][AddrWidth-1:0] tcdm_req_tgt_addr_o, output logic [NrTCDM-1:0] tcdm_req_wen_o, output logic [NrTCDM-1:0][DataWidth-1:0] tcdm_req_wdata_o, output logic [NrTCDM-1:0][3:0] tcdm_req_amo_o, output logic [NrTCDM-1:0][MetaIdWidth-1:0] tcdm_req_id_o, output logic [NrTCDM-1:0][StrbWidth-1:0] tcdm_req_be_o, input logic [NrTCDM-1:0] tcdm_req_ready_i, input logic [NrTCDM-1:0] tcdm_resp_valid_i, output logic [NrTCDM-1:0] tcdm_resp_ready_o, input logic [NrTCDM-1:0][DataWidth-1:0] tcdm_resp_rdata_i, input logic [NrTCDM-1:0][MetaIdWidth-1:0] tcdm_resp_id_i, // to SoC output logic [NrSoC-1:0] [AddrWidth-1:0] soc_qaddr_o, output logic [NrSoC-1:0] soc_qwrite_o, output logic [NrSoC-1:0] [3:0] soc_qamo_o, output logic [NrSoC-1:0] [DataWidth-1:0] soc_qdata_o, output logic [NrSoC-1:0] [StrbWidth-1:0] soc_qstrb_o, output logic [NrSoC-1:0] soc_qvalid_o, input logic [NrSoC-1:0] soc_qready_i, input logic [NrSoC-1:0] [DataWidth-1:0] soc_pdata_i, input logic [NrSoC-1:0] soc_perror_i, input logic [NrSoC-1:0] soc_pvalid_i, output logic [NrSoC-1:0] soc_pready_o, // from core input logic [AddrWidth-1:0] data_qaddr_i, input logic data_qwrite_i, input logic [3:0] data_qamo_i, input logic [DataWidth-1:0] data_qdata_i, input logic [StrbWidth-1:0] data_qstrb_i, input logic [MetaIdWidth-1:0] data_qid_i, input logic data_qvalid_i, output logic data_qready_o, output logic [DataWidth-1:0] data_pdata_o, output logic data_perror_o, output logic [MetaIdWidth-1:0] data_pid_o, output logic data_pvalid_o, input logic data_pready_i, // Address map input address_map_t [NumRules-1:0] address_map_i ); // Imports import snitch_pkg::dreq_t ; import snitch_pkg::dresp_t; // Includes `include "common_cells/registers.svh" dreq_t data_qpayload ; dreq_t [NrSoC-1:0] soc_qpayload ; dreq_t [NrTCDM-1:0] tcdm_qpayload; dresp_t data_ppayload ; dresp_t [NrSoC-1:0] soc_ppayload ; dresp_t [NrTCDM-1:0] tcdm_ppayload; for (genvar i = 0; i < NrTCDM; i++) begin : gen_tcdm_ppayload assign tcdm_ppayload[i].id = tcdm_resp_id_i[i] ; assign tcdm_ppayload[i].data = tcdm_resp_rdata_i[i]; assign tcdm_ppayload[i].error = 1'b0 ; end // ROB IDs of the SoC requests (come back in order) logic [NrSoC-1:0][MetaIdWidth-1:0] soc_meta_id; for (genvar i = 0; i < NrSoC; i++) begin: gen_soc_meta_id_fifo fifo_v3 #( .DEPTH (MaxOutStandingReads), .DATA_WIDTH(MetaIdWidth ) ) i_soc_meta_id_fifo ( .clk_i (clk_i ), .rst_ni (rst_ni ), .flush_i (1'b0 ), .testmode_i(1'b0 ), .data_i (data_qid_i ), .push_i (soc_qvalid_o[i] & soc_qready_i[i] &!soc_qwrite_o[i]), .full_o (/* Unused */ ), .data_o (soc_meta_id[i] ), .pop_i (soc_pvalid_i[i] & soc_pready_o[i] ), .empty_o (/* Unused */ ), .usage_o (/* Unused */ ) ); end: gen_soc_meta_id_fifo // Demux according to address snitch_addr_demux #( .NrOutput (NumOutput), .AddressWidth (AddrWidth), .NumRules (NumRules ), // TODO .req_t (dreq_t ), .resp_t (dresp_t ) ) i_snitch_addr_demux ( .clk_i (clk_i ), .rst_ni (rst_ni ), .req_addr_i (data_qaddr_i ), .req_payload_i (data_qpayload ), .req_valid_i (data_qvalid_i ), .req_ready_o (data_qready_o ), .resp_payload_o(data_ppayload ), .resp_valid_o (data_pvalid_o ), .resp_ready_i (data_pready_i ), .req_payload_o ({soc_qpayload, tcdm_qpayload} ), .req_valid_o ({soc_qvalid_o, tcdm_req_valid_o} ), .req_ready_i ({soc_qready_i, tcdm_req_ready_i} ), .resp_payload_i({soc_ppayload, tcdm_ppayload} ), .resp_valid_i ({soc_pvalid_i, tcdm_resp_valid_i}), .resp_ready_o ({soc_pready_o, tcdm_resp_ready_o}), .address_map_i (address_map_i ) ); // Connect TCDM output ports for (genvar i = 0; i < NrTCDM; i++) begin : gen_tcdm_con assign tcdm_req_tgt_addr_o[i] = tcdm_qpayload[i].addr ; assign tcdm_req_wdata_o[i] = tcdm_qpayload[i].data ; assign tcdm_req_amo_o[i] = tcdm_qpayload[i].amo ; assign tcdm_req_id_o[i] = tcdm_qpayload[i].id ; assign tcdm_req_wen_o[i] = tcdm_qpayload[i].write; assign tcdm_req_be_o[i] = tcdm_qpayload[i].strb ; end // Connect SOCs for (genvar i = 0; i < NrSoC; i++) begin : gen_soc_con assign soc_qaddr_o[i] = soc_qpayload[i].addr ; assign soc_qwrite_o[i] = soc_qpayload[i].write; assign soc_qamo_o[i] = soc_qpayload[i].amo ; assign soc_qdata_o[i] = soc_qpayload[i].data ; assign soc_qstrb_o[i] = soc_qpayload[i].strb ; assign soc_ppayload[i].data = soc_pdata_i[i] ; assign soc_ppayload[i].id = soc_meta_id[i] ; assign soc_ppayload[i].error = soc_perror_i[i] ; end // Request interface assign data_qpayload.addr = data_qaddr_i ; assign data_qpayload.write = data_qwrite_i; assign data_qpayload.amo = data_qamo_i ; assign data_qpayload.data = data_qdata_i ; assign data_qpayload.id = data_qid_i ; assign data_qpayload.strb = data_qstrb_i ; // Response interface assign data_pdata_o = data_ppayload.data ; assign data_perror_o = data_ppayload.error; assign data_pid_o = data_ppayload.id ; // Elaboration-time assertions if (AddrWidth != 32) $fatal(1, "[tcdm_shim] Only support 32-bit wide addresses."); if (DataWidth != 32) $fatal(1, "[tcdm_shim] Only support a data width of 32 bits."); endmodule