tcdm_shim.sv 8.17 KB
Newer Older
sakundu committed
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 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180
// 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