From 38693c51e319d618360e006b1533f64beb8aa322 Mon Sep 17 00:00:00 2001 From: Manuel Eggimann Date: Sun, 1 Nov 2020 17:58:27 +0100 Subject: [PATCH 01/30] Refactored soc_interconnect. Not yet tested. --- ips_list.yml | 5 +- rtl/include/tcdm_explode_macros.svh | 51 +++++ rtl/pulp_soc/axi64_to_lint32_wrap.sv | 149 ++++++++++++++ rtl/pulp_soc/boot_rom.sv | 36 +++- rtl/pulp_soc/contiguous_crossbar.sv | 136 +++++++++++++ rtl/pulp_soc/interleaved_crossbar.sv | 124 ++++++++++++ rtl/pulp_soc/l2_ram_multi_bank.sv | 241 +++++++++++++---------- rtl/pulp_soc/lint_2_axi_wrap.sv | 132 +++++++++++++ rtl/pulp_soc/pkg_soc_interconnect.sv | 9 + rtl/pulp_soc/pulp_soc.sv | 77 +++++--- rtl/pulp_soc/soc_interconnect_v2.sv | 230 +++++++++++++++++++++ rtl/pulp_soc/soc_interconnect_wrap_v2.sv | 201 +++++++++++++++++++ rtl/pulp_soc/tcdm_demux.sv | 146 ++++++++++++++ src_files.yml | 16 +- 14 files changed, 1411 insertions(+), 142 deletions(-) create mode 100644 rtl/include/tcdm_explode_macros.svh create mode 100644 rtl/pulp_soc/axi64_to_lint32_wrap.sv create mode 100644 rtl/pulp_soc/contiguous_crossbar.sv create mode 100644 rtl/pulp_soc/interleaved_crossbar.sv create mode 100644 rtl/pulp_soc/lint_2_axi_wrap.sv create mode 100644 rtl/pulp_soc/pkg_soc_interconnect.sv create mode 100644 rtl/pulp_soc/soc_interconnect_v2.sv create mode 100644 rtl/pulp_soc/soc_interconnect_wrap_v2.sv create mode 100644 rtl/pulp_soc/tcdm_demux.sv diff --git a/ips_list.yml b/ips_list.yml index 0c176a29..74663a6c 100644 --- a/ips_list.yml +++ b/ips_list.yml @@ -21,6 +21,9 @@ L2_tcdm_hybrid_interco: commit: pulpissimo-v1.0 domain: [soc] +cluster_interconnect: + commit: master + domain: [soc] adv_dbg_if: commit: v0.0.1 domain: [cluster, soc] @@ -43,7 +46,7 @@ apb_interrupt_cntrl: commit: v0.0.1 domain: [soc] axi/axi: - commit: v0.7.1 + commit: v0.24.0 domain: [cluster, soc] axi/axi_node: commit: v1.1.4 diff --git a/rtl/include/tcdm_explode_macros.svh b/rtl/include/tcdm_explode_macros.svh new file mode 100644 index 00000000..b238e578 --- /dev/null +++ b/rtl/include/tcdm_explode_macros.svh @@ -0,0 +1,51 @@ +`ifndef TCDM_EXPLODE_MACROS_SVH +`define TCDM_EXPLODE_MACROS_SVH + + + `define TCDM_EXPLODE_ARRAY_DECLARE(signal_prefix, length) \ +logic [length-1:0] signal_prefix``_req; \ +logic [length-1:0][31:0] signal_prefix``_add; \ +logic [length-1:0] signal_prefix``_wen; \ +logic [length-1:0][31:0] signal_prefix``_wdata; \ +logic [length-1:0][3:0] signal_prefix``_be; \ +logic [length-1:0] signal_prefix``_gnt; \ +logic [length-1:0] signal_prefix``_r_opc; \ +logic [length-1:0][31:0] signal_prefix``_r_rdata; \ +logic [length-1:0] signal_prefix``_r_valid; + + `define TCDM_EXPLODE_DECLARE(signal_prefix) \ +logic signal_prefix``_req; \ +logic [31:0] signal_prefix``_add; \ +logic signal_prefix``_wen; \ +logic [31:0] signal_prefix``_wdata; \ +logic [3:0] signal_prefix``_be; \ +logic signal_prefix``_gnt; \ +logic signal_prefix``_r_opc; \ +logic [31:0] signal_prefix``_r_rdata; \ +logic signal_prefix``_r_valid; + +//Connect a TCDM Master Interface to a set of exploded interface signals + `define TCDM_SLAVE_EXPLODE(iface, exploded_prefix, postfix) \ +assign iface.req = exploded_prefix``_req postfix; \ +assign iface.add = exploded_prefix``_add postfix; \ +assign iface.wen = exploded_prefix``_wen postfix; \ +assign iface.wdata = exploded_prefix``_wdata postfix; \ +assign iface.be = exploded_prefix``_be postfix; \ +assign exploded_prefix``_gnt postfix = iface.gnt; \ +assign exploded_prefix``_r_opc postfix = iface.r_opc; \ +assign exploded_prefix``_r_rdata postfix = iface.r_rdata; \ +assign exploded_prefix``_r_valid postfix = iface.r_valid; + +//Connect a TCDM Slave Interface to a set of exploded interface signals + `define TCDM_MASTER_EXPLODE(iface, exploded_prefix, postfix) \ +assign exploded_prefix``_req postfix = iface.req; \ +assign exploded_prefix``_add postfix = iface.add; \ +assign exploded_prefix``_wen postfix = iface.wen; \ +assign exploded_prefix``_wdata postfix = iface.wdata; \ +assign exploded_prefix``_be postfix = iface.be; \ +assign iface.gnt = exploded_prefix``_gnt postfix; \ +assign iface.r_opc = exploded_prefix``_r_opc postfix; \ +assign iface.r_rdata = exploded_prefix``_r_rdata postfix; \ +assign iface.r_val = exploded_prefix``_r_valid postfix; + +`endif diff --git a/rtl/pulp_soc/axi64_to_lint32_wrap.sv b/rtl/pulp_soc/axi64_to_lint32_wrap.sv new file mode 100644 index 00000000..e5d74159 --- /dev/null +++ b/rtl/pulp_soc/axi64_to_lint32_wrap.sv @@ -0,0 +1,149 @@ +//----------------------------------------------------------------------------- +// Title : AXI64 to 32-bit TCDM Bridge Wrapper +//----------------------------------------------------------------------------- +// File : axi64_to_lint_wrap.sv +// Author : Manuel Eggimann +// Created : 01.11.2020 +//----------------------------------------------------------------------------- +// Description : +// This is a wrapper for the legacy 64-bit AXI to TCDM bridge that accepts +// interfaces at the inputs +//----------------------------------------------------------------------------- +// Copyright (C) 2013-2020 ETH Zurich, University of Bologna +// Copyright and related rights are licensed under the Solderpad Hardware +// License, Version 0.51 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law +// or agreed to in writing, software, hardware and materials distributed under +// this License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. +//----------------------------------------------------------------------------- + +`include "tcdm_explode_macros.svh" + +module axi64_2_lint32_wrap + #( + parameter int unsigned AXI_USER_WIDTH, + parameter int unsigned AXI_ID_WIDTH + )( + input logic clk_i, + input logic rst_ni, + input logic test_en_i, + AXI_BUS.Slave axi_master, + TCDM_BUS.Master tcdm_slaves[4] + ); + + // *Do not change* The legacy wrapper was never tested for other bitwidths. + localparam AXI_ADDR_WIDTH = 32; + localparam AXI_DATA_WIDTH = 64; + localparam AXI_STRB_WIDTH = AXI_DATA_WIDTH/8; + localparam TCDM_DATA_WIDTH = 32; + localparam TCDM_ADDR_WIDTH = 32; + localparam TCDM_BE_WIDTH = TCDM_DATA_WIDTH/8; + + //Explode the output TCDM interface into arrays of individual signals + `TCDM_EXPLODE_DECLARE_ARRAY(tcdm_slaves, 4) + for (genvar i = 0; i < 4; i++) begin + `TCDM_SLAVE_EXPLODE(tcdm_slaves, tcdm_slaves) + end + + + + axi64_2_lint32 #( + .AXI_ADDR_WIDTH ( AXI_ADDR_WIDTH ), //= 32, + .AXI_DATA_WIDTH ( AXI_DATA_WIDTH ), //= 64, + .AXI_STRB_WIDTH ( AXI_STRB_WIDTH ), //= 8, + .AXI_USER_WIDTH ( AXI_USER_WIDTH ), //= 6, + .AXI_ID_WIDTH ( AXI_ID_WIDTH ), //= 7, + .BUFF_DEPTH_SLICES ( 4 ), //= 4, + .DATA_WIDTH ( TCDM_DATA_WIDTH ), //= 64, + .BE_WIDTH ( TCDM_BE_WIDTH ), //= DATA_WIDTH/8, + .ADDR_WIDTH ( TCDM_ADDR_WIDTH ), //= 10 + ) axi64_2_lint32_i ( + // AXI GLOBAL SIGNALS + .clk ( clk_i ), + .rst_n ( rst_ni ), + .test_en_i ( test_en_i ), + // AXI INTERFACE + .AW_ADDR_i ( axi_master.aw_addr ), + .AW_PROT_i ( axi_master.aw_prot ), + .AW_REGION_i ( axi_master.aw_region ), + .AW_LEN_i ( axi_master.aw_len ), + .AW_SIZE_i ( axi_master.aw_size ), + .AW_BURST_i ( axi_master.aw_burst ), + .AW_LOCK_i ( axi_master.aw_lock ), + .AW_CACHE_i ( axi_master.aw_cache ), + .AW_QOS_i ( axi_master.aw_qos ), + .AW_ID_i ( axi_master.aw_id ), + .AW_USER_i ( axi_master.aw_user ), + .AW_VALID_i ( axi_master.aw_valid ), + .AW_READY_o ( axi_master.aw_ready ), + // ADDRESS READ CHANNEL + .AR_ADDR_i ( axi_master.ar_addr ), + .AR_PROT_i ( axi_master.ar_prot ), + .AR_REGION_i ( axi_master.ar_region ), + .AR_LEN_i ( axi_master.ar_len ), + .AR_SIZE_i ( axi_master.ar_size ), + .AR_BURST_i ( axi_master.ar_burst ), + .AR_LOCK_i ( axi_master.ar_lock ), + .AR_CACHE_i ( axi_master.ar_cache ), + .AR_QOS_i ( axi_master.ar_qos ), + .AR_ID_i ( axi_master.ar_id ), + .AR_USER_i ( axi_master.ar_user ), + .AR_VALID_i ( axi_master.ar_valid ), + .AR_READY_o ( axi_master.ar_ready ), + // WRITE CHANNEL + .W_USER_i ( axi_master.w_user ), + .W_DATA_i ( axi_master.w_data ), + .W_STRB_i ( axi_master.w_strb ), + .W_LAST_i ( axi_master.w_last ), + .W_VALID_i ( axi_master.w_valid ), + .W_READY_o ( axi_master.w_ready ), + // WRITE RESPONSE CHANNEL + .B_ID_o ( axi_master.b_id ), + .B_RESP_o ( axi_master.b_resp ), + .B_USER_o ( axi_master.b_user ), + .B_VALID_o ( axi_master.b_valid ), + .B_READY_i ( axi_master.b_ready ), + // READ CHANNEL + .R_ID_o ( axi_master.r_id ), + .R_USER_o ( axi_master.r_user ), + .R_DATA_o ( axi_master.r_data ), + .R_RESP_o ( axi_master.r_resp ), + .R_LAST_o ( axi_master.r_last ), + .R_VALID_o ( axi_master.r_valid ), + .R_READY_i ( axi_master.r_ready ), + + // LINT Interface - WRITE Request + .data_W_req_o ( tcdm_slaves_req [1:0] ), + .data_W_gnt_i ( tcdm_slaves_gnt [1:0] ), + .data_W_wdata_o ( tcdm_slaves_wdata [1:0] ), + .data_W_add_o ( tcdm_slaves_add [1:0] ), + .data_W_wen_o ( tcdm_slaves_wen [1:0] ), + .data_W_be_o ( tcdm_slaves_be [1:0] ), + .data_W_aux_o ( ), // We don't need this signal + + // LINT Interface - Response + .data_W_r_valid_i ( tcdm_slaves_r_valid [1:0] ), + .data_W_r_rdata_i ( tcdm_slaves_r_rdata [1:0] ), + .data_W_r_opc_i ( tcdm_slaves_r_opc [1:0] ), + .data_W_r_aux_i ( '0 ), // We don't need this signal + + // LINT Interface - READ Request + .data_R_req_o ( tcdm_slaves_req [3:2] ), + .data_R_gnt_i ( tcdm_slaves_gnt [3:2] ), + .data_R_wdata_o ( tcdm_slaves_wdata [3:2] ), + .data_R_add_o ( tcdm_slaves_add [3:2] ), + .data_R_wen_o ( tcdm_slaves_wen [3:2] ), + .data_R_be_o ( tcdm_slaves_be [3:2] ), + .data_R_aux_o ( ), // We don't need this signal + + // LINT Interface - Responseesponse + .data_R_r_valid_i ( tcdm_slaves_r_valid [3:2] ), + .data_R_r_rdata_i ( tcdm_slaves_r_rdata [3:2] ), + .data_R_r_opc_i ( tcdm_slaves_r_opc [3:2] ), + .data_R_r_aux_i ( '0 ) // We don't need this signal + ); + +endmodule : axi64_2_lint_wrap diff --git a/rtl/pulp_soc/boot_rom.sv b/rtl/pulp_soc/boot_rom.sv index f2e51698..a09d0a25 100644 --- a/rtl/pulp_soc/boot_rom.sv +++ b/rtl/pulp_soc/boot_rom.sv @@ -9,7 +9,7 @@ // specific language governing permissions and limitations under the License. -`include "pulp_soc_defines.sv" +`include "soc_mem_map.svh" module boot_rom #( parameter ROM_ADDR_WIDTH = 13 @@ -18,20 +18,35 @@ module boot_rom #( input logic clk_i, input logic rst_ni, input logic init_ni, - UNICAD_MEM_BUS_32.Slave mem_slave, + XBAR_TCDM_BUS.Slave mem_slave, input logic test_mode_i ); + //Perform TCDM handshaking for constant 1 cycle latency + assign mem_slave.gnt = mem_slave.req; + always_ff @(posedge clk_i, negedge rst_ni) begin + if (!rst_ni) begin + mem_slave.r_valid <= 1'b0; + end else begin + mem_slave.r_valid <= mem_slave.req; + end + end + + //Remove address offset + logic [31:0] address; + assign address = mem_slave.add - SOC_MEM_MAP_BOOT_ROM_START_ADDR; + `ifndef PULP_FPGA_EMUL generic_rom #( - .ADDR_WIDTH(ROM_ADDR_WIDTH-2), + .ADDR_WIDTH(ROM_ADDR_WIDTH-2), //The ROM uses 32-bit word addressing while the bus addresses bytes .DATA_WIDTH(32) ) rom_mem_i ( .CLK ( clk_i ), - .CEN ( mem_slave.csn ), - .A ( mem_slave.add[ROM_ADDR_WIDTH-1:2] ), - .Q ( mem_slave.rdata ) + .CEN ( ~mem_slave.req ), + .A ( address[ROM_ADDR_WIDTH-1:2] ), //Cutoff insignificant address bits. The + //interconnect makes sure we only receive addresses in the bootrom address space + .Q ( mem_slave.r_rdata ) ); // assign mem_slave.add[31:ROM_ADDR_WIDTH] = '0; @@ -39,13 +54,14 @@ module boot_rom #( `else // !`ifndef PULP_FPGA_EMUL fpga_bootrom #( - .ADDR_WIDTH(ROM_ADDR_WIDTH-2), + .ADDR_WIDTH(ROM_ADDR_WIDTH-2), //The ROM uses 32-bit word addressing while the bus addresses bytes .DATA_WIDTH(32) ) rom_mem_i ( .CLK(clk_i), - .CEN(mem_slave.csn), - .A(mem_slave.add[ROM_ADDR_WIDTH-1:2]), - .Q(mem_slave.rdata) + .CEN(~mem_slave.req), + .A(address[ROM_ADDR_WIDTH-1:2]), //Cutoff insignificant address bits. The interconnect + //makes sure we only receive addresses in the bootrom address space + .Q(mem_slave.r_rdata) ); `endif diff --git a/rtl/pulp_soc/contiguous_crossbar.sv b/rtl/pulp_soc/contiguous_crossbar.sv new file mode 100644 index 00000000..4e90fe10 --- /dev/null +++ b/rtl/pulp_soc/contiguous_crossbar.sv @@ -0,0 +1,136 @@ +//----------------------------------------------------------------------------- +// Title : Contiguous Crossbar +//----------------------------------------------------------------------------- +// File : contiguous_crossbar.sv +// Author : Manuel Eggimann +// Created : 30.10.2020 +//----------------------------------------------------------------------------- +// Description : +// Crossbar to arbitrate access from multiple master ports to multiple slave ports +// using address range to slave port mapping rules. If an address doesn't match +// any of the supplied address rules it is routed to the error port. +//----------------------------------------------------------------------------- +// Copyright (C) 2013-2020 ETH Zurich, University of Bologna +// Copyright and related rights are licensed under the Solderpad Hardware +// License, Version 0.51 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law +// or agreed to in writing, software, hardware and materials distributed under +// this License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. +//----------------------------------------------------------------------------- + +module contiguous_crossbar + import pkg_soc_interconnect::addr_map_rule_t; + #( + parameter int unsigned NR_MASTER_PORTS, + parameter int unsigned NR_SLAVE_PORTS, + parameter int unsigned NR_ADDR_RULES + )( + input logic clk_i, + input logic rst_ni, + input logic test_en_i, + XBAR_TCDM_BUS.Slave master_ports[NR_MASTER_PORTS], + XBAR_TCDM_BUS.Master slave_ports[NR_SLAVE_PORTS], + XBAR_TCDM_BUS.Master error_port, + input addr_map_rule_t addr_rules[NR_ADDR_RULES] + ); + // Do **not** change. The TCDM interface uses hardcoded bus widths so we cannot just change them here. + localparam int unsigned BE_WIDTH = 2; + localparam int unsigned ADDR_WIDTH = 32; + localparam int unsigned DATA_WIDTH = 32; + localparam int unsigned NR_SLAVE_PORTS_INTERNAL = NR_SLAVE_PORTS+1; // We have one additional slave port for the + // default error port + localparam int unsigned PORT_SEL_WIDTH = $clog2(NR_SLAVE_PORTS_INTERNAL); + + // Explode the input interface array to arrays of individual signals + //Master Ports + `TCDM_EXPLODE_ARRAY_DECLARE(master_ports, NR_MASTER_PORTS) + for (genvar i = 0; islave signals into the write data and unpack it at the output of the crossbar. This + // is exactly the same trick that the tcdm_interconnect.sv uses. We do the same for the response channel to pack the + // opc signal into the rdata. + + //Aggregated Request Data (from Master -> slaves) + localparam int unsigned REQ_AGG_DATA_WIDTH = 1+BE_WIDTH+ADDR_WIDTH+DATA_WIDTH; // +1 is for the write enable (wen), + logic [NR_MASTER_PORTS-1:0][REQ_AGG_DATA_WIDTH-1:0] req_data_agg_in; + logic [NR_SLAVE_PORTS_INTERNAL-1:0][REQ_AGG_DATA_WIDTH-1:0] req_data_agg_out; + //Aggreagate the input data + for (genvar i = 0; i < NR_MASTER_PORTS; i++) begin + assign req_data_agg_in[i] = {master_ports_wen[i], master_ports_add[i], master_ports_wdata[i]}; + end + //Disaggregate the output data + for (genvar i = 0; i < NR_SLAVE_PORTS_INTERNAL; i++) begin : disaggregate_outputs + assign {slave_ports_wen[i], slave_ports_add[i], slave_ports_wdata[i]} = req_data_agg_out[i]; + end + + //Aggregated response data (from Slaves -> Master) + localparam int unsigned RESP_AGG_DATA_WIDTH = DATA_WIDTH+1; + logic [NR_SLAVE_PORTS_INTERNAL-1:0][RESP_AGG_DATA_WIDTH-1:0] resp_data_agg_in; + logic [NR_MASTER_PORTS-1:0][RESP_AGG_DATA_WIDTH-1:0] resp_data_agg_out; + for (genvar i = 0; i < NR_SLAVE_PORTS_INTERNAL; i++) begin + assign resp_data_agg_in[i] = {slave_ports_r_rdata[i], slave_ports_r_opc[i]}; + end + for (genvar i = 0; i < NR_MASTER_PORTS; i++) begin + assign {master_ports_r_rdata[i], master_ports_r_opc[i]} = resp_data_agg_out[i]; + end + + //Address Decoder + logic [NR_MASTER_PORTS-1:0] [PORT_SEL_WIDTH-1:0] port_sel; + for (genvar i = 0; i < NR_MASTER_PORTS; i++) begin : gen_addr_decoders + addr_decode #( + .NoIndices(NR_SLAVE_PORTS_INTERNAL), + .NoRules(NR_ADDR_RULES), + .addr_t(logic[31:0]), + .rule_t(pkg_soc_interconnect::addr_map_rule_t) + ) i_addr_decode ( + .addr_i(master_ports_add[i]), + .addr_map_i(addr_rules), + .idx_o(port_sel[i]), + .dec_valid_o(), + .dec_error_o(), + .en_default_idx_i(1'b1), + .default_idx_i(NR_SLAVE_PORTS_INTERNAL-1) //If no rule matches we route to the + //error port + ); + end + + + //Crossbar instantiation + xbar #( + .numin(NR_MASTER_PORTS), + .numout(NR_SLAVE_PORTS), + .reqdatawidth(REQ_AGG_DATA_WIDTH), + .respdatawidth(RESP_AGG_DATA_WIDTH), + .RespLat(1), + .WriteRespOn(1) + ) i_xbar ( + .clk_i, + .rst_ni, + .req_i ( master_ports_req ), + .add_i ( port_sel ), + .wen_i ( master_ports_wen ), + .wdata_i ( req_data_agg_in ), + .gnt_o ( master_ports_gnt ), + .rdata_o ( resp_data_agg_out), + .rr_i ( '0 ), + .vld_o ( master_ports_r_valid ), + .gnt_i ( slave_ports_gnt ), + .req_o ( slave_ports_req ), + .wdata_o ( req_data_agg_out ), + .rdata_i ( resp_data_agg_in ) + ); + +endmodule : contiguous_crossbar diff --git a/rtl/pulp_soc/interleaved_crossbar.sv b/rtl/pulp_soc/interleaved_crossbar.sv new file mode 100644 index 00000000..ddfaa5db --- /dev/null +++ b/rtl/pulp_soc/interleaved_crossbar.sv @@ -0,0 +1,124 @@ +//----------------------------------------------------------------------------- +// Title : Interleaved Crossbar Wrapper +//----------------------------------------------------------------------------- +// File : interleaved_crossbar.sv +// Author : Manuel Eggimann +// Created : 30.10.2020 +//----------------------------------------------------------------------------- +// Description : +// This is a wrapper module that instantiates the cluster logarithmic interconnect +// and deals with repurposing the request and response channel to pass along +// additional signals not present in the cluster interconnect. The interconnect +// uses a fully connected crossbar and interleavingly maps 32-bi words at their +// naturaly word boundary to the output ports. +//----------------------------------------------------------------------------- +// Copyright (C) 2013-2020 ETH Zurich, University of Bologna +// Copyright and related rights are licensed under the Solderpad Hardware +// License, Version 0.51 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law +// or agreed to in writing, software, hardware and materials distributed under +// this License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. +//----------------------------------------------------------------------------- + +`include "tcdm_explode_macros.svh" + +module interleaved_crossbar + #( + parameter int unsigned NR_MASTER_PORTS, + parameter int unsigned NR_SLAVE_PORTS //Must be a power of two + )( + input logic clk_i, + input logic rst_ni, + input logic test_en_i, + XBAR_TCDM_BUS.Slave master_ports[NR_MASTER_PORTS], + XBAR_TCDM_BUS.Master slave_ports[NR_SLAVE_PORTS] + ); + // Do **not** change. The TCDM interface uses hardcoded bus widths so we cannot just change them here. + localparam int unsigned BE_WIDTH = 2; + localparam int unsigned ADDR_WIDTH = 32; + localparam int unsigned DATA_WIDTH = 32; + localparam int unsigned PORT_SEL_WIDTH = $clog2(NR_SLAVE_PORTS); + + //Elaboration time asserations + //Number of slaves must be power of two + if ((NR_SLAVE_PORTS & (NR_SLAVE_PORTS-1)) != 0) begin + $error("NR_SLAVE_PORTS must be power of two but was %d", NR_SLAVE_PORTS); + end + + // Explode the input interface array to arrays of individual signals + //Master Ports + `TCDM_EXPLODE_ARRAY_DECLARE(master_ports, NR_MASTER_PORTS) + for (genvar i = 0; islave signals into the write data and unpack it at the output of the crossbar. This + // is exactly the same trick that the tcdm_interconnect.sv uses. We do the same for the response channel to pack the + // opc signal into the rdata. + + //Aggregated Request Data (from Master -> slaves) + localparam int unsigned REQ_AGG_DATA_WIDTH = 1+BE_WIDTH+ADDR_WIDTH+DATA_WIDTH; // +1 is for the write enable (wen), + logic [NR_MASTER_PORTS-1:0][REQ_AGG_DATA_WIDTH-1:0] req_data_agg_in; + logic [NR_SLAVE_PORTS-1:0][REQ_AGG_DATA_WIDTH-1:0] req_data_agg_out; + //Aggreagate the input data + for (genvar i = 0; i < NR_MASTER_PORTS; i++) begin + assign req_data_agg_in[i] = {master_ports_wen[i], master_ports_add[i], master_ports_wdata[i]}; + end + //Disaggregate the output data + for (genvar i = 0; i < NR_SLAVE_PORTS; i++) begin : disaggregate_outputs + assign {slave_ports_wen[i], slave_ports_add[i], slave_ports_wdata[i]} = req_data_agg_out[i]; + end + + //Aggregated response data (from Slaves -> Master) + localparam int unsigned RESP_AGG_DATA_WIDTH = DATA_WIDTH+1; + logic [NR_SLAVE_PORTS-1:0][RESP_AGG_DATA_WIDTH-1:0] resp_data_agg_in; + logic [NR_MASTER_PORTS-1:0][RESP_AGG_DATA_WIDTH-1:0] resp_data_agg_out; + for (genvar i = 0; i < NR_SLAVE_PORTS; i++) begin + assign resp_data_agg_in[i] = {slave_ports_r_rdata[i], slave_ports_r_opc[i]}; + end + for (genvar i = 0; i < NR_MASTER_PORTS; i++) begin + assign {master_ports_r_rdata[i], master_ports_r_opc[i]} = resp_data_agg_out[i]; + end + + //Interleaved Output Port Selection + logic [NR_MASTER_PORTS-1:0] [PORT_SEL_WIDTH-1:0] port_sel; + for (genvar i = 0; i < NR_MASTER_PORTS; i++) begin + assign port_sel[i] = master_ports[i].add[BE_WIDTH+PORT_SEL_WIDTH-1:BE_WIDTH]; + end + + //Crossbar instantiation + xbar #( + .numin(NR_MASTER_PORTS), + .numout(NR_SLAVE_PORTS), + .reqdatawidth(REQ_AGG_DATA_WIDTH), + .respdatawidth(RESP_AGG_DATA_WIDTH), + .RespLat(1), + .WriteRespOn(1) + ) i_xbar ( + .clk_i, + .rst_ni, + .req_i ( master_ports_req ), + .add_i ( port_sel ), + .wen_i ( master_ports_wen ), + .wdata_i ( req_data_agg_in ), + .gnt_o ( master_ports_gnt ), + .rdata_o ( resp_data_agg_out), + .rr_i ( '0 ), + .vld_o ( master_ports_r_valid ), + .gnt_i ( slave_ports_gnt ), + .req_o ( slave_ports_req ), + .wdata_o ( req_data_agg_out ), + .rdata_i ( resp_data_agg_in ) + ); + +endmodule : interleaved_crossbar diff --git a/rtl/pulp_soc/l2_ram_multi_bank.sv b/rtl/pulp_soc/l2_ram_multi_bank.sv index 85216421..8a7a47f0 100644 --- a/rtl/pulp_soc/l2_ram_multi_bank.sv +++ b/rtl/pulp_soc/l2_ram_multi_bank.sv @@ -8,123 +8,164 @@ // CONDITIONS OF ANY KIND, either express or implied. See the License for the // specific language governing permissions and limitations under the License. +`include "soc_mem_map.svh" module l2_ram_multi_bank #( - parameter NB_BANKS = 4, - parameter NB_BANKS_PRI = 2, - parameter BANK_SIZE = 29184, - parameter MEM_ADDR_WIDTH = 14, - parameter MEM_ADDR_WIDTH_PRI = 13 + parameter NB_BANKS = 4 ) ( input logic clk_i, input logic rst_ni, input logic init_ni, input logic test_mode_i, - UNICAD_MEM_BUS_32.Slave mem_slave[NB_BANKS-1:0], - UNICAD_MEM_BUS_32.Slave mem_pri_slave[NB_BANKS_PRI-1:0] + XBAR_TCDM_BUS.Slave mem_slave[NB_BANKS], + XBAR_TCDM_BUS.Slave mem_pri_slave[2] ); - //Used in testbenches - localparam BANK_SIZE_PRI1 = 8192; - localparam BANK_SIZE_PRI0_SRAM = 6144; - localparam BANK_SIZE_PRI0_SCM = 2048; + // Don't forget to adjust the SRAM macros and the FPGA settings if you change the banksizes + localparam BANK_SIZE_INTL_SRAM = 32768; //Number of 32-bit words + localparam BANK_SIZE_PRI0 = 8192; //Number of 32-bit words + localparam BANK_SIZE_PRI1 = 8192; //Number of 32-bit words - localparam BANK_SIZE_INTL_SRAM = 28672; - localparam BANK_SIZE_INTL_SCM = 512; + //Derived parameters + localparam INTL_MEM_ADDR_WIDTH = $clog2(BANK_SIZE_INTL_SRAM); + localparam PRI0_MEM_ADDR_WIDTH = $clog2(BANK_SIZE_PRI0); + localparam PRI1_MEM_ADDR_WIDTH = $clog2(BANK_SIZE_PRI1); + //Used in testbenches - genvar i,j; - generate - //INTERLEAVED - for(i=0; i +// Created : 30.10.2020 +//----------------------------------------------------------------------------- +// Description : +// This is a wrapper for the legacy TCDM to AXI protocol converter. The converter +// converts from a single 32-bit TCDM protocol to a 32-bit AXI4 bus. Since the TCDM +// port can only perform either a read or write operation per cycle, the AXI port +// is only 50% utilized, either read channel or write channel active. +//----------------------------------------------------------------------------- +// Copyright (C) 2013-2020 ETH Zurich, University of Bologna +// Copyright and related rights are licensed under the Solderpad Hardware +// License, Version 0.51 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law +// or agreed to in writing, software, hardware and materials distributed under +// this License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. +//----------------------------------------------------------------------------- + + +module lint2axi_wrap + #( + parameter int unsigned AXI_ID_WIDTH, + parameter int unsigned AXI_USER_WIDTH + ) + ( + input logic clk_i, + input logic rst_ni, + TCDM_BUS.Slave master, + AXI_BUS.Master slave + ); + + //Do *not* change. Correct behavior is not tested for other values. + localparam int unsigned ADDR_WIDTH = 32; + localparam int unsigned DATA_WIDTH = 32; + localparam int unsigned BE_WIDTH = DATA_WIDTH/8; + + lint_2_axi #( + .ADDR_WIDTH ( ADDR_WIDTH ), + .DATA_WIDTH ( DATA_WIDTH ), + .BE_WIDTH ( BE_WIDTH ), + .USER_WIDTH ( AXI_USER_WIDTH ), + .AXI_ID_WIDTH ( AXI_ID_WIDTH ), + .REGISTERED_GRANT ( "FALSE" ) // "TRUE"|"FALSE" + ) i_lint_2_axi ( + // Clock and Reset + .clk_i, + .rst_ni, + + .data_req_i ( master.req ), + .data_addr_i ( master.add ), + .data_we_i ( ~master.wen ), + .data_wdata_i ( master.wdata ), + .data_be_i ( master.be ), + .data_aux_i ('0 ), // We don't need this signal + .data_ID_i ('0 ), // We don't need this signal + .data_gnt_o ( master.gnt ), + + .data_rvalid_o ( master.r_valid ), + .data_rdata_o ( master.r_rdata ), + .data_ropc_o ( master.r_opc ), + .data_raux_o ( ), // We don't need this signal + .data_rID_o ( ), // We don't need this signal + // --------------------------------------------------------- + // AXI TARG Port Declarations ------------------------------ + // --------------------------------------------------------- + //AXI write address bus -------------- // USED// ----------- + .aw_id_o ( slave.aw_id ), + .aw_addr_o ( slave.aw_addr ), + .aw_len_o ( slave.aw_len ), + .aw_size_o ( slave.aw_size ), + .aw_burst_o ( slave.aw_burst ), + .aw_lock_o ( slave.aw_lock ), + .aw_cache_o ( slave.aw_cache ), + .aw_prot_o ( slave.aw_prot ), + .aw_region_o ( slave.aw_region ), + .aw_user_o ( slave.aw_user ), + .aw_qos_o ( slave.aw_qos ), + .aw_valid_o ( slave.aw_valid ), + .aw_ready_i ( slave.aw_ready ), + // --------------------------------------------------------- + + //AXI write data bus -------------- // USED// -------------- + .w_data_o ( slave.w_data ), + .w_strb_o ( slave.w_strb ), + .w_last_o ( slave.w_last ), + .w_user_o ( slave.w_user ), + .w_valid_o ( slave.w_valid ), + .w_ready_i ( slave.w_ready ), + // --------------------------------------------------------- + + //AXI write response bus -------------- // USED// ---------- + .b_id_i ( slave.b_id ), + .b_resp_i ( slave.b_resp ), + .b_valid_i ( slave.b_valid ), + .b_user_i ( slave.b_user ), + .b_ready_o ( slave.b_ready ), + // --------------------------------------------------------- + + //AXI read address bus ------------------------------------- + .ar_id_o ( slave.ar_id ), + .ar_addr_o ( slave.ar_addr ), + .ar_len_o ( slave.ar_len ), + .ar_size_o ( slave.ar_size ), + .ar_burst_o ( slave.ar_burst ), + .ar_lock_o ( slave.ar_lock ), + .ar_cache_o ( slave.ar_cache ), + .ar_prot_o ( slave.ar_prot ), + .ar_region_o ( slave.ar_region ), + .ar_user_o ( slave.ar_user ), + .ar_qos_o ( slave.ar_qos ), + .ar_valid_o ( slave.ar_valid ), + .ar_ready_i ( slave.ar_ready ), + // --------------------------------------------------------- + + //AXI read data bus ---------------------------------------- + .r_id_i ( slave.r_id ), + .r_data_i ( slave.r_data ), + .r_resp_i ( slave.r_resp ), + .r_last_i ( slave.r_last ), + .r_user_i ( slave.r_user ), + .r_valid_i ( slave.r_valid ), + .r_ready_o ( slave.r_ready ) + // --------------------------------------------------------- + ); + +endmodule : lint2axi_wrap diff --git a/rtl/pulp_soc/pkg_soc_interconnect.sv b/rtl/pulp_soc/pkg_soc_interconnect.sv new file mode 100644 index 00000000..14e36579 --- /dev/null +++ b/rtl/pulp_soc/pkg_soc_interconnect.sv @@ -0,0 +1,9 @@ +package pkg_soc_interconnect; + + typedef struct packed { + logic [31:0] idx; + logic [31:0] start_addr; + logic [31:0] end_addr; + } addr_map_rule_t; + +endpackage : pkg_soc_interconnect diff --git a/rtl/pulp_soc/pulp_soc.sv b/rtl/pulp_soc/pulp_soc.sv index d25df061..dcc04313 100644 --- a/rtl/pulp_soc/pulp_soc.sv +++ b/rtl/pulp_soc/pulp_soc.sv @@ -232,12 +232,13 @@ module pulp_soc import dm::*; #( localparam FLL_ADDR_WIDTH = 32; localparam FLL_DATA_WIDTH = 32; - localparam NB_L2_BANKS = `NB_L2_CHANNELS; + localparam NB_L2_BANKS = `NB_L2_CHANNELS; + //The L2 parameter do not influence the size of the memories. Change them in the l2_ram_multibank. This parameters + //are only here to save area in the uDMA by only storing relevant bits. localparam L2_BANK_SIZE = 29184; // in 32-bit words localparam L2_MEM_ADDR_WIDTH = $clog2(L2_BANK_SIZE * NB_L2_BANKS) - $clog2(NB_L2_BANKS); // 2**L2_MEM_ADDR_WIDTH rows (64bit each) in L2 --> TOTAL L2 SIZE = 8byte * 2^L2_MEM_ADDR_WIDTH localparam NB_L2_BANKS_PRI = 2; - localparam L2_BANK_SIZE_PRI = 8192; // in 32-bit words - localparam L2_MEM_ADDR_WIDTH_PRI = $clog2(L2_BANK_SIZE_PRI * NB_L2_BANKS_PRI) - $clog2(NB_L2_BANKS_PRI); + localparam ROM_ADDR_WIDTH = 13; localparam FC_CORE_CLUSTER_ID = 6'd31; @@ -343,9 +344,9 @@ module pulp_soc import dm::*; #( logic jtag_resp_valid; dm::dmi_req_t jtag_dmi_req; dm::dmi_resp_t debug_resp; - logic slave_grant, slave_valid, slave_req , slave_we; - logic [31:0] slave_addr, slave_wdata, slave_rdata; - logic [3:0] slave_be; + logic slave_grant, slave_valid, dm_slave_req , dm_slave_we; + logic [31:0] dm_slave_addr, dm_slave_wdata, dm_slave_rdata; + logic [3:0] dm_slave_be; logic lint_riscv_jtag_bus_master_we; logic int_td; @@ -428,10 +429,10 @@ module pulp_soc import dm::*; #( APB_BUS s_apb_periph_bus (); - UNICAD_MEM_BUS_32 s_mem_rom_bus (); + XBAR_TCDM_BUS s_mem_rom_bus (); - UNICAD_MEM_BUS_32 s_mem_l2_bus[NB_L2_BANKS-1:0](); - UNICAD_MEM_BUS_32 s_mem_l2_pri_bus[NB_L2_BANKS_PRI-1:0](); + XBAR_TCDM_BUS s_mem_l2_bus[NB_L2_BANKS-1:0](); + XBAR_TCDM_BUS s_mem_l2_pri_bus[NB_L2_BANKS_PRI-1:0](); XBAR_TCDM_BUS s_lint_debug_bus(); XBAR_TCDM_BUS s_lint_pulp_jtag_bus(); @@ -503,11 +504,7 @@ module pulp_soc import dm::*; #( //******************************************************** l2_ram_multi_bank #( - .MEM_ADDR_WIDTH ( L2_MEM_ADDR_WIDTH ), - .NB_BANKS ( NB_L2_BANKS ), - .BANK_SIZE ( L2_BANK_SIZE ), - .MEM_ADDR_WIDTH_PRI ( L2_MEM_ADDR_WIDTH_PRI ), - .NB_BANKS_PRI ( NB_L2_BANKS_PRI ) + .NB_BANKS ( NB_L2_BANKS ) ) l2_ram_i ( .clk_i ( s_soc_clk ), .rst_ni ( s_soc_rstn ), @@ -782,6 +779,32 @@ module pulp_soc import dm::*; #( .clk_per_o ( s_periph_clk ) ); + soc_interconnect_wrap #( + .NR_HWPE_PORTS(NB_HWPE_PORTS), + .NR_L2_PORTS(NB_L2_BANKS), + .NR_L2_PRIVATE_PORTS(NB_L2_BANKS_PRI), + .AXI_IN_ID_WIDTH(AXI_ID_IN_WIDTH), + .AXI_IN_USER_WIDTH(AXI_USER_WIDTH), + .AXI_OUT_ID_WIDTH(AXI_ID_OUT_WIDTH), + .AXI_OUT_USER_WIDTH(AXI_USER_WIDTH) + ) i_soc_interconnect_wrap ( + .clk_i ( s_soc_clk ), + .rst_ni ( s_soc_rstn ), + .test_en_i ( dft_test_mode_i ), + .tcdm_fc_data ( s_lint_fc_data_bus ), + .tcdm_fc_instr ( s_lint_fc_instr_bus ), + .tcdm_udma_rx ( s_lint_udma_rx_bus ), + .tcdm_udma_tx ( s_lint_udma_tx_bus ), + .tcdm_debug ( s_lint_debug_bus ), + .tcdm_hwpe ( s_lint_hwpe_bus ), + .axi_master_plug ( s_data_in_bus ), + .axi_slave_plug ( s_data_out_bus ), + .apb_peripheral_bus ( s_apb_periph_bus ), + .l2_interleaved_slaves ( s_mem_l2_bus ), + .l2_private_slaves ( s_mem_l2_pri_bus ), + .boot_rom_slave ( s_mem_rom_bus ) + ); + soc_interconnect_wrap #( .N_L2_BANKS ( NB_L2_BANKS ), .ADDR_MEM_WIDTH ( L2_MEM_ADDR_WIDTH ), @@ -871,12 +894,12 @@ module pulp_soc import dm::*; #( .unavailable_i ( ~SELECTABLE_HARTS ), .hartinfo_i ( hartinfo ), - .slave_req_i ( slave_req ), - .slave_we_i ( slave_we ), - .slave_addr_i ( slave_addr ), - .slave_be_i ( slave_be ), - .slave_wdata_i ( slave_wdata ), - .slave_rdata_o ( slave_rdata ), + .slave_req_i ( dm_slave_req ), + .slave_we_i ( dm_slave_we ), + .slave_addr_i ( dm_slave_addr ), + .slave_be_i ( dm_slave_be ), + .slave_wdata_i ( dm_slave_wdata ), + .slave_rdata_o ( dm_slave_rdata ), .master_req_o ( s_lint_riscv_jtag_bus.req ), .master_add_o ( s_lint_riscv_jtag_bus.add ), @@ -960,18 +983,18 @@ module pulp_soc import dm::*; #( .PREADY ( s_apb_debug_bus.pready ), .PSLVERR ( s_apb_debug_bus.pslverr ), - .per_master_req_o ( slave_req ), - .per_master_add_o ( slave_addr ), - .per_master_we_o ( slave_we ), - .per_master_wdata_o ( slave_wdata ), - .per_master_be_o ( slave_be ), + .per_master_req_o ( dm_slave_req ), + .per_master_add_o ( dm_slave_addr ), + .per_master_we_o ( dm_slave_we ), + .per_master_wdata_o ( dm_slave_wdata ), + .per_master_be_o ( dm_slave_be ), .per_master_gnt_i ( slave_grant ), .per_master_r_valid_i ( slave_valid ), .per_master_r_opc_i ( '0 ), - .per_master_r_rdata_i ( slave_rdata ) + .per_master_r_rdata_i ( dm_slave_rdata ) ); - assign slave_grant = slave_req; + assign slave_grant = dm_slave_req; always_ff @(posedge s_soc_clk or negedge s_soc_rstn) begin : apb2per_valid if(~s_soc_rstn) begin slave_valid <= 0; diff --git a/rtl/pulp_soc/soc_interconnect_v2.sv b/rtl/pulp_soc/soc_interconnect_v2.sv new file mode 100644 index 00000000..cda346f3 --- /dev/null +++ b/rtl/pulp_soc/soc_interconnect_v2.sv @@ -0,0 +1,230 @@ +//----------------------------------------------------------------------------- +// Title : soc_interconnect +//----------------------------------------------------------------------------- +// File : soc_interconnect.sv +// Author : Manuel Eggimann +// Created : 29.10.2020 +//----------------------------------------------------------------------------- +// Description : +// +//----------------------------------------------------------------------------- +// Copyright (C) 2013-2020 ETH Zurich, University of Bologna +// Copyright and related rights are licensed under the Solderpad Hardware +// License, Version 0.51 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law +// or agreed to in writing, software, hardware and materials distributed under +// this License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. +//----------------------------------------------------------------------------- +`include "tcdm_explode_macros.svh" + +module soc_interconnect + import pkg_soc_interconnect::addr_map_rule_t; + #( + // TCDM Bus Master Config + parameter int unsigned NR_MASTER_PORTS, //Master Ports to the SoC interconnect with access to all memory regions + parameter int unsigned NR_MASTER_PORTS_INTERLEAVED_ONLY, //Master ports with access restricted to only the interleaved + //ports (no axes to APB, AXI, or contiguous slaves) TCDM Bus + //Slave Config + // L2 Demux Addr rules + parameter int unsigned NR_ADDR_RULES_L2_DEMUX, + // Interleaved TCDM slave + parameter int unsigned NR_SLAVE_PORTS_INTERLEAVED, + // Contiguous TCDM slave + parameter int unsigned NR_SLAVE_PORTS_CONTIG, + parameter int unsigned NR_ADDR_RULES_SLAVE_PORTS_CONTIG, + // AXI Slaves + parameter int unsigned NR_AXI_SLAVE_PORTS, + parameter int unsigned NR_ADDR_RULES_AXI_SLAVE_PORTS + ) + ( + input logic clk_i, + input logic rst_ni, + input logic test_en_i, // 0 Normal operation, 1 put sub-IPs into testmode (bypass clock gates) + XBAR_TCDM_BUS.Slave master_ports[NR_MASTER_PORTS], + XBAR_TCDM_BUS.Slave master_ports_interleaved_only[NR_MASTER_PORTS_INTERLEAVED_ONLY], + input addr_map_rule_t[NR_ADDR_RULES_L2_DEMUX-1:0] addr_space_l2_demux, + //Interleaved Slave + XBAR_TCDM_BUS.Master interleaved_slaves[NR_SLAVE_PORTS_INTERLEAVED], + //Contiguous Slave + input addr_map_rule_t[NR_ADDR_RULES_SLAVE_PORTS_CONTIG-1:0] addr_space_contiguous, + XBAR_TCDM_BUS.Master contiguous_slaves[NR_SLAVE_PORTS_CONTIG], + //AXI Slave + input addr_map_rule_t [NR_ADDR_RULES_AXI_SLAVE_PORTS-1:0] addr_space_axi, + AXI_BUS.Master axi_slaves[NR_AXI_SLAVE_PORTS] + ); + + + // Internal Parameters + // Do **NOT** change + localparam int BUS_DATA_WIDTH = 32; + localparam int BUS_ADDR_WIDTH = 32; + + // Internal Wiring Signals + TCDM_BUS l2_demux_2_interleaved_xbar[NR_MASTER_PORTS](); + TCDM_BUS l2_demux_2_contiguous_xbar[NR_MASTER_PORTS](); + TCDM_BUS l2_demux_2_axi_bridge[NR_MASTER_PORTS](); + + ////////////////////// + // L2 Demultiplexer // + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // This is the first stage of the interconnect. For every master, transactions are multiplexed between three // + // different target slaves. The first slave port routes to the axi crossbar, the second slave port routes // + // to the contiguous crossbar and the third slave port connects to the interleaved crossbar. // + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + for (genvar i = 0; i < NR_MASTER_PORTS; i++) begin : l2_demux + tcdm_demux #( + .NR_OUTPUTS(3), + .NR_ADDR_MAP_RULES(NR_ADDR_RULES_SLAVE_PORTS_INTERLEAVED) + ) i_l2_demux( + .clk_i, + .rst_ni, + .test_en_i, + .addr_map_rules(addr_space_interleaved), + .master_port(master_ports[i]), + .output_ports('{l2_demux_2_axi_bridge[i], l2_demux_2_contiguous_xbar[i], l2_demux_2_interleaved_xbar[i]}) + ); + end + + + ////////////////////////// + // Interleaved Crossbar // + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // This is a fully connected crossbar with combinational arbitration (logarithmic Inteconnect). It arbitrates // + // from the master ports from the L2 demultiplexer and the interleaved-only master ports (ports that do not have // + // access to the other address spaces) to the TCDM slaves with address interleaving. That is, the least // + // significant **word address** bits are used to select the slave port. This results in a more equal load on the // + // SRAM banks when the master access memory regions in a sequential manner. EVERY SLAVE IS EXPECTED TO HAVE // + // CONSTANT LATENCY OF 1 CYCLE. Slaves that cannot respond within a single cycle must appropriately delay the // + // assertion of the gnt (grant) signal. Asserting grant without asserting r_valid in the next cycle results in // + // undefined behavior. // + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + interleaved_crossbar #( + .NR_MASTER_PORTS(NR_MASTER_PORTS+NR_MASTER_PORTS_INTERLEAVED_ONLY), + .NR_SLAVE_PORTS(NR_SLAVE_PORTS_INTERLEAVED) + ) i_interleaved_xbar( + // Interfaces + .master_ports (l2_demux_2_interleaved_xbar), + .slave_ports (interleaved_slaves), + // Inputs + .clk_i, + .rst_ni, + .test_en_i + ); + + ///////////////////////// + // Contiguous Crossbar // + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // This is a fully connected crossbar with combinational arbitration (logarithmic Inteconnect). Internally, there // + // is an address decoder that matches each master_port address against a number of address range to output port // + // mapping rules. Addresses not matching any of the address mapping rules will end up on a default port that // + // always grants the request, raises the opc line for one cycle and in the case of a read acces, responds with // + // the word 0xBADACCE5. EVERY SLAVE IS EXPECTED TO HAVE CONSTANT LATENCY OF 1 CYCLE. Slaves that cannot respond // + // within a single cycle must appropriately delay the assertion of the gnt (grant) signal. Asserting grant // + // without asserting r_valid in the next cycle results in undefined behavior. // + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + TCDM_BUS error_slave(); + contiguous_crossbar #( + .NR_MASTER_PORTS(NR_MASTER_PORTS), + .NR_SLAVE_PORTS(NR_SLAVE_PORTS_CONTIG), + .NR_ADDR_RULES(NR_ADDR_RULES_SLAVE_PORTS_CONTIG) + ) i_contiguous_xbar( + // Interfaces + .master_ports (l2_demux_2_contiguous_xbar), + .slave_ports (contiguous_slaves), + .error_port (error_slave), + .addr_rules (addr_space_contiguous), + // Inputs + .clk_i, + .rst_ni, + .test_en_i + ); + //Error Slave + // This dummy slave is responsible to generate the buserror described above + logic error_valid_d, error_valid_q; + assign error_slave.gnt = error_slave.req; + assign error_valid_d = error_slave.req; + assign error_valid.r_opc = error_slave.req; + assign error_valid.r_rdata = 32'hBADACCE5; + + always_ff @(posedge clk_i, negedge rst_ni) begin + if (!rst_ni) begin + error_valid_q <= 1'b0; + end else begin + error_valid_q <= error_valid_d; + end + end + + + //////////////////////// + // TCDM to AXI Bridge // + //////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // Instantiate a TCDM to AXI protocol converter for each master port from the L2 demultiplexer. The converter // + // converts one 32-bit TCDM port to one 32-bit AXI port. // + //////////////////////////////////////////////////////////////////////////////////////////////////////////////// + AXI_BUS #(.AXI_ADDR_WIDTH(32), + .AXI_DATA_WIDTH(32), + .AXI_ID_WIDTH(AXI_ID_WIDTH), + .AXI_USER_WIDTH(AXI_USER_WIDTH) + ) axi_bridge_2_axi_xbar[NR_MASTER_PORTS](); + for (genvar i = 0; i < NR_MASTER_PORTS; i++) begin + lint2axi_wrap #( + .AXI_ID_WIDTH(AXI_ID_WIDTH), + .AXI_USER_WIDTH(AXI_USER_WIDTH) + ) i_axi_bridge ( + .clk_i, + .rst_ni, + .master(l2_demux_2_axi_bridge[i]), + .slave(axi_bridge_2_axi_xbar[i]) + ); + end + + + // AXI Crossbar + localparam pkg_axi::xbar_cfg_t AXI_XBAR_CFG = '{ + NoSlvPorts: NR_MASTER_PORTS, + NoMstPorts: NR_AXI_SLAVE_PORTS, + MaxMstTrans: 1, //The TCDM ports do not support + //outstanding transactiions anyways + MaxSlvTrans: 1, + MaxMstTrans: 4, //Allow up to 4 in-flight transactions + //per slave port + FallThrough: 0, //Use the reccomended default config + LatencyMode: pkg_axi:CUT_ALL_AX, + AxiIdWidthSlvPorts: AXI_ID_WIDTH, + AxiIdUsedSlvPorts: 0, //We do not really use IDs on the + //master ports since TCDM does not support + //outstanding transactions + AxiAddrWidth: BUS_ADDR_WIDTH, + AxiDataWidth: BUS_DATA_WIDTH, + NoAddrRules: NR_ADDR_RULES_AXI_SLAVE_PORTS + }; + + /////////////////// + // AXI4 Crossbar // + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // The AXI crossbar accepts a set of address to slave port mapping rules (addr_map_i) and decodes the transaction // + // address accordingly. Illegal addresses that do not map to any defined address space are anaswered with a // + // decode error and Read Responses contain the data 0xBADCAB1E. Check the axi_xbar documentation for more // + // information. // + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + axi_xbar_intf #( + .AXI_USER_WIDTH(AXI_USER_WIDTH), + .Cfg(AXI_XBAR_CFG), + .rule_t(addr_map_rule_t) + ) i_axi_xbar ( + .clk_i, + .rst_ni, + .test_i(test_en_i), + .slv_ports(axi_bridge_2_axi_xbar), + .mst_ports(axi_slaves), + .addr_map_i(addr_space_axi), + .en_default_mst_port_i('0), + .default_mst_port_i('0) + ); + +endmodule : soc_interconnect diff --git a/rtl/pulp_soc/soc_interconnect_wrap_v2.sv b/rtl/pulp_soc/soc_interconnect_wrap_v2.sv new file mode 100644 index 00000000..a64a4c20 --- /dev/null +++ b/rtl/pulp_soc/soc_interconnect_wrap_v2.sv @@ -0,0 +1,201 @@ +//----------------------------------------------------------------------------- +// Title : SoC Interconnect Wrapper +//----------------------------------------------------------------------------- +// File : soc_interconnect_wrap_v2.sv +// Author : Manuel Eggimann +// Created : 30.10.2020 +//----------------------------------------------------------------------------- +// Description : +// This module instantiates the SoC interconnect and attaches the various SoC +// ports. Furthermore, the wrapper also instantiates the required protocol converters +// (AXI, APB). +//----------------------------------------------------------------------------- +// Copyright (C) 2013-2020 ETH Zurich, University of Bologna +// Copyright and related rights are licensed under the Solderpad Hardware +// License, Version 0.51 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law +// or agreed to in writing, software, hardware and materials distributed under +// this License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. +//----------------------------------------------------------------------------- + +`include "soc_mem_map.svh" + +module soc_interconnect_wrap + import pkg_soc_interconnect::addr_map_rule_t; + #( + parameter int NR_HWPE_PORTS = 0, + parameter int NR_L2_PORTS = 4, + // AXI Input Plug + localparam int AXI_IN_ADDR_WIDTH = 32, // All addresses in the SoC must be 32-bit + localparam int AXI_IN_DATA_WIDTH = 64, // The internal AXI->TCDM protocol converter does not support any other + // datawidths than 64-bit + parameter int AXI_IN_ID_WIDTH = 6, + parameter int AXI_IN_USER_WIDTH = 6, + // Axi Output Plug + localparam int AXI_OUT_ADDR_WIDTH = 32, // All addresses in the SoC must be 32-bit + localparam int AXI_OUT_DATA_WIDTH = 32, // The internal TCDM->AXI protocol converter does not support any other + // datawidths than 32-bit + parameter int AXI_OUT_ID_WIDTH = 6, + parameter int AXI_OUT_USER_WIDTH = 6 + ) ( + logic clk_i, + logic rst_ni, + logic test_en_i, + XBAR_TCDM_BUS.Slave tcdm_fc_data, //Data Port of the Fabric Controller + XBAR_TCDM_BUS.Slave tcdm_fc_instr, //Instruction Port of the Fabric Controller + XBAR_TCDM_BUS.Slave tcdm_udma_tx, //TX Channel for the uDMA + XBAR_TCDM_BUS.Slave tcdm_udma_rx, //RX Channel for the uDMA + XBAR_TCDM_BUS.Slave tcdm_debug, //Debug access port from either the legacy or the riscv-debug unit + XBAR_TCDM_BUS.Slave tcdm_hwpe[NR_HWPE_PORTS], //Hardware Processing Element ports + AXI_BUS.Slave axi_master_plug, // Normaly used for cluster -> SoC communication + AXI_BUS.Master axi_slave_plug, // Normaly used for SoC -> cluster communication + APB_BUS.Master apb_peripheral_bus, // Connects to all the SoC Peripherals + XBAR_TCDM_BUS.Master l2_interleaved_slaves[NR_L2_PORTS], // Connects to the interleaved memory banks + XBAR_TCDM_BUS.Master l2_private_slaves[2], // Connects to core-private memory banks + XBAR_TCDM_BUS.Master boot_rom_slave //Connects to the bootrom + ); + + //**Do not change these values unles you verified that all downstream IPs are properly parametrized and support it** + localparam ADDR_WIDTH = 32; + localparam DATA_WIDTH = 32; + + + ////////////////////////////////////////////////////////////// + // 64-bit AXI to TCDM Bridge (Cluster to SoC communication) // + ////////////////////////////////////////////////////////////// + TCDM_BUS axi_bridge_2_interconnect[4](); //We need 4 32-bit TCDM ports to achieve fullbandwidth with one 64-bit AXI + //port + + axi64_2_lint32 #( + .AXI_USER_WIDTH(AXI_IN_USER_WIDTH), + .AXI_ID_WIDTH(AXI_IN_ID_WIDTH) + ) i_axi64_to_lint32( + .clk_i, + .rst_ni, + .test_en_i, + .axi_master(axi_master_plug), + .tcdm_slaves(axi_bridge_2_interconnect) + ); + + + + //////////////////////////////////////// + // Address Rules for the interconnect // + //////////////////////////////////////// + localparam NR_RULES_L2_DEMUX = 4; + //Everything that is not routed to port 1 or 2 ends up in port 0 by default + localparam addr_map_rule_t [NR_RULES_L2_DEMUX-1:0] L2_DEMUX_RULES = '{ + '{ idx: 1 , start_addr: SOC_MEM_MAP_PRIVATE_BANK0_START_ADDR , end_addr: SOC_MEM_MAP_PRIVATE_BANK1_END_ADDR} , //Both , bank0 and bank1 are in the same address block + '{ idx: 1 , start_addr: SOC_MEM_MAP_BOOT_ROM_START_ADDR , end_addr: SOC_MEM_MAP_BOOT_ROM_END_ADDR} , + '{ idx: 2 , start_addr: SOC_MEM_MAP_TCDM_START_ADDR , end_addr: SOC_MEM_MAP_TCDM_END_ADDR } , + '{ idx: 2 , start_addr: SOC_MEM_MAP_TCDM_ALIAS_START_ADDR , end_addr: SOC_MEM_MAP_TCDM_ALIAS_END_ADDR}}; + + localparam NR_RULES_CONTIG_CROSSBAR = 3; + localparam addr_map_rule_t [NR_RULES_CONTIG_CROSSBAR-1:0] CONTIGUOUS_CROSSBAR_RULES = '{ + '{ idx: 0 , start_addr: SOC_MEM_MAP_PRIVATE_BANK0_START_ADDR , end_addr: SOC_MEM_MAP_PRIVATE_BANK0_END_ADDR} , + '{ idx: 1 , start_addr: SOC_MEM_MAP_PRIVATE_BANK1_START_ADDR , end_addr: SOC_MEM_MAP_PRIVATE_BANK1_END_ADDR} , + '{ idx: 2 , start_addr: SOC_MEM_MAP_BOOT_ROM_START_ADDR , end_addr: SOC_MEM_MAP_BOOT_ROM_END_ADDR}}; + + localparam NR_RULES_AXI_CROSSBAR = 2; + localparam addr_map_rule_t [NR_RULES_AXI_CROSSBAR-1:0] AXI_CROSSBAR_RULES = '{ + '{ idx: 0, start_addr: SOC_MEM_MAP_AXI_PLUG_START_ADDR, end_addr: SOC_MEM_MAP_AXI_PLUG_END_ADDR}, + '{ idx: 1, start_addr: SOC_MEM_MAP_PERIPHERALS_START_ADDR, end_addr: SOC_MEM_MAP_PERIPHERALS_END_ADDR}}; + + ////////////////////////////// + // Instantiate Interconnect // + ////////////////////////////// + + //Internal wiring to APB protocol converter + AXI_BUS #(.AXI_ADDR_WIDTH(32), + .AXI_DATA_WIDTH(32), + .AXI_ID_WIDTH(AXI_OUT_ID_WIDTH), + .AXI_USER_WIDTH(AXI_OUT_USER_WIDTH) + ) axi_to_axi_lite_bridge(); + + + soc_interconnect #( + .NR_MASTER_PORTS(5), // FC instructions, FC data, uDMA RX, uDMA TX, debug access + .NR_MASTER_PORTS_INTERLEAVED_ONLY(NR_HWPE_PORTS), // HWPEs (PULP accelerators) only have access + // to the interleaved memory region + .NR_ADDR_RULES_L2_DEMUX(NR_RULES_L2_DEMUX), + .NR_SLAVE_PORTS_INTERLEAVED(NR_L2_PORTS), // Number of interleaved memory banks + .NR_SLAVE_PORTS_CONTIG(NR_L2_PRIVATE_PORTS), // Number of private memory banks (normally 1 for + // programm instructions and 1 for programm stack ) + .NR_ADDR_RULES_SLAVE_PORTS_CONTIG(NR_RULES_CONTIG_CROSSBAR), + .NR_AXI_SLAVE_PORTS(2), // 1 for AXI to cluster, 1 for SoC peripherals (converted to APB) + .NR_ADDR_RULES_AXI_SLAVE_PORTS(NR_RULES_AXI_CROSSBAR) + ) i_soc_interconnect ( + .clk_i, + .rst_ni, + .test_en_i, + .master_ports('{tcdm_fc_data, tcdm_fc_instr, tcdm_udma_tx, tcdm_udma_rx, tcdm_debug}), + .slave_ports(tcdm_hwpe), + .addr_space_l2_demux(L2_DEMUX_RULES), + .interleaved_slaves(l2_interleaved_slaves), + .addr_space_contiguous(CONTIGUOUS_CROSSBAR_RULES), + .contiguous_slaves('{l2_private_slaves[0], l2_private_slaves[1], boot_rom_slave}), + .addr_space_axi(AXI_CROSSBAR_RULES), + .axi_slaves('{axi_slave_plug, axi_to_axi_lite_bridge}) + ); + + + //////////////////////// + // AXI4 to APB Bridge // + /////////////////////////////////////////////////////////////////////////////////////////// + // We do the conversion in two steps: We convert AXI4 to AXI4 lite and from there to APB // + /////////////////////////////////////////////////////////////////////////////////////////// + + AXI_LITE #( + .AXI_ADDR_WIDTH(32), + .AXI_DATA_WIDTH(32)) axi_lite_to_apb_bridge(); + + axi_to_axi_lite_intf #( + .AXI_ADDR_WIDTH(32), + .AXI_DATA_WIDTH(32), + .AXI_ID_WIDTH(AXI_OUT_ID_WIDTH), + .AXI_USER_WIDTH(AXI_OUT_USER_WIDTH), + .AXI_MAX_WRITE_TXNS(1), + .AXI_MAX_READ_TXNS(1), + .FALL_THROUGH(1) + ) i_axi_to_axi_lite ( + .clk_i, + .rst_ni, + .testmode_i(test_en_i), + .slv(axi_to_axi_lite_bridge), + .mst(axi_lite_to_apb_bridge) + ); + + // The AXI-Lite to APB bridge is capable of connecting one AXI to multiple APB ports using address mapping rules. + // We do not use this feature and just supply a default rule that matches everything in the peripheral region + + localparam addr_map_rule_t APB_BRIDGE_RULES = '{ + '{ idx: 0, start_addr: SOC_MEM_MAP_PERIPHERALS_START_ADDR, end_addr: SOC_MEM_MAP_PERIPHERALS_END_ADDR}}; + + axi_lite_to_apb_intf #( + .NoApbSlaves(1), + .NoRules(1), + .AddrWidth(32), + .DataWidth(32), + .rule_t(addr_map_rule_t) + ) i_axi_lite_to_apb ( + .clk_i, + .rst_ni, + .slv(axi_lite_to_apb_bridge), + .paddr_o(apb_periph_bus.paddr), + .pprot_o(), + .pselx_o(apb_periph_bus.psel), + .penable_o(apb_periph_bus.penable), + .pwrite_o(apb_periph_bus.pwrite), + .pwdata_o(apb_periph_bus.pwdata), + .pstrb_o(), + .pready_i(apb_periph_bus.pready), + .prdata_i(apb_periph_bus.prdata), + .pslverr_i(apb_periph_bus.pslverr), + .addr_map_i(APB_BRIDGE_RULES) + ); + + +endmodule : soc_interconnect_wrap diff --git a/rtl/pulp_soc/tcdm_demux.sv b/rtl/pulp_soc/tcdm_demux.sv new file mode 100644 index 00000000..7dc61a0f --- /dev/null +++ b/rtl/pulp_soc/tcdm_demux.sv @@ -0,0 +1,146 @@ +//----------------------------------------------------------------------------- +// Title : TCDM Demultiplexer +//----------------------------------------------------------------------------- +// File : tcdm_demux.sv +// Author : Manuel Eggimann +// Created : 29.10.2020 +//----------------------------------------------------------------------------- +// Description : +// This IP demultiplexes transactions on an input TCDM port to several TCDM output +// ports. +//----------------------------------------------------------------------------- +// Copyright (C) 2013-2020 ETH Zurich, University of Bologna +// Copyright and related rights are licensed under the Solderpad Hardware +// License, Version 0.51 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law +// or agreed to in writing, software, hardware and materials distributed under +// this License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. +//----------------------------------------------------------------------------- +`include "tcdm_explode_macros.svh" + +module tcdm_demux + import pkg_soc_interconnect::addr_map_rule_t; + #( + parameter int unsigned NR_OUTPUTS = 2, + parameter int unsigned NR_ADDR_MAP_RULES, + localparam int unsigned SLAVE_SEL_WIDTH = $clog2(NR_OUTPUTS) + ) + ( + input logic clk_i, + input logic rst_ni, + input logic test_en_i, + input addr_map_rule_t addr_map_rules[NR_ADDR_MAP_RULES], + XBAR_TCDM_BUS.Slave master_port, + XBAR_TCDM_BUS.Master slave_ports[NR_OUTPUTS] + ); + // Do **not** change. The TCDM interface uses hardcoded bus widths so we cannot just change them here. + localparam int unsigned BE_WIDTH = 2; + localparam int unsigned ADDR_WIDTH = 32; + localparam int unsigned DATA_WIDTH = 32; + + // Explode the output interfaces to individual signals + `TCDM_EXPLODE_DECLARE_ARRAY(slave_ports, NR_OUTPUTS) + for (genvar i = 0; i < NR_OUTPUTS; i++) begin + `TCDM_SLAVE_EXPLODE(slave_ports, slave_ports) + end + + //The Address Decoder module generates the select signal for the demux. If there is no match in the input rules, the + //address decoder will select port 0 by default. + + logic port_sel; + addr_decode #( + .NoIndices(NR_SLAVE_PORTS_INTERNAL), + .NoRules(NR_ADDR_RULES), + .addr_t(logic[31:0]), + .rule_t(pkg_soc_interconnect::addr_map_rule_t) + ) i_addr_decode ( + .addr_i(master_ports_add[i]), + .addr_map_i(addr_rules), + .idx_o(port_sel[i]), + .dec_valid_o(), + .dec_error_o(), + .en_default_idx_i(1'b1), + .default_idx_i(0) //If no rule matches we route to the first slave + //port + ); + + typedef enum logic[0:0] {IDLE, PENDING} state_e; + + state_e state_d, state_q; + logic [SLAVE_SEL_WIDTH-1:0] active_slave_d, active_slave_q; + + //Flip-Flop for FSM state + always_ff @(posedge clk_i, negedge rst_ni) begin + if (!rst_ni) begin + state_q <= IDLE; + active_slave_q <= '0; + end else begin + state_q <= state_d; + active_slave_q <= active_slave_d; + end + end + + //Broadcast to all slaves. Only the request is actualy demultiplexed + assign slave_ports_add[port_sel] = master_port.add; + assign slave_ports_wen[port_sel] = master_port.wen; + assign slave_ports_wdata[port_sel] = master_port.wdata; + assign slave_ports_be[port_sel] = master_port.be; + + //Transaction FSM + always_comb begin + master_port.r_opc = 1'b0; + master_port.r_rdata = '0; + master_port.r_valid = 1'b0; + master_port.gnt = 1'b0; + slave_ports_req = '0; + state_d = state_q; + active_slave_d = active_slave_q; + case (state_q) + IDLE: begin + if (master_port_req) begin + //Issue the request to the right port and change the state + slave_ports_req[port_sel] = master_port.req; + master_port.gnt = slave_ports_gnt[port_sel]; + active_slave_d = port_sel; + //Wait until we receive the grant signal from the slave + if (slave_ports_gnt[port_sel]) begin + state_d = PENDING; + end else begin + state_d = IDLE; + end + end else begin + state_d = IDLE; + end + end // case: IDLE + + PENDING: begin + master_port.r_valid = slave_ports_r_valid[active_slave_q]; + master_port.r_rdata = slave_ports_r_rdata[active_slave_q]; + master_port.r_opc = slave_ports_r_opc[active_slave_q]; + //Wait until we receive the r_valid + if (slave_ports_r_valid[active_slave_q]) begin + //Check if we receive another request back to back + if (master_port.req) begin + slave_ports_req[port_sel] = master_port.req; + master_port.gnt = slave_ports_sel[port_sel]; + active_slave_d = port_sel; + //If we receive the grant we remain in the pending state. Otherwise we switch to IDLE state + if (slave_ports_gnt[port_sel]) begin + state_d = PENDING; + end else begin + state_d = IDLE; + end + end else begin + state_d = IDLE; + end + end else begin + state_d = PENDING; + end + end + endcase + end + +endmodule : tcdm_demux diff --git a/src_files.yml b/src_files.yml index 38ac71a1..614965e1 100644 --- a/src_files.yml +++ b/src_files.yml @@ -1,9 +1,17 @@ pulp_soc: incdirs: [ - ../../rtl/includes, + ../../rtl/include, ] files: [ - rtl/pulp_soc/soc_interconnect.sv, + rtl/pulp_soc/pkg_soc_interconnect.sv, + rtl/pulp_soc/axi64_to_lint32_wrap.sv, + rtl/pulp_soc/lint_2_axi_wrap.sv, + rtl/pulp_soc/contiguous_crossbar.sv, + rtl/pulp_soc/interleaved_crossbar.sv, + rtl/pulp_soc/soc_interconnect_v2.sv, + rtl/pulp_soc/soc_interconnect_wrap_v2.sv, + rtl/pulp_soc/tcdm_demux.sv, + rtl/pulp_soc/soc_interconnect_v2.sv, rtl/pulp_soc/boot_rom.sv, rtl/pulp_soc/l2_ram_multi_bank.sv, rtl/pulp_soc/lint_jtag_wrap.sv, @@ -12,7 +20,7 @@ pulp_soc: rtl/pulp_soc/soc_event_arbiter.sv, rtl/pulp_soc/soc_event_generator.sv, rtl/pulp_soc/soc_event_queue.sv, - rtl/pulp_soc/soc_interconnect_wrap.sv, + rtl/pulp_soc/soc_interconnect_wrap_v2.sv, rtl/pulp_soc/soc_peripherals.sv, rtl/pulp_soc/pulp_soc.sv, ] @@ -80,4 +88,4 @@ components_behav: ] flags: [ skip_synthesis, - ] \ No newline at end of file + ] From f137f2380e69831ec942c99a35401ec633c13f35 Mon Sep 17 00:00:00 2001 From: Manuel Eggimann Date: Sun, 1 Nov 2020 22:20:56 +0100 Subject: [PATCH 02/30] Fix IP dependencies --- ips_list.yml | 15 +++++++-------- rtl/pulp_soc/soc_interconnect.sv | 3 +-- src_files.yml | 4 +--- 3 files changed, 9 insertions(+), 13 deletions(-) diff --git a/ips_list.yml b/ips_list.yml index 74663a6c..540348e9 100644 --- a/ips_list.yml +++ b/ips_list.yml @@ -17,7 +17,9 @@ # state of DETACHED HEAD. Before committing any additional # work, make sure to checkout a branch. # - +common_cells: + commit: v1.19.0 + domain: [cluster, soc] L2_tcdm_hybrid_interco: commit: pulpissimo-v1.0 domain: [soc] @@ -46,11 +48,11 @@ apb_interrupt_cntrl: commit: v0.0.1 domain: [soc] axi/axi: - commit: v0.24.0 - domain: [cluster, soc] -axi/axi_node: - commit: v1.1.4 + commit: 6765d6d domain: [cluster, soc] +# axi/axi_node: +# commit: v1.1.4 +# domain: [cluster, soc] axi/axi_slice: commit: v1.1.4 domain: [cluster, soc] @@ -60,9 +62,6 @@ axi/axi_slice_dc: timer_unit: commit: v1.0.2 domain: [cluster, soc] -common_cells: - commit: v1.13.1 - domain: [cluster, soc] fpnew: commit: v0.6.4 domain: [cluster, soc] diff --git a/rtl/pulp_soc/soc_interconnect.sv b/rtl/pulp_soc/soc_interconnect.sv index b6931197..423284fd 100644 --- a/rtl/pulp_soc/soc_interconnect.sv +++ b/rtl/pulp_soc/soc_interconnect.sv @@ -244,7 +244,6 @@ module soc_interconnect #( output logic [N_L2_BANKS_PRI-1:0] [BE_WIDTH-1:0] L2_pri_BE_o, input logic [N_L2_BANKS_PRI-1:0] [DATA_WIDTH-1:0] L2_pri_Q_i ); - localparam N_CH0 = N_MASTER_32 ; localparam N_CH1 = N_MASTER_AXI_64*4; @@ -261,7 +260,7 @@ module soc_interconnect #( localparam logic [N_PERIPHS-1:0][ADDR_WIDTH-1:0] PER_END_ADDR = { 32'h1C01_0000, 32'h1C00_8000, 32'h1A04_0000, 32'h1040_0000, 32'h1A40_0000}; localparam logic [ADDR_WIDTH-1:0] TCDM_START_ADDR = {32'h1C01_0000}; // Start of L2 interleaved - localparam logic [ADDR_WIDTH-1:0] TCDM_END_ADDR = {32'h1C08_2000}; // END of L2 interleaved + localparam logic [ADDR_WIDTH-1:0] TCDM_END_ADDR = {32'h1C09_0000}; // END of L2 interleaved logic [N_MASTER_32-1:0] FC_data_req_INT_32; logic [N_MASTER_32-1:0] [ADDR_WIDTH - 1:0] FC_data_add_INT_32; diff --git a/src_files.yml b/src_files.yml index 614965e1..da882304 100644 --- a/src_files.yml +++ b/src_files.yml @@ -1,6 +1,6 @@ pulp_soc: incdirs: [ - ../../rtl/include, + ../../rtl/includes, ] files: [ rtl/pulp_soc/pkg_soc_interconnect.sv, @@ -8,8 +8,6 @@ pulp_soc: rtl/pulp_soc/lint_2_axi_wrap.sv, rtl/pulp_soc/contiguous_crossbar.sv, rtl/pulp_soc/interleaved_crossbar.sv, - rtl/pulp_soc/soc_interconnect_v2.sv, - rtl/pulp_soc/soc_interconnect_wrap_v2.sv, rtl/pulp_soc/tcdm_demux.sv, rtl/pulp_soc/soc_interconnect_v2.sv, rtl/pulp_soc/boot_rom.sv, From f8d3b0b02fa937c699019c133df54926cb855dee Mon Sep 17 00:00:00 2001 From: Manuel Eggimann Date: Tue, 3 Nov 2020 11:56:17 +0100 Subject: [PATCH 03/30] Fix numerous bugs Hello world is no passing the tests --- ...cdm_explode_macros.svh => tcdm_macros.svh} | 13 +- ..._lint32_wrap.sv => axi64_2_lint32_wrap.sv} | 12 +- rtl/pulp_soc/boot_rom.sv | 2 +- rtl/pulp_soc/contiguous_crossbar.sv | 34 ++--- rtl/pulp_soc/interleaved_crossbar.sv | 16 +-- rtl/pulp_soc/l2_ram_multi_bank.sv | 10 +- rtl/pulp_soc/lint_2_axi_wrap.sv | 6 +- rtl/pulp_soc/pulp_soc.sv | 50 +------ rtl/pulp_soc/soc_interconnect_v2.sv | 133 ++++++++++++------ rtl/pulp_soc/soc_interconnect_wrap_v2.sv | 119 ++++++++++------ rtl/pulp_soc/tcdm_demux.sv | 49 ++++--- src_files.yml | 5 +- 12 files changed, 255 insertions(+), 194 deletions(-) rename rtl/include/{tcdm_explode_macros.svh => tcdm_macros.svh} (87%) rename rtl/pulp_soc/{axi64_to_lint32_wrap.sv => axi64_2_lint32_wrap.sv} (96%) diff --git a/rtl/include/tcdm_explode_macros.svh b/rtl/include/tcdm_macros.svh similarity index 87% rename from rtl/include/tcdm_explode_macros.svh rename to rtl/include/tcdm_macros.svh index b238e578..6af73986 100644 --- a/rtl/include/tcdm_explode_macros.svh +++ b/rtl/include/tcdm_macros.svh @@ -46,6 +46,17 @@ assign exploded_prefix``_be postfix = iface.be; \ assign iface.gnt = exploded_prefix``_gnt postfix; \ assign iface.r_opc = exploded_prefix``_r_opc postfix; \ assign iface.r_rdata = exploded_prefix``_r_rdata postfix; \ -assign iface.r_val = exploded_prefix``_r_valid postfix; +assign iface.r_valid = exploded_prefix``_r_valid postfix; + + `define TCDM_MASTER_ASSIGN(b, a) \ +assign b.req = a.req; \ +assign b.add = a.add; \ +assign b.wen = a.wen; \ +assign b.wdata = a.wdata; \ +assign b.be = a.be; \ +assign a.gnt = b.gnt ; \ +assign a.r_opc = b.r_opc ; \ +assign a.r_rdata= b.r_rdata ; \ +assign a.r_valid = b.r_valid ; `endif diff --git a/rtl/pulp_soc/axi64_to_lint32_wrap.sv b/rtl/pulp_soc/axi64_2_lint32_wrap.sv similarity index 96% rename from rtl/pulp_soc/axi64_to_lint32_wrap.sv rename to rtl/pulp_soc/axi64_2_lint32_wrap.sv index e5d74159..8b75e434 100644 --- a/rtl/pulp_soc/axi64_to_lint32_wrap.sv +++ b/rtl/pulp_soc/axi64_2_lint32_wrap.sv @@ -20,7 +20,7 @@ // specific language governing permissions and limitations under the License. //----------------------------------------------------------------------------- -`include "tcdm_explode_macros.svh" +`include "tcdm_macros.svh" module axi64_2_lint32_wrap #( @@ -31,7 +31,7 @@ module axi64_2_lint32_wrap input logic rst_ni, input logic test_en_i, AXI_BUS.Slave axi_master, - TCDM_BUS.Master tcdm_slaves[4] + XBAR_TCDM_BUS.Master tcdm_slaves[4] ); // *Do not change* The legacy wrapper was never tested for other bitwidths. @@ -43,9 +43,9 @@ module axi64_2_lint32_wrap localparam TCDM_BE_WIDTH = TCDM_DATA_WIDTH/8; //Explode the output TCDM interface into arrays of individual signals - `TCDM_EXPLODE_DECLARE_ARRAY(tcdm_slaves, 4) + `TCDM_EXPLODE_ARRAY_DECLARE(tcdm_slaves, 4) for (genvar i = 0; i < 4; i++) begin - `TCDM_SLAVE_EXPLODE(tcdm_slaves, tcdm_slaves) + `TCDM_SLAVE_EXPLODE(tcdm_slaves[i], tcdm_slaves, [i]) end @@ -59,7 +59,7 @@ module axi64_2_lint32_wrap .BUFF_DEPTH_SLICES ( 4 ), //= 4, .DATA_WIDTH ( TCDM_DATA_WIDTH ), //= 64, .BE_WIDTH ( TCDM_BE_WIDTH ), //= DATA_WIDTH/8, - .ADDR_WIDTH ( TCDM_ADDR_WIDTH ), //= 10 + .ADDR_WIDTH ( TCDM_ADDR_WIDTH ) //= 10 ) axi64_2_lint32_i ( // AXI GLOBAL SIGNALS .clk ( clk_i ), @@ -146,4 +146,4 @@ module axi64_2_lint32_wrap .data_R_r_aux_i ( '0 ) // We don't need this signal ); -endmodule : axi64_2_lint_wrap +endmodule diff --git a/rtl/pulp_soc/boot_rom.sv b/rtl/pulp_soc/boot_rom.sv index a09d0a25..1a4c5f23 100644 --- a/rtl/pulp_soc/boot_rom.sv +++ b/rtl/pulp_soc/boot_rom.sv @@ -34,7 +34,7 @@ module boot_rom #( //Remove address offset logic [31:0] address; - assign address = mem_slave.add - SOC_MEM_MAP_BOOT_ROM_START_ADDR; + assign address = mem_slave.add - `SOC_MEM_MAP_BOOT_ROM_START_ADDR; `ifndef PULP_FPGA_EMUL diff --git a/rtl/pulp_soc/contiguous_crossbar.sv b/rtl/pulp_soc/contiguous_crossbar.sv index 4e90fe10..170e76bd 100644 --- a/rtl/pulp_soc/contiguous_crossbar.sv +++ b/rtl/pulp_soc/contiguous_crossbar.sv @@ -21,23 +21,25 @@ // specific language governing permissions and limitations under the License. //----------------------------------------------------------------------------- +`include "tcdm_macros.svh" + module contiguous_crossbar import pkg_soc_interconnect::addr_map_rule_t; #( parameter int unsigned NR_MASTER_PORTS, parameter int unsigned NR_SLAVE_PORTS, parameter int unsigned NR_ADDR_RULES - )( - input logic clk_i, - input logic rst_ni, - input logic test_en_i, - XBAR_TCDM_BUS.Slave master_ports[NR_MASTER_PORTS], - XBAR_TCDM_BUS.Master slave_ports[NR_SLAVE_PORTS], - XBAR_TCDM_BUS.Master error_port, - input addr_map_rule_t addr_rules[NR_ADDR_RULES] - ); + )( + input logic clk_i, + input logic rst_ni, + input logic test_en_i, + XBAR_TCDM_BUS.Slave master_ports[NR_MASTER_PORTS], + XBAR_TCDM_BUS.Master slave_ports[NR_SLAVE_PORTS], + XBAR_TCDM_BUS.Master error_port, + input addr_map_rule_t [NR_ADDR_RULES-1:0] addr_rules + ); // Do **not** change. The TCDM interface uses hardcoded bus widths so we cannot just change them here. - localparam int unsigned BE_WIDTH = 2; + localparam int unsigned BE_WIDTH = 4; localparam int unsigned ADDR_WIDTH = 32; localparam int unsigned DATA_WIDTH = 32; localparam int unsigned NR_SLAVE_PORTS_INTERNAL = NR_SLAVE_PORTS+1; // We have one additional slave port for the @@ -69,11 +71,11 @@ module contiguous_crossbar logic [NR_SLAVE_PORTS_INTERNAL-1:0][REQ_AGG_DATA_WIDTH-1:0] req_data_agg_out; //Aggreagate the input data for (genvar i = 0; i < NR_MASTER_PORTS; i++) begin - assign req_data_agg_in[i] = {master_ports_wen[i], master_ports_add[i], master_ports_wdata[i]}; + assign req_data_agg_in[i] = {master_ports_wen[i], master_ports_be[i], master_ports_add[i], master_ports_wdata[i]}; end //Disaggregate the output data for (genvar i = 0; i < NR_SLAVE_PORTS_INTERNAL; i++) begin : disaggregate_outputs - assign {slave_ports_wen[i], slave_ports_add[i], slave_ports_wdata[i]} = req_data_agg_out[i]; + assign {slave_ports_wen[i], slave_ports_be[i], slave_ports_add[i], slave_ports_wdata[i]} = req_data_agg_out[i]; end //Aggregated response data (from Slaves -> Master) @@ -110,10 +112,10 @@ module contiguous_crossbar //Crossbar instantiation xbar #( - .numin(NR_MASTER_PORTS), - .numout(NR_SLAVE_PORTS), - .reqdatawidth(REQ_AGG_DATA_WIDTH), - .respdatawidth(RESP_AGG_DATA_WIDTH), + .NumIn(NR_MASTER_PORTS), + .NumOut(NR_SLAVE_PORTS_INTERNAL), + .ReqDataWidth(REQ_AGG_DATA_WIDTH), + .RespDataWidth(RESP_AGG_DATA_WIDTH), .RespLat(1), .WriteRespOn(1) ) i_xbar ( diff --git a/rtl/pulp_soc/interleaved_crossbar.sv b/rtl/pulp_soc/interleaved_crossbar.sv index ddfaa5db..ab687896 100644 --- a/rtl/pulp_soc/interleaved_crossbar.sv +++ b/rtl/pulp_soc/interleaved_crossbar.sv @@ -23,7 +23,7 @@ // specific language governing permissions and limitations under the License. //----------------------------------------------------------------------------- -`include "tcdm_explode_macros.svh" +`include "tcdm_macros.svh" module interleaved_crossbar #( @@ -37,7 +37,7 @@ module interleaved_crossbar XBAR_TCDM_BUS.Master slave_ports[NR_SLAVE_PORTS] ); // Do **not** change. The TCDM interface uses hardcoded bus widths so we cannot just change them here. - localparam int unsigned BE_WIDTH = 2; + localparam int unsigned BE_WIDTH = 4; localparam int unsigned ADDR_WIDTH = 32; localparam int unsigned DATA_WIDTH = 32; localparam int unsigned PORT_SEL_WIDTH = $clog2(NR_SLAVE_PORTS); @@ -72,11 +72,11 @@ module interleaved_crossbar logic [NR_SLAVE_PORTS-1:0][REQ_AGG_DATA_WIDTH-1:0] req_data_agg_out; //Aggreagate the input data for (genvar i = 0; i < NR_MASTER_PORTS; i++) begin - assign req_data_agg_in[i] = {master_ports_wen[i], master_ports_add[i], master_ports_wdata[i]}; + assign req_data_agg_in[i] = {master_ports_wen[i], master_ports_be[i], master_ports_add[i], master_ports_wdata[i]}; end //Disaggregate the output data for (genvar i = 0; i < NR_SLAVE_PORTS; i++) begin : disaggregate_outputs - assign {slave_ports_wen[i], slave_ports_add[i], slave_ports_wdata[i]} = req_data_agg_out[i]; + assign {slave_ports_wen[i], slave_ports_be[i], slave_ports_add[i], slave_ports_wdata[i]} = req_data_agg_out[i]; end //Aggregated response data (from Slaves -> Master) @@ -98,10 +98,10 @@ module interleaved_crossbar //Crossbar instantiation xbar #( - .numin(NR_MASTER_PORTS), - .numout(NR_SLAVE_PORTS), - .reqdatawidth(REQ_AGG_DATA_WIDTH), - .respdatawidth(RESP_AGG_DATA_WIDTH), + .NumIn(NR_MASTER_PORTS), + .NumOut(NR_SLAVE_PORTS), + .ReqDataWidth(REQ_AGG_DATA_WIDTH), + .RespDataWidth(RESP_AGG_DATA_WIDTH), .RespLat(1), .WriteRespOn(1) ) i_xbar ( diff --git a/rtl/pulp_soc/l2_ram_multi_bank.sv b/rtl/pulp_soc/l2_ram_multi_bank.sv index 8a7a47f0..54045c8e 100644 --- a/rtl/pulp_soc/l2_ram_multi_bank.sv +++ b/rtl/pulp_soc/l2_ram_multi_bank.sv @@ -47,7 +47,7 @@ module l2_ram_multi_bank #( end end //Remove Address offset - assign interleaved_addresses[i] = mem_slave[i].add - SOC_MEM_MAP_TCDM_START_ADDR; + assign interleaved_addresses[i] = mem_slave[i].add - `SOC_MEM_MAP_TCDM_START_ADDR; `ifndef PULP_FPGA_EMUL /* @@ -55,9 +55,9 @@ module l2_ram_multi_bank #( that has been tape-out. */ generic_memory #( - .ADDR_WIDTH ( BANK_SIZE_INTL_SRAM ), + .ADDR_WIDTH ( INTL_MEM_ADDR_WIDTH ), .DATA_WIDTH ( 32 ) - ) bank_sram_pri1_i ( + ) bank_i ( .CLK ( clk_i ), .INITN ( 1'b1 ), .CEN ( ~mem_slave[i].req ), @@ -96,7 +96,7 @@ module l2_ram_multi_bank #( end //Remove Address offset logic [31:0] pri0_address; - assign pri0_address = mem_pri_slave[0].add - SOC_MEM_MAP_PRIVATE_BANK0_START_ADDR; + assign pri0_address = mem_pri_slave[0].add - `SOC_MEM_MAP_PRIVATE_BANK0_START_ADDR; `ifndef PULP_FPGA_EMUL generic_memory #( .ADDR_WIDTH ( PRI0_MEM_ADDR_WIDTH ), @@ -138,7 +138,7 @@ module l2_ram_multi_bank #( end //Remove Address offset logic [31:0] pri1_address; - assign pri0_address = mem_pri_slave[1].add - SOC_MEM_MAP_PRIVATE_BANK1_START_ADDR; + assign pri1_address = mem_pri_slave[1].add - `SOC_MEM_MAP_PRIVATE_BANK1_START_ADDR; `ifndef PULP_FPGA_EMUL generic_memory #( .ADDR_WIDTH ( PRI1_MEM_ADDR_WIDTH ), diff --git a/rtl/pulp_soc/lint_2_axi_wrap.sv b/rtl/pulp_soc/lint_2_axi_wrap.sv index bf06b492..a529ccc6 100644 --- a/rtl/pulp_soc/lint_2_axi_wrap.sv +++ b/rtl/pulp_soc/lint_2_axi_wrap.sv @@ -31,7 +31,7 @@ module lint2axi_wrap ( input logic clk_i, input logic rst_ni, - TCDM_BUS.Slave master, + XBAR_TCDM_BUS.Slave master, AXI_BUS.Master slave ); @@ -40,6 +40,10 @@ module lint2axi_wrap localparam int unsigned DATA_WIDTH = 32; localparam int unsigned BE_WIDTH = DATA_WIDTH/8; + //Assign atomic attributes to zero. Otherwise the axi to axi_lite atop_filter will not work properly since it + //receives X on the atop signal + assign slave.aw_atop = '0; + lint_2_axi #( .ADDR_WIDTH ( ADDR_WIDTH ), .DATA_WIDTH ( DATA_WIDTH ), diff --git a/rtl/pulp_soc/pulp_soc.sv b/rtl/pulp_soc/pulp_soc.sv index dcc04313..18350b79 100644 --- a/rtl/pulp_soc/pulp_soc.sv +++ b/rtl/pulp_soc/pulp_soc.sv @@ -21,7 +21,9 @@ module pulp_soc import dm::*; #( parameter AXI_DATA_IN_WIDTH = 64, parameter AXI_DATA_OUT_WIDTH = 32, parameter AXI_ID_IN_WIDTH = 6, - parameter AXI_ID_OUT_WIDTH = 6, + localparam AXI_ID_OUT_WIDTH = AXI_ID_IN_WIDTH+$clog2(2), //Account for additional bits needed by AXI_XBAR to + //backroute responses. At the moment we have 3 xbar + //slaves (SoC2Cluster plug and APB peripherals plug) parameter AXI_USER_WIDTH = 6, parameter AXI_STRB_WIDTH_IN = AXI_DATA_IN_WIDTH/8, parameter AXI_STRB_WIDTH_OUT = AXI_DATA_OUT_WIDTH/8, @@ -461,7 +463,7 @@ module pulp_soc import dm::*; #( assign cluster_rtc_o = ref_clk_i; assign cluster_test_en_o = dft_test_mode_i; // isolate dc if the cluster is down - assign s_cluster_isolate_dc = 1'b0; + assign s_cluster_isolate_dc = 1'b1; //cluster_byp_o; // If you want to connect a real PULP cluster you also need a cluster_busy_i signal @@ -782,11 +784,8 @@ module pulp_soc import dm::*; #( soc_interconnect_wrap #( .NR_HWPE_PORTS(NB_HWPE_PORTS), .NR_L2_PORTS(NB_L2_BANKS), - .NR_L2_PRIVATE_PORTS(NB_L2_BANKS_PRI), .AXI_IN_ID_WIDTH(AXI_ID_IN_WIDTH), - .AXI_IN_USER_WIDTH(AXI_USER_WIDTH), - .AXI_OUT_ID_WIDTH(AXI_ID_OUT_WIDTH), - .AXI_OUT_USER_WIDTH(AXI_USER_WIDTH) + .AXI_USER_WIDTH(AXI_USER_WIDTH) ) i_soc_interconnect_wrap ( .clk_i ( s_soc_clk ), .rst_ni ( s_soc_rstn ), @@ -805,45 +804,6 @@ module pulp_soc import dm::*; #( .boot_rom_slave ( s_mem_rom_bus ) ); - soc_interconnect_wrap #( - .N_L2_BANKS ( NB_L2_BANKS ), - .ADDR_MEM_WIDTH ( L2_MEM_ADDR_WIDTH ), - .N_HWPE_PORTS ( NB_HWPE_PORTS ), - - .N_L2_BANKS_PRI ( NB_L2_BANKS_PRI ), - .ADDR_MEM_PRI_WIDTH ( L2_MEM_ADDR_WIDTH_PRI ), - - .ROM_ADDR_WIDTH ( ROM_ADDR_WIDTH ), - - .AXI_32_ID_WIDTH ( AXI_ID_OUT_WIDTH ), - .AXI_32_USER_WIDTH ( AXI_USER_WIDTH ), - - .AXI_ADDR_WIDTH ( AXI_ADDR_WIDTH ), - .AXI_DATA_WIDTH ( AXI_DATA_IN_WIDTH ), - .AXI_STRB_WIDTH ( AXI_DATA_IN_WIDTH/8 ), - .AXI_USER_WIDTH ( AXI_USER_WIDTH ), - .AXI_ID_WIDTH ( AXI_ID_IN_WIDTH ) - ) i_soc_interconnect_wrap ( - .clk_i ( s_soc_clk ), - .rstn_i ( s_soc_rstn ), - .test_en_i ( dft_test_mode_i ), - .lint_fc_data ( s_lint_fc_data_bus ), - .lint_fc_instr ( s_lint_fc_instr_bus ), - .lint_udma_tx ( s_lint_udma_tx_bus ), - .lint_udma_rx ( s_lint_udma_rx_bus ), - .lint_debug ( s_lint_debug_bus ), - .lint_hwpe ( s_lint_hwpe_bus ), - - .axi_from_cluster ( s_data_in_bus ), - .axi_to_cluster ( s_data_out_bus ), - - .apb_periph_bus ( s_apb_periph_bus ), - .mem_l2_bus ( s_mem_l2_bus ), - .mem_l2_pri_bus ( s_mem_l2_pri_bus ), - .mem_rom_bus ( s_mem_rom_bus ) - ); - - /* Debug Subsystem */ dmi_jtag #( diff --git a/rtl/pulp_soc/soc_interconnect_v2.sv b/rtl/pulp_soc/soc_interconnect_v2.sv index cda346f3..3c214402 100644 --- a/rtl/pulp_soc/soc_interconnect_v2.sv +++ b/rtl/pulp_soc/soc_interconnect_v2.sv @@ -18,26 +18,35 @@ // CONDITIONS OF ANY KIND, either express or implied. See the License for the // specific language governing permissions and limitations under the License. //----------------------------------------------------------------------------- -`include "tcdm_explode_macros.svh" +`include "tcdm_macros.svh" +`include "axi/assign.svh" module soc_interconnect import pkg_soc_interconnect::addr_map_rule_t; #( // TCDM Bus Master Config - parameter int unsigned NR_MASTER_PORTS, //Master Ports to the SoC interconnect with access to all memory regions - parameter int unsigned NR_MASTER_PORTS_INTERLEAVED_ONLY, //Master ports with access restricted to only the interleaved + parameter int unsigned NR_MASTER_PORTS, //Master Ports to the SoC interconnect with access to all memory regions + parameter int unsigned NR_MASTER_PORTS_INTERLEAVED_ONLY, //Master ports with access restricted to only the interleaved //ports (no axes to APB, AXI, or contiguous slaves) TCDM Bus //Slave Config // L2 Demux Addr rules - parameter int unsigned NR_ADDR_RULES_L2_DEMUX, + parameter int unsigned NR_ADDR_RULES_L2_DEMUX, // Interleaved TCDM slave - parameter int unsigned NR_SLAVE_PORTS_INTERLEAVED, + parameter int unsigned NR_SLAVE_PORTS_INTERLEAVED, // Contiguous TCDM slave - parameter int unsigned NR_SLAVE_PORTS_CONTIG, - parameter int unsigned NR_ADDR_RULES_SLAVE_PORTS_CONTIG, + parameter int unsigned NR_SLAVE_PORTS_CONTIG, + parameter int unsigned NR_ADDR_RULES_SLAVE_PORTS_CONTIG, + // AXI Master ID Width + parameter int unsigned AXI_MASTER_ID_WIDTH = 1, // Not really used since we only connect TCDM masters to the + // axi_xbar with protocol converters. However, the value must not be zero. // AXI Slaves - parameter int unsigned NR_AXI_SLAVE_PORTS, - parameter int unsigned NR_ADDR_RULES_AXI_SLAVE_PORTS + parameter int unsigned NR_AXI_SLAVE_PORTS, + parameter int unsigned NR_ADDR_RULES_AXI_SLAVE_PORTS, + localparam int unsigned AXI_SLAVE_ID_WIDTH = AXI_MASTER_ID_WIDTH + $clog2(NR_MASTER_PORTS), //The actual ID + //width of the AXI slaves is clog2(NR_AXI_MASTERS) larger than the master id width since the + //axi_mux in the XBAR will append an identificatoin tag to the outgoing transactions + //towards the axi slaves so it can backroute the responses + parameter int unsigned AXI_USER_WIDTH ) ( input logic clk_i, @@ -53,7 +62,8 @@ module soc_interconnect XBAR_TCDM_BUS.Master contiguous_slaves[NR_SLAVE_PORTS_CONTIG], //AXI Slave input addr_map_rule_t [NR_ADDR_RULES_AXI_SLAVE_PORTS-1:0] addr_space_axi, - AXI_BUS.Master axi_slaves[NR_AXI_SLAVE_PORTS] + AXI_BUS.Master axi_slaves[NR_AXI_SLAVE_PORTS] //AXI_ID width must be + //at least clog2(NR_AXI_SLAVES) ); @@ -63,9 +73,9 @@ module soc_interconnect localparam int BUS_ADDR_WIDTH = 32; // Internal Wiring Signals - TCDM_BUS l2_demux_2_interleaved_xbar[NR_MASTER_PORTS](); - TCDM_BUS l2_demux_2_contiguous_xbar[NR_MASTER_PORTS](); - TCDM_BUS l2_demux_2_axi_bridge[NR_MASTER_PORTS](); + XBAR_TCDM_BUS l2_demux_2_interleaved_xbar[NR_MASTER_PORTS](); + XBAR_TCDM_BUS l2_demux_2_contiguous_xbar[NR_MASTER_PORTS](); + XBAR_TCDM_BUS l2_demux_2_axi_bridge[NR_MASTER_PORTS](); ////////////////////// // L2 Demultiplexer // @@ -75,17 +85,24 @@ module soc_interconnect // to the contiguous crossbar and the third slave port connects to the interleaved crossbar. // /////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - for (genvar i = 0; i < NR_MASTER_PORTS; i++) begin : l2_demux + + for (genvar i = 0; i < NR_MASTER_PORTS; i++) begin : gen_l2_demux + XBAR_TCDM_BUS demux_slaves[3](); + `TCDM_MASTER_ASSIGN(l2_demux_2_axi_bridge[i], demux_slaves[0]); + `TCDM_MASTER_ASSIGN(l2_demux_2_contiguous_xbar[i], demux_slaves[1]); + `TCDM_MASTER_ASSIGN(l2_demux_2_interleaved_xbar[i], demux_slaves[2]); + + tcdm_demux #( .NR_OUTPUTS(3), - .NR_ADDR_MAP_RULES(NR_ADDR_RULES_SLAVE_PORTS_INTERLEAVED) + .NR_ADDR_MAP_RULES(NR_ADDR_RULES_L2_DEMUX) ) i_l2_demux( .clk_i, .rst_ni, .test_en_i, - .addr_map_rules(addr_space_interleaved), + .addr_map_rules(addr_space_l2_demux), .master_port(master_ports[i]), - .output_ports('{l2_demux_2_axi_bridge[i], l2_demux_2_contiguous_xbar[i], l2_demux_2_interleaved_xbar[i]}) + .slave_ports(demux_slaves) ); end @@ -103,12 +120,22 @@ module soc_interconnect // undefined behavior. // //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + //Concatenate the l2 demux master port array and the interleaved only port array + XBAR_TCDM_BUS interleaved_masters[NR_MASTER_PORTS+NR_MASTER_PORTS_INTERLEAVED_ONLY](); + for (genvar i = 0; i < NR_MASTER_PORTS; i++) begin + `TCDM_MASTER_ASSIGN(interleaved_masters[i], l2_demux_2_interleaved_xbar[i]) + end + + for (genvar i = 0; i < NR_MASTER_PORTS_INTERLEAVED_ONLY; i++) begin + `TCDM_MASTER_ASSIGN(interleaved_masters[NR_MASTER_PORTS+i], master_ports_interleaved_only[i]) + end + interleaved_crossbar #( .NR_MASTER_PORTS(NR_MASTER_PORTS+NR_MASTER_PORTS_INTERLEAVED_ONLY), .NR_SLAVE_PORTS(NR_SLAVE_PORTS_INTERLEAVED) ) i_interleaved_xbar( // Interfaces - .master_ports (l2_demux_2_interleaved_xbar), + .master_ports (interleaved_masters), .slave_ports (interleaved_slaves), // Inputs .clk_i, @@ -127,7 +154,7 @@ module soc_interconnect // within a single cycle must appropriately delay the assertion of the gnt (grant) signal. Asserting grant // // without asserting r_valid in the next cycle results in undefined behavior. // //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - TCDM_BUS error_slave(); + XBAR_TCDM_BUS error_slave(); contiguous_crossbar #( .NR_MASTER_PORTS(NR_MASTER_PORTS), .NR_SLAVE_PORTS(NR_SLAVE_PORTS_CONTIG), @@ -148,8 +175,8 @@ module soc_interconnect logic error_valid_d, error_valid_q; assign error_slave.gnt = error_slave.req; assign error_valid_d = error_slave.req; - assign error_valid.r_opc = error_slave.req; - assign error_valid.r_rdata = 32'hBADACCE5; + assign error_slave.r_opc = error_slave.req; + assign error_slave.r_rdata = 32'hBADACCE5; always_ff @(posedge clk_i, negedge rst_ni) begin if (!rst_ni) begin @@ -168,14 +195,14 @@ module soc_interconnect //////////////////////////////////////////////////////////////////////////////////////////////////////////////// AXI_BUS #(.AXI_ADDR_WIDTH(32), .AXI_DATA_WIDTH(32), - .AXI_ID_WIDTH(AXI_ID_WIDTH), + .AXI_ID_WIDTH(AXI_MASTER_ID_WIDTH), .AXI_USER_WIDTH(AXI_USER_WIDTH) ) axi_bridge_2_axi_xbar[NR_MASTER_PORTS](); - for (genvar i = 0; i < NR_MASTER_PORTS; i++) begin + for (genvar i = 0; i < NR_MASTER_PORTS; i++) begin : gen_tcdm_2_axi_bridge lint2axi_wrap #( - .AXI_ID_WIDTH(AXI_ID_WIDTH), + .AXI_ID_WIDTH(AXI_MASTER_ID_WIDTH), .AXI_USER_WIDTH(AXI_USER_WIDTH) - ) i_axi_bridge ( + ) i_lint2axi_bridge ( .clk_i, .rst_ni, .master(l2_demux_2_axi_bridge[i]), @@ -184,34 +211,51 @@ module soc_interconnect end - // AXI Crossbar - localparam pkg_axi::xbar_cfg_t AXI_XBAR_CFG = '{ + /////////////////// + // AXI4 Crossbar // + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // The AXI crossbar accepts a set of address to slave port mapping rules (addr_map_i) and decodes the transaction // + // address accordingly. Illegal addresses that do not map to any defined address space are anaswered with a // + // decode error and Read Responses contain the data 0xBADCAB1E. Check the axi_xbar documentation for more // + // information. // + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + localparam axi_pkg::xbar_cfg_t AXI_XBAR_CFG = '{ NoSlvPorts: NR_MASTER_PORTS, NoMstPorts: NR_AXI_SLAVE_PORTS, MaxMstTrans: 1, //The TCDM ports do not support //outstanding transactiions anyways - MaxSlvTrans: 1, - MaxMstTrans: 4, //Allow up to 4 in-flight transactions + MaxSlvTrans: 4, //Allow up to 4 in-flight transactions //per slave port FallThrough: 0, //Use the reccomended default config - LatencyMode: pkg_axi:CUT_ALL_AX, - AxiIdWidthSlvPorts: AXI_ID_WIDTH, - AxiIdUsedSlvPorts: 0, //We do not really use IDs on the - //master ports since TCDM does not support - //outstanding transactions + LatencyMode: axi_pkg::CUT_ALL_AX, + AxiIdWidthSlvPorts: AXI_MASTER_ID_WIDTH, + AxiIdUsedSlvPorts: AXI_MASTER_ID_WIDTH, AxiAddrWidth: BUS_ADDR_WIDTH, AxiDataWidth: BUS_DATA_WIDTH, NoAddrRules: NR_ADDR_RULES_AXI_SLAVE_PORTS }; - /////////////////// - // AXI4 Crossbar // - //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - // The AXI crossbar accepts a set of address to slave port mapping rules (addr_map_i) and decodes the transaction // - // address accordingly. Illegal addresses that do not map to any defined address space are anaswered with a // - // decode error and Read Responses contain the data 0xBADCAB1E. Check the axi_xbar documentation for more // - // information. // - //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + //Reverse interface array ordering since axi_xbar uses big-endian ordering of the arrays + AXI_BUS #(.AXI_ADDR_WIDTH(32), + .AXI_DATA_WIDTH(32), + .AXI_ID_WIDTH(AXI_MASTER_ID_WIDTH), + .AXI_USER_WIDTH(AXI_USER_WIDTH) + ) axi_bridge_2_axi_xbar_reversed[NR_MASTER_PORTS-1:0](); + AXI_BUS #(.AXI_ADDR_WIDTH(32), + .AXI_DATA_WIDTH(32), + .AXI_ID_WIDTH(AXI_SLAVE_ID_WIDTH), + .AXI_USER_WIDTH(AXI_USER_WIDTH) + ) axi_slaves_reversed[NR_AXI_SLAVE_PORTS-1:0](); + + for (genvar i = 0; i < NR_MASTER_PORTS; i++) begin + `AXI_ASSIGN(axi_bridge_2_axi_xbar_reversed[i], axi_bridge_2_axi_xbar[i]) + end + + for (genvar i = 0; i < NR_AXI_SLAVE_PORTS; i++) begin + `AXI_ASSIGN(axi_slaves[i], axi_slaves_reversed[i]) + end + axi_xbar_intf #( .AXI_USER_WIDTH(AXI_USER_WIDTH), .Cfg(AXI_XBAR_CFG), @@ -220,11 +264,12 @@ module soc_interconnect .clk_i, .rst_ni, .test_i(test_en_i), - .slv_ports(axi_bridge_2_axi_xbar), - .mst_ports(axi_slaves), + .slv_ports(axi_bridge_2_axi_xbar_reversed), + .mst_ports(axi_slaves_reversed), .addr_map_i(addr_space_axi), .en_default_mst_port_i('0), .default_mst_port_i('0) ); + endmodule : soc_interconnect diff --git a/rtl/pulp_soc/soc_interconnect_wrap_v2.sv b/rtl/pulp_soc/soc_interconnect_wrap_v2.sv index a64a4c20..66fed6e7 100644 --- a/rtl/pulp_soc/soc_interconnect_wrap_v2.sv +++ b/rtl/pulp_soc/soc_interconnect_wrap_v2.sv @@ -22,6 +22,9 @@ //----------------------------------------------------------------------------- `include "soc_mem_map.svh" +`include "tcdm_macros.svh" +`include "axi/assign.svh" + module soc_interconnect_wrap import pkg_soc_interconnect::addr_map_rule_t; @@ -33,17 +36,15 @@ module soc_interconnect_wrap localparam int AXI_IN_DATA_WIDTH = 64, // The internal AXI->TCDM protocol converter does not support any other // datawidths than 64-bit parameter int AXI_IN_ID_WIDTH = 6, - parameter int AXI_IN_USER_WIDTH = 6, + parameter int AXI_USER_WIDTH = 6, // Axi Output Plug localparam int AXI_OUT_ADDR_WIDTH = 32, // All addresses in the SoC must be 32-bit - localparam int AXI_OUT_DATA_WIDTH = 32, // The internal TCDM->AXI protocol converter does not support any other - // datawidths than 32-bit - parameter int AXI_OUT_ID_WIDTH = 6, - parameter int AXI_OUT_USER_WIDTH = 6 + localparam int AXI_OUT_DATA_WIDTH = 32 // The internal TCDM->AXI protocol converter does not support any other + // datawidths than 32-bit ) ( - logic clk_i, - logic rst_ni, - logic test_en_i, + input logic clk_i, + input logic rst_ni, + input logic test_en_i, XBAR_TCDM_BUS.Slave tcdm_fc_data, //Data Port of the Fabric Controller XBAR_TCDM_BUS.Slave tcdm_fc_instr, //Instruction Port of the Fabric Controller XBAR_TCDM_BUS.Slave tcdm_udma_tx, //TX Channel for the uDMA @@ -66,11 +67,11 @@ module soc_interconnect_wrap ////////////////////////////////////////////////////////////// // 64-bit AXI to TCDM Bridge (Cluster to SoC communication) // ////////////////////////////////////////////////////////////// - TCDM_BUS axi_bridge_2_interconnect[4](); //We need 4 32-bit TCDM ports to achieve fullbandwidth with one 64-bit AXI - //port + XBAR_TCDM_BUS axi_bridge_2_interconnect[4](); //We need 4 32-bit TCDM ports to achieve fullbandwidth with one 64-bit AXI + //port - axi64_2_lint32 #( - .AXI_USER_WIDTH(AXI_IN_USER_WIDTH), + axi64_2_lint32_wrap #( + .AXI_USER_WIDTH(AXI_USER_WIDTH), .AXI_ID_WIDTH(AXI_IN_ID_WIDTH) ) i_axi64_to_lint32( .clk_i, @@ -88,57 +89,89 @@ module soc_interconnect_wrap localparam NR_RULES_L2_DEMUX = 4; //Everything that is not routed to port 1 or 2 ends up in port 0 by default localparam addr_map_rule_t [NR_RULES_L2_DEMUX-1:0] L2_DEMUX_RULES = '{ - '{ idx: 1 , start_addr: SOC_MEM_MAP_PRIVATE_BANK0_START_ADDR , end_addr: SOC_MEM_MAP_PRIVATE_BANK1_END_ADDR} , //Both , bank0 and bank1 are in the same address block - '{ idx: 1 , start_addr: SOC_MEM_MAP_BOOT_ROM_START_ADDR , end_addr: SOC_MEM_MAP_BOOT_ROM_END_ADDR} , - '{ idx: 2 , start_addr: SOC_MEM_MAP_TCDM_START_ADDR , end_addr: SOC_MEM_MAP_TCDM_END_ADDR } , - '{ idx: 2 , start_addr: SOC_MEM_MAP_TCDM_ALIAS_START_ADDR , end_addr: SOC_MEM_MAP_TCDM_ALIAS_END_ADDR}}; + '{ idx: 1 , start_addr: `SOC_MEM_MAP_PRIVATE_BANK0_START_ADDR , end_addr: `SOC_MEM_MAP_PRIVATE_BANK1_END_ADDR} , //Both , bank0 and bank1 are in the same address block + '{ idx: 1 , start_addr: `SOC_MEM_MAP_BOOT_ROM_START_ADDR , end_addr: `SOC_MEM_MAP_BOOT_ROM_END_ADDR} , + '{ idx: 2 , start_addr: `SOC_MEM_MAP_TCDM_START_ADDR , end_addr: `SOC_MEM_MAP_TCDM_END_ADDR } , + '{ idx: 2 , start_addr: `SOC_MEM_MAP_TCDM_ALIAS_START_ADDR , end_addr: `SOC_MEM_MAP_TCDM_ALIAS_END_ADDR}}; localparam NR_RULES_CONTIG_CROSSBAR = 3; localparam addr_map_rule_t [NR_RULES_CONTIG_CROSSBAR-1:0] CONTIGUOUS_CROSSBAR_RULES = '{ - '{ idx: 0 , start_addr: SOC_MEM_MAP_PRIVATE_BANK0_START_ADDR , end_addr: SOC_MEM_MAP_PRIVATE_BANK0_END_ADDR} , - '{ idx: 1 , start_addr: SOC_MEM_MAP_PRIVATE_BANK1_START_ADDR , end_addr: SOC_MEM_MAP_PRIVATE_BANK1_END_ADDR} , - '{ idx: 2 , start_addr: SOC_MEM_MAP_BOOT_ROM_START_ADDR , end_addr: SOC_MEM_MAP_BOOT_ROM_END_ADDR}}; + '{ idx: 0 , start_addr: `SOC_MEM_MAP_PRIVATE_BANK0_START_ADDR , end_addr: `SOC_MEM_MAP_PRIVATE_BANK0_END_ADDR} , + '{ idx: 1 , start_addr: `SOC_MEM_MAP_PRIVATE_BANK1_START_ADDR , end_addr: `SOC_MEM_MAP_PRIVATE_BANK1_END_ADDR} , + '{ idx: 2 , start_addr: `SOC_MEM_MAP_BOOT_ROM_START_ADDR , end_addr: `SOC_MEM_MAP_BOOT_ROM_END_ADDR}}; localparam NR_RULES_AXI_CROSSBAR = 2; localparam addr_map_rule_t [NR_RULES_AXI_CROSSBAR-1:0] AXI_CROSSBAR_RULES = '{ - '{ idx: 0, start_addr: SOC_MEM_MAP_AXI_PLUG_START_ADDR, end_addr: SOC_MEM_MAP_AXI_PLUG_END_ADDR}, - '{ idx: 1, start_addr: SOC_MEM_MAP_PERIPHERALS_START_ADDR, end_addr: SOC_MEM_MAP_PERIPHERALS_END_ADDR}}; + '{ idx: 0, start_addr: `SOC_MEM_MAP_AXI_PLUG_START_ADDR, end_addr: `SOC_MEM_MAP_AXI_PLUG_END_ADDR}, + '{ idx: 1, start_addr: `SOC_MEM_MAP_PERIPHERALS_START_ADDR, end_addr: `SOC_MEM_MAP_PERIPHERALS_END_ADDR}}; ////////////////////////////// // Instantiate Interconnect // ////////////////////////////// + localparam INTERNAL_NR_AXI_XBAR_MASTERS = 5 + 4; //5 for fc_instr, fc_data, udma_rx, udma_tx, debug_access and 4 + //four 64-bit axi plug + localparam AXI_SLAVE_ID_WIDTH = AXI_IN_ID_WIDTH + $clog2(INTERNAL_NR_AXI_XBAR_MASTERS); + //Internal wiring to APB protocol converter AXI_BUS #(.AXI_ADDR_WIDTH(32), .AXI_DATA_WIDTH(32), - .AXI_ID_WIDTH(AXI_OUT_ID_WIDTH), - .AXI_USER_WIDTH(AXI_OUT_USER_WIDTH) + .AXI_ID_WIDTH(AXI_SLAVE_ID_WIDTH), + .AXI_USER_WIDTH(AXI_USER_WIDTH) ) axi_to_axi_lite_bridge(); + //Wiring signals to interconncet. Unfortunately Synopsys-2019.3 does not support assignment patterns in port lists + //directly + XBAR_TCDM_BUS master_ports[5+4](); + `TCDM_MASTER_ASSIGN(master_ports[0], tcdm_fc_data) + `TCDM_MASTER_ASSIGN(master_ports[1], tcdm_fc_instr) + `TCDM_MASTER_ASSIGN(master_ports[2], tcdm_udma_tx) + `TCDM_MASTER_ASSIGN(master_ports[3], tcdm_udma_rx) + `TCDM_MASTER_ASSIGN(master_ports[4], tcdm_debug) + for (genvar i = 0; i < 4; i++) begin + `TCDM_MASTER_ASSIGN(master_ports[5+i], axi_bridge_2_interconnect[i]) + end + + XBAR_TCDM_BUS contiguous_slaves[3](); + `TCDM_MASTER_ASSIGN(l2_private_slaves[0], contiguous_slaves[0]) + `TCDM_MASTER_ASSIGN(l2_private_slaves[1], contiguous_slaves[1]) + `TCDM_MASTER_ASSIGN(boot_rom_slave, contiguous_slaves[2]) + + AXI_BUS #(.AXI_ADDR_WIDTH(32), + .AXI_DATA_WIDTH(32), + .AXI_ID_WIDTH(AXI_SLAVE_ID_WIDTH), + .AXI_USER_WIDTH(AXI_USER_WIDTH) + ) axi_slaves[2](); + `AXI_ASSIGN(axi_slave_plug, axi_slaves[0]) + `AXI_ASSIGN(axi_to_axi_lite_bridge, axi_slaves[1]) + //Interconnect instantiation soc_interconnect #( - .NR_MASTER_PORTS(5), // FC instructions, FC data, uDMA RX, uDMA TX, debug access + .NR_MASTER_PORTS(5+4), // FC instructions, FC data, uDMA RX, uDMA TX, debug access, 4 four 64-bit + // axi plug .NR_MASTER_PORTS_INTERLEAVED_ONLY(NR_HWPE_PORTS), // HWPEs (PULP accelerators) only have access // to the interleaved memory region .NR_ADDR_RULES_L2_DEMUX(NR_RULES_L2_DEMUX), .NR_SLAVE_PORTS_INTERLEAVED(NR_L2_PORTS), // Number of interleaved memory banks - .NR_SLAVE_PORTS_CONTIG(NR_L2_PRIVATE_PORTS), // Number of private memory banks (normally 1 for - // programm instructions and 1 for programm stack ) + .NR_SLAVE_PORTS_CONTIG(3), // Bootrom + number of private memory banks (normally 1 for + // programm instructions and 1 for programm stack ) .NR_ADDR_RULES_SLAVE_PORTS_CONTIG(NR_RULES_CONTIG_CROSSBAR), .NR_AXI_SLAVE_PORTS(2), // 1 for AXI to cluster, 1 for SoC peripherals (converted to APB) - .NR_ADDR_RULES_AXI_SLAVE_PORTS(NR_RULES_AXI_CROSSBAR) + .NR_ADDR_RULES_AXI_SLAVE_PORTS(NR_RULES_AXI_CROSSBAR), + .AXI_MASTER_ID_WIDTH(AXI_IN_ID_WIDTH), + .AXI_USER_WIDTH(AXI_USER_WIDTH) ) i_soc_interconnect ( .clk_i, .rst_ni, .test_en_i, - .master_ports('{tcdm_fc_data, tcdm_fc_instr, tcdm_udma_tx, tcdm_udma_rx, tcdm_debug}), - .slave_ports(tcdm_hwpe), + .master_ports(master_ports), + .master_ports_interleaved_only(tcdm_hwpe), .addr_space_l2_demux(L2_DEMUX_RULES), .interleaved_slaves(l2_interleaved_slaves), .addr_space_contiguous(CONTIGUOUS_CROSSBAR_RULES), - .contiguous_slaves('{l2_private_slaves[0], l2_private_slaves[1], boot_rom_slave}), + .contiguous_slaves(contiguous_slaves), .addr_space_axi(AXI_CROSSBAR_RULES), - .axi_slaves('{axi_slave_plug, axi_to_axi_lite_bridge}) + .axi_slaves(axi_slaves) ); @@ -155,8 +188,8 @@ module soc_interconnect_wrap axi_to_axi_lite_intf #( .AXI_ADDR_WIDTH(32), .AXI_DATA_WIDTH(32), - .AXI_ID_WIDTH(AXI_OUT_ID_WIDTH), - .AXI_USER_WIDTH(AXI_OUT_USER_WIDTH), + .AXI_ID_WIDTH(AXI_SLAVE_ID_WIDTH), + .AXI_USER_WIDTH(AXI_USER_WIDTH), .AXI_MAX_WRITE_TXNS(1), .AXI_MAX_READ_TXNS(1), .FALL_THROUGH(1) @@ -171,8 +204,8 @@ module soc_interconnect_wrap // The AXI-Lite to APB bridge is capable of connecting one AXI to multiple APB ports using address mapping rules. // We do not use this feature and just supply a default rule that matches everything in the peripheral region - localparam addr_map_rule_t APB_BRIDGE_RULES = '{ - '{ idx: 0, start_addr: SOC_MEM_MAP_PERIPHERALS_START_ADDR, end_addr: SOC_MEM_MAP_PERIPHERALS_END_ADDR}}; + localparam addr_map_rule_t [0:0] APB_BRIDGE_RULES = '{ + '{ idx: 0, start_addr: `SOC_MEM_MAP_PERIPHERALS_START_ADDR, end_addr: `SOC_MEM_MAP_PERIPHERALS_END_ADDR}}; axi_lite_to_apb_intf #( .NoApbSlaves(1), @@ -184,16 +217,16 @@ module soc_interconnect_wrap .clk_i, .rst_ni, .slv(axi_lite_to_apb_bridge), - .paddr_o(apb_periph_bus.paddr), + .paddr_o(apb_peripheral_bus.paddr), .pprot_o(), - .pselx_o(apb_periph_bus.psel), - .penable_o(apb_periph_bus.penable), - .pwrite_o(apb_periph_bus.pwrite), - .pwdata_o(apb_periph_bus.pwdata), + .pselx_o(apb_peripheral_bus.psel), + .penable_o(apb_peripheral_bus.penable), + .pwrite_o(apb_peripheral_bus.pwrite), + .pwdata_o(apb_peripheral_bus.pwdata), .pstrb_o(), - .pready_i(apb_periph_bus.pready), - .prdata_i(apb_periph_bus.prdata), - .pslverr_i(apb_periph_bus.pslverr), + .pready_i(apb_peripheral_bus.pready), + .prdata_i(apb_peripheral_bus.prdata), + .pslverr_i(apb_peripheral_bus.pslverr), .addr_map_i(APB_BRIDGE_RULES) ); diff --git a/rtl/pulp_soc/tcdm_demux.sv b/rtl/pulp_soc/tcdm_demux.sv index 7dc61a0f..1c17a5e0 100644 --- a/rtl/pulp_soc/tcdm_demux.sv +++ b/rtl/pulp_soc/tcdm_demux.sv @@ -19,7 +19,7 @@ // CONDITIONS OF ANY KIND, either express or implied. See the License for the // specific language governing permissions and limitations under the License. //----------------------------------------------------------------------------- -`include "tcdm_explode_macros.svh" +`include "tcdm_macros.svh" module tcdm_demux import pkg_soc_interconnect::addr_map_rule_t; @@ -29,12 +29,12 @@ module tcdm_demux localparam int unsigned SLAVE_SEL_WIDTH = $clog2(NR_OUTPUTS) ) ( - input logic clk_i, - input logic rst_ni, - input logic test_en_i, - input addr_map_rule_t addr_map_rules[NR_ADDR_MAP_RULES], - XBAR_TCDM_BUS.Slave master_port, - XBAR_TCDM_BUS.Master slave_ports[NR_OUTPUTS] + input logic clk_i, + input logic rst_ni, + input logic test_en_i, + input addr_map_rule_t[NR_ADDR_MAP_RULES-1:0] addr_map_rules, + XBAR_TCDM_BUS.Slave master_port, + XBAR_TCDM_BUS.Master slave_ports[NR_OUTPUTS] ); // Do **not** change. The TCDM interface uses hardcoded bus widths so we cannot just change them here. localparam int unsigned BE_WIDTH = 2; @@ -42,28 +42,28 @@ module tcdm_demux localparam int unsigned DATA_WIDTH = 32; // Explode the output interfaces to individual signals - `TCDM_EXPLODE_DECLARE_ARRAY(slave_ports, NR_OUTPUTS) + `TCDM_EXPLODE_ARRAY_DECLARE(slave_ports, NR_OUTPUTS) for (genvar i = 0; i < NR_OUTPUTS; i++) begin - `TCDM_SLAVE_EXPLODE(slave_ports, slave_ports) + `TCDM_SLAVE_EXPLODE(slave_ports[i], slave_ports, [i]) end //The Address Decoder module generates the select signal for the demux. If there is no match in the input rules, the //address decoder will select port 0 by default. - logic port_sel; + logic[SLAVE_SEL_WIDTH-1:0] port_sel; addr_decode #( - .NoIndices(NR_SLAVE_PORTS_INTERNAL), - .NoRules(NR_ADDR_RULES), + .NoIndices(NR_OUTPUTS), + .NoRules(NR_ADDR_MAP_RULES), .addr_t(logic[31:0]), .rule_t(pkg_soc_interconnect::addr_map_rule_t) ) i_addr_decode ( - .addr_i(master_ports_add[i]), - .addr_map_i(addr_rules), - .idx_o(port_sel[i]), + .addr_i(master_port.add), + .addr_map_i(addr_map_rules), + .idx_o(port_sel), .dec_valid_o(), .dec_error_o(), .en_default_idx_i(1'b1), - .default_idx_i(0) //If no rule matches we route to the first slave + .default_idx_i('0) //If no rule matches we route to the first slave //port ); @@ -84,13 +84,14 @@ module tcdm_demux end //Broadcast to all slaves. Only the request is actualy demultiplexed - assign slave_ports_add[port_sel] = master_port.add; - assign slave_ports_wen[port_sel] = master_port.wen; - assign slave_ports_wdata[port_sel] = master_port.wdata; - assign slave_ports_be[port_sel] = master_port.be; //Transaction FSM always_comb begin + slave_ports_add[port_sel] = master_port.add; + slave_ports_wen[port_sel] = master_port.wen; + slave_ports_wdata[port_sel] = master_port.wdata; + slave_ports_be[port_sel] = master_port.be; + master_port.r_opc = 1'b0; master_port.r_rdata = '0; master_port.r_valid = 1'b0; @@ -100,15 +101,16 @@ module tcdm_demux active_slave_d = active_slave_q; case (state_q) IDLE: begin - if (master_port_req) begin + if (master_port.req) begin //Issue the request to the right port and change the state slave_ports_req[port_sel] = master_port.req; - master_port.gnt = slave_ports_gnt[port_sel]; active_slave_d = port_sel; //Wait until we receive the grant signal from the slave if (slave_ports_gnt[port_sel]) begin + master_port.gnt = 1'b1; state_d = PENDING; end else begin + master_port.gnt = 1'b0; state_d = IDLE; end end else begin @@ -125,12 +127,13 @@ module tcdm_demux //Check if we receive another request back to back if (master_port.req) begin slave_ports_req[port_sel] = master_port.req; - master_port.gnt = slave_ports_sel[port_sel]; active_slave_d = port_sel; //If we receive the grant we remain in the pending state. Otherwise we switch to IDLE state if (slave_ports_gnt[port_sel]) begin + master_port.gnt = 1'b1; state_d = PENDING; end else begin + master_port.gnt = 1'b0; state_d = IDLE; end end else begin diff --git a/src_files.yml b/src_files.yml index da882304..e318d806 100644 --- a/src_files.yml +++ b/src_files.yml @@ -1,10 +1,13 @@ pulp_soc: incdirs: [ ../../rtl/includes, + rtl/include, + ../axi/axi/include ] files: [ + ../axi/axi/src/axi_pkg.sv, rtl/pulp_soc/pkg_soc_interconnect.sv, - rtl/pulp_soc/axi64_to_lint32_wrap.sv, + rtl/pulp_soc/axi64_2_lint32_wrap.sv, rtl/pulp_soc/lint_2_axi_wrap.sv, rtl/pulp_soc/contiguous_crossbar.sv, rtl/pulp_soc/interleaved_crossbar.sv, From ba3955bd4220f1cbdd748a509492c00891568606 Mon Sep 17 00:00:00 2001 From: Manuel Eggimann Date: Tue, 3 Nov 2020 16:07:50 +0100 Subject: [PATCH 04/30] update ips_list dependencies to common_cells version fix --- ips_list.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ips_list.yml b/ips_list.yml index 540348e9..4c6c6e1c 100644 --- a/ips_list.yml +++ b/ips_list.yml @@ -18,7 +18,7 @@ # work, make sure to checkout a branch. # common_cells: - commit: v1.19.0 + commit: fix-compile-order domain: [cluster, soc] L2_tcdm_hybrid_interco: commit: pulpissimo-v1.0 @@ -48,7 +48,7 @@ apb_interrupt_cntrl: commit: v0.0.1 domain: [soc] axi/axi: - commit: 6765d6d + commit: fix-ipapprox-deps domain: [cluster, soc] # axi/axi_node: # commit: v1.1.4 @@ -63,7 +63,7 @@ timer_unit: commit: v1.0.2 domain: [cluster, soc] fpnew: - commit: v0.6.4 + commit: bump_common_cells domain: [cluster, soc] jtag_pulp: commit: v0.1 From 7fdc5526ab69fcd6a72df24dcacccf9fe1afcd38 Mon Sep 17 00:00:00 2001 From: Manuel Eggimann Date: Tue, 3 Nov 2020 16:08:05 +0100 Subject: [PATCH 05/30] Whitespace cleanup --- rtl/pulp_soc/soc_interconnect_v2.sv | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/rtl/pulp_soc/soc_interconnect_v2.sv b/rtl/pulp_soc/soc_interconnect_v2.sv index 3c214402..341bb379 100644 --- a/rtl/pulp_soc/soc_interconnect_v2.sv +++ b/rtl/pulp_soc/soc_interconnect_v2.sv @@ -27,8 +27,8 @@ module soc_interconnect // TCDM Bus Master Config parameter int unsigned NR_MASTER_PORTS, //Master Ports to the SoC interconnect with access to all memory regions parameter int unsigned NR_MASTER_PORTS_INTERLEAVED_ONLY, //Master ports with access restricted to only the interleaved - //ports (no axes to APB, AXI, or contiguous slaves) TCDM Bus - //Slave Config + //ports (no axes to APB, AXI, or contiguous slaves) TCDM Bus + //Slave Config // L2 Demux Addr rules parameter int unsigned NR_ADDR_RULES_L2_DEMUX, // Interleaved TCDM slave @@ -43,9 +43,9 @@ module soc_interconnect parameter int unsigned NR_AXI_SLAVE_PORTS, parameter int unsigned NR_ADDR_RULES_AXI_SLAVE_PORTS, localparam int unsigned AXI_SLAVE_ID_WIDTH = AXI_MASTER_ID_WIDTH + $clog2(NR_MASTER_PORTS), //The actual ID - //width of the AXI slaves is clog2(NR_AXI_MASTERS) larger than the master id width since the - //axi_mux in the XBAR will append an identificatoin tag to the outgoing transactions - //towards the axi slaves so it can backroute the responses + //width of the AXI slaves is clog2(NR_AXI_MASTERS) larger than the master id width since the + //axi_mux in the XBAR will append an identificatoin tag to the outgoing transactions + //towards the axi slaves so it can backroute the responses parameter int unsigned AXI_USER_WIDTH ) ( @@ -69,8 +69,8 @@ module soc_interconnect // Internal Parameters // Do **NOT** change - localparam int BUS_DATA_WIDTH = 32; - localparam int BUS_ADDR_WIDTH = 32; + localparam int unsigned BUS_DATA_WIDTH = 32; + localparam int unsigned BUS_ADDR_WIDTH = 32; // Internal Wiring Signals XBAR_TCDM_BUS l2_demux_2_interleaved_xbar[NR_MASTER_PORTS](); From ee2f5afccca00d9a30faca946c183db5713a9abc Mon Sep 17 00:00:00 2001 From: Manuel Eggimann Date: Tue, 3 Nov 2020 16:10:33 +0100 Subject: [PATCH 06/30] Fix wrong fpnew version tag --- ips_list.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ips_list.yml b/ips_list.yml index 4c6c6e1c..440b65b6 100644 --- a/ips_list.yml +++ b/ips_list.yml @@ -63,7 +63,7 @@ timer_unit: commit: v1.0.2 domain: [cluster, soc] fpnew: - commit: bump_common_cells + commit: bump-common-cells domain: [cluster, soc] jtag_pulp: commit: v0.1 From 6c4375aa27ca37269a72c27ab223803aae1006e9 Mon Sep 17 00:00:00 2001 From: Manuel Eggimann Date: Tue, 3 Nov 2020 18:17:06 +0100 Subject: [PATCH 07/30] Remove duplicate interface that is colliding with the axi repo --- rtl/components/pulp_interfaces.sv | 93 ------------------------------- 1 file changed, 93 deletions(-) diff --git a/rtl/components/pulp_interfaces.sv b/rtl/components/pulp_interfaces.sv index 58eba6a1..22a7e50f 100644 --- a/rtl/components/pulp_interfaces.sv +++ b/rtl/components/pulp_interfaces.sv @@ -585,99 +585,6 @@ interface AXI_BUS_ASYNC2 ); -endinterface - -interface AXI_LITE - #( - parameter AXI_ADDR_WIDTH = 32, - parameter AXI_DATA_WIDTH = 64, - parameter AXI_ID_WIDTH = 6, - parameter AXI_USER_WIDTH = 6 - ); - - localparam AXI_STRB_WIDTH = `EVAL_BE_WIDTH(AXI_DATA_WIDTH); - - logic [AXI_ADDR_WIDTH-1:0] aw_addr; - logic aw_valid; - logic aw_ready; - - logic [AXI_DATA_WIDTH-1:0] w_data; - logic w_valid; - logic w_ready; - logic [AXI_STRB_WIDTH-1:0] w_strb; - - logic [1:0] b_resp; - logic b_valid; - logic b_ready; - - logic [AXI_ADDR_WIDTH-1:0] ar_addr; - logic ar_valid; - logic ar_ready; - - logic [AXI_DATA_WIDTH-1:0] r_data; - logic [1:0] r_resp; - logic r_valid; - logic r_ready; - - - // Master Side - //*************************************** - modport Master - ( - - output aw_addr, - output aw_valid, - input aw_ready, - - output w_data, - output w_valid, - input w_ready, - output w_strb, - - input b_resp, - input b_valid, - output b_ready, - - output ar_addr, - output ar_valid, - input ar_ready, - - input r_data, - input r_resp, - input r_valid, - output r_ready - - ); - - // Slave Side - //*************************************** - modport Slave - ( - - input aw_addr, - input aw_valid, - output aw_ready, - - input w_data, - input w_valid, - output w_ready, - input w_strb, - - output b_resp, - output b_valid, - input b_ready, - - input ar_addr, - input ar_valid, - output ar_ready, - - output r_data, - output r_resp, - output r_valid, - input r_ready - - ); - endinterface //******************************************************** From 9414e43cf7ea0053898ebd1905e1782c5824fadb Mon Sep 17 00:00:00 2001 From: Manuel Eggimann Date: Tue, 3 Nov 2020 18:18:01 +0100 Subject: [PATCH 08/30] Fix fpga related bugs --- rtl/pulp_soc/l2_ram_multi_bank.sv | 4 ++-- rtl/pulp_soc/soc_interconnect_v2.sv | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/rtl/pulp_soc/l2_ram_multi_bank.sv b/rtl/pulp_soc/l2_ram_multi_bank.sv index 54045c8e..48259a49 100644 --- a/rtl/pulp_soc/l2_ram_multi_bank.sv +++ b/rtl/pulp_soc/l2_ram_multi_bank.sv @@ -112,7 +112,7 @@ module l2_ram_multi_bank #( .Q ( mem_pri_slave[0].r_rdata ) ); `else // !`ifndef PULP_FPGA_EMUL - fpga_private_ram #(.ADDR_WIDTH(MEM_ADDR_WIDTH_PRI)) bank_sram_pri0_i + fpga_private_ram #(.ADDR_WIDTH(PRI0_MEM_ADDR_WIDTH)) bank_sram_pri0_i ( .clk_i, .rst_ni, @@ -154,7 +154,7 @@ module l2_ram_multi_bank #( .Q ( mem_pri_slave[1].r_rdata ) ); `else // !`ifndef PULP_FPGA_EMUL - fpga_private_ram #(.ADDR_WIDTH(MEM_ADDR_WIDTH_PRI)) bank_sram_pri1_i + fpga_private_ram #(.ADDR_WIDTH(PRI1_MEM_ADDR_WIDTH)) bank_sram_pri1_i ( .clk_i, .rst_ni, diff --git a/rtl/pulp_soc/soc_interconnect_v2.sv b/rtl/pulp_soc/soc_interconnect_v2.sv index 341bb379..edbaf7df 100644 --- a/rtl/pulp_soc/soc_interconnect_v2.sv +++ b/rtl/pulp_soc/soc_interconnect_v2.sv @@ -177,6 +177,7 @@ module soc_interconnect assign error_valid_d = error_slave.req; assign error_slave.r_opc = error_slave.req; assign error_slave.r_rdata = 32'hBADACCE5; + assign error_slave.r_valid = error_valid_q; always_ff @(posedge clk_i, negedge rst_ni) begin if (!rst_ni) begin From cf094fea1c43bed0dcaacc3aaeabb36f225d2eb2 Mon Sep 17 00:00:00 2001 From: Manuel Eggimann Date: Wed, 4 Nov 2020 12:56:27 +0100 Subject: [PATCH 09/30] Workaround apb_gpio pad cfg bits inconsistency --- ips_list.yml | 2 +- rtl/pulp_soc/pulp_soc.sv | 2 +- rtl/pulp_soc/soc_peripherals.sv | 9 ++------- 3 files changed, 4 insertions(+), 9 deletions(-) diff --git a/ips_list.yml b/ips_list.yml index 440b65b6..e4db6926 100644 --- a/ips_list.yml +++ b/ips_list.yml @@ -39,7 +39,7 @@ apb/apb_fll_if: commit: pulpissimo-v1.0 domain: [soc] apb/apb_gpio: - commit: v0.2.0 + commit: 0e9f142 domain: [soc] apb/apb_node: commit: v0.1.1 diff --git a/rtl/pulp_soc/pulp_soc.sv b/rtl/pulp_soc/pulp_soc.sv index 18350b79..933a75a6 100644 --- a/rtl/pulp_soc/pulp_soc.sv +++ b/rtl/pulp_soc/pulp_soc.sv @@ -34,7 +34,7 @@ module pulp_soc import dm::*; #( parameter NGPIO = 43, parameter NPAD = 64, //Must not be changed as other parts //downstreams are not parametrci - parameter NBIT_PADCFG = 4, //Must not be changed as other parts + parameter NBIT_PADCFG = 6, //Must not be changed as other parts //downstreams are not parametrci parameter NBIT_PADMUX = 2, diff --git a/rtl/pulp_soc/soc_peripherals.sv b/rtl/pulp_soc/soc_peripherals.sv index 80a5644d..49c495b7 100644 --- a/rtl/pulp_soc/soc_peripherals.sv +++ b/rtl/pulp_soc/soc_peripherals.sv @@ -338,15 +338,10 @@ module soc_peripherals #( // ╚═╝ ╚═╝╚═╝ ╚═════╝ ╚═════╝ ╚═╝ ╚═╝ ╚═════╝ // /////////////////////////////////////////////////////////////// - if (NBIT_PADCFG != 4) - $error("apb_gpio doesn't support a NBIT_PADCFG bitwidth other than 4"); - - if (NBIT_PADMUX != 2) - $error("apb_gpio doesn't support a NBIT_PADMUX bitwidth other than 2"); - apb_gpio #( .APB_ADDR_WIDTH (APB_ADDR_WIDTH), - .PAD_NUM (NGPIO) + .PAD_NUM (NGPIO), + .NBIT_PADCFG (NBIT_PADCFG) ) i_apb_gpio ( .HCLK ( clk_i ), .HRESETn ( rst_ni ), From 2a3ab70e1e4508a3d65802281219fea404be0f01 Mon Sep 17 00:00:00 2001 From: Manuel Eggimann Date: Wed, 4 Nov 2020 12:56:55 +0100 Subject: [PATCH 10/30] Fix issues with unsupported lang constructs in Synopsys --- rtl/pulp_soc/pulp_soc.sv | 7 ++++--- rtl/pulp_soc/soc_interconnect_v2.sv | 26 ++++++++++++++++++++------ rtl/pulp_soc/tcdm_demux.sv | 19 ++++++++++++------- 3 files changed, 36 insertions(+), 16 deletions(-) diff --git a/rtl/pulp_soc/pulp_soc.sv b/rtl/pulp_soc/pulp_soc.sv index 933a75a6..4040131c 100644 --- a/rtl/pulp_soc/pulp_soc.sv +++ b/rtl/pulp_soc/pulp_soc.sv @@ -21,9 +21,10 @@ module pulp_soc import dm::*; #( parameter AXI_DATA_IN_WIDTH = 64, parameter AXI_DATA_OUT_WIDTH = 32, parameter AXI_ID_IN_WIDTH = 6, - localparam AXI_ID_OUT_WIDTH = AXI_ID_IN_WIDTH+$clog2(2), //Account for additional bits needed by AXI_XBAR to - //backroute responses. At the moment we have 3 xbar - //slaves (SoC2Cluster plug and APB peripherals plug) + localparam AXI_ID_OUT_WIDTH = AXI_ID_IN_WIDTH+$clog2(5+4), //Account for additional bits needed by AXI_XBAR to + //backroute responses. At the moment we have 9 masters 5 for fc_data, fc_instr, udma_rx, + //udma_tx, debug_access and 4 for the 64-bit + //cluster2soc axi plug parameter AXI_USER_WIDTH = 6, parameter AXI_STRB_WIDTH_IN = AXI_DATA_IN_WIDTH/8, parameter AXI_STRB_WIDTH_OUT = AXI_DATA_OUT_WIDTH/8, diff --git a/rtl/pulp_soc/soc_interconnect_v2.sv b/rtl/pulp_soc/soc_interconnect_v2.sv index edbaf7df..44c0c6e2 100644 --- a/rtl/pulp_soc/soc_interconnect_v2.sv +++ b/rtl/pulp_soc/soc_interconnect_v2.sv @@ -86,11 +86,11 @@ module soc_interconnect /////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + XBAR_TCDM_BUS demux_slaves[NR_MASTER_PORTS][3](); for (genvar i = 0; i < NR_MASTER_PORTS; i++) begin : gen_l2_demux - XBAR_TCDM_BUS demux_slaves[3](); - `TCDM_MASTER_ASSIGN(l2_demux_2_axi_bridge[i], demux_slaves[0]); - `TCDM_MASTER_ASSIGN(l2_demux_2_contiguous_xbar[i], demux_slaves[1]); - `TCDM_MASTER_ASSIGN(l2_demux_2_interleaved_xbar[i], demux_slaves[2]); + `TCDM_MASTER_ASSIGN(l2_demux_2_axi_bridge[i], demux_slaves[i][0]); + `TCDM_MASTER_ASSIGN(l2_demux_2_contiguous_xbar[i], demux_slaves[i][1]); + `TCDM_MASTER_ASSIGN(l2_demux_2_interleaved_xbar[i], demux_slaves[i][2]); tcdm_demux #( @@ -102,7 +102,7 @@ module soc_interconnect .test_en_i, .addr_map_rules(addr_space_l2_demux), .master_port(master_ports[i]), - .slave_ports(demux_slaves) + .slave_ports(demux_slaves[i]) ); end @@ -126,8 +126,22 @@ module soc_interconnect `TCDM_MASTER_ASSIGN(interleaved_masters[i], l2_demux_2_interleaved_xbar[i]) end + + //Synopsys is to stupid to handle expressions for array indices on the left-hand side of assignments. This is a + // verbose workaround for it. + for (genvar i = NR_MASTER_PORTS; i < NR_MASTER_PORTS_INTERLEAVED_ONLY+NR_MASTER_PORTS; i++) begin + // `TCDM_MASTER_ASSIGN(interleaved_masters[NR_MASTER_PORTS+i], master_ports_interleaved_only[i]) + assign interleaved_masters[i].req = master_ports_interleaved_only[i-NR_MASTER_PORTS].req; + assign interleaved_masters[i].add = master_ports_interleaved_only[i-NR_MASTER_PORTS].add; + assign interleaved_masters[i].wen = master_ports_interleaved_only[i-NR_MASTER_PORTS].wen; + assign interleaved_masters[i].wdata = master_ports_interleaved_only[i-NR_MASTER_PORTS].wdata; + assign interleaved_masters[i].be = master_ports_interleaved_only[i-NR_MASTER_PORTS].be; + end // for (genvar i = NR_MASTER_PORTS; i < NR_MASTER_PORTS_INTERLEAVED_ONLY+NR_MASTER_PORTS; i++) for (genvar i = 0; i < NR_MASTER_PORTS_INTERLEAVED_ONLY; i++) begin - `TCDM_MASTER_ASSIGN(interleaved_masters[NR_MASTER_PORTS+i], master_ports_interleaved_only[i]) + assign master_ports_interleaved_only[i].gnt = interleaved_masters[NR_MASTER_PORTS+i].gnt ; + assign master_ports_interleaved_only[i].r_opc = interleaved_masters[NR_MASTER_PORTS+i].r_opc ; + assign master_ports_interleaved_only[i].r_rdata= interleaved_masters[NR_MASTER_PORTS+i].r_rdata ; + assign master_ports_interleaved_only[i].r_valid = interleaved_masters[NR_MASTER_PORTS+i].r_valid ; end interleaved_crossbar #( diff --git a/rtl/pulp_soc/tcdm_demux.sv b/rtl/pulp_soc/tcdm_demux.sv index 1c17a5e0..82f19d65 100644 --- a/rtl/pulp_soc/tcdm_demux.sv +++ b/rtl/pulp_soc/tcdm_demux.sv @@ -87,18 +87,23 @@ module tcdm_demux //Transaction FSM always_comb begin + slave_ports_add = '0; + slave_ports_wen = '1; + slave_ports_wdata = '0; + slave_ports_be = '0; + slave_ports_add[port_sel] = master_port.add; slave_ports_wen[port_sel] = master_port.wen; slave_ports_wdata[port_sel] = master_port.wdata; slave_ports_be[port_sel] = master_port.be; - master_port.r_opc = 1'b0; - master_port.r_rdata = '0; - master_port.r_valid = 1'b0; - master_port.gnt = 1'b0; - slave_ports_req = '0; - state_d = state_q; - active_slave_d = active_slave_q; + master_port.r_opc = 1'b0; + master_port.r_rdata = '0; + master_port.r_valid = 1'b0; + master_port.gnt = 1'b0; + slave_ports_req = '0; + state_d = state_q; + active_slave_d = active_slave_q; case (state_q) IDLE: begin if (master_port.req) begin From 19fa2e56eadff7598a4c91938f262d54c9fc6f27 Mon Sep 17 00:00:00 2001 From: Manuel Eggimann Date: Wed, 4 Nov 2020 14:01:11 +0100 Subject: [PATCH 11/30] Fix wrong linkage with axi_pkg --- rtl/pulp_soc/soc_interconnect_v2.sv | 14 ++++++++------ src_files.yml | 2 +- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/rtl/pulp_soc/soc_interconnect_v2.sv b/rtl/pulp_soc/soc_interconnect_v2.sv index 44c0c6e2..e202d9ae 100644 --- a/rtl/pulp_soc/soc_interconnect_v2.sv +++ b/rtl/pulp_soc/soc_interconnect_v2.sv @@ -23,6 +23,7 @@ module soc_interconnect import pkg_soc_interconnect::addr_map_rule_t; + import axi_pkg::xbar_cfg_t; #( // TCDM Bus Master Config parameter int unsigned NR_MASTER_PORTS, //Master Ports to the SoC interconnect with access to all memory regions @@ -86,11 +87,12 @@ module soc_interconnect /////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - XBAR_TCDM_BUS demux_slaves[NR_MASTER_PORTS][3](); for (genvar i = 0; i < NR_MASTER_PORTS; i++) begin : gen_l2_demux - `TCDM_MASTER_ASSIGN(l2_demux_2_axi_bridge[i], demux_slaves[i][0]); - `TCDM_MASTER_ASSIGN(l2_demux_2_contiguous_xbar[i], demux_slaves[i][1]); - `TCDM_MASTER_ASSIGN(l2_demux_2_interleaved_xbar[i], demux_slaves[i][2]); + XBAR_TCDM_BUS demux_slaves[3](); + + `TCDM_MASTER_ASSIGN(l2_demux_2_axi_bridge[i], demux_slaves[0]); + `TCDM_MASTER_ASSIGN(l2_demux_2_contiguous_xbar[i], demux_slaves[1]); + `TCDM_MASTER_ASSIGN(l2_demux_2_interleaved_xbar[i], demux_slaves[2]); tcdm_demux #( @@ -102,7 +104,7 @@ module soc_interconnect .test_en_i, .addr_map_rules(addr_space_l2_demux), .master_port(master_ports[i]), - .slave_ports(demux_slaves[i]) + .slave_ports(demux_slaves) ); end @@ -235,7 +237,7 @@ module soc_interconnect // information. // //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - localparam axi_pkg::xbar_cfg_t AXI_XBAR_CFG = '{ + localparam xbar_cfg_t AXI_XBAR_CFG = '{ NoSlvPorts: NR_MASTER_PORTS, NoMstPorts: NR_AXI_SLAVE_PORTS, MaxMstTrans: 1, //The TCDM ports do not support diff --git a/src_files.yml b/src_files.yml index e318d806..4b6b7bb2 100644 --- a/src_files.yml +++ b/src_files.yml @@ -5,7 +5,6 @@ pulp_soc: ../axi/axi/include ] files: [ - ../axi/axi/src/axi_pkg.sv, rtl/pulp_soc/pkg_soc_interconnect.sv, rtl/pulp_soc/axi64_2_lint32_wrap.sv, rtl/pulp_soc/lint_2_axi_wrap.sv, @@ -27,6 +26,7 @@ pulp_soc: ] vlog_opts : [ -L riscv_dbg_lib, + -L axi_lib ] udma_subsystem: incdirs: [ From 2ba0446f3fe379d4ac62bb80d2fc418d241fed14 Mon Sep 17 00:00:00 2001 From: Manuel Eggimann Date: Wed, 4 Nov 2020 17:58:00 +0100 Subject: [PATCH 12/30] Cut combinatorial loop between APB converter and L2 demux --- rtl/pulp_soc/soc_interconnect_v2.sv | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rtl/pulp_soc/soc_interconnect_v2.sv b/rtl/pulp_soc/soc_interconnect_v2.sv index e202d9ae..f7be3ca3 100644 --- a/rtl/pulp_soc/soc_interconnect_v2.sv +++ b/rtl/pulp_soc/soc_interconnect_v2.sv @@ -244,8 +244,8 @@ module soc_interconnect //outstanding transactiions anyways MaxSlvTrans: 4, //Allow up to 4 in-flight transactions //per slave port - FallThrough: 0, //Use the reccomended default config - LatencyMode: axi_pkg::CUT_ALL_AX, + FallThrough: 1, //Use the reccomended default config + LatencyMode: axi_pkg::CUT_MST_PORTS, AxiIdWidthSlvPorts: AXI_MASTER_ID_WIDTH, AxiIdUsedSlvPorts: AXI_MASTER_ID_WIDTH, AxiAddrWidth: BUS_ADDR_WIDTH, From 5ec232d0dee53ed325f9e9e1579973a8aa3c207b Mon Sep 17 00:00:00 2001 From: Manuel Eggimann Date: Wed, 4 Nov 2020 17:59:03 +0100 Subject: [PATCH 13/30] Add preprocessor guard to frequency meters in soc_clk_rst_gen --- rtl/pulp_soc/soc_clk_rst_gen.sv | 2 ++ 1 file changed, 2 insertions(+) diff --git a/rtl/pulp_soc/soc_clk_rst_gen.sv b/rtl/pulp_soc/soc_clk_rst_gen.sv index 7692f305..c7d10c0e 100644 --- a/rtl/pulp_soc/soc_clk_rst_gen.sv +++ b/rtl/pulp_soc/soc_clk_rst_gen.sv @@ -64,9 +64,11 @@ module soc_clk_rst_gen ( logic s_rstn_cluster_sync; //synopsys translate_off + `ifndef SYNTHESIS freq_meter #(.FLL_NAME("SOC_FLL"), .MAX_SAMPLE(4096)) SOC_METER (.clk(s_clk_fll_soc)); freq_meter #(.FLL_NAME("PER_FLL"), .MAX_SAMPLE(4096)) PER_METER (.clk(s_clk_fll_per)); freq_meter #(.FLL_NAME("CLUSTER_FLL"), .MAX_SAMPLE(4096)) CLUSTER_METER (.clk(s_clk_fll_cluster)); + `endif //synopsys translate_on // currently, FLLs are not supported for FPGA emulation From 070e202452c8a4d20f6c6a32ce2e028378fc7bcd Mon Sep 17 00:00:00 2001 From: Manuel Eggimann Date: Wed, 4 Nov 2020 19:18:29 +0100 Subject: [PATCH 14/30] Fix synthesis related issues --- rtl/include/tcdm_macros.svh | 13 +++++++- rtl/pulp_soc/contiguous_crossbar.sv | 5 ++-- rtl/pulp_soc/soc_interconnect_v2.sv | 38 +++++++++++------------- rtl/pulp_soc/soc_interconnect_wrap_v2.sv | 18 +++++------ 4 files changed, 41 insertions(+), 33 deletions(-) diff --git a/rtl/include/tcdm_macros.svh b/rtl/include/tcdm_macros.svh index 6af73986..70a79835 100644 --- a/rtl/include/tcdm_macros.svh +++ b/rtl/include/tcdm_macros.svh @@ -48,7 +48,7 @@ assign iface.r_opc = exploded_prefix``_r_opc postfix; \ assign iface.r_rdata = exploded_prefix``_r_rdata postfix; \ assign iface.r_valid = exploded_prefix``_r_valid postfix; - `define TCDM_MASTER_ASSIGN(b, a) \ + `define TCDM_ASSIGN_INTF(b, a) \ assign b.req = a.req; \ assign b.add = a.add; \ assign b.wen = a.wen; \ @@ -59,4 +59,15 @@ assign a.r_opc = b.r_opc ; \ assign a.r_rdata= b.r_rdata ; \ assign a.r_valid = b.r_valid ; + `define TCDM_ASSIGN(b, postfix_b, a, postfix_a) \ +assign b``_req postfix_b = a``_req postfix_a; \ +assign b``_add postfix_b = a``_add postfix_a; \ +assign b``_wen postfix_b = a``_wen postfix_a; \ +assign b``_wdata postfix_b = a``_wdata postfix_a; \ +assign b``_be postfix_b = a``_be postfix_a; \ +assign a``_gnt postfix_a = b``_gnt postfix_b ; \ +assign a``_r_opc postfix_a = b``_r_opc postfix_b ; \ +assign a``_r_rdata postfix_a= b``_r_rdata postfix_b ; \ +assign a``_r_valid postfix_a = b``_r_valid postfix_b ; + `endif diff --git a/rtl/pulp_soc/contiguous_crossbar.sv b/rtl/pulp_soc/contiguous_crossbar.sv index 170e76bd..734987d6 100644 --- a/rtl/pulp_soc/contiguous_crossbar.sv +++ b/rtl/pulp_soc/contiguous_crossbar.sv @@ -91,6 +91,8 @@ module contiguous_crossbar //Address Decoder logic [NR_MASTER_PORTS-1:0] [PORT_SEL_WIDTH-1:0] port_sel; + localparam logic [PORT_SEL_WIDTH-1:0] DEFAULT_IDX = NR_SLAVE_PORTS_INTERNAL - 1; //If no rule matches we route to the + //error port for (genvar i = 0; i < NR_MASTER_PORTS; i++) begin : gen_addr_decoders addr_decode #( .NoIndices(NR_SLAVE_PORTS_INTERNAL), @@ -104,8 +106,7 @@ module contiguous_crossbar .dec_valid_o(), .dec_error_o(), .en_default_idx_i(1'b1), - .default_idx_i(NR_SLAVE_PORTS_INTERNAL-1) //If no rule matches we route to the - //error port + .default_idx_i(DEFAULT_IDX) ); end diff --git a/rtl/pulp_soc/soc_interconnect_v2.sv b/rtl/pulp_soc/soc_interconnect_v2.sv index f7be3ca3..fa17d6a0 100644 --- a/rtl/pulp_soc/soc_interconnect_v2.sv +++ b/rtl/pulp_soc/soc_interconnect_v2.sv @@ -90,9 +90,9 @@ module soc_interconnect for (genvar i = 0; i < NR_MASTER_PORTS; i++) begin : gen_l2_demux XBAR_TCDM_BUS demux_slaves[3](); - `TCDM_MASTER_ASSIGN(l2_demux_2_axi_bridge[i], demux_slaves[0]); - `TCDM_MASTER_ASSIGN(l2_demux_2_contiguous_xbar[i], demux_slaves[1]); - `TCDM_MASTER_ASSIGN(l2_demux_2_interleaved_xbar[i], demux_slaves[2]); + `TCDM_ASSIGN_INTF(l2_demux_2_axi_bridge[i], demux_slaves[0]); + `TCDM_ASSIGN_INTF(l2_demux_2_contiguous_xbar[i], demux_slaves[1]); + `TCDM_ASSIGN_INTF(l2_demux_2_interleaved_xbar[i], demux_slaves[2]); tcdm_demux #( @@ -124,26 +124,22 @@ module soc_interconnect //Concatenate the l2 demux master port array and the interleaved only port array XBAR_TCDM_BUS interleaved_masters[NR_MASTER_PORTS+NR_MASTER_PORTS_INTERLEAVED_ONLY](); - for (genvar i = 0; i < NR_MASTER_PORTS; i++) begin - `TCDM_MASTER_ASSIGN(interleaved_masters[i], l2_demux_2_interleaved_xbar[i]) - end - - //Synopsys is to stupid to handle expressions for array indices on the left-hand side of assignments. This is a - // verbose workaround for it. - for (genvar i = NR_MASTER_PORTS; i < NR_MASTER_PORTS_INTERLEAVED_ONLY+NR_MASTER_PORTS; i++) begin - // `TCDM_MASTER_ASSIGN(interleaved_masters[NR_MASTER_PORTS+i], master_ports_interleaved_only[i]) - assign interleaved_masters[i].req = master_ports_interleaved_only[i-NR_MASTER_PORTS].req; - assign interleaved_masters[i].add = master_ports_interleaved_only[i-NR_MASTER_PORTS].add; - assign interleaved_masters[i].wen = master_ports_interleaved_only[i-NR_MASTER_PORTS].wen; - assign interleaved_masters[i].wdata = master_ports_interleaved_only[i-NR_MASTER_PORTS].wdata; - assign interleaved_masters[i].be = master_ports_interleaved_only[i-NR_MASTER_PORTS].be; - end // for (genvar i = NR_MASTER_PORTS; i < NR_MASTER_PORTS_INTERLEAVED_ONLY+NR_MASTER_PORTS; i++) + // verbose workaround for it. The next couple of ugly macro magic unpacks each interface into individual signal arrays, + // performs the assignments to the interface and packs the signal back to an array of interfaces. + `TCDM_EXPLODE_ARRAY_DECLARE(interleaved_masters, NR_MASTER_PORTS+NR_MASTER_PORTS_INTERLEAVED_ONLY) + for (genvar i = 0; i < NR_MASTER_PORTS + NR_MASTER_PORTS_INTERLEAVED_ONLY; i++) begin + `TCDM_SLAVE_EXPLODE(interleaved_masters[i], interleaved_masters, [i]) + end + `TCDM_EXPLODE_ARRAY_DECLARE(l2_demux_2_interleaved_xbar, NR_MASTER_PORTS) + for (genvar i = 0; i < NR_MASTER_PORTS; i++) begin + `TCDM_MASTER_EXPLODE(l2_demux_2_interleaved_xbar[i], l2_demux_2_interleaved_xbar, [i]) + `TCDM_ASSIGN(interleaved_masters, [i], l2_demux_2_interleaved_xbar, [i]) + end + `TCDM_EXPLODE_ARRAY_DECLARE(master_ports_interleaved_only, NR_MASTER_PORTS_INTERLEAVED_ONLY) for (genvar i = 0; i < NR_MASTER_PORTS_INTERLEAVED_ONLY; i++) begin - assign master_ports_interleaved_only[i].gnt = interleaved_masters[NR_MASTER_PORTS+i].gnt ; - assign master_ports_interleaved_only[i].r_opc = interleaved_masters[NR_MASTER_PORTS+i].r_opc ; - assign master_ports_interleaved_only[i].r_rdata= interleaved_masters[NR_MASTER_PORTS+i].r_rdata ; - assign master_ports_interleaved_only[i].r_valid = interleaved_masters[NR_MASTER_PORTS+i].r_valid ; + `TCDM_MASTER_EXPLODE(master_ports_interleaved_only[i], master_ports_interleaved_only, [i]) + `TCDM_ASSIGN(interleaved_masters, [NR_MASTER_PORTS + i], master_ports_interleaved_only, [i]) end interleaved_crossbar #( diff --git a/rtl/pulp_soc/soc_interconnect_wrap_v2.sv b/rtl/pulp_soc/soc_interconnect_wrap_v2.sv index 66fed6e7..4adffe1f 100644 --- a/rtl/pulp_soc/soc_interconnect_wrap_v2.sv +++ b/rtl/pulp_soc/soc_interconnect_wrap_v2.sv @@ -123,19 +123,19 @@ module soc_interconnect_wrap //Wiring signals to interconncet. Unfortunately Synopsys-2019.3 does not support assignment patterns in port lists //directly XBAR_TCDM_BUS master_ports[5+4](); - `TCDM_MASTER_ASSIGN(master_ports[0], tcdm_fc_data) - `TCDM_MASTER_ASSIGN(master_ports[1], tcdm_fc_instr) - `TCDM_MASTER_ASSIGN(master_ports[2], tcdm_udma_tx) - `TCDM_MASTER_ASSIGN(master_ports[3], tcdm_udma_rx) - `TCDM_MASTER_ASSIGN(master_ports[4], tcdm_debug) + `TCDM_ASSIGN_INTF(master_ports[0], tcdm_fc_data) + `TCDM_ASSIGN_INTF(master_ports[1], tcdm_fc_instr) + `TCDM_ASSIGN_INTF(master_ports[2], tcdm_udma_tx) + `TCDM_ASSIGN_INTF(master_ports[3], tcdm_udma_rx) + `TCDM_ASSIGN_INTF(master_ports[4], tcdm_debug) for (genvar i = 0; i < 4; i++) begin - `TCDM_MASTER_ASSIGN(master_ports[5+i], axi_bridge_2_interconnect[i]) + `TCDM_ASSIGN_INTF(master_ports[5+i], axi_bridge_2_interconnect[i]) end XBAR_TCDM_BUS contiguous_slaves[3](); - `TCDM_MASTER_ASSIGN(l2_private_slaves[0], contiguous_slaves[0]) - `TCDM_MASTER_ASSIGN(l2_private_slaves[1], contiguous_slaves[1]) - `TCDM_MASTER_ASSIGN(boot_rom_slave, contiguous_slaves[2]) + `TCDM_ASSIGN_INTF(l2_private_slaves[0], contiguous_slaves[0]) + `TCDM_ASSIGN_INTF(l2_private_slaves[1], contiguous_slaves[1]) + `TCDM_ASSIGN_INTF(boot_rom_slave, contiguous_slaves[2]) AXI_BUS #(.AXI_ADDR_WIDTH(32), .AXI_DATA_WIDTH(32), From 0e3e79ee51bf87c0ce5274ea03040b1954593e07 Mon Sep 17 00:00:00 2001 From: Manuel Eggimann Date: Wed, 4 Nov 2020 19:19:14 +0100 Subject: [PATCH 15/30] Bump AXI ip version --- ips_list.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ips_list.yml b/ips_list.yml index e4db6926..38aedd2b 100644 --- a/ips_list.yml +++ b/ips_list.yml @@ -48,7 +48,7 @@ apb_interrupt_cntrl: commit: v0.0.1 domain: [soc] axi/axi: - commit: fix-ipapprox-deps + commit: v0.24.1 domain: [cluster, soc] # axi/axi_node: # commit: v1.1.4 From 18e8cc0f19730293b977dd1591114e4d66826f1d Mon Sep 17 00:00:00 2001 From: Manuel Eggimann Date: Wed, 4 Nov 2020 19:20:57 +0100 Subject: [PATCH 16/30] Bump common_cells version --- ips_list.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ips_list.yml b/ips_list.yml index 38aedd2b..6ebde0a6 100644 --- a/ips_list.yml +++ b/ips_list.yml @@ -18,7 +18,7 @@ # work, make sure to checkout a branch. # common_cells: - commit: fix-compile-order + commit: v1.20.0 domain: [cluster, soc] L2_tcdm_hybrid_interco: commit: pulpissimo-v1.0 From 168d34897dff3a798df6250602f7ff66dcfba4bb Mon Sep 17 00:00:00 2001 From: Manuel Eggimann Date: Wed, 4 Nov 2020 19:44:13 +0100 Subject: [PATCH 17/30] Remove old interconnect and rename the new one --- rtl/pulp_soc/soc_interconnect.sv | 1168 +++++----------------- rtl/pulp_soc/soc_interconnect_v2.sv | 288 ------ rtl/pulp_soc/soc_interconnect_wrap.sv | 562 +++++------ rtl/pulp_soc/soc_interconnect_wrap_v2.sv | 234 ----- src_files.yml | 4 +- 5 files changed, 494 insertions(+), 1762 deletions(-) delete mode 100644 rtl/pulp_soc/soc_interconnect_v2.sv delete mode 100644 rtl/pulp_soc/soc_interconnect_wrap_v2.sv diff --git a/rtl/pulp_soc/soc_interconnect.sv b/rtl/pulp_soc/soc_interconnect.sv index 423284fd..fa17d6a0 100644 --- a/rtl/pulp_soc/soc_interconnect.sv +++ b/rtl/pulp_soc/soc_interconnect.sv @@ -1,924 +1,288 @@ -// Copyright 2018 ETH Zurich and University of Bologna. +//----------------------------------------------------------------------------- +// Title : soc_interconnect +//----------------------------------------------------------------------------- +// File : soc_interconnect.sv +// Author : Manuel Eggimann +// Created : 29.10.2020 +//----------------------------------------------------------------------------- +// Description : +// +//----------------------------------------------------------------------------- +// Copyright (C) 2013-2020 ETH Zurich, University of Bologna // Copyright and related rights are licensed under the Solderpad Hardware // License, Version 0.51 (the "License"); you may not use this file except in -// compliance with the License. You may obtain a copy of the License at +// compliance with the License. You may obtain a copy of the License at // http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law // or agreed to in writing, software, hardware and materials distributed under // this License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR // CONDITIONS OF ANY KIND, either express or implied. See the License for the // specific language governing permissions and limitations under the License. - - -module soc_interconnect #( - parameter USE_AXI = 1, - parameter ADDR_WIDTH = 32, - parameter N_HWPE_PORTS = 4, - parameter N_MASTER_32 = 5+N_HWPE_PORTS, - parameter N_MASTER_AXI_64 = 1, - parameter DATA_WIDTH = 32, - parameter BE_WIDTH = DATA_WIDTH/8, - parameter ID_WIDTH = N_MASTER_32+N_MASTER_AXI_64*4, - parameter AUX_WIDTH = 8, - parameter N_L2_BANKS = 4, - parameter N_L2_BANKS_PRI = 2, - parameter ADDR_L2_WIDTH = 12, - parameter ADDR_L2_PRI_WIDTH = 12, - parameter ROM_ADDR_WIDTH = 10, - // AXI PARAMS - // 32 bit axi Interface - parameter AXI_32_ID_WIDTH = 12, - parameter AXI_32_USER_WIDTH = 6, - // 64 bit axi Interface - parameter AXI_ADDR_WIDTH = 32, - parameter AXI_DATA_WIDTH = 64, - parameter AXI_STRB_WIDTH = 8, - parameter AXI_USER_WIDTH = 6, - parameter AXI_ID_WIDTH = 7 -) ( - input logic clk, - input logic rst_n, - input logic test_en_i, - output logic [N_L2_BANKS-1:0] [DATA_WIDTH-1:0] L2_D_o, - output logic [N_L2_BANKS-1:0] [ADDR_L2_WIDTH-1:0] L2_A_o, - output logic [N_L2_BANKS-1:0] L2_CEN_o, - output logic [N_L2_BANKS-1:0] L2_WEN_o, - output logic [N_L2_BANKS-1:0] [BE_WIDTH-1:0] L2_BE_o, - input logic [N_L2_BANKS-1:0] [DATA_WIDTH-1:0] L2_Q_i, - //RISC DATA PORT - input logic FC_DATA_req_i, - input logic [ADDR_WIDTH-1:0] FC_DATA_add_i, - input logic FC_DATA_wen_i, - input logic [DATA_WIDTH-1:0] FC_DATA_wdata_i, - input logic [BE_WIDTH-1:0] FC_DATA_be_i, - input logic [AUX_WIDTH-1:0] FC_DATA_aux_i, - output logic FC_DATA_gnt_o, - output logic [AUX_WIDTH-1:0] FC_DATA_r_aux_o, - output logic FC_DATA_r_valid_o, - output logic [DATA_WIDTH-1:0] FC_DATA_r_rdata_o, - output logic FC_DATA_r_opc_o, - // RISC INSTR PORT - input logic FC_INSTR_req_i, - input logic [ADDR_WIDTH-1:0] FC_INSTR_add_i, - input logic FC_INSTR_wen_i, - input logic [DATA_WIDTH-1:0] FC_INSTR_wdata_i, - input logic [BE_WIDTH-1:0] FC_INSTR_be_i, - input logic [AUX_WIDTH-1:0] FC_INSTR_aux_i, - output logic FC_INSTR_gnt_o, - output logic [AUX_WIDTH-1:0] FC_INSTR_r_aux_o, - output logic FC_INSTR_r_valid_o, - output logic [DATA_WIDTH-1:0] FC_INSTR_r_rdata_o, - output logic FC_INSTR_r_opc_o, - // UDMA TX - input logic UDMA_TX_req_i, - input logic [ADDR_WIDTH-1:0] UDMA_TX_add_i, - input logic UDMA_TX_wen_i, - input logic [DATA_WIDTH-1:0] UDMA_TX_wdata_i, - input logic [BE_WIDTH-1:0] UDMA_TX_be_i, - input logic [AUX_WIDTH-1:0] UDMA_TX_aux_i, - output logic UDMA_TX_gnt_o, - output logic [AUX_WIDTH-1:0] UDMA_TX_r_aux_o, - output logic UDMA_TX_r_valid_o, - output logic [DATA_WIDTH-1:0] UDMA_TX_r_rdata_o, - output logic UDMA_TX_r_opc_o, - // UDMA RX - input logic UDMA_RX_req_i, - input logic [ADDR_WIDTH-1:0] UDMA_RX_add_i, - input logic UDMA_RX_wen_i, - input logic [DATA_WIDTH-1:0] UDMA_RX_wdata_i, - input logic [BE_WIDTH-1:0] UDMA_RX_be_i, - input logic [AUX_WIDTH-1:0] UDMA_RX_aux_i, - output logic UDMA_RX_gnt_o, - output logic [AUX_WIDTH-1:0] UDMA_RX_r_aux_o, - output logic UDMA_RX_r_valid_o, - output logic [DATA_WIDTH-1:0] UDMA_RX_r_rdata_o, - output logic UDMA_RX_r_opc_o, - // DBG - input logic DBG_RX_req_i, - input logic [ADDR_WIDTH-1:0] DBG_RX_add_i, - input logic DBG_RX_wen_i, - input logic [DATA_WIDTH-1:0] DBG_RX_wdata_i, - input logic [BE_WIDTH-1:0] DBG_RX_be_i, - input logic [AUX_WIDTH-1:0] DBG_RX_aux_i, - output logic DBG_RX_gnt_o, - output logic [AUX_WIDTH-1:0] DBG_RX_r_aux_o, - output logic DBG_RX_r_valid_o, - output logic [DATA_WIDTH-1:0] DBG_RX_r_rdata_o, - output logic DBG_RX_r_opc_o, - // HWPE - input logic [N_HWPE_PORTS-1:0] HWPE_req_i, - input logic [N_HWPE_PORTS-1:0] [ADDR_WIDTH-1:0] HWPE_add_i, - input logic [N_HWPE_PORTS-1:0] HWPE_wen_i, - input logic [N_HWPE_PORTS-1:0] [DATA_WIDTH-1:0] HWPE_wdata_i, - input logic [N_HWPE_PORTS-1:0] [BE_WIDTH-1:0] HWPE_be_i, - input logic [N_HWPE_PORTS-1:0] [AUX_WIDTH-1:0] HWPE_aux_i, - output logic [N_HWPE_PORTS-1:0] HWPE_gnt_o, - output logic [N_HWPE_PORTS-1:0] [AUX_WIDTH-1:0] HWPE_r_aux_o, - output logic [N_HWPE_PORTS-1:0] HWPE_r_valid_o, - output logic [N_HWPE_PORTS-1:0] [DATA_WIDTH-1:0] HWPE_r_rdata_o, - output logic [N_HWPE_PORTS-1:0] HWPE_r_opc_o, - // AXI INTERFACE (FROM CLUSTER) - input logic [AXI_ADDR_WIDTH-1:0] AXI_Slave_aw_addr_i, - input logic [2:0] AXI_Slave_aw_prot_i, - input logic [3:0] AXI_Slave_aw_region_i, - input logic [7:0] AXI_Slave_aw_len_i, - input logic [2:0] AXI_Slave_aw_size_i, - input logic [1:0] AXI_Slave_aw_burst_i, - input logic AXI_Slave_aw_lock_i, - input logic [3:0] AXI_Slave_aw_cache_i, - input logic [3:0] AXI_Slave_aw_qos_i, - input logic [AXI_ID_WIDTH-1:0] AXI_Slave_aw_id_i, - input logic [AXI_USER_WIDTH-1:0] AXI_Slave_aw_user_i, - input logic AXI_Slave_aw_valid_i, - output logic AXI_Slave_aw_ready_o, - // ADDRESS READ CHANNEL - input logic [AXI_ADDR_WIDTH-1:0] AXI_Slave_ar_addr_i, - input logic [2:0] AXI_Slave_ar_prot_i, - input logic [3:0] AXI_Slave_ar_region_i, - input logic [7:0] AXI_Slave_ar_len_i, - input logic [2:0] AXI_Slave_ar_size_i, - input logic [1:0] AXI_Slave_ar_burst_i, - input logic AXI_Slave_ar_lock_i, - input logic [3:0] AXI_Slave_ar_cache_i, - input logic [3:0] AXI_Slave_ar_qos_i, - input logic [AXI_ID_WIDTH-1:0] AXI_Slave_ar_id_i, - input logic [AXI_USER_WIDTH-1:0] AXI_Slave_ar_user_i, - input logic AXI_Slave_ar_valid_i, - output logic AXI_Slave_ar_ready_o, - // WRITE CHANNEL - input logic [AXI_USER_WIDTH-1:0] AXI_Slave_w_user_i, - input logic [AXI_DATA_WIDTH-1:0] AXI_Slave_w_data_i, - input logic [AXI_STRB_WIDTH-1:0] AXI_Slave_w_strb_i, - input logic AXI_Slave_w_last_i, - input logic AXI_Slave_w_valid_i, - output logic AXI_Slave_w_ready_o, - // WRITE RESPONSE CHANNEL - output logic [AXI_ID_WIDTH-1:0] AXI_Slave_b_id_o, - output logic [1:0] AXI_Slave_b_resp_o, - output logic [AXI_USER_WIDTH-1:0] AXI_Slave_b_user_o, - output logic AXI_Slave_b_valid_o, - input logic AXI_Slave_b_ready_i, - // READ CHANNEL - output logic [AXI_ID_WIDTH-1:0] AXI_Slave_r_id_o, - output logic [AXI_USER_WIDTH-1:0] AXI_Slave_r_user_o, - output logic [AXI_DATA_WIDTH-1:0] AXI_Slave_r_data_o, - output logic [1:0] AXI_Slave_r_resp_o, - output logic AXI_Slave_r_last_o, - output logic AXI_Slave_r_valid_o, - input logic AXI_Slave_r_ready_i, - // BRIDGES - // CH_0 --> APB - output logic [ADDR_WIDTH-1:0] APB_PADDR_o, - output logic [DATA_WIDTH-1:0] APB_PWDATA_o, - output logic APB_PWRITE_o, - output logic APB_PSEL_o, - output logic APB_PENABLE_o, - input logic [DATA_WIDTH-1:0] APB_PRDATA_i, - input logic APB_PREADY_i, - input logic APB_PSLVERR_i, - // CH_1 --> AXI - // --------------------------------------------------------- - // AXI TARG Port Declarations ------------------------------ - // --------------------------------------------------------- - //AXI write address bus -------------- // USED// ----------- - output logic [AXI_32_ID_WIDTH-1:0] AXI_Master_aw_id_o, - output logic [ADDR_WIDTH-1:0] AXI_Master_aw_addr_o, - output logic [7:0] AXI_Master_aw_len_o, - output logic [2:0] AXI_Master_aw_size_o, - output logic [1:0] AXI_Master_aw_burst_o, - output logic AXI_Master_aw_lock_o, - output logic [3:0] AXI_Master_aw_cache_o, - output logic [2:0] AXI_Master_aw_prot_o, - output logic [3:0] AXI_Master_aw_region_o, - output logic [AXI_32_USER_WIDTH-1:0] AXI_Master_aw_user_o, - output logic [3:0] AXI_Master_aw_qos_o, - output logic AXI_Master_aw_valid_o, - input logic AXI_Master_aw_ready_i, - // --------------------------------------------------------- - //AXI write data bus -------------- // USED// -------------- - output logic [DATA_WIDTH-1:0] AXI_Master_w_data_o, - output logic [BE_WIDTH-1:0] AXI_Master_w_strb_o, - output logic AXI_Master_w_last_o, - output logic [AXI_32_USER_WIDTH-1:0] AXI_Master_w_user_o, - output logic AXI_Master_w_valid_o, - input logic AXI_Master_w_ready_i, - // --------------------------------------------------------- - //AXI write response bus -------------- // USED// ---------- - input logic [AXI_32_ID_WIDTH-1:0] AXI_Master_b_id_i, - input logic [1:0] AXI_Master_b_resp_i, - input logic AXI_Master_b_valid_i, - input logic [AXI_32_USER_WIDTH-1:0] AXI_Master_b_user_i, - output logic AXI_Master_b_ready_o, - // --------------------------------------------------------- - //AXI read address bus ------------------------------------- - output logic [AXI_32_ID_WIDTH-1:0] AXI_Master_ar_id_o, - output logic [ADDR_WIDTH-1:0] AXI_Master_ar_addr_o, - output logic [7:0] AXI_Master_ar_len_o, - output logic [2:0] AXI_Master_ar_size_o, - output logic [1:0] AXI_Master_ar_burst_o, - output logic AXI_Master_ar_lock_o, - output logic [3:0] AXI_Master_ar_cache_o, - output logic [2:0] AXI_Master_ar_prot_o, - output logic [3:0] AXI_Master_ar_region_o, - output logic [AXI_32_USER_WIDTH-1:0] AXI_Master_ar_user_o, - output logic [3:0] AXI_Master_ar_qos_o, - output logic AXI_Master_ar_valid_o, - input logic AXI_Master_ar_ready_i, - // --------------------------------------------------------- - //AXI read data bus ---------------------------------------- - input logic [AXI_32_ID_WIDTH-1:0] AXI_Master_r_id_i, - input logic [DATA_WIDTH-1:0] AXI_Master_r_data_i, - input logic [1:0] AXI_Master_r_resp_i, - input logic AXI_Master_r_last_i, - input logic [AXI_32_USER_WIDTH-1:0] AXI_Master_r_user_i, - input logic AXI_Master_r_valid_i, - output logic AXI_Master_r_ready_o, - // CH_2 --> ROM - output logic rom_csn_o, - output logic [ROM_ADDR_WIDTH-1:0] rom_add_o, - input logic [DATA_WIDTH-1:0] rom_rdata_i, - // CH_3, CH_4 Private Mem Banks (L2) - output logic [N_L2_BANKS_PRI-1:0] [DATA_WIDTH-1:0] L2_pri_D_o, - output logic [N_L2_BANKS_PRI-1:0] [ADDR_L2_PRI_WIDTH-1:0] L2_pri_A_o, - output logic [N_L2_BANKS_PRI-1:0] L2_pri_CEN_o, - output logic [N_L2_BANKS_PRI-1:0] L2_pri_WEN_o, - output logic [N_L2_BANKS_PRI-1:0] [BE_WIDTH-1:0] L2_pri_BE_o, - input logic [N_L2_BANKS_PRI-1:0] [DATA_WIDTH-1:0] L2_pri_Q_i -); - localparam N_CH0 = N_MASTER_32 ; - localparam N_CH1 = N_MASTER_AXI_64*4; - - localparam N_CH0_BRIDGE = N_CH0; - localparam N_CH1_BRIDGE = N_CH1; - - localparam PER_ID_WIDTH = N_CH0_BRIDGE+N_CH1_BRIDGE; - localparam N_PERIPHS = 3+N_L2_BANKS_PRI ; - - localparam L2_OFFSET_PRI = 15'h1000; // FIXME Put the right FORMULA - - // PRI_L2_CH1 //PRI_L2_CH0 //ROM // AXI // APB - localparam logic [N_PERIPHS-1:0][ADDR_WIDTH-1:0] PER_START_ADDR = { 32'h1C00_8000, 32'h1C00_0000, 32'h1A00_0000, 32'h1000_0000, 32'h1A10_0000}; - localparam logic [N_PERIPHS-1:0][ADDR_WIDTH-1:0] PER_END_ADDR = { 32'h1C01_0000, 32'h1C00_8000, 32'h1A04_0000, 32'h1040_0000, 32'h1A40_0000}; - - localparam logic [ADDR_WIDTH-1:0] TCDM_START_ADDR = {32'h1C01_0000}; // Start of L2 interleaved - localparam logic [ADDR_WIDTH-1:0] TCDM_END_ADDR = {32'h1C09_0000}; // END of L2 interleaved - - logic [N_MASTER_32-1:0] FC_data_req_INT_32; - logic [N_MASTER_32-1:0] [ADDR_WIDTH - 1:0] FC_data_add_INT_32; - logic [ADDR_WIDTH-1:0] FC_DATA_add_int; - logic [N_MASTER_32-1:0] FC_data_wen_INT_32; - logic [N_MASTER_32-1:0] [DATA_WIDTH - 1:0] FC_data_wdata_INT_32; - logic [N_MASTER_32-1:0] [BE_WIDTH - 1:0] FC_data_be_INT_32; - logic [N_MASTER_32-1:0] [AUX_WIDTH - 1:0] FC_data_aux_INT_32; - logic [N_MASTER_32-1:0] FC_data_gnt_INT_32; - logic [N_MASTER_32-1:0] [AUX_WIDTH-1:0] FC_data_r_aux_INT_32; - logic [N_MASTER_32-1:0] FC_data_r_valid_INT_32; - logic [N_MASTER_32-1:0] [DATA_WIDTH - 1:0] FC_data_r_rdata_INT_32; - logic [N_MASTER_32-1:0] FC_data_r_opc_INT_32; - - logic [N_MASTER_AXI_64*4-1:0] AXI_data_req_INT_64; - logic [N_MASTER_AXI_64*4-1:0] [ADDR_WIDTH - 1:0] AXI_data_add_INT_64; - logic [N_MASTER_AXI_64*4-1:0] AXI_data_wen_INT_64; - logic [N_MASTER_AXI_64*4-1:0] [DATA_WIDTH - 1:0] AXI_data_wdata_INT_64; - logic [N_MASTER_AXI_64*4-1:0] [BE_WIDTH - 1:0] AXI_data_be_INT_64; - logic [N_MASTER_AXI_64*4-1:0] [AUX_WIDTH - 1:0] AXI_data_aux_INT_64; - logic [N_MASTER_AXI_64*4-1:0] AXI_data_gnt_INT_64; - logic [N_MASTER_AXI_64*4-1:0] [AUX_WIDTH-1:0] AXI_data_r_aux_INT_64; - logic [N_MASTER_AXI_64*4-1:0] AXI_data_r_valid_INT_64; - logic [N_MASTER_AXI_64*4-1:0] [DATA_WIDTH - 1:0] AXI_data_r_rdata_INT_64; - logic [N_MASTER_AXI_64*4-1:0] AXI_data_r_opc_INT_64; - - logic [N_CH0+N_CH1-1:0] PER_data_req_DEM_2_L2_XBAR; - logic [N_CH0+N_CH1-1:0][ADDR_WIDTH-1:0] PER_data_add_DEM_2_L2_XBAR; - logic [N_CH0+N_CH1-1:0] PER_data_wen_DEM_2_L2_XBAR; - logic [N_CH0+N_CH1-1:0][DATA_WIDTH-1:0] PER_data_wdata_DEM_2_L2_XBAR; - logic [N_CH0+N_CH1-1:0][BE_WIDTH-1:0] PER_data_be_DEM_2_L2_XBAR; - logic [N_CH0+N_CH1-1:0][AUX_WIDTH-1:0] PER_data_aux_DEM_2_L2_XBAR; - logic [N_CH0+N_CH1-1:0] PER_data_gnt_DEM_2_L2_XBAR; - - logic [N_CH0+N_CH1-1:0] PER_data_r_valid_DEM_2_L2_XBAR; - logic [N_CH0+N_CH1-1:0][DATA_WIDTH-1:0] PER_data_r_rdata_DEM_2_L2_XBAR; - logic [N_CH0+N_CH1-1:0] PER_data_r_opc_DEM_2_L2_XBAR; - logic [N_CH0+N_CH1-1:0][AUX_WIDTH-1:0] PER_data_r_aux_DEM_2_L2_XBAR; - - // ---------------- BRIDGE SIDE -------------------------- - // Req --> to Mem - logic [N_PERIPHS-1:0] PER_data_req_TO_BRIDGE; - logic [N_PERIPHS-1:0][ADDR_WIDTH-1:0] PER_data_add_TO_BRIDGE; - logic [N_PERIPHS-1:0] PER_data_wen_TO_BRIDGE; - logic [N_PERIPHS-1:0][DATA_WIDTH-1:0] PER_data_wdata_TO_BRIDGE; - logic [N_PERIPHS-1:0][BE_WIDTH-1:0] PER_data_be_TO_BRIDGE; - logic [N_PERIPHS-1:0][PER_ID_WIDTH-1:0] PER_data_ID_TO_BRIDGE; - logic [N_PERIPHS-1:0][AUX_WIDTH-1:0] PER_data_aux_TO_BRIDGE; - logic [N_PERIPHS-1:0] PER_data_gnt_TO_BRIDGE; - - // Resp --> From Mem - logic [N_PERIPHS-1:0][DATA_WIDTH-1:0] PER_data_r_rdata_TO_BRIDGE; - logic [N_PERIPHS-1:0] PER_data_r_valid_TO_BRIDGE; - logic [N_PERIPHS-1:0][PER_ID_WIDTH-1:0] PER_data_r_ID_TO_BRIDGE; - logic [N_PERIPHS-1:0] PER_data_r_opc_TO_BRIDGE; - logic [N_PERIPHS-1:0][AUX_WIDTH-1:0] PER_data_r_aux_TO_BRIDGE; - - logic [N_CH0 + N_CH1-1:0][DATA_WIDTH-1:0] TCDM_data_wdata_DEM_TO_XBAR; - logic [N_CH0 + N_CH1-1:0][ADDR_WIDTH-1:0] TCDM_data_add_DEM_TO_XBAR; - logic [N_CH0 + N_CH1-1:0][ADDR_L2_WIDTH+$clog2(N_L2_BANKS)-1:0] TCDM_data_add_DEM_TO_XBAR_resized; - logic [N_CH0 + N_CH1-1:0] TCDM_data_req_DEM_TO_XBAR; - logic [N_CH0 + N_CH1-1:0] TCDM_data_wen_DEM_TO_XBAR; - logic [N_CH0 + N_CH1-1:0][BE_WIDTH-1:0] TCDM_data_be_DEM_TO_XBAR; - logic [N_CH0 + N_CH1-1:0] TCDM_data_gnt_DEM_TO_XBAR; - logic [N_CH0 + N_CH1-1:0][DATA_WIDTH-1:0] TCDM_data_r_rdata_DEM_TO_XBAR; - logic [N_CH0 + N_CH1-1:0] TCDM_data_r_valid_DEM_TO_XBAR; - - - logic [N_L2_BANKS-1:0][DATA_WIDTH-1:0] TCDM_data_wdata_TO_MEM; - logic [N_L2_BANKS-1:0][ADDR_L2_WIDTH-1:0] TCDM_data_add_TO_MEM; - logic [N_L2_BANKS-1:0] TCDM_data_req_TO_MEM; - logic [N_L2_BANKS-1:0] TCDM_data_wen_TO_MEM; - logic [N_L2_BANKS-1:0][BE_WIDTH-1:0] TCDM_data_be_TO_MEM; - logic [N_L2_BANKS-1:0][ID_WIDTH-1:0] TCDM_data_ID_TO_MEM; - logic [N_L2_BANKS-1:0][DATA_WIDTH-1:0] TCDM_data_rdata_TO_MEM; - logic [N_L2_BANKS-1:0] TCDM_data_rvalid_TO_MEM; - logic [N_L2_BANKS-1:0][ID_WIDTH-1:0] TCDM_data_rID_TO_MEM; - - // ROM BINDING - assign rom_csn_o = ~PER_data_req_TO_BRIDGE[2]; - assign rom_add_o = PER_data_add_TO_BRIDGE[2]; - assign PER_data_r_rdata_TO_BRIDGE[2] = rom_rdata_i; - - assign PER_data_gnt_TO_BRIDGE[2] = 1'b1; - assign PER_data_r_opc_TO_BRIDGE[2] = 1'b0; - always_ff @(posedge clk or negedge rst_n) - begin : proc_ - if(~rst_n) - begin - PER_data_r_valid_TO_BRIDGE[2] <= '0; - PER_data_r_ID_TO_BRIDGE[2] <= '0; - PER_data_r_aux_TO_BRIDGE[2] <= '0; - end - else - begin - PER_data_r_ID_TO_BRIDGE[2] <= PER_data_ID_TO_BRIDGE[2]; - PER_data_r_valid_TO_BRIDGE[2] <= PER_data_req_TO_BRIDGE[2]; - PER_data_r_aux_TO_BRIDGE[2] <= PER_data_aux_TO_BRIDGE[2]; - end +//----------------------------------------------------------------------------- +`include "tcdm_macros.svh" +`include "axi/assign.svh" + +module soc_interconnect + import pkg_soc_interconnect::addr_map_rule_t; + import axi_pkg::xbar_cfg_t; + #( + // TCDM Bus Master Config + parameter int unsigned NR_MASTER_PORTS, //Master Ports to the SoC interconnect with access to all memory regions + parameter int unsigned NR_MASTER_PORTS_INTERLEAVED_ONLY, //Master ports with access restricted to only the interleaved + //ports (no axes to APB, AXI, or contiguous slaves) TCDM Bus + //Slave Config + // L2 Demux Addr rules + parameter int unsigned NR_ADDR_RULES_L2_DEMUX, + // Interleaved TCDM slave + parameter int unsigned NR_SLAVE_PORTS_INTERLEAVED, + // Contiguous TCDM slave + parameter int unsigned NR_SLAVE_PORTS_CONTIG, + parameter int unsigned NR_ADDR_RULES_SLAVE_PORTS_CONTIG, + // AXI Master ID Width + parameter int unsigned AXI_MASTER_ID_WIDTH = 1, // Not really used since we only connect TCDM masters to the + // axi_xbar with protocol converters. However, the value must not be zero. + // AXI Slaves + parameter int unsigned NR_AXI_SLAVE_PORTS, + parameter int unsigned NR_ADDR_RULES_AXI_SLAVE_PORTS, + localparam int unsigned AXI_SLAVE_ID_WIDTH = AXI_MASTER_ID_WIDTH + $clog2(NR_MASTER_PORTS), //The actual ID + //width of the AXI slaves is clog2(NR_AXI_MASTERS) larger than the master id width since the + //axi_mux in the XBAR will append an identificatoin tag to the outgoing transactions + //towards the axi slaves so it can backroute the responses + parameter int unsigned AXI_USER_WIDTH + ) + ( + input logic clk_i, + input logic rst_ni, + input logic test_en_i, // 0 Normal operation, 1 put sub-IPs into testmode (bypass clock gates) + XBAR_TCDM_BUS.Slave master_ports[NR_MASTER_PORTS], + XBAR_TCDM_BUS.Slave master_ports_interleaved_only[NR_MASTER_PORTS_INTERLEAVED_ONLY], + input addr_map_rule_t[NR_ADDR_RULES_L2_DEMUX-1:0] addr_space_l2_demux, + //Interleaved Slave + XBAR_TCDM_BUS.Master interleaved_slaves[NR_SLAVE_PORTS_INTERLEAVED], + //Contiguous Slave + input addr_map_rule_t[NR_ADDR_RULES_SLAVE_PORTS_CONTIG-1:0] addr_space_contiguous, + XBAR_TCDM_BUS.Master contiguous_slaves[NR_SLAVE_PORTS_CONTIG], + //AXI Slave + input addr_map_rule_t [NR_ADDR_RULES_AXI_SLAVE_PORTS-1:0] addr_space_axi, + AXI_BUS.Master axi_slaves[NR_AXI_SLAVE_PORTS] //AXI_ID width must be + //at least clog2(NR_AXI_SLAVES) + ); + + + // Internal Parameters + // Do **NOT** change + localparam int unsigned BUS_DATA_WIDTH = 32; + localparam int unsigned BUS_ADDR_WIDTH = 32; + + // Internal Wiring Signals + XBAR_TCDM_BUS l2_demux_2_interleaved_xbar[NR_MASTER_PORTS](); + XBAR_TCDM_BUS l2_demux_2_contiguous_xbar[NR_MASTER_PORTS](); + XBAR_TCDM_BUS l2_demux_2_axi_bridge[NR_MASTER_PORTS](); + + ////////////////////// + // L2 Demultiplexer // + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // This is the first stage of the interconnect. For every master, transactions are multiplexed between three // + // different target slaves. The first slave port routes to the axi crossbar, the second slave port routes // + // to the contiguous crossbar and the third slave port connects to the interleaved crossbar. // + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + + for (genvar i = 0; i < NR_MASTER_PORTS; i++) begin : gen_l2_demux + XBAR_TCDM_BUS demux_slaves[3](); + + `TCDM_ASSIGN_INTF(l2_demux_2_axi_bridge[i], demux_slaves[0]); + `TCDM_ASSIGN_INTF(l2_demux_2_contiguous_xbar[i], demux_slaves[1]); + `TCDM_ASSIGN_INTF(l2_demux_2_interleaved_xbar[i], demux_slaves[2]); + + + tcdm_demux #( + .NR_OUTPUTS(3), + .NR_ADDR_MAP_RULES(NR_ADDR_RULES_L2_DEMUX) + ) i_l2_demux( + .clk_i, + .rst_ni, + .test_en_i, + .addr_map_rules(addr_space_l2_demux), + .master_port(master_ports[i]), + .slave_ports(demux_slaves) + ); end - genvar k; - generate - // Private mem Binding - for (k = 0; k< N_L2_BANKS_PRI; k++) begin - assign L2_pri_D_o [k] = PER_data_wdata_TO_BRIDGE[k+3]; - assign L2_pri_A_o [k] = PER_data_add_TO_BRIDGE [k+3][ADDR_L2_PRI_WIDTH+1:2]; - assign L2_pri_CEN_o [k] = ~PER_data_req_TO_BRIDGE [k+3]; - assign L2_pri_WEN_o [k] = PER_data_wen_TO_BRIDGE [k+3]; - assign L2_pri_BE_o [k] = PER_data_be_TO_BRIDGE [k+3]; - - assign PER_data_r_rdata_TO_BRIDGE[k+3] = L2_pri_Q_i [k]; - assign PER_data_gnt_TO_BRIDGE[k+3] = 1'b1; - assign PER_data_r_opc_TO_BRIDGE[k+3] = '0; - - always_ff @(posedge clk or negedge rst_n) - begin : proc_L2_CH_pri_rvalid_gen - if(~rst_n) begin - PER_data_r_valid_TO_BRIDGE[k+3] <= '0; - PER_data_r_ID_TO_BRIDGE[k+3] <= '0; - PER_data_r_aux_TO_BRIDGE[k+3] <= '0; - end - else begin - PER_data_r_valid_TO_BRIDGE[k+3] <= PER_data_req_TO_BRIDGE[k+3]; - PER_data_r_ID_TO_BRIDGE[k+3] <= PER_data_ID_TO_BRIDGE[k+3]; - PER_data_r_aux_TO_BRIDGE[k+3] <= PER_data_aux_TO_BRIDGE[k+3]; - end - end - end - endgenerate - - always_comb - begin - FC_DATA_add_int = FC_DATA_add_i; - if(FC_DATA_add_i[31:20] == 12'h000) - FC_DATA_add_int[31:20] = 12'h1C0; + ////////////////////////// + // Interleaved Crossbar // + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // This is a fully connected crossbar with combinational arbitration (logarithmic Inteconnect). It arbitrates // + // from the master ports from the L2 demultiplexer and the interleaved-only master ports (ports that do not have // + // access to the other address spaces) to the TCDM slaves with address interleaving. That is, the least // + // significant **word address** bits are used to select the slave port. This results in a more equal load on the // + // SRAM banks when the master access memory regions in a sequential manner. EVERY SLAVE IS EXPECTED TO HAVE // + // CONSTANT LATENCY OF 1 CYCLE. Slaves that cannot respond within a single cycle must appropriately delay the // + // assertion of the gnt (grant) signal. Asserting grant without asserting r_valid in the next cycle results in // + // undefined behavior. // + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + //Concatenate the l2 demux master port array and the interleaved only port array + XBAR_TCDM_BUS interleaved_masters[NR_MASTER_PORTS+NR_MASTER_PORTS_INTERLEAVED_ONLY](); + //Synopsys is to stupid to handle expressions for array indices on the left-hand side of assignments. This is a + // verbose workaround for it. The next couple of ugly macro magic unpacks each interface into individual signal arrays, + // performs the assignments to the interface and packs the signal back to an array of interfaces. + `TCDM_EXPLODE_ARRAY_DECLARE(interleaved_masters, NR_MASTER_PORTS+NR_MASTER_PORTS_INTERLEAVED_ONLY) + for (genvar i = 0; i < NR_MASTER_PORTS + NR_MASTER_PORTS_INTERLEAVED_ONLY; i++) begin + `TCDM_SLAVE_EXPLODE(interleaved_masters[i], interleaved_masters, [i]) end - - assign FC_data_req_INT_32 = { FC_INSTR_req_i , UDMA_TX_req_i , UDMA_RX_req_i , DBG_RX_req_i , FC_DATA_req_i }; - assign FC_data_add_INT_32 = { FC_INSTR_add_i , UDMA_TX_add_i , UDMA_RX_add_i , DBG_RX_add_i , FC_DATA_add_int }; - assign FC_data_wen_INT_32 = { FC_INSTR_wen_i , UDMA_TX_wen_i , UDMA_RX_wen_i , DBG_RX_wen_i , FC_DATA_wen_i }; - assign FC_data_wdata_INT_32 = { FC_INSTR_wdata_i , UDMA_TX_wdata_i , UDMA_RX_wdata_i , DBG_RX_wdata_i , FC_DATA_wdata_i }; - assign FC_data_be_INT_32 = { FC_INSTR_be_i , UDMA_TX_be_i , UDMA_RX_be_i , DBG_RX_be_i , FC_DATA_be_i }; - assign FC_data_aux_INT_32 = { FC_INSTR_aux_i , UDMA_TX_aux_i , UDMA_RX_aux_i , DBG_RX_aux_i , FC_DATA_aux_i }; - assign { FC_INSTR_gnt_o , UDMA_TX_gnt_o , UDMA_RX_gnt_o , DBG_RX_gnt_o , FC_DATA_gnt_o } = FC_data_gnt_INT_32 ; - assign { FC_INSTR_r_aux_o , UDMA_TX_r_aux_o , UDMA_RX_r_aux_o , DBG_RX_r_aux_o , FC_DATA_r_aux_o } = FC_data_r_aux_INT_32 ; - assign { FC_INSTR_r_valid_o , UDMA_TX_r_valid_o , UDMA_RX_r_valid_o , DBG_RX_r_valid_o , FC_DATA_r_valid_o } = FC_data_r_valid_INT_32 ; - assign { FC_INSTR_r_rdata_o , UDMA_TX_r_rdata_o , UDMA_RX_r_rdata_o , DBG_RX_r_rdata_o , FC_DATA_r_rdata_o } = FC_data_r_rdata_INT_32 ; - assign { FC_INSTR_r_opc_o , UDMA_TX_r_opc_o , UDMA_RX_r_opc_o , DBG_RX_r_opc_o , FC_DATA_r_opc_o } = FC_data_r_opc_INT_32 ; - - // the accelerator is directly connected to the interleaved region - assign TCDM_data_req_DEM_TO_XBAR [N_CH0-1:N_CH0-N_HWPE_PORTS] = HWPE_req_i; - assign TCDM_data_add_DEM_TO_XBAR [N_CH0-1:N_CH0-N_HWPE_PORTS] = HWPE_add_i; - assign TCDM_data_wen_DEM_TO_XBAR [N_CH0-1:N_CH0-N_HWPE_PORTS] = HWPE_wen_i; - assign TCDM_data_wdata_DEM_TO_XBAR [N_CH0-1:N_CH0-N_HWPE_PORTS] = HWPE_wdata_i; - assign TCDM_data_be_DEM_TO_XBAR [N_CH0-1:N_CH0-N_HWPE_PORTS] = HWPE_be_i; - assign HWPE_gnt_o = TCDM_data_gnt_DEM_TO_XBAR [N_CH0-1:N_CH0-N_HWPE_PORTS]; - assign HWPE_r_valid_o = TCDM_data_r_valid_DEM_TO_XBAR [N_CH0-1:N_CH0-N_HWPE_PORTS]; - assign HWPE_r_rdata_o = TCDM_data_r_rdata_DEM_TO_XBAR [N_CH0-1:N_CH0-N_HWPE_PORTS]; - - genvar j; - generate - for(j=0;j 2 for read, 2 for write) - XBAR_L2 #( - .N_CH0 ( N_CH0 ), - .N_CH1 ( N_CH1 ), - .N_SLAVE ( N_L2_BANKS ), - .ID_WIDTH ( N_CH0+N_CH1 ), - - //FRONT END PARAMS - .ADDR_IN_WIDTH ( ADDR_L2_WIDTH+$clog2(N_L2_BANKS) ), - .DATA_WIDTH ( DATA_WIDTH ), - .BE_WIDTH ( BE_WIDTH ), - .ADDR_MEM_WIDTH ( ADDR_L2_WIDTH ) - ) XBAR_L2_i ( - // ---------------- MASTER CH0+CH1 SIDE -------------------------- - .data_req_i ( TCDM_data_req_DEM_TO_XBAR ), - .data_add_i ( TCDM_data_add_DEM_TO_XBAR_resized ), - .data_wen_i ( TCDM_data_wen_DEM_TO_XBAR ), - .data_wdata_i ( TCDM_data_wdata_DEM_TO_XBAR ), - .data_be_i ( TCDM_data_be_DEM_TO_XBAR ), - .data_gnt_o ( TCDM_data_gnt_DEM_TO_XBAR ), - .data_r_valid_o ( TCDM_data_r_valid_DEM_TO_XBAR ), - .data_r_rdata_o ( TCDM_data_r_rdata_DEM_TO_XBAR ), - - // ---------------- MM_SIDE (Interleaved) -------------------------- - .data_req_o ( TCDM_data_req_TO_MEM ), - .data_add_o ( TCDM_data_add_TO_MEM ), - .data_wen_o ( TCDM_data_wen_TO_MEM ), - .data_wdata_o ( TCDM_data_wdata_TO_MEM ), - .data_be_o ( TCDM_data_be_TO_MEM ), - .data_ID_o ( TCDM_data_ID_TO_MEM ), - - .data_r_rdata_i ( TCDM_data_rdata_TO_MEM ), - .data_r_valid_i ( TCDM_data_rvalid_TO_MEM ), - .data_r_ID_i ( TCDM_data_rID_TO_MEM ), - - .clk ( clk ), - .rst_n ( rst_n ) - ); - - // ██████╗ ██████╗ ██╗██████╗ ██████╗ ███████╗ ██╗ ██╗██████╗ █████╗ ██████╗ - // ██╔══██╗██╔══██╗██║██╔══██╗██╔════╝ ██╔════╝ ╚██╗██╔╝██╔══██╗██╔══██╗██╔══██╗ - // ██████╔╝██████╔╝██║██║ ██║██║ ███╗█████╗ ╚███╔╝ ██████╔╝███████║██████╔╝ - // ██╔══██╗██╔══██╗██║██║ ██║██║ ██║██╔══╝ ██╔██╗ ██╔══██╗██╔══██║██╔══██╗ - // ██████╔╝██║ ██║██║██████╔╝╚██████╔╝███████╗███████╗██╔╝ ██╗██████╔╝██║ ██║██║ ██║ - // ╚═════╝ ╚═╝ ╚═╝╚═╝╚═════╝ ╚═════╝ ╚══════╝╚══════╝╚═╝ ╚═╝╚═════╝ ╚═╝ ╚═╝╚═╝ ╚═╝ - // Full COnnectivity (Full crossbar) - // out channels: 2 channels APB32 and AXI32 - // in channels: 2 from FC( fc_data, debug_in) + 4 (AXI --> 2 for read, 2 for write) - XBAR_BRIDGE #( - .N_CH0 ( N_CH0_BRIDGE ), // 2 --> Removed (FC_instr, udma_tx, udma_rx) - .N_CH1 ( N_CH1_BRIDGE ), // 4 --> AXI64 - .N_SLAVE ( N_PERIPHS ), - .ID_WIDTH ( PER_ID_WIDTH ), - - .AUX_WIDTH ( AUX_WIDTH ), - .ADDR_WIDTH ( ADDR_WIDTH ), - .DATA_WIDTH ( DATA_WIDTH ), - .BE_WIDTH ( BE_WIDTH ) - ) XBAR_BRIDGE_i ( - .data_req_i ( PER_data_req_DEM_2_L2_XBAR ), - .data_add_i ( PER_data_add_DEM_2_L2_XBAR ), - .data_wen_i ( PER_data_wen_DEM_2_L2_XBAR ), - .data_wdata_i ( PER_data_wdata_DEM_2_L2_XBAR ), - .data_be_i ( PER_data_be_DEM_2_L2_XBAR ), - .data_aux_i ( PER_data_aux_DEM_2_L2_XBAR ), - .data_gnt_o ( PER_data_gnt_DEM_2_L2_XBAR ), - .data_r_valid_o ( PER_data_r_valid_DEM_2_L2_XBAR ), - .data_r_rdata_o ( PER_data_r_rdata_DEM_2_L2_XBAR ), - .data_r_opc_o ( PER_data_r_opc_DEM_2_L2_XBAR ), - .data_r_aux_o ( PER_data_r_aux_DEM_2_L2_XBAR ), - - .data_req_o ( PER_data_req_TO_BRIDGE ), - .data_add_o ( PER_data_add_TO_BRIDGE ), - .data_wen_o ( PER_data_wen_TO_BRIDGE ), - .data_wdata_o ( PER_data_wdata_TO_BRIDGE ), - .data_be_o ( PER_data_be_TO_BRIDGE ), - .data_ID_o ( PER_data_ID_TO_BRIDGE ), - .data_aux_o ( PER_data_aux_TO_BRIDGE ), - .data_gnt_i ( PER_data_gnt_TO_BRIDGE ), - - .data_r_rdata_i ( PER_data_r_rdata_TO_BRIDGE ), - .data_r_valid_i ( PER_data_r_valid_TO_BRIDGE ), - .data_r_ID_i ( PER_data_r_ID_TO_BRIDGE ), - .data_r_opc_i ( PER_data_r_opc_TO_BRIDGE ), - .data_r_aux_i ( PER_data_r_aux_TO_BRIDGE ), - - .clk ( clk ), - .rst_n ( rst_n ), - - .START_ADDR ( PER_START_ADDR ), - .END_ADDR ( PER_END_ADDR ) - ); - - genvar i; - generate - // ██╗ ██████╗ ████████╗ ██████╗██████╗ ███╗ ███╗ ██████╗ ███████╗███╗ ███╗██╗ ██╗██╗ ██╗ - // ██║ ╚════██╗ ╚══██╔══╝██╔════╝██╔══██╗████╗ ████║ ██╔══██╗██╔════╝████╗ ████║██║ ██║╚██╗██╔╝ - // ██║ █████╔╝ ██║ ██║ ██║ ██║██╔████╔██║ ██║ ██║█████╗ ██╔████╔██║██║ ██║ ╚███╔╝ - // ██║ ██╔═══╝ ██║ ██║ ██║ ██║██║╚██╔╝██║ ██║ ██║██╔══╝ ██║╚██╔╝██║██║ ██║ ██╔██╗ - // ███████╗███████╗███████╗██║ ╚██████╗██████╔╝██║ ╚═╝ ██║███████╗██████╔╝███████╗██║ ╚═╝ ██║╚██████╔╝██╔╝ ██╗ - // ╚══════╝╚══════╝╚══════╝╚═╝ ╚═════╝╚═════╝ ╚═╝ ╚═╝╚══════╝╚═════╝ ╚══════╝╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝ - for(i=0; i -// Created : 29.10.2020 -//----------------------------------------------------------------------------- -// Description : -// -//----------------------------------------------------------------------------- -// Copyright (C) 2013-2020 ETH Zurich, University of Bologna -// Copyright and related rights are licensed under the Solderpad Hardware -// License, Version 0.51 (the "License"); you may not use this file except in -// compliance with the License. You may obtain a copy of the License at -// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law -// or agreed to in writing, software, hardware and materials distributed under -// this License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR -// CONDITIONS OF ANY KIND, either express or implied. See the License for the -// specific language governing permissions and limitations under the License. -//----------------------------------------------------------------------------- -`include "tcdm_macros.svh" -`include "axi/assign.svh" - -module soc_interconnect - import pkg_soc_interconnect::addr_map_rule_t; - import axi_pkg::xbar_cfg_t; - #( - // TCDM Bus Master Config - parameter int unsigned NR_MASTER_PORTS, //Master Ports to the SoC interconnect with access to all memory regions - parameter int unsigned NR_MASTER_PORTS_INTERLEAVED_ONLY, //Master ports with access restricted to only the interleaved - //ports (no axes to APB, AXI, or contiguous slaves) TCDM Bus - //Slave Config - // L2 Demux Addr rules - parameter int unsigned NR_ADDR_RULES_L2_DEMUX, - // Interleaved TCDM slave - parameter int unsigned NR_SLAVE_PORTS_INTERLEAVED, - // Contiguous TCDM slave - parameter int unsigned NR_SLAVE_PORTS_CONTIG, - parameter int unsigned NR_ADDR_RULES_SLAVE_PORTS_CONTIG, - // AXI Master ID Width - parameter int unsigned AXI_MASTER_ID_WIDTH = 1, // Not really used since we only connect TCDM masters to the - // axi_xbar with protocol converters. However, the value must not be zero. - // AXI Slaves - parameter int unsigned NR_AXI_SLAVE_PORTS, - parameter int unsigned NR_ADDR_RULES_AXI_SLAVE_PORTS, - localparam int unsigned AXI_SLAVE_ID_WIDTH = AXI_MASTER_ID_WIDTH + $clog2(NR_MASTER_PORTS), //The actual ID - //width of the AXI slaves is clog2(NR_AXI_MASTERS) larger than the master id width since the - //axi_mux in the XBAR will append an identificatoin tag to the outgoing transactions - //towards the axi slaves so it can backroute the responses - parameter int unsigned AXI_USER_WIDTH - ) - ( - input logic clk_i, - input logic rst_ni, - input logic test_en_i, // 0 Normal operation, 1 put sub-IPs into testmode (bypass clock gates) - XBAR_TCDM_BUS.Slave master_ports[NR_MASTER_PORTS], - XBAR_TCDM_BUS.Slave master_ports_interleaved_only[NR_MASTER_PORTS_INTERLEAVED_ONLY], - input addr_map_rule_t[NR_ADDR_RULES_L2_DEMUX-1:0] addr_space_l2_demux, - //Interleaved Slave - XBAR_TCDM_BUS.Master interleaved_slaves[NR_SLAVE_PORTS_INTERLEAVED], - //Contiguous Slave - input addr_map_rule_t[NR_ADDR_RULES_SLAVE_PORTS_CONTIG-1:0] addr_space_contiguous, - XBAR_TCDM_BUS.Master contiguous_slaves[NR_SLAVE_PORTS_CONTIG], - //AXI Slave - input addr_map_rule_t [NR_ADDR_RULES_AXI_SLAVE_PORTS-1:0] addr_space_axi, - AXI_BUS.Master axi_slaves[NR_AXI_SLAVE_PORTS] //AXI_ID width must be - //at least clog2(NR_AXI_SLAVES) - ); - - - // Internal Parameters - // Do **NOT** change - localparam int unsigned BUS_DATA_WIDTH = 32; - localparam int unsigned BUS_ADDR_WIDTH = 32; - - // Internal Wiring Signals - XBAR_TCDM_BUS l2_demux_2_interleaved_xbar[NR_MASTER_PORTS](); - XBAR_TCDM_BUS l2_demux_2_contiguous_xbar[NR_MASTER_PORTS](); - XBAR_TCDM_BUS l2_demux_2_axi_bridge[NR_MASTER_PORTS](); - - ////////////////////// - // L2 Demultiplexer // - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - // This is the first stage of the interconnect. For every master, transactions are multiplexed between three // - // different target slaves. The first slave port routes to the axi crossbar, the second slave port routes // - // to the contiguous crossbar and the third slave port connects to the interleaved crossbar. // - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - - - for (genvar i = 0; i < NR_MASTER_PORTS; i++) begin : gen_l2_demux - XBAR_TCDM_BUS demux_slaves[3](); - - `TCDM_ASSIGN_INTF(l2_demux_2_axi_bridge[i], demux_slaves[0]); - `TCDM_ASSIGN_INTF(l2_demux_2_contiguous_xbar[i], demux_slaves[1]); - `TCDM_ASSIGN_INTF(l2_demux_2_interleaved_xbar[i], demux_slaves[2]); - - - tcdm_demux #( - .NR_OUTPUTS(3), - .NR_ADDR_MAP_RULES(NR_ADDR_RULES_L2_DEMUX) - ) i_l2_demux( - .clk_i, - .rst_ni, - .test_en_i, - .addr_map_rules(addr_space_l2_demux), - .master_port(master_ports[i]), - .slave_ports(demux_slaves) - ); - end - - - ////////////////////////// - // Interleaved Crossbar // - //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - // This is a fully connected crossbar with combinational arbitration (logarithmic Inteconnect). It arbitrates // - // from the master ports from the L2 demultiplexer and the interleaved-only master ports (ports that do not have // - // access to the other address spaces) to the TCDM slaves with address interleaving. That is, the least // - // significant **word address** bits are used to select the slave port. This results in a more equal load on the // - // SRAM banks when the master access memory regions in a sequential manner. EVERY SLAVE IS EXPECTED TO HAVE // - // CONSTANT LATENCY OF 1 CYCLE. Slaves that cannot respond within a single cycle must appropriately delay the // - // assertion of the gnt (grant) signal. Asserting grant without asserting r_valid in the next cycle results in // - // undefined behavior. // - //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - - //Concatenate the l2 demux master port array and the interleaved only port array - XBAR_TCDM_BUS interleaved_masters[NR_MASTER_PORTS+NR_MASTER_PORTS_INTERLEAVED_ONLY](); - //Synopsys is to stupid to handle expressions for array indices on the left-hand side of assignments. This is a - // verbose workaround for it. The next couple of ugly macro magic unpacks each interface into individual signal arrays, - // performs the assignments to the interface and packs the signal back to an array of interfaces. - `TCDM_EXPLODE_ARRAY_DECLARE(interleaved_masters, NR_MASTER_PORTS+NR_MASTER_PORTS_INTERLEAVED_ONLY) - for (genvar i = 0; i < NR_MASTER_PORTS + NR_MASTER_PORTS_INTERLEAVED_ONLY; i++) begin - `TCDM_SLAVE_EXPLODE(interleaved_masters[i], interleaved_masters, [i]) - end - `TCDM_EXPLODE_ARRAY_DECLARE(l2_demux_2_interleaved_xbar, NR_MASTER_PORTS) - for (genvar i = 0; i < NR_MASTER_PORTS; i++) begin - `TCDM_MASTER_EXPLODE(l2_demux_2_interleaved_xbar[i], l2_demux_2_interleaved_xbar, [i]) - `TCDM_ASSIGN(interleaved_masters, [i], l2_demux_2_interleaved_xbar, [i]) - end - `TCDM_EXPLODE_ARRAY_DECLARE(master_ports_interleaved_only, NR_MASTER_PORTS_INTERLEAVED_ONLY) - for (genvar i = 0; i < NR_MASTER_PORTS_INTERLEAVED_ONLY; i++) begin - `TCDM_MASTER_EXPLODE(master_ports_interleaved_only[i], master_ports_interleaved_only, [i]) - `TCDM_ASSIGN(interleaved_masters, [NR_MASTER_PORTS + i], master_ports_interleaved_only, [i]) - end - - interleaved_crossbar #( - .NR_MASTER_PORTS(NR_MASTER_PORTS+NR_MASTER_PORTS_INTERLEAVED_ONLY), - .NR_SLAVE_PORTS(NR_SLAVE_PORTS_INTERLEAVED) - ) i_interleaved_xbar( - // Interfaces - .master_ports (interleaved_masters), - .slave_ports (interleaved_slaves), - // Inputs - .clk_i, - .rst_ni, - .test_en_i - ); - - ///////////////////////// - // Contiguous Crossbar // - //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - // This is a fully connected crossbar with combinational arbitration (logarithmic Inteconnect). Internally, there // - // is an address decoder that matches each master_port address against a number of address range to output port // - // mapping rules. Addresses not matching any of the address mapping rules will end up on a default port that // - // always grants the request, raises the opc line for one cycle and in the case of a read acces, responds with // - // the word 0xBADACCE5. EVERY SLAVE IS EXPECTED TO HAVE CONSTANT LATENCY OF 1 CYCLE. Slaves that cannot respond // - // within a single cycle must appropriately delay the assertion of the gnt (grant) signal. Asserting grant // - // without asserting r_valid in the next cycle results in undefined behavior. // - //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - XBAR_TCDM_BUS error_slave(); - contiguous_crossbar #( - .NR_MASTER_PORTS(NR_MASTER_PORTS), - .NR_SLAVE_PORTS(NR_SLAVE_PORTS_CONTIG), - .NR_ADDR_RULES(NR_ADDR_RULES_SLAVE_PORTS_CONTIG) - ) i_contiguous_xbar( - // Interfaces - .master_ports (l2_demux_2_contiguous_xbar), - .slave_ports (contiguous_slaves), - .error_port (error_slave), - .addr_rules (addr_space_contiguous), - // Inputs - .clk_i, - .rst_ni, - .test_en_i - ); - //Error Slave - // This dummy slave is responsible to generate the buserror described above - logic error_valid_d, error_valid_q; - assign error_slave.gnt = error_slave.req; - assign error_valid_d = error_slave.req; - assign error_slave.r_opc = error_slave.req; - assign error_slave.r_rdata = 32'hBADACCE5; - assign error_slave.r_valid = error_valid_q; - - always_ff @(posedge clk_i, negedge rst_ni) begin - if (!rst_ni) begin - error_valid_q <= 1'b0; - end else begin - error_valid_q <= error_valid_d; - end - end - - - //////////////////////// - // TCDM to AXI Bridge // - //////////////////////////////////////////////////////////////////////////////////////////////////////////////// - // Instantiate a TCDM to AXI protocol converter for each master port from the L2 demultiplexer. The converter // - // converts one 32-bit TCDM port to one 32-bit AXI port. // - //////////////////////////////////////////////////////////////////////////////////////////////////////////////// - AXI_BUS #(.AXI_ADDR_WIDTH(32), - .AXI_DATA_WIDTH(32), - .AXI_ID_WIDTH(AXI_MASTER_ID_WIDTH), - .AXI_USER_WIDTH(AXI_USER_WIDTH) - ) axi_bridge_2_axi_xbar[NR_MASTER_PORTS](); - for (genvar i = 0; i < NR_MASTER_PORTS; i++) begin : gen_tcdm_2_axi_bridge - lint2axi_wrap #( - .AXI_ID_WIDTH(AXI_MASTER_ID_WIDTH), - .AXI_USER_WIDTH(AXI_USER_WIDTH) - ) i_lint2axi_bridge ( - .clk_i, - .rst_ni, - .master(l2_demux_2_axi_bridge[i]), - .slave(axi_bridge_2_axi_xbar[i]) - ); - end - - - /////////////////// - // AXI4 Crossbar // - //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - // The AXI crossbar accepts a set of address to slave port mapping rules (addr_map_i) and decodes the transaction // - // address accordingly. Illegal addresses that do not map to any defined address space are anaswered with a // - // decode error and Read Responses contain the data 0xBADCAB1E. Check the axi_xbar documentation for more // - // information. // - //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - - localparam xbar_cfg_t AXI_XBAR_CFG = '{ - NoSlvPorts: NR_MASTER_PORTS, - NoMstPorts: NR_AXI_SLAVE_PORTS, - MaxMstTrans: 1, //The TCDM ports do not support - //outstanding transactiions anyways - MaxSlvTrans: 4, //Allow up to 4 in-flight transactions - //per slave port - FallThrough: 1, //Use the reccomended default config - LatencyMode: axi_pkg::CUT_MST_PORTS, - AxiIdWidthSlvPorts: AXI_MASTER_ID_WIDTH, - AxiIdUsedSlvPorts: AXI_MASTER_ID_WIDTH, - AxiAddrWidth: BUS_ADDR_WIDTH, - AxiDataWidth: BUS_DATA_WIDTH, - NoAddrRules: NR_ADDR_RULES_AXI_SLAVE_PORTS - }; - - //Reverse interface array ordering since axi_xbar uses big-endian ordering of the arrays - AXI_BUS #(.AXI_ADDR_WIDTH(32), - .AXI_DATA_WIDTH(32), - .AXI_ID_WIDTH(AXI_MASTER_ID_WIDTH), - .AXI_USER_WIDTH(AXI_USER_WIDTH) - ) axi_bridge_2_axi_xbar_reversed[NR_MASTER_PORTS-1:0](); - AXI_BUS #(.AXI_ADDR_WIDTH(32), - .AXI_DATA_WIDTH(32), - .AXI_ID_WIDTH(AXI_SLAVE_ID_WIDTH), - .AXI_USER_WIDTH(AXI_USER_WIDTH) - ) axi_slaves_reversed[NR_AXI_SLAVE_PORTS-1:0](); - - for (genvar i = 0; i < NR_MASTER_PORTS; i++) begin - `AXI_ASSIGN(axi_bridge_2_axi_xbar_reversed[i], axi_bridge_2_axi_xbar[i]) - end - - for (genvar i = 0; i < NR_AXI_SLAVE_PORTS; i++) begin - `AXI_ASSIGN(axi_slaves[i], axi_slaves_reversed[i]) - end - - axi_xbar_intf #( - .AXI_USER_WIDTH(AXI_USER_WIDTH), - .Cfg(AXI_XBAR_CFG), - .rule_t(addr_map_rule_t) - ) i_axi_xbar ( - .clk_i, - .rst_ni, - .test_i(test_en_i), - .slv_ports(axi_bridge_2_axi_xbar_reversed), - .mst_ports(axi_slaves_reversed), - .addr_map_i(addr_space_axi), - .en_default_mst_port_i('0), - .default_mst_port_i('0) - ); - - -endmodule : soc_interconnect diff --git a/rtl/pulp_soc/soc_interconnect_wrap.sv b/rtl/pulp_soc/soc_interconnect_wrap.sv index b9b7e7cc..4adffe1f 100644 --- a/rtl/pulp_soc/soc_interconnect_wrap.sv +++ b/rtl/pulp_soc/soc_interconnect_wrap.sv @@ -1,344 +1,234 @@ -// Copyright 2018 ETH Zurich and University of Bologna. +//----------------------------------------------------------------------------- +// Title : SoC Interconnect Wrapper +//----------------------------------------------------------------------------- +// File : soc_interconnect_wrap_v2.sv +// Author : Manuel Eggimann +// Created : 30.10.2020 +//----------------------------------------------------------------------------- +// Description : +// This module instantiates the SoC interconnect and attaches the various SoC +// ports. Furthermore, the wrapper also instantiates the required protocol converters +// (AXI, APB). +//----------------------------------------------------------------------------- +// Copyright (C) 2013-2020 ETH Zurich, University of Bologna // Copyright and related rights are licensed under the Solderpad Hardware // License, Version 0.51 (the "License"); you may not use this file except in -// compliance with the License. You may obtain a copy of the License at +// compliance with the License. You may obtain a copy of the License at // http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law // or agreed to in writing, software, hardware and materials distributed under // this License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR // CONDITIONS OF ANY KIND, either express or implied. See the License for the // specific language governing permissions and limitations under the License. - - -module soc_interconnect_wrap #( - parameter N_L2_BANKS = 4, - parameter N_L2_BANKS_PRI = 2, - parameter N_HWPE_PORTS = 4, - parameter ADDR_MEM_WIDTH = 12, - parameter ADDR_MEM_PRI_WIDTH = 12, - parameter AXI_32_ID_WIDTH = 12, - parameter AXI_32_USER_WIDTH = 6, - parameter ROM_ADDR_WIDTH = 10, - // 64 bit axi Interface - parameter AXI_ADDR_WIDTH = 32, - parameter AXI_DATA_WIDTH = 64, - parameter AXI_STRB_WIDTH = 8, - parameter AXI_USER_WIDTH = 6, - parameter AXI_ID_WIDTH = 7 -) ( - input logic clk_i, - input logic rstn_i, - input logic test_en_i, - XBAR_TCDM_BUS.Slave lint_fc_data, - XBAR_TCDM_BUS.Slave lint_fc_instr, - XBAR_TCDM_BUS.Slave lint_udma_tx, - XBAR_TCDM_BUS.Slave lint_udma_rx, - XBAR_TCDM_BUS.Slave lint_debug, - XBAR_TCDM_BUS.Slave lint_hwpe [N_HWPE_PORTS-1:0], - AXI_BUS.Slave axi_from_cluster, - AXI_BUS.Master axi_to_cluster, - APB_BUS.Master apb_periph_bus, - UNICAD_MEM_BUS_32.Master mem_l2_bus[N_L2_BANKS-1:0], - UNICAD_MEM_BUS_32.Master mem_l2_pri_bus[N_L2_BANKS_PRI-1:0], - UNICAD_MEM_BUS_32.Master mem_rom_bus -); - - logic [N_L2_BANKS-1:0][31:0] mem_wdata; - logic [N_L2_BANKS-1:0][ADDR_MEM_WIDTH-1:0] mem_add; - logic [N_L2_BANKS-1:0] mem_csn; - logic [N_L2_BANKS-1:0] mem_wen; - logic [N_L2_BANKS-1:0][3:0] mem_be; - logic [N_L2_BANKS-1:0][31:0] mem_rdata; - - logic [N_L2_BANKS_PRI-1:0][31:0] mem_pri_wdata; - logic [N_L2_BANKS_PRI-1:0][ADDR_MEM_PRI_WIDTH-1:0] mem_pri_add; - logic [N_L2_BANKS_PRI-1:0] mem_pri_csn; - logic [N_L2_BANKS_PRI-1:0] mem_pri_wen; - logic [N_L2_BANKS_PRI-1:0][3:0] mem_pri_be; - logic [N_L2_BANKS_PRI-1:0][31:0] mem_pri_rdata; - - // accelerator interface - must be unrolled - logic [N_HWPE_PORTS-1:0] s_lint_hwpe_req; - logic [N_HWPE_PORTS-1:0][31:0] s_lint_hwpe_add; - logic [N_HWPE_PORTS-1:0] s_lint_hwpe_wen; - logic [N_HWPE_PORTS-1:0][31:0] s_lint_hwpe_wdata; - logic [N_HWPE_PORTS-1:0][3:0] s_lint_hwpe_be; - logic [N_HWPE_PORTS-1:0] s_lint_hwpe_gnt; - logic [N_HWPE_PORTS-1:0] s_lint_hwpe_r_valid; - logic [N_HWPE_PORTS-1:0][31:0] s_lint_hwpe_r_rdata; - logic [N_HWPE_PORTS-1:0] s_lint_hwpe_r_opc; - - genvar i; - - generate - - for(i=0; iTCDM protocol converter does not support any other + // datawidths than 64-bit + parameter int AXI_IN_ID_WIDTH = 6, + parameter int AXI_USER_WIDTH = 6, + // Axi Output Plug + localparam int AXI_OUT_ADDR_WIDTH = 32, // All addresses in the SoC must be 32-bit + localparam int AXI_OUT_DATA_WIDTH = 32 // The internal TCDM->AXI protocol converter does not support any other + // datawidths than 32-bit + ) ( + input logic clk_i, + input logic rst_ni, + input logic test_en_i, + XBAR_TCDM_BUS.Slave tcdm_fc_data, //Data Port of the Fabric Controller + XBAR_TCDM_BUS.Slave tcdm_fc_instr, //Instruction Port of the Fabric Controller + XBAR_TCDM_BUS.Slave tcdm_udma_tx, //TX Channel for the uDMA + XBAR_TCDM_BUS.Slave tcdm_udma_rx, //RX Channel for the uDMA + XBAR_TCDM_BUS.Slave tcdm_debug, //Debug access port from either the legacy or the riscv-debug unit + XBAR_TCDM_BUS.Slave tcdm_hwpe[NR_HWPE_PORTS], //Hardware Processing Element ports + AXI_BUS.Slave axi_master_plug, // Normaly used for cluster -> SoC communication + AXI_BUS.Master axi_slave_plug, // Normaly used for SoC -> cluster communication + APB_BUS.Master apb_peripheral_bus, // Connects to all the SoC Peripherals + XBAR_TCDM_BUS.Master l2_interleaved_slaves[NR_L2_PORTS], // Connects to the interleaved memory banks + XBAR_TCDM_BUS.Master l2_private_slaves[2], // Connects to core-private memory banks + XBAR_TCDM_BUS.Master boot_rom_slave //Connects to the bootrom + ); + + //**Do not change these values unles you verified that all downstream IPs are properly parametrized and support it** + localparam ADDR_WIDTH = 32; + localparam DATA_WIDTH = 32; + + + ////////////////////////////////////////////////////////////// + // 64-bit AXI to TCDM Bridge (Cluster to SoC communication) // + ////////////////////////////////////////////////////////////// + XBAR_TCDM_BUS axi_bridge_2_interconnect[4](); //We need 4 32-bit TCDM ports to achieve fullbandwidth with one 64-bit AXI + //port + + axi64_2_lint32_wrap #( + .AXI_USER_WIDTH(AXI_USER_WIDTH), + .AXI_ID_WIDTH(AXI_IN_ID_WIDTH) + ) i_axi64_to_lint32( + .clk_i, + .rst_ni, + .test_en_i, + .axi_master(axi_master_plug), + .tcdm_slaves(axi_bridge_2_interconnect) + ); + + + + //////////////////////////////////////// + // Address Rules for the interconnect // + //////////////////////////////////////// + localparam NR_RULES_L2_DEMUX = 4; + //Everything that is not routed to port 1 or 2 ends up in port 0 by default + localparam addr_map_rule_t [NR_RULES_L2_DEMUX-1:0] L2_DEMUX_RULES = '{ + '{ idx: 1 , start_addr: `SOC_MEM_MAP_PRIVATE_BANK0_START_ADDR , end_addr: `SOC_MEM_MAP_PRIVATE_BANK1_END_ADDR} , //Both , bank0 and bank1 are in the same address block + '{ idx: 1 , start_addr: `SOC_MEM_MAP_BOOT_ROM_START_ADDR , end_addr: `SOC_MEM_MAP_BOOT_ROM_END_ADDR} , + '{ idx: 2 , start_addr: `SOC_MEM_MAP_TCDM_START_ADDR , end_addr: `SOC_MEM_MAP_TCDM_END_ADDR } , + '{ idx: 2 , start_addr: `SOC_MEM_MAP_TCDM_ALIAS_START_ADDR , end_addr: `SOC_MEM_MAP_TCDM_ALIAS_END_ADDR}}; + + localparam NR_RULES_CONTIG_CROSSBAR = 3; + localparam addr_map_rule_t [NR_RULES_CONTIG_CROSSBAR-1:0] CONTIGUOUS_CROSSBAR_RULES = '{ + '{ idx: 0 , start_addr: `SOC_MEM_MAP_PRIVATE_BANK0_START_ADDR , end_addr: `SOC_MEM_MAP_PRIVATE_BANK0_END_ADDR} , + '{ idx: 1 , start_addr: `SOC_MEM_MAP_PRIVATE_BANK1_START_ADDR , end_addr: `SOC_MEM_MAP_PRIVATE_BANK1_END_ADDR} , + '{ idx: 2 , start_addr: `SOC_MEM_MAP_BOOT_ROM_START_ADDR , end_addr: `SOC_MEM_MAP_BOOT_ROM_END_ADDR}}; + + localparam NR_RULES_AXI_CROSSBAR = 2; + localparam addr_map_rule_t [NR_RULES_AXI_CROSSBAR-1:0] AXI_CROSSBAR_RULES = '{ + '{ idx: 0, start_addr: `SOC_MEM_MAP_AXI_PLUG_START_ADDR, end_addr: `SOC_MEM_MAP_AXI_PLUG_END_ADDR}, + '{ idx: 1, start_addr: `SOC_MEM_MAP_PERIPHERALS_START_ADDR, end_addr: `SOC_MEM_MAP_PERIPHERALS_END_ADDR}}; + + ////////////////////////////// + // Instantiate Interconnect // + ////////////////////////////// + + localparam INTERNAL_NR_AXI_XBAR_MASTERS = 5 + 4; //5 for fc_instr, fc_data, udma_rx, udma_tx, debug_access and 4 + //four 64-bit axi plug + localparam AXI_SLAVE_ID_WIDTH = AXI_IN_ID_WIDTH + $clog2(INTERNAL_NR_AXI_XBAR_MASTERS); + + //Internal wiring to APB protocol converter + AXI_BUS #(.AXI_ADDR_WIDTH(32), + .AXI_DATA_WIDTH(32), + .AXI_ID_WIDTH(AXI_SLAVE_ID_WIDTH), + .AXI_USER_WIDTH(AXI_USER_WIDTH) + ) axi_to_axi_lite_bridge(); + + //Wiring signals to interconncet. Unfortunately Synopsys-2019.3 does not support assignment patterns in port lists + //directly + XBAR_TCDM_BUS master_ports[5+4](); + `TCDM_ASSIGN_INTF(master_ports[0], tcdm_fc_data) + `TCDM_ASSIGN_INTF(master_ports[1], tcdm_fc_instr) + `TCDM_ASSIGN_INTF(master_ports[2], tcdm_udma_tx) + `TCDM_ASSIGN_INTF(master_ports[3], tcdm_udma_rx) + `TCDM_ASSIGN_INTF(master_ports[4], tcdm_debug) + for (genvar i = 0; i < 4; i++) begin + `TCDM_ASSIGN_INTF(master_ports[5+i], axi_bridge_2_interconnect[i]) + end + + XBAR_TCDM_BUS contiguous_slaves[3](); + `TCDM_ASSIGN_INTF(l2_private_slaves[0], contiguous_slaves[0]) + `TCDM_ASSIGN_INTF(l2_private_slaves[1], contiguous_slaves[1]) + `TCDM_ASSIGN_INTF(boot_rom_slave, contiguous_slaves[2]) + + AXI_BUS #(.AXI_ADDR_WIDTH(32), + .AXI_DATA_WIDTH(32), + .AXI_ID_WIDTH(AXI_SLAVE_ID_WIDTH), + .AXI_USER_WIDTH(AXI_USER_WIDTH) + ) axi_slaves[2](); + `AXI_ASSIGN(axi_slave_plug, axi_slaves[0]) + `AXI_ASSIGN(axi_to_axi_lite_bridge, axi_slaves[1]) + + //Interconnect instantiation soc_interconnect #( - .N_L2_BANKS ( N_L2_BANKS ), - .ADDR_L2_WIDTH ( ADDR_MEM_WIDTH ), - .N_HWPE_PORTS ( N_HWPE_PORTS ), - - .AXI_32_ID_WIDTH ( AXI_32_ID_WIDTH ), - .AXI_32_USER_WIDTH ( AXI_32_USER_WIDTH ), - - .AXI_ADDR_WIDTH ( AXI_ADDR_WIDTH ), - .AXI_DATA_WIDTH ( AXI_DATA_WIDTH ), - .AXI_STRB_WIDTH ( AXI_STRB_WIDTH ), - .AXI_USER_WIDTH ( AXI_USER_WIDTH ), - .AXI_ID_WIDTH ( AXI_ID_WIDTH ), - - .N_L2_BANKS_PRI ( N_L2_BANKS_PRI ), - .ADDR_L2_PRI_WIDTH ( ADDR_MEM_PRI_WIDTH ), - .ROM_ADDR_WIDTH ( ROM_ADDR_WIDTH ) - ) i_soc_interconnect ( - .clk ( clk_i ), - .rst_n ( rstn_i ), - .test_en_i ( test_en_i ), - - .L2_D_o ( mem_wdata ), - .L2_A_o ( mem_add ), - .L2_CEN_o ( mem_csn ), - .L2_WEN_o ( mem_wen ), - .L2_BE_o ( mem_be ), - .L2_Q_i ( mem_rdata ), - - .L2_pri_D_o ( mem_pri_wdata ), - .L2_pri_A_o ( mem_pri_add ), - .L2_pri_CEN_o ( mem_pri_csn ), - .L2_pri_WEN_o ( mem_pri_wen ), - .L2_pri_BE_o ( mem_pri_be ), - .L2_pri_Q_i ( mem_pri_rdata ), - - //RISC DATA PORT - .FC_DATA_req_i ( lint_fc_data.req ), - .FC_DATA_add_i ( lint_fc_data.add ), - .FC_DATA_wen_i ( lint_fc_data.wen ), - .FC_DATA_wdata_i ( lint_fc_data.wdata ), - .FC_DATA_be_i ( lint_fc_data.be ), - .FC_DATA_aux_i ( '0 ), - .FC_DATA_gnt_o ( lint_fc_data.gnt ), - .FC_DATA_r_aux_o ( ), - .FC_DATA_r_valid_o ( lint_fc_data.r_valid ), - .FC_DATA_r_rdata_o ( lint_fc_data.r_rdata ), - .FC_DATA_r_opc_o ( lint_fc_data.r_opc ), - - // RISC INSTR PORT - .FC_INSTR_req_i ( lint_fc_instr.req ), - .FC_INSTR_add_i ( lint_fc_instr.add ), - .FC_INSTR_wen_i ( lint_fc_instr.wen ), - .FC_INSTR_wdata_i ( lint_fc_instr.wdata ), - .FC_INSTR_be_i ( lint_fc_instr.be ), - .FC_INSTR_aux_i ( '0 ), - .FC_INSTR_gnt_o ( lint_fc_instr.gnt ), - .FC_INSTR_r_aux_o ( ), - .FC_INSTR_r_valid_o ( lint_fc_instr.r_valid ), - .FC_INSTR_r_rdata_o ( lint_fc_instr.r_rdata ), - .FC_INSTR_r_opc_o ( lint_fc_instr.r_opc ), - - // UDMA TX - .UDMA_TX_req_i ( lint_udma_tx.req ), - .UDMA_TX_add_i ( lint_udma_tx.add ), - .UDMA_TX_wen_i ( lint_udma_tx.wen ), - .UDMA_TX_wdata_i ( lint_udma_tx.wdata ), - .UDMA_TX_be_i ( lint_udma_tx.be ), - .UDMA_TX_aux_i ( '0 ), - .UDMA_TX_gnt_o ( lint_udma_tx.gnt ), - .UDMA_TX_r_aux_o ( ), - .UDMA_TX_r_valid_o ( lint_udma_tx.r_valid ), - .UDMA_TX_r_rdata_o ( lint_udma_tx.r_rdata ), - .UDMA_TX_r_opc_o ( lint_udma_tx.r_opc ), - - // UDMA RX - .UDMA_RX_req_i ( lint_udma_rx.req ), - .UDMA_RX_add_i ( lint_udma_rx.add ), - .UDMA_RX_wen_i ( lint_udma_rx.wen ), - .UDMA_RX_wdata_i ( lint_udma_rx.wdata ), - .UDMA_RX_be_i ( lint_udma_rx.be ), - .UDMA_RX_aux_i ( '0 ), - .UDMA_RX_gnt_o ( lint_udma_rx.gnt ), - .UDMA_RX_r_aux_o ( ), - .UDMA_RX_r_valid_o ( lint_udma_rx.r_valid ), - .UDMA_RX_r_rdata_o ( lint_udma_rx.r_rdata ), - .UDMA_RX_r_opc_o ( lint_udma_rx.r_opc ), - - // DBG - .DBG_RX_req_i ( lint_debug.req ), - .DBG_RX_add_i ( lint_debug.add ), - .DBG_RX_wen_i ( lint_debug.wen ), - .DBG_RX_wdata_i ( lint_debug.wdata ), - .DBG_RX_be_i ( lint_debug.be ), - .DBG_RX_aux_i ( '0 ), - .DBG_RX_gnt_o ( lint_debug.gnt ), - .DBG_RX_r_aux_o ( ), - .DBG_RX_r_valid_o ( lint_debug.r_valid ), - .DBG_RX_r_rdata_o ( lint_debug.r_rdata ), - .DBG_RX_r_opc_o ( lint_debug.r_opc ), - - // HWPE - .HWPE_req_i ( s_lint_hwpe_req ), - .HWPE_add_i ( s_lint_hwpe_add ), - .HWPE_wen_i ( s_lint_hwpe_wen ), - .HWPE_wdata_i ( s_lint_hwpe_wdata ), - .HWPE_be_i ( s_lint_hwpe_be ), - .HWPE_aux_i ( '0 ), - .HWPE_gnt_o ( s_lint_hwpe_gnt ), - .HWPE_r_aux_o ( ), - .HWPE_r_valid_o ( s_lint_hwpe_r_valid ), - .HWPE_r_rdata_o ( s_lint_hwpe_r_rdata ), - .HWPE_r_opc_o ( s_lint_hwpe_r_opc ), - - // AXI INTERFACE (FROM CLUSTER) - .AXI_Slave_aw_addr_i ( axi_from_cluster.aw_addr ), - .AXI_Slave_aw_prot_i ( axi_from_cluster.aw_prot ), - .AXI_Slave_aw_region_i ( axi_from_cluster.aw_region ), - .AXI_Slave_aw_len_i ( axi_from_cluster.aw_len ), - .AXI_Slave_aw_size_i ( axi_from_cluster.aw_size ), - .AXI_Slave_aw_burst_i ( axi_from_cluster.aw_burst ), - .AXI_Slave_aw_lock_i ( axi_from_cluster.aw_lock ), - .AXI_Slave_aw_cache_i ( axi_from_cluster.aw_cache ), - .AXI_Slave_aw_qos_i ( axi_from_cluster.aw_qos ), - .AXI_Slave_aw_id_i ( axi_from_cluster.aw_id[AXI_ID_WIDTH-1:0] ), - .AXI_Slave_aw_user_i ( axi_from_cluster.aw_user[AXI_USER_WIDTH-1:0] ), - .AXI_Slave_aw_valid_i ( axi_from_cluster.aw_valid ), - .AXI_Slave_aw_ready_o ( axi_from_cluster.aw_ready ), - // ADDRESS READ CHANNEL - .AXI_Slave_ar_addr_i ( axi_from_cluster.ar_addr ), - .AXI_Slave_ar_prot_i ( axi_from_cluster.ar_prot ), - .AXI_Slave_ar_region_i ( axi_from_cluster.ar_region ), - .AXI_Slave_ar_len_i ( axi_from_cluster.ar_len ), - .AXI_Slave_ar_size_i ( axi_from_cluster.ar_size ), - .AXI_Slave_ar_burst_i ( axi_from_cluster.ar_burst ), - .AXI_Slave_ar_lock_i ( axi_from_cluster.ar_lock ), - .AXI_Slave_ar_cache_i ( axi_from_cluster.ar_cache ), - .AXI_Slave_ar_qos_i ( axi_from_cluster.ar_qos ), - .AXI_Slave_ar_id_i ( axi_from_cluster.ar_id[AXI_ID_WIDTH-1:0] ), - .AXI_Slave_ar_user_i ( axi_from_cluster.ar_user[AXI_USER_WIDTH-1:0] ), - .AXI_Slave_ar_valid_i ( axi_from_cluster.ar_valid ), - .AXI_Slave_ar_ready_o ( axi_from_cluster.ar_ready ), - // WRITE CHANNEL - .AXI_Slave_w_user_i ( axi_from_cluster.w_user[AXI_USER_WIDTH-1:0] ), - .AXI_Slave_w_data_i ( axi_from_cluster.w_data ), - .AXI_Slave_w_strb_i ( axi_from_cluster.w_strb ), - .AXI_Slave_w_last_i ( axi_from_cluster.w_last ), - .AXI_Slave_w_valid_i ( axi_from_cluster.w_valid ), - .AXI_Slave_w_ready_o ( axi_from_cluster.w_ready ), - // WRITE RESPONSE CHANNEL - .AXI_Slave_b_id_o ( axi_from_cluster.b_id[AXI_ID_WIDTH-1:0] ), - .AXI_Slave_b_resp_o ( axi_from_cluster.b_resp ), - .AXI_Slave_b_user_o ( axi_from_cluster.b_user[AXI_USER_WIDTH-1:0] ), - .AXI_Slave_b_valid_o ( axi_from_cluster.b_valid ), - .AXI_Slave_b_ready_i ( axi_from_cluster.b_ready ), - // READ CHANNEL - .AXI_Slave_r_id_o ( axi_from_cluster.r_id[AXI_ID_WIDTH-1:0] ), - .AXI_Slave_r_user_o ( axi_from_cluster.r_user[AXI_USER_WIDTH-1:0] ), - .AXI_Slave_r_data_o ( axi_from_cluster.r_data ), - .AXI_Slave_r_resp_o ( axi_from_cluster.r_resp ), - .AXI_Slave_r_last_o ( axi_from_cluster.r_last ), - .AXI_Slave_r_valid_o ( axi_from_cluster.r_valid ), - .AXI_Slave_r_ready_i ( axi_from_cluster.r_ready ), - - // BRIDGES - // LINT TO APB - .APB_PADDR_o ( apb_periph_bus.paddr ), - .APB_PWDATA_o ( apb_periph_bus.pwdata ), - .APB_PWRITE_o ( apb_periph_bus.pwrite ), - .APB_PSEL_o ( apb_periph_bus.psel ), - .APB_PENABLE_o ( apb_periph_bus.penable ), - .APB_PRDATA_i ( apb_periph_bus.prdata ), - .APB_PREADY_i ( apb_periph_bus.pready ), - .APB_PSLVERR_i ( apb_periph_bus.pslverr ), - - // ROM binding --> no need of Flow control, already handled in fc_interconnect - .rom_csn_o ( mem_rom_bus.csn ), - .rom_add_o ( mem_rom_bus.add[ROM_ADDR_WIDTH-1:0] ), - .rom_rdata_i ( mem_rom_bus.rdata ), - - // LINT TO AXI - // --------------------------------------------------------- - // AXI TARG Port Declarations ------------------------------ - // --------------------------------------------------------- - .AXI_Master_aw_addr_o ( axi_to_cluster.aw_addr ), - .AXI_Master_aw_prot_o ( axi_to_cluster.aw_prot ), - .AXI_Master_aw_region_o ( axi_to_cluster.aw_region ), - .AXI_Master_aw_len_o ( axi_to_cluster.aw_len ), - .AXI_Master_aw_size_o ( axi_to_cluster.aw_size ), - .AXI_Master_aw_burst_o ( axi_to_cluster.aw_burst ), - .AXI_Master_aw_lock_o ( axi_to_cluster.aw_lock ), - .AXI_Master_aw_cache_o ( axi_to_cluster.aw_cache ), - .AXI_Master_aw_qos_o ( axi_to_cluster.aw_qos ), - .AXI_Master_aw_id_o ( axi_to_cluster.aw_id[AXI_32_ID_WIDTH-1:0] ), - .AXI_Master_aw_user_o ( axi_to_cluster.aw_user[AXI_32_USER_WIDTH-1:0] ), - .AXI_Master_aw_valid_o ( axi_to_cluster.aw_valid ), - .AXI_Master_aw_ready_i ( axi_to_cluster.aw_ready ), - // ADDRESS READ CHANNEL - .AXI_Master_ar_addr_o ( axi_to_cluster.ar_addr ), - .AXI_Master_ar_prot_o ( axi_to_cluster.ar_prot ), - .AXI_Master_ar_region_o ( axi_to_cluster.ar_region ), - .AXI_Master_ar_len_o ( axi_to_cluster.ar_len ), - .AXI_Master_ar_size_o ( axi_to_cluster.ar_size ), - .AXI_Master_ar_burst_o ( axi_to_cluster.ar_burst ), - .AXI_Master_ar_lock_o ( axi_to_cluster.ar_lock ), - .AXI_Master_ar_cache_o ( axi_to_cluster.ar_cache ), - .AXI_Master_ar_qos_o ( axi_to_cluster.ar_qos ), - .AXI_Master_ar_id_o ( axi_to_cluster.ar_id[AXI_32_ID_WIDTH-1:0] ), - .AXI_Master_ar_user_o ( axi_to_cluster.ar_user[AXI_32_USER_WIDTH-1:0] ), - .AXI_Master_ar_valid_o ( axi_to_cluster.ar_valid ), - .AXI_Master_ar_ready_i ( axi_to_cluster.ar_ready ), - // WRITE CHANNEL - .AXI_Master_w_user_o ( axi_to_cluster.w_user[AXI_32_USER_WIDTH-1:0] ), - .AXI_Master_w_data_o ( axi_to_cluster.w_data ), - .AXI_Master_w_strb_o ( axi_to_cluster.w_strb ), - .AXI_Master_w_last_o ( axi_to_cluster.w_last ), - .AXI_Master_w_valid_o ( axi_to_cluster.w_valid ), - .AXI_Master_w_ready_i ( axi_to_cluster.w_ready ), - // WRITE RESPONSE CHANNEL - .AXI_Master_b_id_i ( axi_to_cluster.b_id[AXI_32_ID_WIDTH-1:0] ), - .AXI_Master_b_resp_i ( axi_to_cluster.b_resp ), - .AXI_Master_b_user_i ( axi_to_cluster.b_user[AXI_32_USER_WIDTH-1:0] ), - .AXI_Master_b_valid_i ( axi_to_cluster.b_valid ), - .AXI_Master_b_ready_o ( axi_to_cluster.b_ready ), - // READ CHANNEL - .AXI_Master_r_id_i ( axi_to_cluster.r_id[AXI_32_ID_WIDTH-1:0] ), - .AXI_Master_r_user_i ( axi_to_cluster.r_user[AXI_32_USER_WIDTH-1:0] ), - .AXI_Master_r_data_i ( axi_to_cluster.r_data ), - .AXI_Master_r_resp_i ( axi_to_cluster.r_resp ), - .AXI_Master_r_last_i ( axi_to_cluster.r_last ), - .AXI_Master_r_valid_i ( axi_to_cluster.r_valid ), - .AXI_Master_r_ready_o ( axi_to_cluster.r_ready ) - ); - -endmodule - + .NR_MASTER_PORTS(5+4), // FC instructions, FC data, uDMA RX, uDMA TX, debug access, 4 four 64-bit + // axi plug + .NR_MASTER_PORTS_INTERLEAVED_ONLY(NR_HWPE_PORTS), // HWPEs (PULP accelerators) only have access + // to the interleaved memory region + .NR_ADDR_RULES_L2_DEMUX(NR_RULES_L2_DEMUX), + .NR_SLAVE_PORTS_INTERLEAVED(NR_L2_PORTS), // Number of interleaved memory banks + .NR_SLAVE_PORTS_CONTIG(3), // Bootrom + number of private memory banks (normally 1 for + // programm instructions and 1 for programm stack ) + .NR_ADDR_RULES_SLAVE_PORTS_CONTIG(NR_RULES_CONTIG_CROSSBAR), + .NR_AXI_SLAVE_PORTS(2), // 1 for AXI to cluster, 1 for SoC peripherals (converted to APB) + .NR_ADDR_RULES_AXI_SLAVE_PORTS(NR_RULES_AXI_CROSSBAR), + .AXI_MASTER_ID_WIDTH(AXI_IN_ID_WIDTH), + .AXI_USER_WIDTH(AXI_USER_WIDTH) + ) i_soc_interconnect ( + .clk_i, + .rst_ni, + .test_en_i, + .master_ports(master_ports), + .master_ports_interleaved_only(tcdm_hwpe), + .addr_space_l2_demux(L2_DEMUX_RULES), + .interleaved_slaves(l2_interleaved_slaves), + .addr_space_contiguous(CONTIGUOUS_CROSSBAR_RULES), + .contiguous_slaves(contiguous_slaves), + .addr_space_axi(AXI_CROSSBAR_RULES), + .axi_slaves(axi_slaves) + ); + + + //////////////////////// + // AXI4 to APB Bridge // + /////////////////////////////////////////////////////////////////////////////////////////// + // We do the conversion in two steps: We convert AXI4 to AXI4 lite and from there to APB // + /////////////////////////////////////////////////////////////////////////////////////////// + + AXI_LITE #( + .AXI_ADDR_WIDTH(32), + .AXI_DATA_WIDTH(32)) axi_lite_to_apb_bridge(); + + axi_to_axi_lite_intf #( + .AXI_ADDR_WIDTH(32), + .AXI_DATA_WIDTH(32), + .AXI_ID_WIDTH(AXI_SLAVE_ID_WIDTH), + .AXI_USER_WIDTH(AXI_USER_WIDTH), + .AXI_MAX_WRITE_TXNS(1), + .AXI_MAX_READ_TXNS(1), + .FALL_THROUGH(1) + ) i_axi_to_axi_lite ( + .clk_i, + .rst_ni, + .testmode_i(test_en_i), + .slv(axi_to_axi_lite_bridge), + .mst(axi_lite_to_apb_bridge) + ); + + // The AXI-Lite to APB bridge is capable of connecting one AXI to multiple APB ports using address mapping rules. + // We do not use this feature and just supply a default rule that matches everything in the peripheral region + + localparam addr_map_rule_t [0:0] APB_BRIDGE_RULES = '{ + '{ idx: 0, start_addr: `SOC_MEM_MAP_PERIPHERALS_START_ADDR, end_addr: `SOC_MEM_MAP_PERIPHERALS_END_ADDR}}; + + axi_lite_to_apb_intf #( + .NoApbSlaves(1), + .NoRules(1), + .AddrWidth(32), + .DataWidth(32), + .rule_t(addr_map_rule_t) + ) i_axi_lite_to_apb ( + .clk_i, + .rst_ni, + .slv(axi_lite_to_apb_bridge), + .paddr_o(apb_peripheral_bus.paddr), + .pprot_o(), + .pselx_o(apb_peripheral_bus.psel), + .penable_o(apb_peripheral_bus.penable), + .pwrite_o(apb_peripheral_bus.pwrite), + .pwdata_o(apb_peripheral_bus.pwdata), + .pstrb_o(), + .pready_i(apb_peripheral_bus.pready), + .prdata_i(apb_peripheral_bus.prdata), + .pslverr_i(apb_peripheral_bus.pslverr), + .addr_map_i(APB_BRIDGE_RULES) + ); + + +endmodule : soc_interconnect_wrap diff --git a/rtl/pulp_soc/soc_interconnect_wrap_v2.sv b/rtl/pulp_soc/soc_interconnect_wrap_v2.sv deleted file mode 100644 index 4adffe1f..00000000 --- a/rtl/pulp_soc/soc_interconnect_wrap_v2.sv +++ /dev/null @@ -1,234 +0,0 @@ -//----------------------------------------------------------------------------- -// Title : SoC Interconnect Wrapper -//----------------------------------------------------------------------------- -// File : soc_interconnect_wrap_v2.sv -// Author : Manuel Eggimann -// Created : 30.10.2020 -//----------------------------------------------------------------------------- -// Description : -// This module instantiates the SoC interconnect and attaches the various SoC -// ports. Furthermore, the wrapper also instantiates the required protocol converters -// (AXI, APB). -//----------------------------------------------------------------------------- -// Copyright (C) 2013-2020 ETH Zurich, University of Bologna -// Copyright and related rights are licensed under the Solderpad Hardware -// License, Version 0.51 (the "License"); you may not use this file except in -// compliance with the License. You may obtain a copy of the License at -// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law -// or agreed to in writing, software, hardware and materials distributed under -// this License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR -// CONDITIONS OF ANY KIND, either express or implied. See the License for the -// specific language governing permissions and limitations under the License. -//----------------------------------------------------------------------------- - -`include "soc_mem_map.svh" -`include "tcdm_macros.svh" -`include "axi/assign.svh" - - -module soc_interconnect_wrap - import pkg_soc_interconnect::addr_map_rule_t; - #( - parameter int NR_HWPE_PORTS = 0, - parameter int NR_L2_PORTS = 4, - // AXI Input Plug - localparam int AXI_IN_ADDR_WIDTH = 32, // All addresses in the SoC must be 32-bit - localparam int AXI_IN_DATA_WIDTH = 64, // The internal AXI->TCDM protocol converter does not support any other - // datawidths than 64-bit - parameter int AXI_IN_ID_WIDTH = 6, - parameter int AXI_USER_WIDTH = 6, - // Axi Output Plug - localparam int AXI_OUT_ADDR_WIDTH = 32, // All addresses in the SoC must be 32-bit - localparam int AXI_OUT_DATA_WIDTH = 32 // The internal TCDM->AXI protocol converter does not support any other - // datawidths than 32-bit - ) ( - input logic clk_i, - input logic rst_ni, - input logic test_en_i, - XBAR_TCDM_BUS.Slave tcdm_fc_data, //Data Port of the Fabric Controller - XBAR_TCDM_BUS.Slave tcdm_fc_instr, //Instruction Port of the Fabric Controller - XBAR_TCDM_BUS.Slave tcdm_udma_tx, //TX Channel for the uDMA - XBAR_TCDM_BUS.Slave tcdm_udma_rx, //RX Channel for the uDMA - XBAR_TCDM_BUS.Slave tcdm_debug, //Debug access port from either the legacy or the riscv-debug unit - XBAR_TCDM_BUS.Slave tcdm_hwpe[NR_HWPE_PORTS], //Hardware Processing Element ports - AXI_BUS.Slave axi_master_plug, // Normaly used for cluster -> SoC communication - AXI_BUS.Master axi_slave_plug, // Normaly used for SoC -> cluster communication - APB_BUS.Master apb_peripheral_bus, // Connects to all the SoC Peripherals - XBAR_TCDM_BUS.Master l2_interleaved_slaves[NR_L2_PORTS], // Connects to the interleaved memory banks - XBAR_TCDM_BUS.Master l2_private_slaves[2], // Connects to core-private memory banks - XBAR_TCDM_BUS.Master boot_rom_slave //Connects to the bootrom - ); - - //**Do not change these values unles you verified that all downstream IPs are properly parametrized and support it** - localparam ADDR_WIDTH = 32; - localparam DATA_WIDTH = 32; - - - ////////////////////////////////////////////////////////////// - // 64-bit AXI to TCDM Bridge (Cluster to SoC communication) // - ////////////////////////////////////////////////////////////// - XBAR_TCDM_BUS axi_bridge_2_interconnect[4](); //We need 4 32-bit TCDM ports to achieve fullbandwidth with one 64-bit AXI - //port - - axi64_2_lint32_wrap #( - .AXI_USER_WIDTH(AXI_USER_WIDTH), - .AXI_ID_WIDTH(AXI_IN_ID_WIDTH) - ) i_axi64_to_lint32( - .clk_i, - .rst_ni, - .test_en_i, - .axi_master(axi_master_plug), - .tcdm_slaves(axi_bridge_2_interconnect) - ); - - - - //////////////////////////////////////// - // Address Rules for the interconnect // - //////////////////////////////////////// - localparam NR_RULES_L2_DEMUX = 4; - //Everything that is not routed to port 1 or 2 ends up in port 0 by default - localparam addr_map_rule_t [NR_RULES_L2_DEMUX-1:0] L2_DEMUX_RULES = '{ - '{ idx: 1 , start_addr: `SOC_MEM_MAP_PRIVATE_BANK0_START_ADDR , end_addr: `SOC_MEM_MAP_PRIVATE_BANK1_END_ADDR} , //Both , bank0 and bank1 are in the same address block - '{ idx: 1 , start_addr: `SOC_MEM_MAP_BOOT_ROM_START_ADDR , end_addr: `SOC_MEM_MAP_BOOT_ROM_END_ADDR} , - '{ idx: 2 , start_addr: `SOC_MEM_MAP_TCDM_START_ADDR , end_addr: `SOC_MEM_MAP_TCDM_END_ADDR } , - '{ idx: 2 , start_addr: `SOC_MEM_MAP_TCDM_ALIAS_START_ADDR , end_addr: `SOC_MEM_MAP_TCDM_ALIAS_END_ADDR}}; - - localparam NR_RULES_CONTIG_CROSSBAR = 3; - localparam addr_map_rule_t [NR_RULES_CONTIG_CROSSBAR-1:0] CONTIGUOUS_CROSSBAR_RULES = '{ - '{ idx: 0 , start_addr: `SOC_MEM_MAP_PRIVATE_BANK0_START_ADDR , end_addr: `SOC_MEM_MAP_PRIVATE_BANK0_END_ADDR} , - '{ idx: 1 , start_addr: `SOC_MEM_MAP_PRIVATE_BANK1_START_ADDR , end_addr: `SOC_MEM_MAP_PRIVATE_BANK1_END_ADDR} , - '{ idx: 2 , start_addr: `SOC_MEM_MAP_BOOT_ROM_START_ADDR , end_addr: `SOC_MEM_MAP_BOOT_ROM_END_ADDR}}; - - localparam NR_RULES_AXI_CROSSBAR = 2; - localparam addr_map_rule_t [NR_RULES_AXI_CROSSBAR-1:0] AXI_CROSSBAR_RULES = '{ - '{ idx: 0, start_addr: `SOC_MEM_MAP_AXI_PLUG_START_ADDR, end_addr: `SOC_MEM_MAP_AXI_PLUG_END_ADDR}, - '{ idx: 1, start_addr: `SOC_MEM_MAP_PERIPHERALS_START_ADDR, end_addr: `SOC_MEM_MAP_PERIPHERALS_END_ADDR}}; - - ////////////////////////////// - // Instantiate Interconnect // - ////////////////////////////// - - localparam INTERNAL_NR_AXI_XBAR_MASTERS = 5 + 4; //5 for fc_instr, fc_data, udma_rx, udma_tx, debug_access and 4 - //four 64-bit axi plug - localparam AXI_SLAVE_ID_WIDTH = AXI_IN_ID_WIDTH + $clog2(INTERNAL_NR_AXI_XBAR_MASTERS); - - //Internal wiring to APB protocol converter - AXI_BUS #(.AXI_ADDR_WIDTH(32), - .AXI_DATA_WIDTH(32), - .AXI_ID_WIDTH(AXI_SLAVE_ID_WIDTH), - .AXI_USER_WIDTH(AXI_USER_WIDTH) - ) axi_to_axi_lite_bridge(); - - //Wiring signals to interconncet. Unfortunately Synopsys-2019.3 does not support assignment patterns in port lists - //directly - XBAR_TCDM_BUS master_ports[5+4](); - `TCDM_ASSIGN_INTF(master_ports[0], tcdm_fc_data) - `TCDM_ASSIGN_INTF(master_ports[1], tcdm_fc_instr) - `TCDM_ASSIGN_INTF(master_ports[2], tcdm_udma_tx) - `TCDM_ASSIGN_INTF(master_ports[3], tcdm_udma_rx) - `TCDM_ASSIGN_INTF(master_ports[4], tcdm_debug) - for (genvar i = 0; i < 4; i++) begin - `TCDM_ASSIGN_INTF(master_ports[5+i], axi_bridge_2_interconnect[i]) - end - - XBAR_TCDM_BUS contiguous_slaves[3](); - `TCDM_ASSIGN_INTF(l2_private_slaves[0], contiguous_slaves[0]) - `TCDM_ASSIGN_INTF(l2_private_slaves[1], contiguous_slaves[1]) - `TCDM_ASSIGN_INTF(boot_rom_slave, contiguous_slaves[2]) - - AXI_BUS #(.AXI_ADDR_WIDTH(32), - .AXI_DATA_WIDTH(32), - .AXI_ID_WIDTH(AXI_SLAVE_ID_WIDTH), - .AXI_USER_WIDTH(AXI_USER_WIDTH) - ) axi_slaves[2](); - `AXI_ASSIGN(axi_slave_plug, axi_slaves[0]) - `AXI_ASSIGN(axi_to_axi_lite_bridge, axi_slaves[1]) - - //Interconnect instantiation - soc_interconnect #( - .NR_MASTER_PORTS(5+4), // FC instructions, FC data, uDMA RX, uDMA TX, debug access, 4 four 64-bit - // axi plug - .NR_MASTER_PORTS_INTERLEAVED_ONLY(NR_HWPE_PORTS), // HWPEs (PULP accelerators) only have access - // to the interleaved memory region - .NR_ADDR_RULES_L2_DEMUX(NR_RULES_L2_DEMUX), - .NR_SLAVE_PORTS_INTERLEAVED(NR_L2_PORTS), // Number of interleaved memory banks - .NR_SLAVE_PORTS_CONTIG(3), // Bootrom + number of private memory banks (normally 1 for - // programm instructions and 1 for programm stack ) - .NR_ADDR_RULES_SLAVE_PORTS_CONTIG(NR_RULES_CONTIG_CROSSBAR), - .NR_AXI_SLAVE_PORTS(2), // 1 for AXI to cluster, 1 for SoC peripherals (converted to APB) - .NR_ADDR_RULES_AXI_SLAVE_PORTS(NR_RULES_AXI_CROSSBAR), - .AXI_MASTER_ID_WIDTH(AXI_IN_ID_WIDTH), - .AXI_USER_WIDTH(AXI_USER_WIDTH) - ) i_soc_interconnect ( - .clk_i, - .rst_ni, - .test_en_i, - .master_ports(master_ports), - .master_ports_interleaved_only(tcdm_hwpe), - .addr_space_l2_demux(L2_DEMUX_RULES), - .interleaved_slaves(l2_interleaved_slaves), - .addr_space_contiguous(CONTIGUOUS_CROSSBAR_RULES), - .contiguous_slaves(contiguous_slaves), - .addr_space_axi(AXI_CROSSBAR_RULES), - .axi_slaves(axi_slaves) - ); - - - //////////////////////// - // AXI4 to APB Bridge // - /////////////////////////////////////////////////////////////////////////////////////////// - // We do the conversion in two steps: We convert AXI4 to AXI4 lite and from there to APB // - /////////////////////////////////////////////////////////////////////////////////////////// - - AXI_LITE #( - .AXI_ADDR_WIDTH(32), - .AXI_DATA_WIDTH(32)) axi_lite_to_apb_bridge(); - - axi_to_axi_lite_intf #( - .AXI_ADDR_WIDTH(32), - .AXI_DATA_WIDTH(32), - .AXI_ID_WIDTH(AXI_SLAVE_ID_WIDTH), - .AXI_USER_WIDTH(AXI_USER_WIDTH), - .AXI_MAX_WRITE_TXNS(1), - .AXI_MAX_READ_TXNS(1), - .FALL_THROUGH(1) - ) i_axi_to_axi_lite ( - .clk_i, - .rst_ni, - .testmode_i(test_en_i), - .slv(axi_to_axi_lite_bridge), - .mst(axi_lite_to_apb_bridge) - ); - - // The AXI-Lite to APB bridge is capable of connecting one AXI to multiple APB ports using address mapping rules. - // We do not use this feature and just supply a default rule that matches everything in the peripheral region - - localparam addr_map_rule_t [0:0] APB_BRIDGE_RULES = '{ - '{ idx: 0, start_addr: `SOC_MEM_MAP_PERIPHERALS_START_ADDR, end_addr: `SOC_MEM_MAP_PERIPHERALS_END_ADDR}}; - - axi_lite_to_apb_intf #( - .NoApbSlaves(1), - .NoRules(1), - .AddrWidth(32), - .DataWidth(32), - .rule_t(addr_map_rule_t) - ) i_axi_lite_to_apb ( - .clk_i, - .rst_ni, - .slv(axi_lite_to_apb_bridge), - .paddr_o(apb_peripheral_bus.paddr), - .pprot_o(), - .pselx_o(apb_peripheral_bus.psel), - .penable_o(apb_peripheral_bus.penable), - .pwrite_o(apb_peripheral_bus.pwrite), - .pwdata_o(apb_peripheral_bus.pwdata), - .pstrb_o(), - .pready_i(apb_peripheral_bus.pready), - .prdata_i(apb_peripheral_bus.prdata), - .pslverr_i(apb_peripheral_bus.pslverr), - .addr_map_i(APB_BRIDGE_RULES) - ); - - -endmodule : soc_interconnect_wrap diff --git a/src_files.yml b/src_files.yml index 4b6b7bb2..62c9262c 100644 --- a/src_files.yml +++ b/src_files.yml @@ -11,7 +11,6 @@ pulp_soc: rtl/pulp_soc/contiguous_crossbar.sv, rtl/pulp_soc/interleaved_crossbar.sv, rtl/pulp_soc/tcdm_demux.sv, - rtl/pulp_soc/soc_interconnect_v2.sv, rtl/pulp_soc/boot_rom.sv, rtl/pulp_soc/l2_ram_multi_bank.sv, rtl/pulp_soc/lint_jtag_wrap.sv, @@ -20,7 +19,8 @@ pulp_soc: rtl/pulp_soc/soc_event_arbiter.sv, rtl/pulp_soc/soc_event_generator.sv, rtl/pulp_soc/soc_event_queue.sv, - rtl/pulp_soc/soc_interconnect_wrap_v2.sv, + rtl/pulp_soc/soc_interconnect.sv, + rtl/pulp_soc/soc_interconnect_wrap.sv, rtl/pulp_soc/soc_peripherals.sv, rtl/pulp_soc/pulp_soc.sv, ] From 95fdc3fe844a9a3e9aa13efbce5e361fb11ac6f4 Mon Sep 17 00:00:00 2001 From: Manuel Eggimann Date: Mon, 9 Nov 2020 17:12:58 +0100 Subject: [PATCH 18/30] Bump fpnew version --- ips_list.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ips_list.yml b/ips_list.yml index 6ebde0a6..9576b5bf 100644 --- a/ips_list.yml +++ b/ips_list.yml @@ -63,7 +63,7 @@ timer_unit: commit: v1.0.2 domain: [cluster, soc] fpnew: - commit: bump-common-cells + commit: v0.6.5 domain: [cluster, soc] jtag_pulp: commit: v0.1 From 94b8c4512d35b8e753a2e330489170f049078b8b Mon Sep 17 00:00:00 2001 From: Manuel Eggimann Date: Wed, 18 Nov 2020 11:27:49 +0100 Subject: [PATCH 19/30] Add register interface dependency --- ips_list.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/ips_list.yml b/ips_list.yml index 9576b5bf..961f77ef 100644 --- a/ips_list.yml +++ b/ips_list.yml @@ -117,3 +117,6 @@ hwpe-mac-engine: riscv-dbg: commit: v0.2 domain: [soc] +register_interface: + commit: add_ipapprox + domain: [soc] From 588ff161a1b8cdd88df78d87d980d7e37aa63134 Mon Sep 17 00:00:00 2001 From: Manuel Eggimann Date: Fri, 4 Dec 2020 17:35:37 +0100 Subject: [PATCH 20/30] Fix wrong usage of BE_WIDTH in soc_interconnect --- rtl/pulp_soc/interleaved_crossbar.sv | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rtl/pulp_soc/interleaved_crossbar.sv b/rtl/pulp_soc/interleaved_crossbar.sv index ab687896..e5df15cd 100644 --- a/rtl/pulp_soc/interleaved_crossbar.sv +++ b/rtl/pulp_soc/interleaved_crossbar.sv @@ -93,7 +93,7 @@ module interleaved_crossbar //Interleaved Output Port Selection logic [NR_MASTER_PORTS-1:0] [PORT_SEL_WIDTH-1:0] port_sel; for (genvar i = 0; i < NR_MASTER_PORTS; i++) begin - assign port_sel[i] = master_ports[i].add[BE_WIDTH+PORT_SEL_WIDTH-1:BE_WIDTH]; + assign port_sel[i] = master_ports[i].add[$clog2(BE_WIDTH)+PORT_SEL_WIDTH-1:$clog2(BE_WIDTH)]; end //Crossbar instantiation From 75c800dadf14115f937b3556e96a7e2bccf7642e Mon Sep 17 00:00:00 2001 From: Manuel Eggimann Date: Sat, 5 Dec 2020 22:28:18 +0100 Subject: [PATCH 21/30] Fix wrong address connection to FPGA specific SRAM bank1 --- rtl/pulp_soc/l2_ram_multi_bank.sv | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rtl/pulp_soc/l2_ram_multi_bank.sv b/rtl/pulp_soc/l2_ram_multi_bank.sv index 48259a49..01157746 100644 --- a/rtl/pulp_soc/l2_ram_multi_bank.sv +++ b/rtl/pulp_soc/l2_ram_multi_bank.sv @@ -161,7 +161,7 @@ module l2_ram_multi_bank #( .csn_i ( ~mem_pri_slave[1].req ), .wen_i ( mem_pri_slave[1].wen ), .be_i ( mem_pri_slave[1].be ), - .addr_i ( pri0_address[PRI1_MEM_ADDR_WIDTH+1:2] ), //Convert from byte to word addressing + .addr_i ( pri1_address[PRI1_MEM_ADDR_WIDTH+1:2] ), //Convert from byte to word addressing .wdata_i ( mem_pri_slave[1].wdata ), .rdata_o ( mem_pri_slave[1].r_rdata ) ); From 7a2bc37e87dfcdb4934c3411958058201eb11c3f Mon Sep 17 00:00:00 2001 From: Manuel Eggimann Date: Wed, 9 Dec 2020 14:12:17 +0100 Subject: [PATCH 22/30] Remove obsolet header file include --- rtl/fc/fc_subsystem.sv | 2 -- rtl/pulp_soc/pulp_soc.sv | 1 - 2 files changed, 3 deletions(-) diff --git a/rtl/fc/fc_subsystem.sv b/rtl/fc/fc_subsystem.sv index 4d86acb3..dd4f9451 100644 --- a/rtl/fc/fc_subsystem.sv +++ b/rtl/fc/fc_subsystem.sv @@ -9,8 +9,6 @@ // specific language governing permissions and limitations under the License. -`include "soc_bus_defines.sv" - module fc_subsystem #( parameter CORE_TYPE = 0, parameter USE_FPU = 1, diff --git a/rtl/pulp_soc/pulp_soc.sv b/rtl/pulp_soc/pulp_soc.sv index 4040131c..38ec998a 100644 --- a/rtl/pulp_soc/pulp_soc.sv +++ b/rtl/pulp_soc/pulp_soc.sv @@ -10,7 +10,6 @@ `include "pulp_soc_defines.sv" -`include "soc_bus_defines.sv" module pulp_soc import dm::*; #( parameter CORE_TYPE = 0, From a6f68ace6efa2170ce10c014d23d805141ed69e2 Mon Sep 17 00:00:00 2001 From: Manuel Eggimann Date: Wed, 9 Dec 2020 15:36:14 +0100 Subject: [PATCH 23/30] Move hardcoded TCDM master port count value to package --- rtl/pulp_soc/pkg_soc_interconnect.sv | 5 +++++ rtl/pulp_soc/pulp_soc.sv | 17 +++++++++++++---- rtl/pulp_soc/soc_interconnect_wrap.sv | 24 +++++++++++++++--------- 3 files changed, 33 insertions(+), 13 deletions(-) diff --git a/rtl/pulp_soc/pkg_soc_interconnect.sv b/rtl/pulp_soc/pkg_soc_interconnect.sv index 14e36579..ce956399 100644 --- a/rtl/pulp_soc/pkg_soc_interconnect.sv +++ b/rtl/pulp_soc/pkg_soc_interconnect.sv @@ -6,4 +6,9 @@ package pkg_soc_interconnect; logic [31:0] end_addr; } addr_map_rule_t; + localparam NR_SOC_TCDM_MASTER_PORTS = 5; // FC instructions, FC data, uDMA RX, uDMA TX, debug access + localparam NR_CLUSTER_2_SOC_TCDM_MASTER_PORTS = 4; // 4 ports for 64-bit axi plug + localparam NR_TCDM_MASTER_PORTS = NR_SOC_TCDM_MASTER_PORTS + NR_CLUSTER_2_SOC_TCDM_MASTER_PORTS; + localparam NR_EXTRA_BITS_AXI_ID_OUT = $clog2(NR_TCDM_MASTER_PORTS); + endpackage : pkg_soc_interconnect diff --git a/rtl/pulp_soc/pulp_soc.sv b/rtl/pulp_soc/pulp_soc.sv index 38ec998a..fea5113d 100644 --- a/rtl/pulp_soc/pulp_soc.sv +++ b/rtl/pulp_soc/pulp_soc.sv @@ -20,10 +20,19 @@ module pulp_soc import dm::*; #( parameter AXI_DATA_IN_WIDTH = 64, parameter AXI_DATA_OUT_WIDTH = 32, parameter AXI_ID_IN_WIDTH = 6, - localparam AXI_ID_OUT_WIDTH = AXI_ID_IN_WIDTH+$clog2(5+4), //Account for additional bits needed by AXI_XBAR to - //backroute responses. At the moment we have 9 masters 5 for fc_data, fc_instr, udma_rx, - //udma_tx, debug_access and 4 for the 64-bit - //cluster2soc axi plug + localparam AXI_ID_OUT_WIDTH = AXI_ID_IN_WIDTH+pkg_soc_interconnect::NR_EXTRA_BITS_AXI_ID_OUT, //Account for + //additional bits + //needed by AXI_XBAR + //to backroute + //responses. At the + //moment we have 9 + //masters 5 for + //fc_data, fc_instr, + //udma_rx, udma_tx, + //debug_access and 4 + //for the 64-bit + //cluster2soc axi + //plug parameter AXI_USER_WIDTH = 6, parameter AXI_STRB_WIDTH_IN = AXI_DATA_IN_WIDTH/8, parameter AXI_STRB_WIDTH_OUT = AXI_DATA_OUT_WIDTH/8, diff --git a/rtl/pulp_soc/soc_interconnect_wrap.sv b/rtl/pulp_soc/soc_interconnect_wrap.sv index 4adffe1f..0af5366e 100644 --- a/rtl/pulp_soc/soc_interconnect_wrap.sv +++ b/rtl/pulp_soc/soc_interconnect_wrap.sv @@ -67,8 +67,14 @@ module soc_interconnect_wrap ////////////////////////////////////////////////////////////// // 64-bit AXI to TCDM Bridge (Cluster to SoC communication) // ////////////////////////////////////////////////////////////// - XBAR_TCDM_BUS axi_bridge_2_interconnect[4](); //We need 4 32-bit TCDM ports to achieve fullbandwidth with one 64-bit AXI - //port + XBAR_TCDM_BUS axi_bridge_2_interconnect[pkg_soc_interconnect::NR_CLUSTER_2_SOC_TCDM_MASTER_PORTS](); //We need 4 + //32-bit TCDM + //ports to + //achieve full + //bandwidth + //with one + //64-bit AXI + //port axi64_2_lint32_wrap #( .AXI_USER_WIDTH(AXI_USER_WIDTH), @@ -109,9 +115,7 @@ module soc_interconnect_wrap // Instantiate Interconnect // ////////////////////////////// - localparam INTERNAL_NR_AXI_XBAR_MASTERS = 5 + 4; //5 for fc_instr, fc_data, udma_rx, udma_tx, debug_access and 4 - //four 64-bit axi plug - localparam AXI_SLAVE_ID_WIDTH = AXI_IN_ID_WIDTH + $clog2(INTERNAL_NR_AXI_XBAR_MASTERS); + localparam AXI_SLAVE_ID_WIDTH = AXI_IN_ID_WIDTH + $clog2(pkg_soc_interconnect::NR_TCDM_MASTER_PORTS); //Internal wiring to APB protocol converter AXI_BUS #(.AXI_ADDR_WIDTH(32), @@ -122,14 +126,16 @@ module soc_interconnect_wrap //Wiring signals to interconncet. Unfortunately Synopsys-2019.3 does not support assignment patterns in port lists //directly - XBAR_TCDM_BUS master_ports[5+4](); + XBAR_TCDM_BUS master_ports[pkg_soc_interconnect::NR_TCDM_MASTER_PORTS](); //increase the package localparma as well + //if you want to add new master ports. The parameter is used by other IPs to calcualte + //the required AXI ID width. `TCDM_ASSIGN_INTF(master_ports[0], tcdm_fc_data) `TCDM_ASSIGN_INTF(master_ports[1], tcdm_fc_instr) `TCDM_ASSIGN_INTF(master_ports[2], tcdm_udma_tx) `TCDM_ASSIGN_INTF(master_ports[3], tcdm_udma_rx) `TCDM_ASSIGN_INTF(master_ports[4], tcdm_debug) - for (genvar i = 0; i < 4; i++) begin - `TCDM_ASSIGN_INTF(master_ports[5+i], axi_bridge_2_interconnect[i]) + for (genvar i = 0; i < pkg_soc_interconnect::NR_CLUSTER_2_SOC_TCDM_MASTER_PORTS; i++) begin + `TCDM_ASSIGN_INTF(master_ports[pkg_soc_interconnect::NR_SOC_TCDM_MASTER_PORTS+i], axi_bridge_2_interconnect[i]) end XBAR_TCDM_BUS contiguous_slaves[3](); @@ -147,7 +153,7 @@ module soc_interconnect_wrap //Interconnect instantiation soc_interconnect #( - .NR_MASTER_PORTS(5+4), // FC instructions, FC data, uDMA RX, uDMA TX, debug access, 4 four 64-bit + .NR_MASTER_PORTS(pkg_soc_interconnect::NR_TCDM_MASTER_PORTS), // FC instructions, FC data, uDMA RX, uDMA TX, debug access, 4 four 64-bit // axi plug .NR_MASTER_PORTS_INTERLEAVED_ONLY(NR_HWPE_PORTS), // HWPEs (PULP accelerators) only have access // to the interleaved memory region From ecbfc7f8402cebbb473440fab1637aa7281fffb7 Mon Sep 17 00:00:00 2001 From: Manuel Eggimann Date: Wed, 9 Dec 2020 18:15:02 +0100 Subject: [PATCH 24/30] Remove dependency of output AXI_ID width from input ID width --- rtl/pulp_soc/pkg_soc_interconnect.sv | 2 +- rtl/pulp_soc/pulp_soc.sv | 14 +------------- rtl/pulp_soc/soc_interconnect_wrap.sv | 11 ++++++----- 3 files changed, 8 insertions(+), 19 deletions(-) diff --git a/rtl/pulp_soc/pkg_soc_interconnect.sv b/rtl/pulp_soc/pkg_soc_interconnect.sv index ce956399..2ad08d50 100644 --- a/rtl/pulp_soc/pkg_soc_interconnect.sv +++ b/rtl/pulp_soc/pkg_soc_interconnect.sv @@ -9,6 +9,6 @@ package pkg_soc_interconnect; localparam NR_SOC_TCDM_MASTER_PORTS = 5; // FC instructions, FC data, uDMA RX, uDMA TX, debug access localparam NR_CLUSTER_2_SOC_TCDM_MASTER_PORTS = 4; // 4 ports for 64-bit axi plug localparam NR_TCDM_MASTER_PORTS = NR_SOC_TCDM_MASTER_PORTS + NR_CLUSTER_2_SOC_TCDM_MASTER_PORTS; - localparam NR_EXTRA_BITS_AXI_ID_OUT = $clog2(NR_TCDM_MASTER_PORTS); + localparam AXI_ID_OUT_WIDTH = 1 + $clog2(NR_TCDM_MASTER_PORTS); endpackage : pkg_soc_interconnect diff --git a/rtl/pulp_soc/pulp_soc.sv b/rtl/pulp_soc/pulp_soc.sv index fea5113d..e257afd3 100644 --- a/rtl/pulp_soc/pulp_soc.sv +++ b/rtl/pulp_soc/pulp_soc.sv @@ -20,19 +20,7 @@ module pulp_soc import dm::*; #( parameter AXI_DATA_IN_WIDTH = 64, parameter AXI_DATA_OUT_WIDTH = 32, parameter AXI_ID_IN_WIDTH = 6, - localparam AXI_ID_OUT_WIDTH = AXI_ID_IN_WIDTH+pkg_soc_interconnect::NR_EXTRA_BITS_AXI_ID_OUT, //Account for - //additional bits - //needed by AXI_XBAR - //to backroute - //responses. At the - //moment we have 9 - //masters 5 for - //fc_data, fc_instr, - //udma_rx, udma_tx, - //debug_access and 4 - //for the 64-bit - //cluster2soc axi - //plug + localparam AXI_ID_OUT_WIDTH = pkg_soc_interconnect::AXI_ID_OUT_WIDTH, parameter AXI_USER_WIDTH = 6, parameter AXI_STRB_WIDTH_IN = AXI_DATA_IN_WIDTH/8, parameter AXI_STRB_WIDTH_OUT = AXI_DATA_OUT_WIDTH/8, diff --git a/rtl/pulp_soc/soc_interconnect_wrap.sv b/rtl/pulp_soc/soc_interconnect_wrap.sv index 0af5366e..e9413a9b 100644 --- a/rtl/pulp_soc/soc_interconnect_wrap.sv +++ b/rtl/pulp_soc/soc_interconnect_wrap.sv @@ -115,12 +115,11 @@ module soc_interconnect_wrap // Instantiate Interconnect // ////////////////////////////// - localparam AXI_SLAVE_ID_WIDTH = AXI_IN_ID_WIDTH + $clog2(pkg_soc_interconnect::NR_TCDM_MASTER_PORTS); //Internal wiring to APB protocol converter AXI_BUS #(.AXI_ADDR_WIDTH(32), .AXI_DATA_WIDTH(32), - .AXI_ID_WIDTH(AXI_SLAVE_ID_WIDTH), + .AXI_ID_WIDTH(pkg_soc_interconnect::AXI_ID_OUT_WIDTH), .AXI_USER_WIDTH(AXI_USER_WIDTH) ) axi_to_axi_lite_bridge(); @@ -145,7 +144,7 @@ module soc_interconnect_wrap AXI_BUS #(.AXI_ADDR_WIDTH(32), .AXI_DATA_WIDTH(32), - .AXI_ID_WIDTH(AXI_SLAVE_ID_WIDTH), + .AXI_ID_WIDTH(pkg_soc_interconnect::AXI_ID_OUT_WIDTH), .AXI_USER_WIDTH(AXI_USER_WIDTH) ) axi_slaves[2](); `AXI_ASSIGN(axi_slave_plug, axi_slaves[0]) @@ -164,7 +163,9 @@ module soc_interconnect_wrap .NR_ADDR_RULES_SLAVE_PORTS_CONTIG(NR_RULES_CONTIG_CROSSBAR), .NR_AXI_SLAVE_PORTS(2), // 1 for AXI to cluster, 1 for SoC peripherals (converted to APB) .NR_ADDR_RULES_AXI_SLAVE_PORTS(NR_RULES_AXI_CROSSBAR), - .AXI_MASTER_ID_WIDTH(AXI_IN_ID_WIDTH), + .AXI_MASTER_ID_WIDTH(1), //Doesn't need to be changed. All axi masters in the current + //interconnect come from a TCDM protocol converter and thus do not have and AXI ID. + //However, the unerlaying IPs do not support an ID lenght of 0, thus we use 1. .AXI_USER_WIDTH(AXI_USER_WIDTH) ) i_soc_interconnect ( .clk_i, @@ -194,7 +195,7 @@ module soc_interconnect_wrap axi_to_axi_lite_intf #( .AXI_ADDR_WIDTH(32), .AXI_DATA_WIDTH(32), - .AXI_ID_WIDTH(AXI_SLAVE_ID_WIDTH), + .AXI_ID_WIDTH(pkg_soc_interconnect::AXI_ID_OUT_WIDTH), .AXI_USER_WIDTH(AXI_USER_WIDTH), .AXI_MAX_WRITE_TXNS(1), .AXI_MAX_READ_TXNS(1), From b82a724e784010b531507eaa0d160333332424c3 Mon Sep 17 00:00:00 2001 From: Manuel Eggimann Date: Thu, 10 Dec 2020 12:05:28 +0100 Subject: [PATCH 25/30] Add ISOLATE_CLUSTER_CDC parameter to pulp_soc and realing p-list --- rtl/pulp_soc/pulp_soc.sv | 53 +++++++++++++++++++++------------------- 1 file changed, 28 insertions(+), 25 deletions(-) diff --git a/rtl/pulp_soc/pulp_soc.sv b/rtl/pulp_soc/pulp_soc.sv index e257afd3..7e4d7f5b 100644 --- a/rtl/pulp_soc/pulp_soc.sv +++ b/rtl/pulp_soc/pulp_soc.sv @@ -12,32 +12,35 @@ `include "pulp_soc_defines.sv" module pulp_soc import dm::*; #( - parameter CORE_TYPE = 0, - parameter USE_FPU = 1, - parameter USE_HWPE = 1, - parameter USE_CLUSTER_EVENT = 1, - parameter AXI_ADDR_WIDTH = 32, - parameter AXI_DATA_IN_WIDTH = 64, - parameter AXI_DATA_OUT_WIDTH = 32, - parameter AXI_ID_IN_WIDTH = 6, - localparam AXI_ID_OUT_WIDTH = pkg_soc_interconnect::AXI_ID_OUT_WIDTH, - parameter AXI_USER_WIDTH = 6, - parameter AXI_STRB_WIDTH_IN = AXI_DATA_IN_WIDTH/8, - parameter AXI_STRB_WIDTH_OUT = AXI_DATA_OUT_WIDTH/8, - parameter BUFFER_WIDTH = 8, - parameter EVNT_WIDTH = 8, - parameter NB_CORES = 8, - parameter NB_HWPE_PORTS = 4, - parameter NGPIO = 43, - parameter NPAD = 64, //Must not be changed as other parts + parameter CORE_TYPE = 0, + parameter USE_FPU = 1, + parameter USE_HWPE = 1, + parameter USE_CLUSTER_EVENT = 1, + parameter AXI_ADDR_WIDTH = 32, + parameter AXI_DATA_IN_WIDTH = 64, + parameter AXI_DATA_OUT_WIDTH = 32, + parameter AXI_ID_IN_WIDTH = 6, + localparam AXI_ID_OUT_WIDTH = pkg_soc_interconnect::AXI_ID_OUT_WIDTH, + parameter AXI_USER_WIDTH = 6, + parameter AXI_STRB_WIDTH_IN = AXI_DATA_IN_WIDTH/8, + parameter AXI_STRB_WIDTH_OUT = AXI_DATA_OUT_WIDTH/8, + parameter BUFFER_WIDTH = 8, + parameter EVNT_WIDTH = 8, + parameter NB_CORES = 8, + parameter NB_HWPE_PORTS = 4, + parameter NGPIO = 43, + parameter NPAD = 64, //Must not be changed as other parts //downstreams are not parametrci - parameter NBIT_PADCFG = 6, //Must not be changed as other parts + parameter NBIT_PADCFG = 6, //Must not be changed as other parts //downstreams are not parametrci - parameter NBIT_PADMUX = 2, - - parameter int unsigned N_UART = 1, - parameter int unsigned N_SPI = 1, - parameter int unsigned N_I2C = 2 + parameter NBIT_PADMUX = 2, + + parameter int unsigned N_UART = 1, + parameter int unsigned N_SPI = 1, + parameter int unsigned N_I2C = 2, + parameter bit ISOLATE_CLUSTER_CDC = 0 // If 0, ties the cluster <-> soc AXI CDC isolation signal to 0 statically + // disabling the connection. For PULPissimo (MCU without a cluster) this should be set + // to 0. ) ( input logic ref_clk_i, input logic slow_clk_i, @@ -460,7 +463,7 @@ module pulp_soc import dm::*; #( assign cluster_rtc_o = ref_clk_i; assign cluster_test_en_o = dft_test_mode_i; // isolate dc if the cluster is down - assign s_cluster_isolate_dc = 1'b1; + assign s_cluster_isolate_dc = ISOLATE_CLUSTER_CDC; //cluster_byp_o; // If you want to connect a real PULP cluster you also need a cluster_busy_i signal From 8ddcde6751ee49dfb7d344b79db9fc82c8d92703 Mon Sep 17 00:00:00 2001 From: Manuel Eggimann Date: Thu, 10 Dec 2020 15:07:43 +0100 Subject: [PATCH 26/30] Freeze cluster_interconnect ip version --- ips_list.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ips_list.yml b/ips_list.yml index 961f77ef..155b6716 100644 --- a/ips_list.yml +++ b/ips_list.yml @@ -24,7 +24,7 @@ L2_tcdm_hybrid_interco: commit: pulpissimo-v1.0 domain: [soc] cluster_interconnect: - commit: master + commit: v1.1.0 domain: [soc] adv_dbg_if: commit: v0.0.1 From 38fc3ca95f9732a166d4e099720b6ce8a1136c7b Mon Sep 17 00:00:00 2001 From: Manuel Eggimann Date: Thu, 10 Dec 2020 15:19:43 +0100 Subject: [PATCH 27/30] Freeze register_interface branch --- ips_list.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ips_list.yml b/ips_list.yml index 155b6716..57c5e649 100644 --- a/ips_list.yml +++ b/ips_list.yml @@ -118,5 +118,5 @@ riscv-dbg: commit: v0.2 domain: [soc] register_interface: - commit: add_ipapprox + commit: b1bc9c22e0c2a5801107070c022904498dbae34b domain: [soc] From b3b527e2a8a50737d1f24233f9078e8babf8a929 Mon Sep 17 00:00:00 2001 From: Manuel Eggimann Date: Fri, 11 Dec 2020 13:39:43 +0100 Subject: [PATCH 28/30] Assign 0 to r_opc error signal for sram access --- rtl/pulp_soc/l2_ram_multi_bank.sv | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/rtl/pulp_soc/l2_ram_multi_bank.sv b/rtl/pulp_soc/l2_ram_multi_bank.sv index 01157746..d1d7dad6 100644 --- a/rtl/pulp_soc/l2_ram_multi_bank.sv +++ b/rtl/pulp_soc/l2_ram_multi_bank.sv @@ -38,7 +38,8 @@ module l2_ram_multi_bank #( logic [31:0] interleaved_addresses[NB_BANKS]; for(genvar i=0; i Date: Fri, 11 Dec 2020 13:40:38 +0100 Subject: [PATCH 29/30] Add hw error checker for interleaved_only master ports --- rtl/pulp_soc/soc_interconnect.sv | 65 +++++++++++++++++++-------- rtl/pulp_soc/soc_interconnect_wrap.sv | 7 +++ rtl/pulp_soc/tcdm_error_slave.sv | 53 ++++++++++++++++++++++ src_files.yml | 1 + 4 files changed, 108 insertions(+), 18 deletions(-) create mode 100644 rtl/pulp_soc/tcdm_error_slave.sv diff --git a/rtl/pulp_soc/soc_interconnect.sv b/rtl/pulp_soc/soc_interconnect.sv index fa17d6a0..2c2baae2 100644 --- a/rtl/pulp_soc/soc_interconnect.sv +++ b/rtl/pulp_soc/soc_interconnect.sv @@ -34,6 +34,7 @@ module soc_interconnect parameter int unsigned NR_ADDR_RULES_L2_DEMUX, // Interleaved TCDM slave parameter int unsigned NR_SLAVE_PORTS_INTERLEAVED, + parameter int unsigned NR_ADDR_RULES_SLAVE_PORTS_INTLVD, // Contiguous TCDM slave parameter int unsigned NR_SLAVE_PORTS_CONTIG, parameter int unsigned NR_ADDR_RULES_SLAVE_PORTS_CONTIG, @@ -43,7 +44,7 @@ module soc_interconnect // AXI Slaves parameter int unsigned NR_AXI_SLAVE_PORTS, parameter int unsigned NR_ADDR_RULES_AXI_SLAVE_PORTS, - localparam int unsigned AXI_SLAVE_ID_WIDTH = AXI_MASTER_ID_WIDTH + $clog2(NR_MASTER_PORTS), //The actual ID + localparam int unsigned AXI_SLAVE_ID_WIDTH = AXI_MASTER_ID_WIDTH + $clog2(NR_MASTER_PORTS), //The actual ID //width of the AXI slaves is clog2(NR_AXI_MASTERS) larger than the master id width since the //axi_mux in the XBAR will append an identificatoin tag to the outgoing transactions //towards the axi slaves so it can backroute the responses @@ -57,6 +58,7 @@ module soc_interconnect XBAR_TCDM_BUS.Slave master_ports_interleaved_only[NR_MASTER_PORTS_INTERLEAVED_ONLY], input addr_map_rule_t[NR_ADDR_RULES_L2_DEMUX-1:0] addr_space_l2_demux, //Interleaved Slave + input addr_map_rule_t[NR_ADDR_RULES_SLAVE_PORTS_INTLVD-1:0] addr_space_interleaved, XBAR_TCDM_BUS.Master interleaved_slaves[NR_SLAVE_PORTS_INTERLEAVED], //Contiguous Slave input addr_map_rule_t[NR_ADDR_RULES_SLAVE_PORTS_CONTIG-1:0] addr_space_contiguous, @@ -108,6 +110,40 @@ module soc_interconnect ); end + /////////////////////////////////////// + // Interleaved only address checkers // + ////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // The following code checks, that no interleaved-only master is trying to access address space outside the // + // interleaved memory region. // + ////////////////////////////////////////////////////////////////////////////////////////////////////////////// + XBAR_TCDM_BUS master_ports_interleaved_only_checked[NR_MASTER_PORTS_INTERLEAVED_ONLY](); + for (genvar i = 0; i < NR_MASTER_PORTS_INTERLEAVED_ONLY; i++) begin : gen_interleaved_only_err_checkers + XBAR_TCDM_BUS err_demux_slaves[2](); + + `TCDM_ASSIGN_INTF(master_ports_interleaved_only_checked[i], err_demux_slaves[1]); + + //The tcdm demux will route all transaction that do not match any addr rule to port 0 (which we connect to an + //error slave) + tcdm_demux #( + .NR_OUTPUTS(2), + .NR_ADDR_MAP_RULES(NR_ADDR_RULES_SLAVE_PORTS_INTLVD) + ) i_err_demux( + .clk_i, + .rst_ni, + .test_en_i, + .addr_map_rules ( addr_space_interleaved ), + .master_port ( master_ports_interleaved_only[i] ), + .slave_ports ( err_demux_slaves ) + ); + tcdm_error_slave #( + .ERROR_RESPONSE(32'hBADACCE5) + ) i_error_slave_interleaved ( + .clk_i, + .rst_ni, + .slave(err_demux_slaves[0]) + ); + end + ////////////////////////// // Interleaved Crossbar // @@ -136,10 +172,10 @@ module soc_interconnect `TCDM_MASTER_EXPLODE(l2_demux_2_interleaved_xbar[i], l2_demux_2_interleaved_xbar, [i]) `TCDM_ASSIGN(interleaved_masters, [i], l2_demux_2_interleaved_xbar, [i]) end - `TCDM_EXPLODE_ARRAY_DECLARE(master_ports_interleaved_only, NR_MASTER_PORTS_INTERLEAVED_ONLY) + `TCDM_EXPLODE_ARRAY_DECLARE(master_ports_interleaved_only_checked, NR_MASTER_PORTS_INTERLEAVED_ONLY) for (genvar i = 0; i < NR_MASTER_PORTS_INTERLEAVED_ONLY; i++) begin - `TCDM_MASTER_EXPLODE(master_ports_interleaved_only[i], master_ports_interleaved_only, [i]) - `TCDM_ASSIGN(interleaved_masters, [NR_MASTER_PORTS + i], master_ports_interleaved_only, [i]) + `TCDM_MASTER_EXPLODE(master_ports_interleaved_only_checked[i], master_ports_interleaved_only_checked, [i]) + `TCDM_ASSIGN(interleaved_masters, [NR_MASTER_PORTS + i], master_ports_interleaved_only_checked, [i]) end interleaved_crossbar #( @@ -184,20 +220,13 @@ module soc_interconnect ); //Error Slave // This dummy slave is responsible to generate the buserror described above - logic error_valid_d, error_valid_q; - assign error_slave.gnt = error_slave.req; - assign error_valid_d = error_slave.req; - assign error_slave.r_opc = error_slave.req; - assign error_slave.r_rdata = 32'hBADACCE5; - assign error_slave.r_valid = error_valid_q; - - always_ff @(posedge clk_i, negedge rst_ni) begin - if (!rst_ni) begin - error_valid_q <= 1'b0; - end else begin - error_valid_q <= error_valid_d; - end - end + tcdm_error_slave #( + .ERROR_RESPONSE(32'hBADACCE5) + ) i_error_slave_contig_xbar ( + .clk_i, + .rst_ni, + .slave(error_slave) + ); //////////////////////// diff --git a/rtl/pulp_soc/soc_interconnect_wrap.sv b/rtl/pulp_soc/soc_interconnect_wrap.sv index e9413a9b..462621be 100644 --- a/rtl/pulp_soc/soc_interconnect_wrap.sv +++ b/rtl/pulp_soc/soc_interconnect_wrap.sv @@ -100,6 +100,11 @@ module soc_interconnect_wrap '{ idx: 2 , start_addr: `SOC_MEM_MAP_TCDM_START_ADDR , end_addr: `SOC_MEM_MAP_TCDM_END_ADDR } , '{ idx: 2 , start_addr: `SOC_MEM_MAP_TCDM_ALIAS_START_ADDR , end_addr: `SOC_MEM_MAP_TCDM_ALIAS_END_ADDR}}; + localparam NR_RULES_INTERLEAVED_REGION = 2; + localparam addr_map_rule_t [NR_RULES_INTERLEAVED_REGION-1:0] INTERLEAVED_ADDR_SPACE = '{ + '{ idx: 1 , start_addr: `SOC_MEM_MAP_TCDM_START_ADDR , end_addr: `SOC_MEM_MAP_TCDM_END_ADDR }, + '{ idx: 1 , start_addr: `SOC_MEM_MAP_TCDM_ALIAS_START_ADDR , end_addr: `SOC_MEM_MAP_TCDM_ALIAS_END_ADDR}}; + localparam NR_RULES_CONTIG_CROSSBAR = 3; localparam addr_map_rule_t [NR_RULES_CONTIG_CROSSBAR-1:0] CONTIGUOUS_CROSSBAR_RULES = '{ '{ idx: 0 , start_addr: `SOC_MEM_MAP_PRIVATE_BANK0_START_ADDR , end_addr: `SOC_MEM_MAP_PRIVATE_BANK0_END_ADDR} , @@ -158,6 +163,7 @@ module soc_interconnect_wrap // to the interleaved memory region .NR_ADDR_RULES_L2_DEMUX(NR_RULES_L2_DEMUX), .NR_SLAVE_PORTS_INTERLEAVED(NR_L2_PORTS), // Number of interleaved memory banks + .NR_ADDR_RULES_SLAVE_PORTS_INTLVD(NR_RULES_INTERLEAVED_REGION), .NR_SLAVE_PORTS_CONTIG(3), // Bootrom + number of private memory banks (normally 1 for // programm instructions and 1 for programm stack ) .NR_ADDR_RULES_SLAVE_PORTS_CONTIG(NR_RULES_CONTIG_CROSSBAR), @@ -174,6 +180,7 @@ module soc_interconnect_wrap .master_ports(master_ports), .master_ports_interleaved_only(tcdm_hwpe), .addr_space_l2_demux(L2_DEMUX_RULES), + .addr_space_interleaved(INTERLEAVED_ADDR_SPACE), .interleaved_slaves(l2_interleaved_slaves), .addr_space_contiguous(CONTIGUOUS_CROSSBAR_RULES), .contiguous_slaves(contiguous_slaves), diff --git a/rtl/pulp_soc/tcdm_error_slave.sv b/rtl/pulp_soc/tcdm_error_slave.sv new file mode 100644 index 00000000..084dd131 --- /dev/null +++ b/rtl/pulp_soc/tcdm_error_slave.sv @@ -0,0 +1,53 @@ +//----------------------------------------------------------------------------- +// Title : TCDM Error Slave +//----------------------------------------------------------------------------- +// File : tcdm_error_slave.sv +// Author : Manuel Eggimann +// Created : 11.12.2020 +//----------------------------------------------------------------------------- +// Description : +// This module responds to incoming read requests with a parametrizable error value +// and ignores (but properly acknowledges) write requests. In addition, it asserts the +// opc bus error signal. +//----------------------------------------------------------------------------- +// Copyright (C) 2013-2020 ETH Zurich, University of Bologna +// Copyright and related rights are licensed under the Solderpad Hardware +// License, Version 0.51 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law +// or agreed to in writing, software, hardware and materials distributed under +// this License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. +//----------------------------------------------------------------------------- + +module tcdm_error_slave #( + parameter logic [31:0] ERROR_RESPONSE = 32'hBADACCE5 +) ( + input logic clk_i, + input logic rst_ni, + XBAR_TCDM_BUS.Slave slave +); + + logic error_valid_d, error_valid_q; + assign slave.gnt = slave.req; + assign error_valid_d = slave.req; + assign slave.r_opc = slave.req; + assign slave.r_rdata = ERROR_RESPONSE; + assign slave.r_valid = error_valid_q; + + always_ff @(posedge clk_i, negedge rst_ni) begin + if (!rst_ni) begin + error_valid_q <= 1'b0; + end else begin + error_valid_q <= error_valid_d; + end + end + +`ifndef VERILATOR + no_req : assert property ( + @(posedge clk_i) disable iff (~rst_ni) not slave.req) + else $error("Illegal bus request."); +`endif + +endmodule : tcdm_error_slave diff --git a/src_files.yml b/src_files.yml index 62c9262c..b345cbbd 100644 --- a/src_files.yml +++ b/src_files.yml @@ -19,6 +19,7 @@ pulp_soc: rtl/pulp_soc/soc_event_arbiter.sv, rtl/pulp_soc/soc_event_generator.sv, rtl/pulp_soc/soc_event_queue.sv, + rtl/pulp_soc/tcdm_error_slave.sv, rtl/pulp_soc/soc_interconnect.sv, rtl/pulp_soc/soc_interconnect_wrap.sv, rtl/pulp_soc/soc_peripherals.sv, From 3d9e772717928af8e0c0c70895653e1758a655c8 Mon Sep 17 00:00:00 2001 From: Manuel Eggimann Date: Fri, 11 Dec 2020 19:24:27 +0100 Subject: [PATCH 30/30] Fix smaller issues and add workaround for synopsys index expression bug --- ips_list.yml | 2 +- rtl/pulp_soc/axi64_2_lint32_wrap.sv | 12 ++++++------ rtl/pulp_soc/l2_ram_multi_bank.sv | 12 ++++++------ rtl/pulp_soc/pkg_soc_interconnect.sv | 11 +++++++---- rtl/pulp_soc/soc_interconnect.sv | 8 +++++--- rtl/pulp_soc/soc_interconnect_wrap.sv | 11 +++++++++-- rtl/pulp_soc/tcdm_error_slave.sv | 4 ++-- 7 files changed, 36 insertions(+), 24 deletions(-) diff --git a/ips_list.yml b/ips_list.yml index 57c5e649..aaa17c02 100644 --- a/ips_list.yml +++ b/ips_list.yml @@ -39,7 +39,7 @@ apb/apb_fll_if: commit: pulpissimo-v1.0 domain: [soc] apb/apb_gpio: - commit: 0e9f142 + commit: 0e9f142f2f11278445c953ad011fce1c7ed85b66 domain: [soc] apb/apb_node: commit: v0.1.1 diff --git a/rtl/pulp_soc/axi64_2_lint32_wrap.sv b/rtl/pulp_soc/axi64_2_lint32_wrap.sv index 8b75e434..fb56b483 100644 --- a/rtl/pulp_soc/axi64_2_lint32_wrap.sv +++ b/rtl/pulp_soc/axi64_2_lint32_wrap.sv @@ -35,12 +35,12 @@ module axi64_2_lint32_wrap ); // *Do not change* The legacy wrapper was never tested for other bitwidths. - localparam AXI_ADDR_WIDTH = 32; - localparam AXI_DATA_WIDTH = 64; - localparam AXI_STRB_WIDTH = AXI_DATA_WIDTH/8; - localparam TCDM_DATA_WIDTH = 32; - localparam TCDM_ADDR_WIDTH = 32; - localparam TCDM_BE_WIDTH = TCDM_DATA_WIDTH/8; + localparam int unsigned AXI_ADDR_WIDTH = 32; + localparam int unsigned AXI_DATA_WIDTH = 64; + localparam int unsigned AXI_STRB_WIDTH = AXI_DATA_WIDTH/8; + localparam int unsigned TCDM_DATA_WIDTH = 32; + localparam int unsigned TCDM_ADDR_WIDTH = 32; + localparam int unsigned TCDM_BE_WIDTH = TCDM_DATA_WIDTH/8; //Explode the output TCDM interface into arrays of individual signals `TCDM_EXPLODE_ARRAY_DECLARE(tcdm_slaves, 4) diff --git a/rtl/pulp_soc/l2_ram_multi_bank.sv b/rtl/pulp_soc/l2_ram_multi_bank.sv index d1d7dad6..86ba415b 100644 --- a/rtl/pulp_soc/l2_ram_multi_bank.sv +++ b/rtl/pulp_soc/l2_ram_multi_bank.sv @@ -21,14 +21,14 @@ module l2_ram_multi_bank #( XBAR_TCDM_BUS.Slave mem_pri_slave[2] ); // Don't forget to adjust the SRAM macros and the FPGA settings if you change the banksizes - localparam BANK_SIZE_INTL_SRAM = 32768; //Number of 32-bit words - localparam BANK_SIZE_PRI0 = 8192; //Number of 32-bit words - localparam BANK_SIZE_PRI1 = 8192; //Number of 32-bit words + localparam int unsigned BANK_SIZE_INTL_SRAM = 32768; //Number of 32-bit words + localparam int unsigned BANK_SIZE_PRI0 = 8192; //Number of 32-bit words + localparam int unsigned BANK_SIZE_PRI1 = 8192; //Number of 32-bit words //Derived parameters - localparam INTL_MEM_ADDR_WIDTH = $clog2(BANK_SIZE_INTL_SRAM); - localparam PRI0_MEM_ADDR_WIDTH = $clog2(BANK_SIZE_PRI0); - localparam PRI1_MEM_ADDR_WIDTH = $clog2(BANK_SIZE_PRI1); + localparam int unsigned INTL_MEM_ADDR_WIDTH = $clog2(BANK_SIZE_INTL_SRAM); + localparam int unsigned PRI0_MEM_ADDR_WIDTH = $clog2(BANK_SIZE_PRI0); + localparam int unsigned PRI1_MEM_ADDR_WIDTH = $clog2(BANK_SIZE_PRI1); //Used in testbenches diff --git a/rtl/pulp_soc/pkg_soc_interconnect.sv b/rtl/pulp_soc/pkg_soc_interconnect.sv index 2ad08d50..41dd9a0a 100644 --- a/rtl/pulp_soc/pkg_soc_interconnect.sv +++ b/rtl/pulp_soc/pkg_soc_interconnect.sv @@ -6,9 +6,12 @@ package pkg_soc_interconnect; logic [31:0] end_addr; } addr_map_rule_t; - localparam NR_SOC_TCDM_MASTER_PORTS = 5; // FC instructions, FC data, uDMA RX, uDMA TX, debug access - localparam NR_CLUSTER_2_SOC_TCDM_MASTER_PORTS = 4; // 4 ports for 64-bit axi plug - localparam NR_TCDM_MASTER_PORTS = NR_SOC_TCDM_MASTER_PORTS + NR_CLUSTER_2_SOC_TCDM_MASTER_PORTS; - localparam AXI_ID_OUT_WIDTH = 1 + $clog2(NR_TCDM_MASTER_PORTS); + //Warning, if you change the NR_SOC_TCDM_MASTER_PORTS parameter you must also change the identically named preprocessor + //macro in soc_interconnect_wrap.sv. The macro is a workaround for a synopsys bug that prevent the usage of parameters + //in index expression on the left-hand side of an assignment. + localparam int unsigned NR_SOC_TCDM_MASTER_PORTS = 5; // FC instructions, FC data, uDMA RX, uDMA TX, debug access + localparam int unsigned NR_CLUSTER_2_SOC_TCDM_MASTER_PORTS = 4; // 4 ports for 64-bit axi plug + localparam int unsigned NR_TCDM_MASTER_PORTS = NR_SOC_TCDM_MASTER_PORTS + NR_CLUSTER_2_SOC_TCDM_MASTER_PORTS; + localparam int unsigned AXI_ID_OUT_WIDTH = 1 + $clog2(NR_TCDM_MASTER_PORTS); endpackage : pkg_soc_interconnect diff --git a/rtl/pulp_soc/soc_interconnect.sv b/rtl/pulp_soc/soc_interconnect.sv index 2c2baae2..4fb345fc 100644 --- a/rtl/pulp_soc/soc_interconnect.sv +++ b/rtl/pulp_soc/soc_interconnect.sv @@ -160,9 +160,11 @@ module soc_interconnect //Concatenate the l2 demux master port array and the interleaved only port array XBAR_TCDM_BUS interleaved_masters[NR_MASTER_PORTS+NR_MASTER_PORTS_INTERLEAVED_ONLY](); - //Synopsys is to stupid to handle expressions for array indices on the left-hand side of assignments. This is a - // verbose workaround for it. The next couple of ugly macro magic unpacks each interface into individual signal arrays, - // performs the assignments to the interface and packs the signal back to an array of interfaces. + + //Synopsys 2019.3 has a bug; It doesn't handle expressions for array indices on the left-hand side of assignments. + // E.g. assign a[param+i] = b[i] doesn't work, but assign a[i] = b[i-param] does. + // This is a verbose workaround for it. The next couple of ugly macro magic unpacks each interface into individual + // signal arrays, performs the assignments to the interface and packs the signal back to an array of interfaces. `TCDM_EXPLODE_ARRAY_DECLARE(interleaved_masters, NR_MASTER_PORTS+NR_MASTER_PORTS_INTERLEAVED_ONLY) for (genvar i = 0; i < NR_MASTER_PORTS + NR_MASTER_PORTS_INTERLEAVED_ONLY; i++) begin `TCDM_SLAVE_EXPLODE(interleaved_masters[i], interleaved_masters, [i]) diff --git a/rtl/pulp_soc/soc_interconnect_wrap.sv b/rtl/pulp_soc/soc_interconnect_wrap.sv index 462621be..73791064 100644 --- a/rtl/pulp_soc/soc_interconnect_wrap.sv +++ b/rtl/pulp_soc/soc_interconnect_wrap.sv @@ -138,8 +138,15 @@ module soc_interconnect_wrap `TCDM_ASSIGN_INTF(master_ports[2], tcdm_udma_tx) `TCDM_ASSIGN_INTF(master_ports[3], tcdm_udma_rx) `TCDM_ASSIGN_INTF(master_ports[4], tcdm_debug) - for (genvar i = 0; i < pkg_soc_interconnect::NR_CLUSTER_2_SOC_TCDM_MASTER_PORTS; i++) begin - `TCDM_ASSIGN_INTF(master_ports[pkg_soc_interconnect::NR_SOC_TCDM_MASTER_PORTS+i], axi_bridge_2_interconnect[i]) + + //Assign the 4 master ports from the AXI plug to the interface array + + //Synopsys 2019.3 has a bug; It doesn't handle expressions for array indices on the left-hand side of assignments. + // Using a macro instead of a package parameter is an ugly but necessary workaround. + // E.g. assign a[param+i] = b[i] doesn't work, but assign a[i] = b[i-param] does. + `define NR_SOC_TCDM_MASTER_PORTS 5 + for (genvar i = 0; i < 4; i++) begin + `TCDM_ASSIGN_INTF(master_ports[`NR_SOC_TCDM_MASTER_PORTS + i], axi_bridge_2_interconnect[i]) end XBAR_TCDM_BUS contiguous_slaves[3](); diff --git a/rtl/pulp_soc/tcdm_error_slave.sv b/rtl/pulp_soc/tcdm_error_slave.sv index 084dd131..78e1466c 100644 --- a/rtl/pulp_soc/tcdm_error_slave.sv +++ b/rtl/pulp_soc/tcdm_error_slave.sv @@ -44,10 +44,10 @@ module tcdm_error_slave #( end end -`ifndef VERILATOR +`ifndef SYNTHESIS no_req : assert property ( @(posedge clk_i) disable iff (~rst_ni) not slave.req) - else $error("Illegal bus request."); + else $error("Illegal bus request to address %x.", slave.add); `endif endmodule : tcdm_error_slave