diff --git a/CHANGELOG.md b/CHANGELOG.md index c02b161c..db89532d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,8 +6,18 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] ### Added +- Completely replaced soc_interconnect with a new parametric version +- Added AXI Crossbar to soc_interconnect to attach custom IPs +- Added new pulp_soc parameter to isolate the axi plug CDC fifo in case it is not needed +- Add register_interface as dependency to simplify integration of custom ip using reggen +- Properly assert r_opc signal in new interconnect to indicate bus errors +- Add error checking for illegal access on HWPE ports which only have access to L2 interleaved memory ### Changed +- AXI ID width of cluster plugs are now set to actually required width instead of a hardcoded one +- TCDM protocol to SRAM specific protocol is moved from interconnect to memory bank module ### Removed +- obsolete axi_node dependency +- obsolete header files ### Fixed ## [1.4.1] - 2020-10-28 diff --git a/ips_list.yml b/ips_list.yml index 0c176a29..aaa17c02 100644 --- a/ips_list.yml +++ b/ips_list.yml @@ -17,10 +17,15 @@ # state of DETACHED HEAD. Before committing any additional # work, make sure to checkout a branch. # - +common_cells: + commit: v1.20.0 + domain: [cluster, soc] L2_tcdm_hybrid_interco: commit: pulpissimo-v1.0 domain: [soc] +cluster_interconnect: + commit: v1.1.0 + domain: [soc] adv_dbg_if: commit: v0.0.1 domain: [cluster, soc] @@ -34,7 +39,7 @@ apb/apb_fll_if: commit: pulpissimo-v1.0 domain: [soc] apb/apb_gpio: - commit: v0.2.0 + commit: 0e9f142f2f11278445c953ad011fce1c7ed85b66 domain: [soc] apb/apb_node: commit: v0.1.1 @@ -43,11 +48,11 @@ apb_interrupt_cntrl: commit: v0.0.1 domain: [soc] axi/axi: - commit: v0.7.1 - domain: [cluster, soc] -axi/axi_node: - commit: v1.1.4 + commit: v0.24.1 domain: [cluster, soc] +# axi/axi_node: +# commit: v1.1.4 +# domain: [cluster, soc] axi/axi_slice: commit: v1.1.4 domain: [cluster, soc] @@ -57,11 +62,8 @@ 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 + commit: v0.6.5 domain: [cluster, soc] jtag_pulp: commit: v0.1 @@ -115,3 +117,6 @@ hwpe-mac-engine: riscv-dbg: commit: v0.2 domain: [soc] +register_interface: + commit: b1bc9c22e0c2a5801107070c022904498dbae34b + domain: [soc] 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 //******************************************************** diff --git a/rtl/fc/fc_subsystem.sv b/rtl/fc/fc_subsystem.sv index 249c3ad6..36c5892c 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/include/tcdm_macros.svh b/rtl/include/tcdm_macros.svh new file mode 100644 index 00000000..70a79835 --- /dev/null +++ b/rtl/include/tcdm_macros.svh @@ -0,0 +1,73 @@ +`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_valid = exploded_prefix``_r_valid postfix; + + `define TCDM_ASSIGN_INTF(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 ; + + `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/axi64_2_lint32_wrap.sv b/rtl/pulp_soc/axi64_2_lint32_wrap.sv new file mode 100644 index 00000000..fb56b483 --- /dev/null +++ b/rtl/pulp_soc/axi64_2_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_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, + XBAR_TCDM_BUS.Master tcdm_slaves[4] + ); + + // *Do not change* The legacy wrapper was never tested for other bitwidths. + 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) + for (genvar i = 0; i < 4; i++) begin + `TCDM_SLAVE_EXPLODE(tcdm_slaves[i], tcdm_slaves, [i]) + 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 diff --git a/rtl/pulp_soc/boot_rom.sv b/rtl/pulp_soc/boot_rom.sv index f2e51698..1a4c5f23 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..734987d6 --- /dev/null +++ b/rtl/pulp_soc/contiguous_crossbar.sv @@ -0,0 +1,139 @@ +//----------------------------------------------------------------------------- +// 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. +//----------------------------------------------------------------------------- + +`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 [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 = 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 + // 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_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_be[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; + 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), + .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(DEFAULT_IDX) + ); + end + + + //Crossbar instantiation + xbar #( + .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 ( + .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..e5df15cd --- /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_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 = 4; + 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_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_be[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[$clog2(BE_WIDTH)+PORT_SEL_WIDTH-1:$clog2(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..86ba415b 100644 --- a/rtl/pulp_soc/l2_ram_multi_bank.sv +++ b/rtl/pulp_soc/l2_ram_multi_bank.sv @@ -8,123 +8,167 @@ // 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 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 - localparam BANK_SIZE_INTL_SRAM = 28672; - localparam BANK_SIZE_INTL_SCM = 512; + //Derived parameters + 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 - 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, + XBAR_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; + + //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 ), + .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..41dd9a0a --- /dev/null +++ b/rtl/pulp_soc/pkg_soc_interconnect.sv @@ -0,0 +1,17 @@ +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; + + //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/pulp_soc.sv b/rtl/pulp_soc/pulp_soc.sv index 21f315ff..d4a0344c 100644 --- a/rtl/pulp_soc/pulp_soc.sv +++ b/rtl/pulp_soc/pulp_soc.sv @@ -10,37 +10,38 @@ `include "pulp_soc_defines.sv" -`include "soc_bus_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, - parameter AXI_ID_OUT_WIDTH = 6, - 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 = 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, - - parameter int unsigned N_UART = 1, - parameter int unsigned N_SPI = 1, - parameter int unsigned N_I2C = 2, - - parameter USE_ZFINX = 1 + parameter NBIT_PADMUX = 2, + + parameter int unsigned N_UART = 1, + parameter int unsigned N_SPI = 1, + parameter int unsigned N_I2C = 2, + parameter USE_ZFINX = 1, + 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, @@ -234,12 +235,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; @@ -345,9 +347,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; @@ -430,10 +432,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(); @@ -462,7 +464,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 = ISOLATE_CLUSTER_CDC; //cluster_byp_o; // If you want to connect a real PULP cluster you also need a cluster_busy_i signal @@ -505,11 +507,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 ), @@ -786,43 +784,27 @@ module pulp_soc import dm::*; #( ); 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 ) + .NR_HWPE_PORTS(NB_HWPE_PORTS), + .NR_L2_PORTS(NB_L2_BANKS), + .AXI_IN_ID_WIDTH(AXI_ID_IN_WIDTH), + .AXI_USER_WIDTH(AXI_USER_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 ) - ); - + .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 ) + ); /* Debug Subsystem */ @@ -874,12 +856,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 ), @@ -963,18 +945,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_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 diff --git a/rtl/pulp_soc/soc_interconnect.sv b/rtl/pulp_soc/soc_interconnect.sv index b6931197..4fb345fc 100644 --- a/rtl/pulp_soc/soc_interconnect.sv +++ b/rtl/pulp_soc/soc_interconnect.sv @@ -1,925 +1,319 @@ -// 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'h1C08_2000}; // 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, + 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, + // 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 + 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, + 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 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 - 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 : 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[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), + .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_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} , + '{ 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(pkg_soc_interconnect::AXI_ID_OUT_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[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) + + //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](); + `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(pkg_soc_interconnect::AXI_ID_OUT_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(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 + .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), + .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(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, + .rst_ni, + .test_en_i, + .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), + .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(pkg_soc_interconnect::AXI_ID_OUT_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_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 ), diff --git a/rtl/pulp_soc/tcdm_demux.sv b/rtl/pulp_soc/tcdm_demux.sv new file mode 100644 index 00000000..82f19d65 --- /dev/null +++ b/rtl/pulp_soc/tcdm_demux.sv @@ -0,0 +1,154 @@ +//----------------------------------------------------------------------------- +// 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_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[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; + localparam int unsigned ADDR_WIDTH = 32; + localparam int unsigned DATA_WIDTH = 32; + + // Explode the output interfaces to individual signals + `TCDM_EXPLODE_ARRAY_DECLARE(slave_ports, NR_OUTPUTS) + for (genvar i = 0; i < NR_OUTPUTS; i++) begin + `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[SLAVE_SEL_WIDTH-1:0] port_sel; + addr_decode #( + .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_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 + //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 + + //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; + 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; + 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 + 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; + 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 + state_d = IDLE; + end + end else begin + state_d = PENDING; + end + end + endcase + end + +endmodule : tcdm_demux diff --git a/rtl/pulp_soc/tcdm_error_slave.sv b/rtl/pulp_soc/tcdm_error_slave.sv new file mode 100644 index 00000000..78e1466c --- /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 SYNTHESIS + no_req : assert property ( + @(posedge clk_i) disable iff (~rst_ni) not slave.req) + else $error("Illegal bus request to address %x.", slave.add); +`endif + +endmodule : tcdm_error_slave diff --git a/src_files.yml b/src_files.yml index 38ac71a1..b345cbbd 100644 --- a/src_files.yml +++ b/src_files.yml @@ -1,9 +1,16 @@ pulp_soc: incdirs: [ ../../rtl/includes, + rtl/include, + ../axi/axi/include ] files: [ - rtl/pulp_soc/soc_interconnect.sv, + rtl/pulp_soc/pkg_soc_interconnect.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, + rtl/pulp_soc/tcdm_demux.sv, rtl/pulp_soc/boot_rom.sv, rtl/pulp_soc/l2_ram_multi_bank.sv, rtl/pulp_soc/lint_jtag_wrap.sv, @@ -12,12 +19,15 @@ 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, rtl/pulp_soc/pulp_soc.sv, ] vlog_opts : [ -L riscv_dbg_lib, + -L axi_lib ] udma_subsystem: incdirs: [ @@ -80,4 +90,4 @@ components_behav: ] flags: [ skip_synthesis, - ] \ No newline at end of file + ]