diff --git a/config/compilespecs.yml b/config/compilespecs.yml index a8a200d..3ef5287 100644 --- a/config/compilespecs.yml +++ b/config/compilespecs.yml @@ -4,6 +4,7 @@ files: - src/mcu/config/compile.yml - src/riscv_core/veer_el2/config/compile.yml - src/i3c-core/config/compile.yml + - src/mci/config/compile.yml - third_party/caliptra-rtl/src/libs/config/compile.yml - third_party/caliptra-rtl/src/ahb_lite_bus/config/compile.yml - third_party/caliptra-rtl/src/riscv_core/veer_el2/config/compile.yml diff --git a/src/mci/config/compile.yml b/src/mci/config/compile.yml index 4abff48..0f14edb 100644 --- a/src/mci/config/compile.yml +++ b/src/mci/config/compile.yml @@ -15,18 +15,24 @@ schema_version: 2.4.0 requires: - caliptra_prim - axi_sub - - soc_ifc_top - mci_pkg + # for beh_lib with rvecc_encode/decode + - el2_veer_pkg targets: rtl: directories: - $COMPILE_ROOT/rtl files: - - $COMPILE_ROOT/rtl/mci_boot_seqr.sv - $COMPILE_ROOT/rtl/mci_top.sv + - $COMPILE_ROOT/rtl/mci_axi_sub_decode.sv + - $COMPILE_ROOT/rtl/mci_axi_sub_top.sv + - $COMPILE_ROOT/rtl/mci_mcu_sram_ctrl.sv + - $COMPILE_ROOT/rtl/mci_mcu_sram_if.sv + - $COMPILE_ROOT/rtl/cif_if.sv tops: [mci_top] rtl_lint: directories: [$COMPILE_ROOT/config/design_lint] waiver_files: - $MSFT_REPO_ROOT/src/mci/config/design_lint/mci/sglint_waivers tops: [mci_top] + diff --git a/src/mci/rtl/cif_if.sv b/src/mci/rtl/cif_if.sv new file mode 100644 index 0000000..497dbe8 --- /dev/null +++ b/src/mci/rtl/cif_if.sv @@ -0,0 +1,61 @@ +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the 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. +// +// Description: +// Signals for caliptra's internal fabric interface +// + +interface cif_if #(parameter integer ADDR_WIDTH = 32, parameter integer DATA_WIDTH = 32, parameter integer ID_WIDTH = 8, parameter integer USER_WIDTH = 32) (input logic clk, input logic rst_b); + + typedef struct packed { + logic write; + logic [ADDR_WIDTH-1:0] addr; + logic [DATA_WIDTH-1:0] wdata; + logic [DATA_WIDTH/8-1:0] wstrb; + logic [2:0] size; + logic last; + logic [USER_WIDTH-1:0] user; + logic [ID_WIDTH-1:0] id; + } cif_req_data_t; + + logic dv; + logic hold; + logic write; + logic [DATA_WIDTH-1:0] rdata; + logic error; + cif_req_data_t req_data; + + + // Modport for read manager + modport request ( + + output dv, + output req_data, + + input hold, + input rdata, + input error + ); + + // Modport for write manager + modport response ( + input dv, + input req_data, + + output hold, + output rdata, + output error + ); + +endinterface diff --git a/src/mci/rtl/mci_axi_sub_decode.sv b/src/mci/rtl/mci_axi_sub_decode.sv new file mode 100644 index 0000000..310af53 --- /dev/null +++ b/src/mci/rtl/mci_axi_sub_decode.sv @@ -0,0 +1,108 @@ + +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the 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. +// +// Description: +// Decodes the SOC request and sends to appropriate target. +// + +module mci_axi_sub_decode + import mci_pkg::*; + #( + // Configurable memory blocks + parameter MCU_SRAM_SIZE_KB = 1024, + parameter MBOX0_SIZE_KB = 4, // KB + parameter MBOX1_SIZE_KB = 4, // KB + + + /////////////////////////////////////////////////////////// + // MCI Memory Map + /////////////////////////////////////////////////////////// + localparam CSR_SIZE_KB = 512, // FIXME should I expose? KB + localparam CSR_START_ADDR = 32'h0000_0000, + localparam CSR_END_ADDR = CSR_START_ADDR + (CSR_SIZE_KB * KB) - 1, + localparam MBOX0_START_ADDR = 32'h0008_0000, + localparam MBOX0_END_ADDR = MBOX0_START_ADDR + (MBOX0_SIZE_KB * KB) - 1, + localparam MBOX1_START_ADDR = MBOX0_END_ADDR + 32'h0000_0001, // FIXME: Do we want B2B + localparam MBOX1_END_ADDR = MBOX1_START_ADDR + (MBOX1_SIZE_KB * KB) - 1, + localparam MCU_SRAM_START_ADDR = 32'h0002_0000, + localparam MCU_SRAM_END_ADDR = MCU_SRAM_START_ADDR + (MCU_SRAM_SIZE_KB * KB) - 1 + + + ) + ( + //SOC inf + cif_if.response soc_resp_if, + + //MCU SRAM inf + cif_if.request mcu_sram_req_if +); + +// GRANT signals +logic soc_mcu_sram_gnt; + +// MISC signals +logic soc_req_miss; + + +/////////////////////////////////////////////////////////// +// Decode which address space is being requested +/////////////////////////////////////////////////////////// +//SoC requests to MCU_SRAM +always_comb soc_mcu_sram_gnt = (soc_resp_if.dv & (soc_resp_if.req_data.addr inside {[MCU_SRAM_START_ADDR:MCU_SRAM_END_ADDR]})); + + +/////////////////////////////////////////////////////////// +// Drive DV to appropriate destination +/////////////////////////////////////////////////////////// + +// MCU SRAM +always_comb mcu_sram_req_if.dv = soc_mcu_sram_gnt; + + +/////////////////////////////////////////////////////////// +// Drive data and reqest to approriate destination. +/////////////////////////////////////////////////////////// + +// MCU SRAM +always_comb mcu_sram_req_if.req_data = soc_resp_if.req_data; + + + +/////////////////////////////////////////////////////////// +// Drive read data back +/////////////////////////////////////////////////////////// + +assign soc_resp_if.rdata = soc_mcu_sram_gnt ? mcu_sram_req_if.rdata : '0; + + +/////////////////////////////////////////////////////////// +// Drive approriate hold back +/////////////////////////////////////////////////////////// + +always_comb soc_resp_if.hold = (soc_mcu_sram_gnt & (~soc_mcu_sram_gnt | mcu_sram_req_if.hold)); + + +/////////////////////////////////////////////////////////// +// Drive approriate error back or request misses all desitnations +/////////////////////////////////////////////////////////// + +// Missed all destinations +always_comb soc_req_miss = soc_resp_if.dv & ~(soc_mcu_sram_gnt); + +// Error for SOC +always_comb soc_resp_if.error = (soc_mcu_sram_gnt & mcu_sram_req_if.error) | + soc_req_miss; + +endmodule diff --git a/src/mci/rtl/mci_axi_sub_top.sv b/src/mci/rtl/mci_axi_sub_top.sv new file mode 100644 index 0000000..4e84f36 --- /dev/null +++ b/src/mci/rtl/mci_axi_sub_top.sv @@ -0,0 +1,118 @@ +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the 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. +// +// Description: +// Translates AXI requests to internal fabric. Decoding the requests +// and sending to the appropriate target. +// + + +module mci_axi_sub_top + #( + parameter MCU_SRAM_SIZE_KB = 1024, + parameter MBOX0_SIZE_KB = 4, + parameter MBOX1_SIZE_KB = 4 + ) + ( + input logic clk, + + // MCI Resets + input logic rst_b, + + // MCI AXI Interface + axi_if.w_sub s_axi_w_if, + axi_if.r_sub s_axi_r_if, + + // MCU SRAM Interface + cif_if.request mcu_sram_req_if + + ); + +localparam AXI_ADDR_WIDTH = s_axi_w_if.AW; +localparam AXI_DATA_WIDTH = s_axi_w_if.DW; +localparam AXI_USER_WIDTH = s_axi_w_if.UW; +localparam AXI_ID_WIDTH = s_axi_w_if.IW; + +// Interface between axi_sub and mci decoder +cif_if #( + .ADDR_WIDTH(AXI_ADDR_WIDTH), + .DATA_WIDTH(AXI_DATA_WIDTH), + .ID_WIDTH(AXI_ID_WIDTH), + .USER_WIDTH(AXI_USER_WIDTH) + ) + soc_resp_if( + .clk, + .rst_b(rst_b) + ); + +//AXI Interface +//This module contains the logic for interfacing with the SoC over the AXI Interface +//The SoC sends read and write requests using AXI Protocol +//This wrapper decodes that protocol, collapses the full-duplex protocol to +// simplex, and issues requests to the MIC decode block +axi_sub #( + .AW (AXI_ADDR_WIDTH), + .DW (AXI_DATA_WIDTH), + .UW (AXI_USER_WIDTH), + .IW (AXI_ID_WIDTH ), + .EX_EN(0 ), + .C_LAT(0 ) +) i_axi_sub ( + .clk (clk ), + .rst_n(rst_b), + + // AXI INF + .s_axi_w_if(s_axi_w_if), + .s_axi_r_if(s_axi_r_if), + + //COMPONENT INF + .dv (soc_resp_if.dv ), + .addr (soc_resp_if.req_data.addr ), // Byte address + .write (soc_resp_if.req_data.write ), + .user (soc_resp_if.req_data.user ), + .id (soc_resp_if.req_data.id ), + .wdata (soc_resp_if.req_data.wdata ), // Requires: Component dwidth == AXI dwidth + .wstrb (soc_resp_if.req_data.wstrb ), // FIXME unused today Requires: Component dwidth == AXI dwidth + .rdata (soc_resp_if.rdata ), // Requires: Component dwidth == AXI dwidth + .last (soc_resp_if.req_data.last), // FIXME unused in code today Asserted with final 'dv' of a burst + .hld (soc_resp_if.hold ), + .rd_err(soc_resp_if.error ), + .wr_err(soc_resp_if.error ) +); + +assign soc_resp_if.req_data.size = '0; // FIXME unused? + +//AXI Interface +//This module contains the logic for interfacing with the SoC over the AXI Interface +//The SoC sends read and write requests using AXI Protocol +//This wrapper decodes that protocol, collapses the full-duplex protocol to +// simplex, and issues requests to the MIC decode block +mci_axi_sub_decode #( + .MCU_SRAM_SIZE_KB (MCU_SRAM_SIZE_KB), + .MBOX0_SIZE_KB (MBOX0_SIZE_KB), + .MBOX1_SIZE_KB (MBOX1_SIZE_KB) +) i_mci_axi_sub_decode ( + //SOC inf + .soc_resp_if (soc_resp_if.response), + + //MCU SRAM inf + .mcu_sram_req_if (mcu_sram_req_if) +); + +//req from axi is for soc always +// always_comb soc_req.soc_req = 1'b1; FIXME remove? + + + +endmodule diff --git a/src/mci/rtl/mci_mcu_sram_ctrl.sv b/src/mci/rtl/mci_mcu_sram_ctrl.sv new file mode 100644 index 0000000..d0ec506 --- /dev/null +++ b/src/mci/rtl/mci_mcu_sram_ctrl.sv @@ -0,0 +1,335 @@ +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the 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. +// +// Description: +// This module is used to control requests going to a single MCU SRAM. +// Requests come in through the cif_resp_if and are passed the the SRAM +// on the mci_mcu_sram_req_if. +// +// Fabric Limitations: +// The integrator and higher level fabric is responsible for routing appropriate +// requests to the MCU SRAM as this module cannot detect address aliasing. +// +// Error handling: +// If an access vilation due to USER privilage issues is detected it +// will always return an error on the first cycle of the cif_if. +// ECC errors are returned on the read data phase (second clock cycle) +// +// Region mapping: +// The lower address is mapped to the exec region. Upper address range is mapped +// to prot region. If fw_sram_exec_region_size is larger than the actual SRAM size +// the entier SRAM is considered exec region and there is no prot region + +module mci_mcu_sram_ctrl + #( + parameter MCU_SRAM_SIZE_KB = 1024 + ) + ( + input logic clk, + + // MCI Resets + input logic rst_b, + + // Interface + input logic [15:0] fw_sram_exec_region_size, // 4KB steps with 0 being 4KB + + // Caliptra internal fabric response interface + cif_if.response cif_resp_if, + + // AXI users + input logic [cif_resp_if.USER_WIDTH-1:0] strap_mcu_lsu_axi_user, + input logic [cif_resp_if.USER_WIDTH-1:0] strap_mcu_ifu_axi_user, + input logic [cif_resp_if.USER_WIDTH-1:0] strap_clp_axi_user, + + // Access lock interface + input logic mcu_sram_fw_exec_region_lock, + + // ECC Status + output logic sram_single_ecc_error, + output logic sram_double_ecc_error, + + + // Interface with SRAM + mci_mcu_sram_if.request mci_mcu_sram_req_if + + +); +localparam BITS_IN_BYTE = 8; +localparam KB = 1024; // Bytes in KB + +localparam MCU_SRAM_SIZE_BYTES = MCU_SRAM_SIZE_KB * KB; +localparam MCU_SRAM_DATA_W = mci_mcu_sram_req_if.DATA_WIDTH; +localparam MCU_SRAM_DATA_W_BYTES = MCU_SRAM_DATA_W / BITS_IN_BYTE; +localparam MCU_SRAM_ECC_DATA_W = mci_mcu_sram_req_if.ECC_WIDTH; +localparam MCU_SRAM_DATA_AND_ECC_W = MCU_SRAM_DATA_W + MCU_SRAM_ECC_DATA_W; +localparam MCU_SRAM_DEPTH = MCU_SRAM_SIZE_BYTES / MCU_SRAM_DATA_W_BYTES; +localparam MCU_SRAM_ADDR_W = $clog2(MCU_SRAM_DEPTH); + +// Number of address bits needed on cif_req_if.addr to address the entire +// SRAM. AKA address scope +localparam MCU_SRAM_CIF_ADDR_W = $clog2(MCU_SRAM_SIZE_BYTES); + + + +// Memory region request +logic exec_region_match; +logic exec_region_req; +logic prot_region_req; + +// Momory region mapping +logic [28:0] exec_region_base; // TODO: Report to status register? +logic [28:0] exec_region_end_calc; +logic [28:0] exec_region_end; // TODO: Report to status register? +logic exec_region_overflow; +// fw_sram_exec_region_size size is 16 bits so the max size +// the exec region can be is (0xFFF + 1) << 12 = 10_000_000 +// Which bit 28 set. +logic [28:0] exec_region_size_bytes; + + + +// Filtering status +logic exec_region_filter_success; +logic exec_region_filter_error; + +logic prot_region_filter_success; +logic prot_region_filter_error; + +// Agent request checks +logic mcu_lsu_req; +logic mcu_ifu_req; +logic clp_req; + +// SRAM Read/Write request and phase signals +logic mcu_sram_valid_req; +logic mcu_sram_read_req; +logic mcu_sram_write_req; +logic sram_req_phase; +logic sram_read_req_phase; +logic sram_write_req_phase; +logic sram_read_data_phase; + +// SRAM read/ecc +logic sram_rd_ecc_en; +logic [MCU_SRAM_DATA_W-1:0] sram_rdata; +logic [MCU_SRAM_DATA_W-1:0] sram_rdata_cor; +logic [MCU_SRAM_ECC_DATA_W-1:0] sram_rdata_ecc; + +/////////////////////////////////////////////// +// Calculate all properties about the SRAM +// based on the fw_sram_exec_region_size +/////////////////////////////////////////////// +assign exec_region_base = '0; +// 4KB = 2^12 +assign exec_region_size_bytes = {13'b0, (fw_sram_exec_region_size + 16'b1)} << 12; +// Calculate final address based on the fw_sram_exec_region_size. +assign exec_region_end_calc = exec_region_base + exec_region_size_bytes - 1; +// Check if there was overflow due to fw_sram_exec_region_size being larger than the entire +// SRAM. +assign exec_region_overflow = |exec_region_end_calc[28:MCU_SRAM_CIF_ADDR_W]; +// If there was overflow set to the MCU SRAM size. +// Otherwise take the calculated value +assign exec_region_end = exec_region_overflow ? (MCU_SRAM_SIZE_BYTES-1) : + exec_region_end_calc; + + + + +/////////////////////////////////////////////// +// Determine if protected region or execution +// region is being accessed +/////////////////////////////////////////////// + +// Detect if the address in the MCU_SRAM scope matches the exec region +// When determining the exec_region_end it must address overflow/over provision +// issues for this check to work. +assign exec_region_match = (cif_resp_if.req_data.addr[MCU_SRAM_CIF_ADDR_W-1:0] <= exec_region_end[MCU_SRAM_CIF_ADDR_W-1:0]); + +// Qualify the exec_region_match with DV to detect either exec or prot +// region request +assign exec_region_req = cif_resp_if.dv & exec_region_match; +assign prot_region_req = cif_resp_if.dv & !exec_region_match; + + +/////////////////////////////////////////////// +// Determine if the user matches any of the +// previlaged users +/////////////////////////////////////////////// +assign mcu_lsu_req = ~(|(cif_resp_if.req_data.user ^ strap_mcu_lsu_axi_user)); +assign mcu_ifu_req = ~(|(cif_resp_if.req_data.user ^ strap_mcu_ifu_axi_user)); +assign clp_req = ~(|(cif_resp_if.req_data.user ^ strap_clp_axi_user)); + +/////////////////////////////////////////////// +// Protected data region access protection +/////////////////////////////////////////////// + +// This logic will help in 2 areas: +// 1. We can use these signals to block read or a write +// ever reaching the SRAM. +// 2. Reads take 2 clock cycles. But we can use these signals +// to detect an illegal access and respond with an error +// on the first clock cycle +assign prot_region_filter_success = prot_region_req & mcu_lsu_req; +assign prot_region_filter_error = prot_region_req & ~prot_region_filter_success; + + +/////////////////////////////////////////////// +// Execution data region access protection +/////////////////////////////////////////////// + +// This logic will help in 2 areas: +// 1. We can use these signals to block read or a write +// ever reaching the SRAM. +// 2. Reads take 2 clock cycles. But we can use these signals +// to detect an illegal access and respond with an error +// on the first clock cycle +always_comb begin + exec_region_filter_success = '0; + exec_region_filter_error = '0; + if (exec_region_req) begin + if (mcu_sram_fw_exec_region_lock) begin + exec_region_filter_success = (mcu_lsu_req | mcu_ifu_req); + exec_region_filter_error = ~exec_region_filter_success; + end + else begin + exec_region_filter_success = clp_req; + exec_region_filter_error = ~exec_region_filter_success; + end + end +end + + +/////////////////////////////////////////////// +// Converting the CIF to memory request +/////////////////////////////////////////////// + + +////////// +// Additional control signal +////////// +// CIF read or write request has successfully passed all filtering +// and the request needs to be sent to the SRAM +assign mcu_sram_valid_req = exec_region_filter_success | prot_region_filter_success; + +// Detecting read vs write requests +assign mcu_sram_read_req = mcu_sram_valid_req & (~cif_resp_if.req_data.write); +assign mcu_sram_write_req = mcu_sram_valid_req & cif_resp_if.req_data.write; + + +// Reading the sram takes 2 clock cycles and write request only take +// 1 clock cycles +// 1 - req_phase: Request sent to SRAM to read an address +// 2 - data_phase: Data is read back from the SRAM. Not needed for write requests +assign sram_req_phase = mcu_sram_valid_req & ~sram_read_data_phase; + +assign sram_write_req_phase = sram_req_phase & mcu_sram_write_req; +assign sram_read_req_phase = sram_req_phase & mcu_sram_write_req; + +always_ff @(posedge clk or negedge rst_b) begin + if(!rst_b) begin + sram_read_data_phase <= '0; + end + else begin + sram_read_data_phase <= (sram_req_phase & mcu_sram_read_req); + end + +end + + +////////// +// General Read/Write SRAM controls +////////// + +// All these signals should only be asserted during the sram_req_phase +// otherwise when we do reads that require 2 clock cycles we will +// trigger a second read to the SRAM. + +// Either read or write we need to pass the address to the memory interface. +// Must shift the address to account for sram being more than 1 byte wide +assign mci_mcu_sram_req_if.req.addr = sram_req_phase ? cif_resp_if.req_data.addr [MCU_SRAM_ADDR_W-1:2] : '0; + +// All requests assert CS +assign mci_mcu_sram_req_if.req.cs = sram_req_phase; + + +////////// +// Write SRAM controls +////////// + +// Only toggle WE if write request +assign mci_mcu_sram_req_if.req.we = sram_write_req_phase; + +// Only passing write data to SRAM if write request. +assign mci_mcu_sram_req_if.req.wdata.data = sram_write_req_phase ? cif_resp_if.req_data.wdata : '0; + +// From RISC-V core beh_lib.sv +// 32-bit data width hardcoded +// 7-bit ECC width hardcoded +rvecc_encode ecc_encode ( + .din ( mci_mcu_sram_req_if.req.wdata.data), + .ecc_out( mci_mcu_sram_req_if.req.wdata.ecc ) +); + + +////////// +// Read SRAM controls +////////// + +assign sram_rd_ecc_en = sram_read_req_phase; + +assign sram_rdata = mci_mcu_sram_req_if.resp.rdata.data; +assign sram_rdata_ecc = mci_mcu_sram_req_if.resp.rdata.ecc; + +rvecc_decode ecc_decode ( + .en (sram_rd_ecc_en ), + .sed_ded ( 1'b0 ), // 1 : means only detection + .din (sram_rdata ), + .ecc_in (sram_rdata_ecc ), + .dout (sram_rdata_cor ), + .ecc_out ( ), // Unused in today's design + .single_ecc_error(sram_single_ecc_error), // TODO use to flag write-back + .double_ecc_error(sram_double_ecc_error) // TODO use to flag command error +); + +// Only send data back if we are in the sram_read_data_phase. Assumptions made: +// 1. We will only have sram_read_data_phase if a privilaged agent is doing the read +// 2. If an ECC error is detected it is OK to send garbage data back. +assign cif_resp_if.rdata = sram_read_data_phase ? sram_rdata_cor : '0; + +/////////////////////////////////////////////// +// Hold response +/////////////////////////////////////////////// + +// Only hold up the interface if we have a successful +// read request. Meaning the read request got through all +// the protection filtering and is sent to the SRAM. +// We wait 1 clock cycle and then read data is back +// from the sram +assign cif_resp_if.hold = sram_read_req_phase; + + +/////////////////////////////////////////////// +// Error response +/////////////////////////////////////////////// + +// Anytime an error is detected we pass it back on the interface. +// All error sources in this module shall only assert when DV is asserted. +// This logic is just an aggregate of the error sources and will not check +// for DV. +assign cif_resp_if.error = exec_region_filter_error | + prot_region_filter_error | + sram_double_ecc_error; // FIXME any other error conditions? + + +endmodule diff --git a/src/mci/rtl/mci_mcu_sram_if.sv b/src/mci/rtl/mci_mcu_sram_if.sv new file mode 100644 index 0000000..f0964c4 --- /dev/null +++ b/src/mci/rtl/mci_mcu_sram_if.sv @@ -0,0 +1,63 @@ +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the 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. +// +// Description: +// Signals for an SRAM interface with ECC +// + +interface mci_mcu_sram_if #(parameter integer ADDR_WIDTH = 16, parameter integer DATA_WIDTH = 32, parameter integer ECC_WIDTH = 7) (input logic clk, input logic rst_b); + + // SRAM data + typedef struct packed { + logic [ECC_WIDTH-1:0] ecc; + logic [DATA_WIDTH-1:0] data; + } sram_data_t; + + // Request to sram + typedef struct packed { + logic cs; + logic we; + logic [ADDR_WIDTH-1:0] addr; + sram_data_t wdata; + } sram_req_t; + + // Response from sram + typedef struct packed { + sram_data_t rdata; + } sram_resp_t; + + sram_req_t req; + + sram_resp_t resp; + + // Requester interface + modport request ( + + // Request to SRAM + output req, + + // Response from SRAM + input resp + ); + + // Response interface (typically on SRAM) + modport response ( + // Request to SRAM + input req, + + // Response from SRAM + output resp + ); + +endinterface diff --git a/src/mci/rtl/mci_pkg.sv b/src/mci/rtl/mci_pkg.sv index fd291c7..e2853c1 100644 --- a/src/mci/rtl/mci_pkg.sv +++ b/src/mci/rtl/mci_pkg.sv @@ -16,6 +16,10 @@ `define MCI_PKG package mci_pkg; + localparam KB = 1024; + localparam KB_BASE0 = KB - 1; + localparam MB = KB * 1024; + localparam MB_BASE0 = MB - 1; // Assert reset for 10 cycles then deassert // to facilitate the hitless update @@ -31,8 +35,8 @@ package mci_pkg; BOOT_WAIT_CPTRA = 4'b0110, BOOT_CPTRA = 4'b0111, BOOT_WAIT_UPDATE = 4'b1000, - BOOT_RST_MCU = 4'b1001, + BOOT_RST_MCU = 4'b1001 } mci_boot_fsm_state_e; -endmodule +endpackage `endif /*MCI_PKG*/ diff --git a/src/mci/rtl/mci_top.sv b/src/mci/rtl/mci_top.sv index a6617ea..f24bbed 100644 --- a/src/mci/rtl/mci_top.sv +++ b/src/mci/rtl/mci_top.sv @@ -12,6 +12,100 @@ // See the License for the specific language governing permissions and // limitations under the License. -module mci_top(); +module mci_top + #( + parameter MCU_SRAM_SIZE_KB = 1024 // FIXME - write assertion ensuring this size + // is compatible with the MCU SRAM IF parameters + ) + ( + input logic clk, + + // MCI Resets + input logic mci_rst_b, + + // MCI AXI Interface + axi_if.w_sub s_axi_w_if, + axi_if.r_sub s_axi_r_if, + + // MCU SRAM Interface + mci_mcu_sram_if.request mci_mcu_sram_req_if + + ); + + localparam AXI_ADDR_WIDTH = s_axi_w_if.AW; + localparam AXI_DATA_WIDTH = s_axi_w_if.DW; + localparam AXI_USER_WIDTH = s_axi_w_if.UW; + localparam AXI_ID_WIDTH = s_axi_w_if.IW; + + +// Caliptra internal fabric interface for MCU SRAM +// Address width is set to AXI_ADDR_WIDTH and MCU SRAM +// will mask out upper bits that are "don't care" +cif_if #( + .ADDR_WIDTH(AXI_ADDR_WIDTH) + ,.DATA_WIDTH(AXI_DATA_WIDTH) + ,.ID_WIDTH(AXI_ID_WIDTH) + ,.USER_WIDTH(AXI_USER_WIDTH) +) mcu_sram_req_if( + .clk, + .rst_b(mci_rst_b)); + +//AXI Interface +//This module contains the logic for interfacing with the SoC over the AXI Interface +//The SoC sends read and write requests using AXI Protocol +//This wrapper decodes that protocol, collapses the full-duplex protocol to +// simplex, and issues requests to the MIC decode block +mci_axi_sub_top #( // FIXME: Should SUB and MAIN be under same AXI_TOP module? + .MCU_SRAM_SIZE_KB(MCU_SRAM_SIZE_KB), + .MBOX0_SIZE_KB (4), // FIXME + .MBOX1_SIZE_KB (4) // FIXME +) i_mci_axi_sub_top ( + // MCI clk + .clk (clk ), + + // MCI Resets + .rst_b(mci_rst_b), // FIXME: Need to sync reset + + // AXI INF + .s_axi_w_if(s_axi_w_if), + .s_axi_r_if(s_axi_r_if), + + // MCU SRAM Interface + .mcu_sram_req_if( mcu_sram_req_if.request ) +); + + +// MCU SRAM +// Translates requests from the AXI SUB and sends them to the MCU SRAM. +mci_mcu_sram_ctrl #( + .MCU_SRAM_SIZE_KB(MCU_SRAM_SIZE_KB) +) i_mci_mcu_sram_ctrl ( + // MCI clk + .clk (clk), + + // MCI Resets + .rst_b (mci_rst_b), // FIXME: Need to sync reset + + // Interface + .fw_sram_exec_region_size('0), // FIXME + + // Caliptra internal fabric response interface + .cif_resp_if (mcu_sram_req_if.response), + + // AXI users + .strap_mcu_lsu_axi_user('0), // FIXME + .strap_mcu_ifu_axi_user('0), // FIXME + .strap_clp_axi_user('0), // FIXME + + // Access lock interface + .mcu_sram_fw_exec_region_lock('0), // FIXME + + // ECC Status + .sram_single_ecc_error(), // FIXME + .sram_double_ecc_error(), // FIXME + + // Interface with SRAM + .mci_mcu_sram_req_if(mci_mcu_sram_req_if) +); endmodule