[icache] Add RAM Primitives for scrambling

This commit includes switching to a scrambling RAM primitive for
ICache data and tag RAMs. Also introduces minor changes to ICache
to handle scrambling key valid signal.

It also includes a minor bug fix regarding not initializing
`fill_way_q` signal without ResetAll parameter. When the parameter
is not set and we have our first hit right after ICache enables,
the signal hangs.

Signed-off-by: Canberk Topal <ctopal@lowrisc.org>
This commit is contained in:
Canberk Topal 2021-10-07 18:04:56 +01:00 committed by Greg Chadwick
parent e53b033962
commit 187944c417
25 changed files with 690 additions and 284 deletions

View file

@ -26,6 +26,7 @@ Instantiation Template
.RegFile ( ibex_pkg::RegFileFF ),
.ICache ( 0 ),
.ICacheECC ( 0 ),
.ICacheScramble ( 0 ),
.BranchPrediction ( 0 ),
.SecureIbex ( 0 ),
.RndCnstLfsrSeed ( ibex_pkg::RndCnstLfsrSeedDefault ),
@ -131,6 +132,9 @@ Parameters
| ``ICacheECC`` | bit | 0 | *EXPERIMENTAL* Enable SECDED ECC protection in ICache (if |
| | | | ICache == 1) |
+------------------------------+---------------------+------------+-----------------------------------------------------------------------+
| ``ICacheScramble`` | bit | 0 | *EXPERIMENTAL* Enabling this parameter replaces tag and data RAMs of |
| | | | ICache with scrambling RAM primitives. |
+------------------------------+---------------------+------------+-----------------------------------------------------------------------+
| ``BranchPrediction`` | bit | 0 | *EXPERIMENTAL* Enable Static branch prediction |
+------------------------------+---------------------+------------+-----------------------------------------------------------------------+
| ``SecureIbex`` | bit | 0 | *EXPERIMENTAL* Enable various additional features targeting |
@ -193,6 +197,8 @@ Interfaces
| ``data_*`` | Load-store unit interface, see :ref:`load-store-unit` |
+-------------------------+------------------------------------------------------------------------+
| ``irq_*`` | Interrupt inputs, see :ref:`exceptions-interrupts` |
+-------------------------+-------------------------+-----+----------------------------------------+
| ``scramble_*`` | Scrambling key interface, see :ref:`icache` |
+-------------------------+------------------------------------------------------------------------+
| ``debug_*`` | Debug interface, see :ref:`debug-support` |
+-------------------------+------------------------------------------------------------------------+

View file

@ -93,6 +93,12 @@ Indicative RAM sizes for common configurations are given in the table below:
| 4kB, 4 way, 64bit line | 4 x 128 x 22bit | 4 x 128 x 64bit |
+------------------------------+-----------------+------------------+
If ICacheScramble parameter is enabled, all RAM primitives are replaced with scrambling RAM primitive.
For more information about how scrambling works internally (see :file:`vendor/lowrisc_ip/ip/prim/doc/prim_ram_1p_scr.md`).
Interface for receiving scrambling key follows req / ack protocol.
Ibex first requests a new ephemeral key by asserting the request (`scramble_req_o) and when a fresh valid key is indicated by `scramble_key_valid_i, it deasserts the request.
Note that in current implementation, it is assumed req/ack protocol is synchronized before arriving to Ibex top level.
Sub Unit Description
--------------------

View file

@ -5,24 +5,23 @@ CAPI=2:
name: "lowrisc:ibex:ibex_riscv_compliance:0.1"
description: "Ibex simulation for RISC-V compliance testing (using Verilator)"
filesets:
files_sim_verilator:
files_sim:
depend:
- lowrisc:dv_verilator:memutil_verilator
- lowrisc:dv_verilator:simutil_verilator
- lowrisc:ibex:ibex_top_tracing
- lowrisc:ibex:sim_shared
files:
- rtl/ibex_riscv_compliance.sv
- ibex_riscv_compliance.cc: { file_type: cppSource }
- rtl/riscv_testutil.sv
file_type: systemVerilogSource
files_verilator_waiver:
files_verilator:
depend:
- lowrisc:dv_verilator:memutil_verilator
- lowrisc:dv_verilator:simutil_verilator
files:
- ibex_riscv_compliance.cc: { file_type: cppSource }
- lint/verilator_waiver.vlt: {file_type: vlt}
parameters:
RV32E:
datatype: int
@ -102,12 +101,18 @@ parameters:
default: 0
description: "Enables security hardening features (EXPERIMENTAL) [0/1]"
ICacheScramble:
datatype: int
paramtype: vlogparam
default: 0
description: "Enables ICache scrambling feature (EXPERIMENTAL) [0/1]"
targets:
sim:
default_tool: verilator
filesets:
- tool_verilator ? (files_verilator_waiver)
- files_sim_verilator
- files_sim
- tool_verilator ? (files_verilator)
parameters:
- RV32E
- RV32M
@ -122,6 +127,7 @@ targets:
- PMPGranularity
- PMPNumRegions
- SecureIbex
- ICacheScramble
toplevel: ibex_riscv_compliance
tools:
verilator:

View file

@ -28,6 +28,7 @@ module ibex_riscv_compliance (
parameter bit ICacheECC = 1'b0;
parameter bit BranchPredictor = 1'b0;
parameter bit SecureIbex = 1'b0;
parameter bit ICacheScramble = 1'b0;
logic clk_sys, rst_sys_n;
@ -80,7 +81,6 @@ module ibex_riscv_compliance (
assign cfg_device_addr_base[TestUtilDevice] = 32'h20000;
assign cfg_device_addr_mask[TestUtilDevice] = ~32'h3FF; // 1 kB
bus #(
.NrDevices (NrDevices),
.NrHosts (NrHosts ),
@ -127,53 +127,59 @@ module ibex_riscv_compliance (
.ICacheECC (ICacheECC ),
.BranchPredictor (BranchPredictor ),
.SecureIbex (SecureIbex ),
.ICacheScramble (ICacheScramble ),
.DmHaltAddr (32'h00000000 ),
.DmExceptionAddr (32'h00000000 )
) u_top (
.clk_i (clk_sys ),
.rst_ni (rst_sys_n ),
.clk_i (clk_sys ),
.rst_ni (rst_sys_n ),
.test_en_i ('b0 ),
.scan_rst_ni (1'b1 ),
.ram_cfg_i ('b0 ),
.test_en_i ('b0 ),
.scan_rst_ni (1'b1 ),
.ram_cfg_i ('b0 ),
.hart_id_i (32'b0 ),
.hart_id_i (32'b0 ),
// First instruction executed is at 0x0 + 0x80
.boot_addr_i (32'h00000000 ),
.boot_addr_i (32'h00000000 ),
.instr_req_o (host_req[CoreI] ),
.instr_gnt_i (host_gnt[CoreI] ),
.instr_rvalid_i (host_rvalid[CoreI]),
.instr_addr_o (host_addr[CoreI] ),
.instr_rdata_i (host_rdata[CoreI] ),
.instr_rdata_intg_i ('0 ),
.instr_err_i (host_err[CoreI] ),
.instr_req_o (host_req[CoreI] ),
.instr_gnt_i (host_gnt[CoreI] ),
.instr_rvalid_i (host_rvalid[CoreI]),
.instr_addr_o (host_addr[CoreI] ),
.instr_rdata_i (host_rdata[CoreI] ),
.instr_rdata_intg_i ('0 ),
.instr_err_i (host_err[CoreI] ),
.data_req_o (host_req[CoreD] ),
.data_gnt_i (host_gnt[CoreD] ),
.data_rvalid_i (host_rvalid[CoreD]),
.data_we_o (host_we[CoreD] ),
.data_be_o (host_be[CoreD] ),
.data_addr_o (host_addr[CoreD] ),
.data_wdata_o (host_wdata[CoreD] ),
.data_wdata_intg_o ( ),
.data_rdata_i (host_rdata[CoreD] ),
.data_rdata_intg_i ('0 ),
.data_err_i (host_err[CoreD] ),
.data_req_o (host_req[CoreD] ),
.data_gnt_i (host_gnt[CoreD] ),
.data_rvalid_i (host_rvalid[CoreD]),
.data_we_o (host_we[CoreD] ),
.data_be_o (host_be[CoreD] ),
.data_addr_o (host_addr[CoreD] ),
.data_wdata_o (host_wdata[CoreD] ),
.data_wdata_intg_o ( ),
.data_rdata_i (host_rdata[CoreD] ),
.data_rdata_intg_i ('0 ),
.data_err_i (host_err[CoreD] ),
.irq_software_i (1'b0 ),
.irq_timer_i (1'b0 ),
.irq_external_i (1'b0 ),
.irq_fast_i (15'b0 ),
.irq_nm_i (1'b0 ),
.irq_software_i (1'b0 ),
.irq_timer_i (1'b0 ),
.irq_external_i (1'b0 ),
.irq_fast_i (15'b0 ),
.irq_nm_i (1'b0 ),
.debug_req_i ('b0 ),
.crash_dump_o ( ),
.scramble_key_valid_i ('0 ),
.scramble_key_i ('0 ),
.scramble_nonce_i ('0 ),
.scramble_req_o ( ),
.fetch_enable_i ('b1 ),
.alert_minor_o ( ),
.alert_major_o ( ),
.core_sleep_o ( )
.debug_req_i ('b0 ),
.crash_dump_o ( ),
.fetch_enable_i ('b1 ),
.alert_minor_o ( ),
.alert_major_o ( ),
.core_sleep_o ( )
);
// SRAM block for instruction and data storage

View file

@ -24,13 +24,34 @@ ${PRJ_DIR}/vendor/lowrisc_ip/ip/prim/rtl/prim_secded_inv_39_32_enc.sv
${PRJ_DIR}/vendor/lowrisc_ip/ip/prim/rtl/prim_secded_inv_39_32_dec.sv
${PRJ_DIR}/vendor/lowrisc_ip/ip/prim/rtl/prim_secded_inv_72_64_enc.sv
${PRJ_DIR}/vendor/lowrisc_ip/ip/prim/rtl/prim_secded_inv_72_64_dec.sv
${PRJ_DIR}/vendor/lowrisc_ip/ip/prim/rtl/prim_prince.sv
${PRJ_DIR}/vendor/lowrisc_ip/ip/prim/rtl/prim_subst_perm.sv
${PRJ_DIR}/vendor/lowrisc_ip/ip/prim/rtl/prim_secded_28_22_enc.sv
${PRJ_DIR}/vendor/lowrisc_ip/ip/prim/rtl/prim_secded_28_22_dec.sv
${PRJ_DIR}/vendor/lowrisc_ip/ip/prim/rtl/prim_secded_39_32_enc.sv
${PRJ_DIR}/vendor/lowrisc_ip/ip/prim/rtl/prim_secded_39_32_dec.sv
${PRJ_DIR}/vendor/lowrisc_ip/ip/prim/rtl/prim_secded_72_64_enc.sv
${PRJ_DIR}/vendor/lowrisc_ip/ip/prim/rtl/prim_secded_72_64_dec.sv
// Until this list is generated by FuseSoC, we have to use manually generated
// wrappers around the prim_* modules to instantiate the prim_generic_* ones,
// see https://github.com/lowRISC/ibex/issues/893.
${PRJ_DIR}/dv/uvm/core_ibex/common/prim/prim_pkg.sv
${PRJ_DIR}/vendor/lowrisc_ip/ip/prim/rtl/prim_util_pkg.sv
${PRJ_DIR}/vendor/lowrisc_ip/ip/prim/rtl/prim_secded_pkg.sv
${PRJ_DIR}/vendor/lowrisc_ip/ip/prim/rtl/prim_secded_22_16_dec.sv
${PRJ_DIR}/vendor/lowrisc_ip/ip/prim/rtl/prim_secded_22_16_enc.sv
${PRJ_DIR}/vendor/lowrisc_ip/ip/prim/rtl/prim_secded_64_57_dec.sv
${PRJ_DIR}/vendor/lowrisc_ip/ip/prim/rtl/prim_secded_64_57_enc.sv
${PRJ_DIR}/vendor/lowrisc_ip/ip/prim/rtl/prim_secded_hamming_22_16_dec.sv
${PRJ_DIR}/vendor/lowrisc_ip/ip/prim/rtl/prim_secded_hamming_22_16_enc.sv
${PRJ_DIR}/vendor/lowrisc_ip/ip/prim/rtl/prim_secded_hamming_39_32_dec.sv
${PRJ_DIR}/vendor/lowrisc_ip/ip/prim/rtl/prim_secded_hamming_39_32_enc.sv
${PRJ_DIR}/vendor/lowrisc_ip/ip/prim/rtl/prim_secded_hamming_72_64_dec.sv
${PRJ_DIR}/vendor/lowrisc_ip/ip/prim/rtl/prim_secded_hamming_72_64_enc.sv
${PRJ_DIR}/vendor/lowrisc_ip/ip/prim/rtl/prim_ram_1p_pkg.sv
${PRJ_DIR}/vendor/lowrisc_ip/ip/prim/rtl/prim_ram_1p_adv.sv
${PRJ_DIR}/vendor/lowrisc_ip/ip/prim/rtl/prim_ram_1p_scr.sv
${PRJ_DIR}/vendor/lowrisc_ip/ip/prim_generic/rtl/prim_generic_ram_1p.sv
${PRJ_DIR}/dv/uvm/core_ibex/common/prim/prim_ram_1p.sv
${PRJ_DIR}/vendor/lowrisc_ip/ip/prim_generic/rtl/prim_generic_clock_gating.sv

View file

@ -10,6 +10,7 @@ module core_ibex_tb_top;
import core_ibex_test_pkg::*;
wire clk;
wire scramble_req;
wire rst_n;
clk_rst_if ibex_clk_if(.clk(clk), .rst_n(rst_n));
@ -63,6 +64,7 @@ module core_ibex_tb_top;
parameter bit ICacheECC = 1'b0;
parameter bit BranchPredictor = 1'b0;
parameter bit SecureIbex = 1'b0;
parameter bit ICacheScramble = 1'b0;
ibex_top_tracing #(
.DmHaltAddr (32'h`BOOT_ADDR + 'h0 ),
@ -79,6 +81,7 @@ module core_ibex_tb_top;
.ICache (ICache ),
.ICacheECC (ICacheECC ),
.SecureIbex (SecureIbex ),
.ICacheScramble (ICacheScramble ),
.BranchPredictor (BranchPredictor )
) dut (
.clk_i (clk ),
@ -91,39 +94,44 @@ module core_ibex_tb_top;
.hart_id_i (32'b0 ),
.boot_addr_i (32'h`BOOT_ADDR ), // align with spike boot address
.instr_req_o (instr_mem_vif.request),
.instr_gnt_i (instr_mem_vif.grant ),
.instr_rvalid_i (instr_mem_vif.rvalid ),
.instr_addr_o (instr_mem_vif.addr ),
.instr_rdata_i (instr_mem_vif.rdata ),
.instr_rdata_intg_i (instr_mem_vif.rintg ),
.instr_err_i (instr_mem_vif.error ),
.instr_req_o (instr_mem_vif.request ),
.instr_gnt_i (instr_mem_vif.grant ),
.instr_rvalid_i (instr_mem_vif.rvalid ),
.instr_addr_o (instr_mem_vif.addr ),
.instr_rdata_i (instr_mem_vif.rdata ),
.instr_rdata_intg_i (instr_mem_vif.rintg ),
.instr_err_i (instr_mem_vif.error ),
.data_req_o (data_mem_vif.request ),
.data_gnt_i (data_mem_vif.grant ),
.data_rvalid_i (data_mem_vif.rvalid ),
.data_addr_o (data_mem_vif.addr ),
.data_we_o (data_mem_vif.we ),
.data_be_o (data_mem_vif.be ),
.data_rdata_i (data_mem_vif.rdata ),
.data_rdata_intg_i (data_mem_vif.rintg ),
.data_wdata_o (data_mem_vif.wdata ),
.data_wdata_intg_o (data_mem_vif.wintg ),
.data_err_i (data_mem_vif.error ),
.data_req_o (data_mem_vif.request ),
.data_gnt_i (data_mem_vif.grant ),
.data_rvalid_i (data_mem_vif.rvalid ),
.data_addr_o (data_mem_vif.addr ),
.data_we_o (data_mem_vif.we ),
.data_be_o (data_mem_vif.be ),
.data_rdata_i (data_mem_vif.rdata ),
.data_rdata_intg_i (data_mem_vif.rintg ),
.data_wdata_o (data_mem_vif.wdata ),
.data_wdata_intg_o (data_mem_vif.wintg ),
.data_err_i (data_mem_vif.error ),
.irq_software_i (irq_vif.irq_software ),
.irq_timer_i (irq_vif.irq_timer ),
.irq_external_i (irq_vif.irq_external ),
.irq_fast_i (irq_vif.irq_fast ),
.irq_nm_i (irq_vif.irq_nm ),
.irq_software_i (irq_vif.irq_software ),
.irq_timer_i (irq_vif.irq_timer ),
.irq_external_i (irq_vif.irq_external ),
.irq_fast_i (irq_vif.irq_fast ),
.irq_nm_i (irq_vif.irq_nm ),
.debug_req_i (dut_if.debug_req ),
.crash_dump_o ( ),
.scramble_key_valid_i ('0 ),
.scramble_key_i ('0 ),
.scramble_nonce_i ('0 ),
.scramble_req_o ( ),
.fetch_enable_i (dut_if.fetch_enable ),
.alert_minor_o (dut_if.alert_minor ),
.alert_major_o (dut_if.alert_major ),
.core_sleep_o (dut_if.core_sleep )
.debug_req_i (dut_if.debug_req ),
.crash_dump_o ( ),
.fetch_enable_i (dut_if.fetch_enable ),
.alert_minor_o (dut_if.alert_minor ),
.alert_major_o (dut_if.alert_major ),
.core_sleep_o (dut_if.core_sleep )
);
// We should never see any alerts triggered in normal testing

View file

@ -15,6 +15,7 @@ filesets:
files_dv:
depend:
- lowrisc:dv:ibex_icache_test
- lowrisc:prim:ram_1p_scr
files:
- tb/tb.sv
file_type: systemVerilogSource

View file

@ -23,17 +23,19 @@
// Import additional common sim cfg files.
import_cfgs: [
// Project wide common sim cfg file
"{proj_root}/vendor/lowrisc_ip/dv/tools/dvsim/common_sim_cfg.hjson"
"{proj_root}/vendor/lowrisc_ip/dv/tools/dvsim/common_sim_cfg.hjson",
"{proj_root}/vendor/lowrisc_ip/dv/verilator/memutil_dpi_scrambled_opts.hjson"
]
build_modes: [
{
name: default
en_build_modes: ["{tool}_icache_ecc"]
en_build_modes: ["{tool}_icache_ecc",
"{tool}_memutil_dpi_scrambled_build_opts"]
}
{
name: vcs_icache_ecc
build_opts: ["-gv tb.ICacheECC=1"]
build_opts: ["-gv tb.ICacheECC=1 -gv tb.ICacheScramble=0"]
}
{
name: riviera_icache_ecc

View file

@ -2,7 +2,10 @@
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
//
module ic_top import ibex_pkg::*; #(parameter bit ICacheECC = 1'b0) (
module ic_top import ibex_pkg::*; #(
parameter bit ICacheECC = 1'b0,
parameter bit ICacheScramble = 1'b0
) (
input logic clk_i,
input logic rst_ni,
input logic req_i,
@ -23,6 +26,12 @@ module ic_top import ibex_pkg::*; #(parameter bit ICacheECC = 1'b0) (
input logic instr_err_i,
input logic instr_rvalid_i,
// Scrambling Interface
input logic scramble_key_valid_i,
input logic [SCRAMBLE_KEY_W-1:0] scramble_key_i,
input logic [SCRAMBLE_NONCE_W-1:0] scramble_nonce_i,
output logic scramble_req_o,
input logic icache_enable_i,
input logic icache_inval_i,
output logic busy_o
@ -31,7 +40,8 @@ module ic_top import ibex_pkg::*; #(parameter bit ICacheECC = 1'b0) (
localparam int unsigned BusSizeECC = ICacheECC ? (BUS_SIZE + 7) : BUS_SIZE;
localparam int unsigned LineSizeECC = BusSizeECC * IC_LINE_BEATS;
localparam int unsigned TagSizeECC = ICacheECC ? (IC_TAG_SIZE + 6) : IC_TAG_SIZE;
localparam int unsigned NumAddrScrRounds = ICacheScramble ? 2 : 0;
localparam int unsigned NumDiffRounds = NumAddrScrRounds;
// RAM IO
logic [IC_NUM_WAYS-1:0] ic_tag_req;
logic ic_tag_write;
@ -43,6 +53,12 @@ module ic_top import ibex_pkg::*; #(parameter bit ICacheECC = 1'b0) (
logic [IC_INDEX_W-1:0] ic_data_addr;
logic [LineSizeECC-1:0] ic_data_wdata;
logic [LineSizeECC-1:0] ic_data_rdata [IC_NUM_WAYS];
// Scramble signals
logic [SCRAMBLE_KEY_W-1:0] scramble_key_q, scramble_key_d;
logic [SCRAMBLE_NONCE_W-1:0] scramble_nonce_q, scramble_nonce_d;
logic scramble_key_valid_d, scramble_key_valid_q;
logic scramble_req_d, scramble_req_q;
// DUT
ibex_icache #(
@ -85,43 +101,135 @@ module ic_top import ibex_pkg::*; #(parameter bit ICacheECC = 1'b0) (
.ic_data_addr_o ( ic_data_addr ),
.ic_data_wdata_o ( ic_data_wdata ),
.ic_data_rdata_i ( ic_data_rdata ),
.ic_scr_key_valid_i ( scramble_key_valid_q ),
.icache_enable_i ( icache_enable_i ),
.icache_inval_i ( icache_inval_i ),
.busy_o ( busy_o )
);
///////////////////////////////
// Scrambling Infrastructure //
///////////////////////////////
if (ICacheScramble) begin : gen_scramble
// Scramble key valid starts with OTP returning new valid key and stays high
// until we request a new valid key.
assign scramble_key_valid_d = scramble_req_q ? scramble_key_valid_i :
icache_inval_i ? 1'b0 :
scramble_key_valid_q;
always_ff @(posedge clk_i or negedge rst_ni) begin
if (!rst_ni) begin
scramble_key_q <= 128'hDDDDDDDDEEEEEEEEAAAAAAAADDDDDDDD;
scramble_nonce_q <= 64'hBBBBEEEEEEEEFFFF;
end else if (scramble_key_valid_i) begin
scramble_key_q <= scramble_key_i;
scramble_nonce_q <= scramble_nonce_i;
end
end
always_ff @(posedge clk_i or negedge rst_ni) begin
if (!rst_ni) begin
scramble_key_valid_q <= 1'b1;
scramble_req_q <= '0;
end else begin
scramble_key_valid_q <= scramble_key_valid_d;
scramble_req_q <= scramble_req_d;
end
end
// Scramble key request starts with invalidate signal from ICache and stays high
// until we got a valid key.
assign scramble_req_d = scramble_req_q ? ~scramble_key_valid_i : icache_inval_i;
assign scramble_req_o = scramble_req_q;
end else begin : gen_noscramble
logic unused_scramble_inputs = scramble_key_valid_i & (|scramble_key_i) &
(|scramble_nonce_i) & scramble_req_q & icache_inval_i;
assign scramble_req_d = 1'b0;
assign scramble_req_q = 1'b0;
assign scramble_req_o = 1'b0;
assign scramble_key_d = '0;
assign scramble_key_q = '0;
assign scramble_nonce_d = '0;
assign scramble_nonce_q = '0;
assign scramble_key_valid_q = 1'b1;
assign scramble_key_valid_d = 1'b1;
end
// RAMs
for (genvar way = 0; way < IC_NUM_WAYS; way++) begin : gen_rams
// Tag RAM instantiation
prim_ram_1p #(
.Width (TagSizeECC),
.Depth (IC_NUM_LINES),
.DataBitsPerMask (TagSizeECC)
prim_ram_1p_scr #(
.Width (TagSizeECC),
.Depth (IC_NUM_LINES),
.DataBitsPerMask (TagSizeECC),
.EnableParity (0),
.DiffWidth (TagSizeECC),
.NumAddrScrRounds (NumAddrScrRounds),
.NumDiffRounds (NumDiffRounds)
) tag_bank (
.clk_i (clk_i),
.req_i (ic_tag_req[way]),
.cfg_i ('0),
.write_i (ic_tag_write),
.wmask_i ({TagSizeECC{1'b1}}),
.addr_i (ic_tag_addr),
.wdata_i (ic_tag_wdata),
.rdata_o (ic_tag_rdata[way])
.clk_i,
.rst_ni,
.key_valid_i (scramble_key_valid_q),
.key_i (scramble_key_q),
.nonce_i (scramble_nonce_q),
.req_i (ic_tag_req[way]),
.gnt_o (),
.write_i (ic_tag_write),
.addr_i (ic_tag_addr),
.wdata_i (ic_tag_wdata),
.wmask_i ({TagSizeECC{1'b1}}),
.intg_error_i(1'b0),
.rdata_o (ic_tag_rdata[way]),
.rvalid_o (),
.raddr_o (),
.rerror_o (),
.cfg_i ('0)
);
// Data RAM instantiation
prim_ram_1p #(
.Width (LineSizeECC),
.Depth (IC_NUM_LINES),
.DataBitsPerMask (LineSizeECC)
prim_ram_1p_scr #(
.Width (LineSizeECC),
.Depth (IC_NUM_LINES),
.DataBitsPerMask (LineSizeECC),
.EnableParity (0),
.ReplicateKeyStream (1),
.DiffWidth (LineSizeECC),
.NumAddrScrRounds (NumAddrScrRounds),
.NumDiffRounds (NumDiffRounds)
) data_bank (
.clk_i (clk_i),
.req_i (ic_data_req[way]),
.cfg_i ('0),
.write_i (ic_data_write),
.wmask_i ({LineSizeECC{1'b1}}),
.addr_i (ic_data_addr),
.wdata_i (ic_data_wdata),
.rdata_o (ic_data_rdata[way])
.clk_i,
.rst_ni,
.key_valid_i (scramble_key_valid_q),
.key_i (scramble_key_q),
.nonce_i (scramble_nonce_q),
.req_i (ic_data_req[way]),
.gnt_o (),
.write_i (ic_data_write),
.addr_i (ic_data_addr),
.wdata_i (ic_data_wdata),
.wmask_i ({LineSizeECC{1'b1}}),
.intg_error_i(1'b0),
.rdata_o (ic_data_rdata[way]),
.rvalid_o (),
.raddr_o (),
.rerror_o (),
.cfg_i ('0)
);
end
endmodule

View file

@ -2,7 +2,10 @@
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
//
module tb #(parameter bit ICacheECC = 1'b0);
module tb #(
parameter bit ICacheECC = 1'b0,
parameter bit ICacheScramble = 1'b0
);
// dep packages
import uvm_pkg::*;
import dv_utils_pkg::*;
@ -21,66 +24,93 @@ module tb #(parameter bit ICacheECC = 1'b0);
ibex_icache_core_if core_if (.clk(clk), .rst_n(rst_n));
ibex_icache_mem_if mem_if (.clk(clk), .rst_n(rst_n));
logic scramble_key_valid, scramble_req;
logic [127:0] scramble_key;
logic [63:0] scramble_nonce;
// dut
ic_top #(
.ICacheECC (ICacheECC)
.ICacheECC (ICacheECC),
.ICacheScramble(ICacheScramble)
) dut (
.clk_i (clk),
.rst_ni (rst_n),
// Connect icache <-> core interface
.req_i (core_if.req),
.branch_i (core_if.branch),
.branch_mispredict_i (1'b0),
.mispredict_addr_i (32'b0),
.addr_i (core_if.branch_addr),
.ready_i (core_if.ready),
.valid_o (core_if.valid),
.rdata_o (core_if.rdata),
.addr_o (core_if.addr),
.err_o (core_if.err),
.err_plus2_o (core_if.err_plus2),
.icache_enable_i (core_if.enable),
.icache_inval_i (core_if.invalidate),
.busy_o (core_if.busy),
.req_i (core_if.req),
.branch_i (core_if.branch),
.branch_mispredict_i (1'b0),
.mispredict_addr_i (32'b0),
.addr_i (core_if.branch_addr),
.ready_i (core_if.ready),
.valid_o (core_if.valid),
.rdata_o (core_if.rdata),
.addr_o (core_if.addr),
.err_o (core_if.err),
.err_plus2_o (core_if.err_plus2),
.icache_enable_i (core_if.enable),
.icache_inval_i (core_if.invalidate),
.busy_o (core_if.busy),
.scramble_key_valid_i (scramble_key_valid),
.scramble_key_i (scramble_key),
.scramble_nonce_i (scramble_nonce),
.scramble_req_o (scramble_req),
// Connect icache <-> instruction bus interface
.instr_req_o (mem_if.req),
.instr_gnt_i (mem_if.gnt),
.instr_addr_o (mem_if.addr),
.instr_rdata_i (mem_if.rdata),
.instr_err_i (mem_if.err),
.instr_rvalid_i (mem_if.rvalid)
.instr_req_o (mem_if.req),
.instr_gnt_i (mem_if.gnt),
.instr_addr_o (mem_if.addr),
.instr_rdata_i (mem_if.rdata),
.instr_err_i (mem_if.err),
.instr_rvalid_i (mem_if.rvalid)
);
// If the ICacheECC parameter is set in the DUT, generate another interface for each tag ram and
// each data ram, binding them into the RAMs themselves. ECC tests can use these to insert errors
// into memory lookups.
generate if (dut.ICacheECC) begin : gen_ecc
for (genvar w = 0; w < ibex_pkg::IC_NUM_WAYS; w++) begin : gen_ecc_ifs
bind dut.gen_rams[w].tag_bank.gen_badbit.u_impl_badbit ibex_icache_ecc_if tag_bank_if (.*);
bind dut.gen_rams[w].data_bank.gen_badbit.u_impl_badbit ibex_icache_ecc_if data_bank_if (.*);
bind dut.gen_rams[w].tag_bank.u_prim_ram_1p_adv.u_mem.gen_badbit.u_impl_badbit
ibex_icache_ecc_if tag_bank_if (.*);
bind dut.gen_rams[w].data_bank.u_prim_ram_1p_adv.u_mem.gen_badbit.u_impl_badbit
ibex_icache_ecc_if data_bank_if (.*);
initial begin
uvm_config_db#(virtual ibex_icache_ecc_if)::
set(null,
$sformatf("*.env.ecc_tag_agents[%0d]*", w),
"vif",
dut.gen_rams[w].tag_bank.gen_badbit.u_impl_badbit.tag_bank_if);
dut.gen_rams[w].tag_bank.u_prim_ram_1p_adv.
u_mem.gen_badbit.u_impl_badbit.tag_bank_if);
uvm_config_db#(virtual ibex_icache_ecc_if)::
set(null,
$sformatf("*.env.ecc_data_agents[%0d]*", w),
"vif",
dut.gen_rams[w].data_bank.gen_badbit.u_impl_badbit.data_bank_if);
dut.gen_rams[w].data_bank.u_prim_ram_1p_adv.
u_mem.gen_badbit.u_impl_badbit.data_bank_if);
end
end
end
endgenerate
always @(posedge scramble_req) begin
scramble_key_valid = 1'b0;
#(20 * $urandom_range(1, 10))
scramble_key = {$urandom(),$urandom(),$urandom(),$urandom()};
scramble_nonce = {$urandom(),$urandom()};
scramble_key_valid = 1'b1;
#20
scramble_key_valid = 1'b0;
end
initial begin
// drive clk and rst_n from clk_if
clk_rst_if.set_active();
scramble_key = {$urandom(),$urandom(),$urandom(),$urandom()};
scramble_nonce = {$urandom(),$urandom()};
scramble_key_valid = 1'b0;
// Store virtual interfaces into the UVM config database. ECC interfaces are done separately
// above because otherwise you have to repeat the (verbose) generate loop.

View file

@ -100,6 +100,12 @@ parameters:
paramtype: vlogparam
description: "Number of PMP regions"
ICacheScramble:
datatype: int
default: 0
paramtype: vlogparam
description: "Enables ICache scrambling feature (EXPERIMENTAL) [0/1]"
targets:
default: &default_target
filesets:
@ -119,6 +125,7 @@ targets:
- PMPEnable
- PMPGranularity
- PMPNumRegions
- ICacheScramble
- SRAMInitFile
lint:

View file

@ -72,6 +72,12 @@ parameters:
paramtype: vlogparam
description: "Enables security hardening features (EXPERIMENTAL) [0/1]"
ICacheScramble:
datatype: int
default: 0
paramtype: vlogparam
description: "Enables ICache scrambling feature (EXPERIMENTAL) [0/1]"
BranchPredictor:
datatype: int
paramtype: vlogparam
@ -107,6 +113,7 @@ targets:
- RV32B
- RegFile
- ICache
- ICacheScramble
- ICacheECC
- BranchTargetALU
- WritebackStage

View file

@ -30,7 +30,6 @@ filesets:
targets:
default:
filesets:
- tool_verilator ? (files_verilator)
- tool_veriblelint ? (files_lint_verible)
- files_sim
- files_verilator
- tool_verilator ? (files_verilator)

View file

@ -36,6 +36,7 @@ module ibex_simple_system (
);
parameter bit SecureIbex = 1'b0;
parameter bit ICacheScramble = 1'b0;
parameter bit PMPEnable = 1'b0;
parameter int unsigned PMPGranularity = 0;
parameter int unsigned PMPNumRegions = 4;
@ -163,6 +164,7 @@ module ibex_simple_system (
ibex_top_tracing #(
.SecureIbex ( SecureIbex ),
.ICacheScramble ( ICacheScramble ),
.PMPEnable ( PMPEnable ),
.PMPGranularity ( PMPGranularity ),
.PMPNumRegions ( PMPNumRegions ),
@ -216,6 +218,11 @@ module ibex_simple_system (
.irq_fast_i (15'b0),
.irq_nm_i (1'b0),
.scramble_key_valid_i ('0),
.scramble_key_i ('0),
.scramble_nonce_i ('0),
.scramble_req_o (),
.debug_req_i ('b0),
.crash_dump_o (),

View file

@ -21,6 +21,7 @@ small:
PMPGranularity : 0
PMPNumRegions : 4
SecureIbex : 0
ICacheScramble : 0
# Configuration to match that used in the OpenTitan project
opentitan:
@ -37,6 +38,7 @@ opentitan:
PMPGranularity : 0
PMPNumRegions : 16
SecureIbex : 1
ICacheScramble : 0
# ===============================
# * EXPERIMENTAL CONFIGURATIONS *
@ -59,6 +61,7 @@ experimental-maxperf:
PMPGranularity : 0
PMPNumRegions : 4
SecureIbex : 0
ICacheScramble : 0
# experimental-maxperf config above plus PMP enabled with 16 regions.
experimental-maxperf-pmp:
@ -75,6 +78,7 @@ experimental-maxperf-pmp:
PMPGranularity : 0
PMPNumRegions : 16
SecureIbex : 0
ICacheScramble : 0
# experimental-maxperf-pmp config above with balanced bitmanip extension
experimental-maxperf-pmp-bmbalanced:
@ -91,6 +95,7 @@ experimental-maxperf-pmp-bmbalanced:
PMPGranularity : 0
PMPNumRegions : 16
SecureIbex : 0
ICacheScramble : 0
# experimental-maxperf-pmp config above with full bitmanip extension
experimental-maxperf-pmp-bmfull:
@ -107,6 +112,7 @@ experimental-maxperf-pmp-bmfull:
PMPGranularity : 0
PMPNumRegions : 16
SecureIbex : 0
ICacheScramble : 0
# experimental-maxperf-pmp-bmfull config above with icache enabled
experimental-maxperf-pmp-bmfull-icache:
@ -123,6 +129,7 @@ experimental-maxperf-pmp-bmfull-icache:
PMPGranularity : 0
PMPNumRegions : 16
SecureIbex : 0
ICacheScramble : 0
# experimental-maxperf with branch predictor switched on. This exists to allow
# easy use of Ibex with the branch predictor in particular for CI runs. The
@ -142,4 +149,5 @@ experimental-branch-predictor:
PMPGranularity : 0
PMPNumRegions : 4
SecureIbex : 0
ICacheScramble : 0

View file

@ -8,7 +8,6 @@ filesets:
files_rtl:
depend:
- lowrisc:prim:secded
- lowrisc:prim:ram_1p
- lowrisc:prim:assert
- lowrisc:ibex:ibex_pkg
files:

View file

@ -13,6 +13,7 @@ filesets:
- lowrisc:prim:buf
- lowrisc:prim:clock_mux2
- lowrisc:prim:flop
- lowrisc:prim:ram_1p_scr
files:
- rtl/ibex_register_file_ff.sv # generic FF-based
- rtl/ibex_register_file_fpga.sv # FPGA
@ -107,6 +108,12 @@ parameters:
paramtype: vlogparam
description: "Enables security hardening features (EXPERIMENTAL) [0/1]"
ICacheScramble:
datatype: int
default: 0
paramtype: vlogparam
description: "Enables ICache scrambling feature (EXPERIMENTAL) [0/1]"
PMPEnable:
datatype: int
default: 0

View file

@ -83,6 +83,12 @@ parameters:
paramtype: vlogparam
description: "Enables security hardening features (EXPERIMENTAL) [0/1]"
ICacheScramble:
datatype: int
default: 0
paramtype: vlogparam
description: "Enables ICache scrambling feature (EXPERIMENTAL) [0/1]"
PMPEnable:
datatype: int
default: 0
@ -124,6 +130,7 @@ targets:
- WritebackStage
- BranchPredictor
- SecureIbex
- ICacheScramble
- PMPEnable
- PMPGranularity
- PMPNumRegions

View file

@ -88,6 +88,7 @@ module ibex_core import ibex_pkg::*; #(
output logic [IC_INDEX_W-1:0] ic_data_addr_o,
output logic [LineSizeECC-1:0] ic_data_wdata_o,
input logic [LineSizeECC-1:0] ic_data_rdata_i [IC_NUM_WAYS],
input logic ic_scr_key_valid_i,
// Interrupt inputs
input logic irq_software_i,
@ -138,6 +139,7 @@ module ibex_core import ibex_pkg::*; #(
input logic fetch_enable_i,
output logic alert_minor_o,
output logic alert_major_o,
output logic icache_inval_o,
output logic core_busy_o
);
@ -383,16 +385,17 @@ module ibex_core import ibex_pkg::*; #(
.instr_rdata_i (instr_rdata_i),
.instr_err_i (instr_err_i),
.ic_tag_req_o (ic_tag_req_o),
.ic_tag_write_o (ic_tag_write_o),
.ic_tag_addr_o (ic_tag_addr_o),
.ic_tag_wdata_o (ic_tag_wdata_o),
.ic_tag_rdata_i (ic_tag_rdata_i),
.ic_data_req_o (ic_data_req_o),
.ic_data_write_o(ic_data_write_o),
.ic_data_addr_o (ic_data_addr_o),
.ic_data_wdata_o(ic_data_wdata_o),
.ic_data_rdata_i(ic_data_rdata_i),
.ic_tag_req_o (ic_tag_req_o),
.ic_tag_write_o (ic_tag_write_o),
.ic_tag_addr_o (ic_tag_addr_o),
.ic_tag_wdata_o (ic_tag_wdata_o),
.ic_tag_rdata_i (ic_tag_rdata_i),
.ic_data_req_o (ic_data_req_o),
.ic_data_write_o (ic_data_write_o),
.ic_data_addr_o (ic_data_addr_o),
.ic_data_wdata_o (ic_data_wdata_o),
.ic_data_rdata_i (ic_data_rdata_i),
.ic_scr_key_valid_i(ic_scr_key_valid_i),
// outputs to ID stage
.instr_valid_id_o (instr_valid_id),
@ -608,6 +611,7 @@ module ibex_core import ibex_pkg::*; #(
.instr_id_done_o (instr_id_done)
);
assign icache_inval_o = icache_inval;
// for RVFI only
assign unused_illegal_insn_id = illegal_insn_id;

View file

@ -59,6 +59,7 @@ module ibex_icache import ibex_pkg::*; #(
output logic [IC_INDEX_W-1:0] ic_data_addr_o,
output logic [LineSizeECC-1:0] ic_data_wdata_o,
input logic [LineSizeECC-1:0] ic_data_rdata_i [IC_NUM_WAYS],
input logic ic_scr_key_valid_i,
// Cache status
input logic icache_enable_i,
@ -184,6 +185,7 @@ module ibex_icache import ibex_pkg::*; #(
logic output_err;
// Invalidations
logic start_inval, inval_done;
logic inval_lock, inval_req_d, inval_req_q;
logic reset_inval_q;
logic inval_prog_d, inval_prog_q;
logic [IC_INDEX_W-1:0] inval_index_d, inval_index_q;
@ -252,7 +254,8 @@ module ibex_icache import ibex_pkg::*; #(
assign fill_grant_ic0 = fill_req_ic0 & ~lookup_req_ic0 & ~inval_prog_q &
~ecc_write_req;
// Qualified lookup grant to mask ram signals in IC1 if access was not made
assign lookup_actual_ic0 = lookup_grant_ic0 & icache_enable_i & ~inval_prog_q & ~start_inval;
assign lookup_actual_ic0 = lookup_grant_ic0 & icache_enable_i & ~inval_prog_q &
~icache_inval_i & ~inval_lock & ~start_inval;
// Tagram
assign tag_req_ic0 = lookup_req_ic0 | fill_req_ic0 | inval_prog_q | ecc_write_req;
@ -530,7 +533,7 @@ module ibex_icache import ibex_pkg::*; #(
end
assign fill_cache_new = (branch_i | (|cache_cnt_q)) & icache_enable_i &
~icache_inval_i & ~inval_prog_q;
~icache_inval_i & ~inval_lock & ~inval_prog_q;
end else begin : gen_cache_all
@ -598,7 +601,7 @@ module ibex_icache import ibex_pkg::*; #(
// Any invalidation or disabling of the cache while the buffer is busy will stop allocation
assign fill_cache_d[fb] = (fill_alloc[fb] & fill_cache_new) |
(fill_cache_q[fb] & fill_busy_q[fb] &
icache_enable_i & ~icache_inval_i);
icache_enable_i & ~icache_inval_i & ~inval_lock);
// Record whether the request hit in the cache
assign fill_hit_ic1[fb] = lookup_valid_ic1 & fill_in_ic1[fb] & tag_hit_ic1 & ~ecc_err_ic1;
assign fill_hit_d[fb] = fill_hit_ic1[fb] | (fill_hit_q[fb] & fill_busy_q[fb]);
@ -784,19 +787,11 @@ module ibex_icache import ibex_pkg::*; #(
end
end
if (ResetAll) begin : g_fill_way_ra
always_ff @(posedge clk_i or negedge rst_ni) begin
if (!rst_ni) begin
fill_way_q[fb] <= '0;
end else if (fill_way_en[fb]) begin
fill_way_q[fb] <= sel_way_ic1;
end
end
end else begin : g_fill_way_nr
always_ff @(posedge clk_i) begin
if (fill_way_en[fb]) begin
fill_way_q[fb] <= sel_way_ic1;
end
always_ff @(posedge clk_i or negedge rst_ni) begin
if (!rst_ni) begin
fill_way_q[fb] <= '0;
end else if (fill_way_en[fb]) begin
fill_way_q[fb] <= sel_way_ic1;
end
end
@ -1065,13 +1060,31 @@ module ibex_icache import ibex_pkg::*; #(
// Invalidations //
///////////////////
// We need to save the invalidation request inside a register. That way we can wait
// until we have a valid scrambling key to do it. Since the key itself is needed for
// starting to fill in the RAMs and read from them, ICache also needs to stop operating.
assign inval_req_d = (inval_req_q | icache_inval_i) & ~(inval_done & inval_prog_q);
always_ff @(posedge clk_i or negedge rst_ni) begin
if (!rst_ni) begin
inval_req_q <= 1'b0;
end else begin
inval_req_q <= inval_req_d;
end
end
// This will act like a lock mechanism.
// Main idea is to lock the invalidation request until we got a valid scrambling key.
assign inval_lock = inval_req_d & ~ic_scr_key_valid_i;
// Invalidate on reset, or when instructed. If an invalidation request is received while a
// previous invalidation is ongoing, it does not need to be restarted.
assign start_inval = (~reset_inval_q | icache_inval_i) & ~inval_prog_q;
assign inval_prog_d = start_inval | (inval_prog_q & ~inval_done);
// previous invalidation is ongoing, it does not need to be restarted. Do not start
// this process until inval lock is removed meaning the scrambling key is valid.
assign start_inval = ~inval_lock & (~reset_inval_q | inval_req_q) & ~inval_prog_q ;
assign inval_prog_d = ~inval_lock & (start_inval | (inval_prog_q & ~inval_done));
assign inval_done = &inval_index_q;
assign inval_index_d = start_inval ? '0 :
(inval_index_q + {{IC_INDEX_W-1{1'b0}},1'b1});
assign inval_index_d = start_inval ? '0 : (inval_index_q + {{IC_INDEX_W-1{1'b0}},1'b1});
always_ff @(posedge clk_i or negedge rst_ni) begin
if (!rst_ni) begin
@ -1105,7 +1118,7 @@ module ibex_icache import ibex_pkg::*; #(
// Only busy (for WFI purposes) while an invalidation is in-progress, or external requests are
// outstanding.
assign busy_o = inval_prog_q | (|(fill_busy_q & ~fill_rvd_done));
assign busy_o = inval_req_q | (|(fill_busy_q & ~fill_rvd_done));
////////////////
// Assertions //

View file

@ -52,6 +52,7 @@ module ibex_if_stage import ibex_pkg::*; #(
output logic [IC_INDEX_W-1:0] ic_data_addr_o,
output logic [LineSizeECC-1:0] ic_data_wdata_o,
input logic [LineSizeECC-1:0] ic_data_rdata_i [IC_NUM_WAYS],
input logic ic_scr_key_valid_i,
// output of ID stage
output logic instr_valid_id_o, // instr in IF-ID is valid
@ -246,6 +247,7 @@ module ibex_if_stage import ibex_pkg::*; #(
.ic_data_addr_o ( ic_data_addr_o ),
.ic_data_wdata_o ( ic_data_wdata_o ),
.ic_data_rdata_i ( ic_data_rdata_i ),
.ic_scr_key_valid_i ( ic_scr_key_valid_i ),
.icache_enable_i ( icache_enable_i ),
.icache_inval_i ( icache_inval_i ),
@ -283,13 +285,14 @@ module ibex_if_stage import ibex_pkg::*; #(
.busy_o ( prefetch_busy )
);
// ICache tieoffs
logic unused_icen, unused_icinv;
logic unused_icen, unused_icinv, unused_scr_key_valid;
logic [TagSizeECC-1:0] unused_tag_ram_input [IC_NUM_WAYS];
logic [LineSizeECC-1:0] unused_data_ram_input [IC_NUM_WAYS];
assign unused_icen = icache_enable_i;
assign unused_icinv = icache_inval_i;
assign unused_tag_ram_input = ic_tag_rdata_i;
assign unused_data_ram_input = ic_data_rdata_i;
assign unused_scr_key_valid = ic_scr_key_valid_i;
assign ic_tag_req_o = 'b0;
assign ic_tag_write_o = 'b0;
assign ic_tag_addr_o = 'b0;

View file

@ -81,6 +81,7 @@ module ibex_lockstep import ibex_pkg::*; #(
input logic [IC_INDEX_W-1:0] ic_data_addr_i,
input logic [LineSizeECC-1:0] ic_data_wdata_i,
input logic [LineSizeECC-1:0] ic_data_rdata_i [IC_NUM_WAYS],
input logic ic_scr_key_valid_i,
input logic irq_software_i,
input logic irq_timer_i,
@ -95,6 +96,7 @@ module ibex_lockstep import ibex_pkg::*; #(
input logic fetch_enable_i,
output logic alert_minor_o,
output logic alert_major_o,
input logic icache_inval_i,
input logic core_busy_i,
input logic test_en_i,
input logic scan_rst_ni
@ -178,6 +180,7 @@ module ibex_lockstep import ibex_pkg::*; #(
logic irq_nm;
logic debug_req;
logic fetch_enable;
logic ic_scr_key_valid;
} delayed_inputs_t;
delayed_inputs_t [LockstepOffset-1:0] shadow_inputs_q;
@ -188,23 +191,24 @@ module ibex_lockstep import ibex_pkg::*; #(
logic [LineSizeECC-1:0] shadow_data_rdata_q [IC_NUM_WAYS][LockstepOffset];
// Assign the inputs to the delay structure
assign shadow_inputs_in.instr_gnt = instr_gnt_i;
assign shadow_inputs_in.instr_rvalid = instr_rvalid_i;
assign shadow_inputs_in.instr_rdata = instr_rdata_i;
assign shadow_inputs_in.instr_err = instr_err_i;
assign shadow_inputs_in.data_gnt = data_gnt_i;
assign shadow_inputs_in.data_rvalid = data_rvalid_i;
assign shadow_inputs_in.data_rdata = data_rdata_i;
assign shadow_inputs_in.data_err = data_err_i;
assign shadow_inputs_in.rf_rdata_a_ecc = rf_rdata_a_ecc_i;
assign shadow_inputs_in.rf_rdata_b_ecc = rf_rdata_b_ecc_i;
assign shadow_inputs_in.irq_software = irq_software_i;
assign shadow_inputs_in.irq_timer = irq_timer_i;
assign shadow_inputs_in.irq_external = irq_external_i;
assign shadow_inputs_in.irq_fast = irq_fast_i;
assign shadow_inputs_in.irq_nm = irq_nm_i;
assign shadow_inputs_in.debug_req = debug_req_i;
assign shadow_inputs_in.fetch_enable = fetch_enable_i;
assign shadow_inputs_in.instr_gnt = instr_gnt_i;
assign shadow_inputs_in.instr_rvalid = instr_rvalid_i;
assign shadow_inputs_in.instr_rdata = instr_rdata_i;
assign shadow_inputs_in.instr_err = instr_err_i;
assign shadow_inputs_in.data_gnt = data_gnt_i;
assign shadow_inputs_in.data_rvalid = data_rvalid_i;
assign shadow_inputs_in.data_rdata = data_rdata_i;
assign shadow_inputs_in.data_err = data_err_i;
assign shadow_inputs_in.rf_rdata_a_ecc = rf_rdata_a_ecc_i;
assign shadow_inputs_in.rf_rdata_b_ecc = rf_rdata_b_ecc_i;
assign shadow_inputs_in.irq_software = irq_software_i;
assign shadow_inputs_in.irq_timer = irq_timer_i;
assign shadow_inputs_in.irq_external = irq_external_i;
assign shadow_inputs_in.irq_fast = irq_fast_i;
assign shadow_inputs_in.irq_nm = irq_nm_i;
assign shadow_inputs_in.debug_req = debug_req_i;
assign shadow_inputs_in.fetch_enable = fetch_enable_i;
assign shadow_inputs_in.ic_scr_key_valid = ic_scr_key_valid_i;
// Delay the inputs
always_ff @(posedge clk_i or negedge rst_ni) begin
@ -290,6 +294,7 @@ module ibex_lockstep import ibex_pkg::*; #(
logic [LineSizeECC-1:0] ic_data_wdata;
logic irq_pending;
crash_dump_t crash_dump;
logic icache_inval;
logic core_busy;
} delayed_outputs_t;
@ -321,6 +326,7 @@ module ibex_lockstep import ibex_pkg::*; #(
assign core_outputs_in.ic_data_wdata = ic_data_wdata_i;
assign core_outputs_in.irq_pending = irq_pending_i;
assign core_outputs_in.crash_dump = crash_dump_i;
assign core_outputs_in.icache_inval = icache_inval_i;
assign core_outputs_in.core_busy = core_busy_i;
// Delay the outputs
@ -366,58 +372,59 @@ module ibex_lockstep import ibex_pkg::*; #(
.DmHaltAddr ( DmHaltAddr ),
.DmExceptionAddr ( DmExceptionAddr )
) u_shadow_core (
.clk_i (clk_i),
.rst_ni (rst_shadow_n),
.clk_i (clk_i),
.rst_ni (rst_shadow_n),
.hart_id_i (hart_id_i),
.boot_addr_i (boot_addr_i),
.hart_id_i (hart_id_i),
.boot_addr_i (boot_addr_i),
.instr_req_o (shadow_outputs_d.instr_req),
.instr_gnt_i (shadow_inputs_q[0].instr_gnt),
.instr_rvalid_i (shadow_inputs_q[0].instr_rvalid),
.instr_addr_o (shadow_outputs_d.instr_addr),
.instr_rdata_i (shadow_inputs_q[0].instr_rdata),
.instr_err_i (shadow_inputs_q[0].instr_err),
.instr_req_o (shadow_outputs_d.instr_req),
.instr_gnt_i (shadow_inputs_q[0].instr_gnt),
.instr_rvalid_i (shadow_inputs_q[0].instr_rvalid),
.instr_addr_o (shadow_outputs_d.instr_addr),
.instr_rdata_i (shadow_inputs_q[0].instr_rdata),
.instr_err_i (shadow_inputs_q[0].instr_err),
.data_req_o (shadow_outputs_d.data_req),
.data_gnt_i (shadow_inputs_q[0].data_gnt),
.data_rvalid_i (shadow_inputs_q[0].data_rvalid),
.data_we_o (shadow_outputs_d.data_we),
.data_be_o (shadow_outputs_d.data_be),
.data_addr_o (shadow_outputs_d.data_addr),
.data_wdata_o (shadow_outputs_d.data_wdata),
.data_rdata_i (shadow_inputs_q[0].data_rdata),
.data_err_i (shadow_inputs_q[0].data_err),
.data_req_o (shadow_outputs_d.data_req),
.data_gnt_i (shadow_inputs_q[0].data_gnt),
.data_rvalid_i (shadow_inputs_q[0].data_rvalid),
.data_we_o (shadow_outputs_d.data_we),
.data_be_o (shadow_outputs_d.data_be),
.data_addr_o (shadow_outputs_d.data_addr),
.data_wdata_o (shadow_outputs_d.data_wdata),
.data_rdata_i (shadow_inputs_q[0].data_rdata),
.data_err_i (shadow_inputs_q[0].data_err),
.dummy_instr_id_o (shadow_outputs_d.dummy_instr_id),
.rf_raddr_a_o (shadow_outputs_d.rf_raddr_a),
.rf_raddr_b_o (shadow_outputs_d.rf_raddr_b),
.rf_waddr_wb_o (shadow_outputs_d.rf_waddr_wb),
.rf_we_wb_o (shadow_outputs_d.rf_we_wb),
.rf_wdata_wb_ecc_o (shadow_outputs_d.rf_wdata_wb_ecc),
.rf_rdata_a_ecc_i (shadow_inputs_q[0].rf_rdata_a_ecc),
.rf_rdata_b_ecc_i (shadow_inputs_q[0].rf_rdata_b_ecc),
.dummy_instr_id_o (shadow_outputs_d.dummy_instr_id),
.rf_raddr_a_o (shadow_outputs_d.rf_raddr_a),
.rf_raddr_b_o (shadow_outputs_d.rf_raddr_b),
.rf_waddr_wb_o (shadow_outputs_d.rf_waddr_wb),
.rf_we_wb_o (shadow_outputs_d.rf_we_wb),
.rf_wdata_wb_ecc_o (shadow_outputs_d.rf_wdata_wb_ecc),
.rf_rdata_a_ecc_i (shadow_inputs_q[0].rf_rdata_a_ecc),
.rf_rdata_b_ecc_i (shadow_inputs_q[0].rf_rdata_b_ecc),
.ic_tag_req_o (shadow_outputs_d.ic_tag_req),
.ic_tag_write_o (shadow_outputs_d.ic_tag_write),
.ic_tag_addr_o (shadow_outputs_d.ic_tag_addr),
.ic_tag_wdata_o (shadow_outputs_d.ic_tag_wdata),
.ic_tag_rdata_i (shadow_tag_rdata_q[0]),
.ic_data_req_o (shadow_outputs_d.ic_data_req),
.ic_data_write_o (shadow_outputs_d.ic_data_write),
.ic_data_addr_o (shadow_outputs_d.ic_data_addr),
.ic_data_wdata_o (shadow_outputs_d.ic_data_wdata),
.ic_data_rdata_i (shadow_data_rdata_q[0]),
.ic_tag_req_o (shadow_outputs_d.ic_tag_req),
.ic_tag_write_o (shadow_outputs_d.ic_tag_write),
.ic_tag_addr_o (shadow_outputs_d.ic_tag_addr),
.ic_tag_wdata_o (shadow_outputs_d.ic_tag_wdata),
.ic_tag_rdata_i (shadow_tag_rdata_q[0]),
.ic_data_req_o (shadow_outputs_d.ic_data_req),
.ic_data_write_o (shadow_outputs_d.ic_data_write),
.ic_data_addr_o (shadow_outputs_d.ic_data_addr),
.ic_data_wdata_o (shadow_outputs_d.ic_data_wdata),
.ic_data_rdata_i (shadow_data_rdata_q[0]),
.ic_scr_key_valid_i (shadow_inputs_q[0].ic_scr_key_valid),
.irq_software_i (shadow_inputs_q[0].irq_software),
.irq_timer_i (shadow_inputs_q[0].irq_timer),
.irq_external_i (shadow_inputs_q[0].irq_external),
.irq_fast_i (shadow_inputs_q[0].irq_fast),
.irq_nm_i (shadow_inputs_q[0].irq_nm),
.irq_pending_o (shadow_outputs_d.irq_pending),
.irq_software_i (shadow_inputs_q[0].irq_software),
.irq_timer_i (shadow_inputs_q[0].irq_timer),
.irq_external_i (shadow_inputs_q[0].irq_external),
.irq_fast_i (shadow_inputs_q[0].irq_fast),
.irq_nm_i (shadow_inputs_q[0].irq_nm),
.irq_pending_o (shadow_outputs_d.irq_pending),
.debug_req_i (shadow_inputs_q[0].debug_req),
.crash_dump_o (shadow_outputs_d.crash_dump),
.debug_req_i (shadow_inputs_q[0].debug_req),
.crash_dump_o (shadow_outputs_d.crash_dump),
`ifdef RVFI
.rvfi_valid (),
@ -452,6 +459,7 @@ module ibex_lockstep import ibex_pkg::*; #(
.fetch_enable_i (shadow_inputs_q[0].fetch_enable),
.alert_minor_o (shadow_alert_minor),
.alert_major_o (shadow_alert_major),
.icache_inval_o (shadow_outputs_d.icache_inval),
.core_busy_o (shadow_outputs_d.core_busy)
);

View file

@ -330,22 +330,25 @@ package ibex_pkg;
} dbg_cause_e;
// ICache constants
parameter int unsigned ADDR_W = 32;
parameter int unsigned BUS_SIZE = 32;
parameter int unsigned BUS_BYTES = BUS_SIZE/8;
parameter int unsigned BUS_W = $clog2(BUS_BYTES);
parameter int unsigned IC_SIZE_BYTES = 4096;
parameter int unsigned IC_NUM_WAYS = 2;
parameter int unsigned IC_LINE_SIZE = 64;
parameter int unsigned IC_LINE_BYTES = IC_LINE_SIZE/8;
parameter int unsigned IC_LINE_W = $clog2(IC_LINE_BYTES);
parameter int unsigned IC_NUM_LINES = IC_SIZE_BYTES / IC_NUM_WAYS / IC_LINE_BYTES;
parameter int unsigned IC_LINE_BEATS = IC_LINE_BYTES / BUS_BYTES;
parameter int unsigned IC_LINE_BEATS_W = $clog2(IC_LINE_BEATS);
parameter int unsigned IC_INDEX_W = $clog2(IC_NUM_LINES);
parameter int unsigned IC_INDEX_HI = IC_INDEX_W + IC_LINE_W - 1;
parameter int unsigned IC_TAG_SIZE = ADDR_W - IC_INDEX_W - IC_LINE_W + 1; // 1 valid bit
parameter int unsigned IC_OUTPUT_BEATS = (BUS_BYTES / 2); // number of halfwords
parameter int unsigned ADDR_W = 32;
parameter int unsigned BUS_SIZE = 32;
parameter int unsigned BUS_BYTES = BUS_SIZE/8;
parameter int unsigned BUS_W = $clog2(BUS_BYTES);
parameter int unsigned IC_SIZE_BYTES = 4096;
parameter int unsigned IC_NUM_WAYS = 2;
parameter int unsigned IC_LINE_SIZE = 64;
parameter int unsigned IC_LINE_BYTES = IC_LINE_SIZE/8;
parameter int unsigned IC_LINE_W = $clog2(IC_LINE_BYTES);
parameter int unsigned IC_NUM_LINES = IC_SIZE_BYTES / IC_NUM_WAYS / IC_LINE_BYTES;
parameter int unsigned IC_LINE_BEATS = IC_LINE_BYTES / BUS_BYTES;
parameter int unsigned IC_LINE_BEATS_W = $clog2(IC_LINE_BEATS);
parameter int unsigned IC_INDEX_W = $clog2(IC_NUM_LINES);
parameter int unsigned IC_INDEX_HI = IC_INDEX_W + IC_LINE_W - 1;
parameter int unsigned IC_TAG_SIZE = ADDR_W - IC_INDEX_W - IC_LINE_W + 1; // 1 valid bit
parameter int unsigned IC_OUTPUT_BEATS = (BUS_BYTES / 2); // number of halfwords
// ICache Scrambling Parameters
parameter int unsigned SCRAMBLE_KEY_W = 128;
parameter int unsigned SCRAMBLE_NONCE_W = 64;
// PMP constants
parameter int unsigned PMP_MAX_REGIONS = 16;
@ -599,5 +602,8 @@ package ibex_pkg;
parameter lfsr_perm_t RndCnstLfsrPermDefault = {
160'h1e35ecba467fd1b12e958152c04fa43878a8daed
};
parameter logic [SCRAMBLE_KEY_W-1:0] RndCnstIbexKeyDefault =
128'h14e8cecae3040d5e12286bb3cc113298;
parameter logic [SCRAMBLE_NONCE_W-1:0] RndCnstIbexNonceDefault =
64'hf79780bc735f3843;
endpackage

View file

@ -30,10 +30,14 @@ module ibex_top import ibex_pkg::*; #(
parameter bit DbgTriggerEn = 1'b0,
parameter int unsigned DbgHwBreakNum = 1,
parameter bit SecureIbex = 1'b0,
parameter bit ICacheScramble = 1'b0,
parameter lfsr_seed_t RndCnstLfsrSeed = RndCnstLfsrSeedDefault,
parameter lfsr_perm_t RndCnstLfsrPerm = RndCnstLfsrPermDefault,
parameter int unsigned DmHaltAddr = 32'h1A110800,
parameter int unsigned DmExceptionAddr = 32'h1A110808
parameter int unsigned DmExceptionAddr = 32'h1A110808,
// Default seed and nonce for scrambling
parameter logic [SCRAMBLE_KEY_W-1:0] RndCnstIbexKey = RndCnstIbexKeyDefault,
parameter logic [SCRAMBLE_NONCE_W-1:0] RndCnstIbexNonce = RndCnstIbexNonceDefault
) (
// Clock and Reset
input logic clk_i,
@ -74,6 +78,12 @@ module ibex_top import ibex_pkg::*; #(
input logic [14:0] irq_fast_i,
input logic irq_nm_i, // non-maskeable interrupt
// Scrambling Interface
input logic scramble_key_valid_i,
input logic [SCRAMBLE_KEY_W-1:0] scramble_key_i,
input logic [SCRAMBLE_NONCE_W-1:0] scramble_nonce_i,
output logic scramble_req_o,
// Debug Interface
input logic debug_req_i,
output crash_dump_t crash_dump_o,
@ -130,6 +140,9 @@ module ibex_top import ibex_pkg::*; #(
localparam int unsigned BusSizeECC = ICacheECC ? (BUS_SIZE + 7) : BUS_SIZE;
localparam int unsigned LineSizeECC = BusSizeECC * IC_LINE_BEATS;
localparam int unsigned TagSizeECC = ICacheECC ? (IC_TAG_SIZE + 6) : IC_TAG_SIZE;
// Scrambling Parameter
localparam int unsigned NumAddrScrRounds = ICacheScramble ? 2 : 0;
localparam int unsigned NumDiffRounds = NumAddrScrRounds;
// Clock signals
logic clk;
@ -159,6 +172,12 @@ module ibex_top import ibex_pkg::*; #(
// Alert signals
logic core_alert_major, core_alert_minor;
logic lockstep_alert_major, lockstep_alert_minor;
// Scramble signals
logic icache_inval;
logic [SCRAMBLE_KEY_W-1:0] scramble_key_q;
logic [SCRAMBLE_NONCE_W-1:0] scramble_nonce_q;
logic scramble_key_valid_d, scramble_key_valid_q;
logic scramble_req_d, scramble_req_q;
/////////////////////
// Main clock gate //
@ -247,16 +266,17 @@ module ibex_top import ibex_pkg::*; #(
.rf_rdata_a_ecc_i (rf_rdata_a_ecc),
.rf_rdata_b_ecc_i (rf_rdata_b_ecc),
.ic_tag_req_o (ic_tag_req),
.ic_tag_write_o (ic_tag_write),
.ic_tag_addr_o (ic_tag_addr),
.ic_tag_wdata_o (ic_tag_wdata),
.ic_tag_rdata_i (ic_tag_rdata),
.ic_data_req_o (ic_data_req),
.ic_data_write_o(ic_data_write),
.ic_data_addr_o (ic_data_addr),
.ic_data_wdata_o(ic_data_wdata),
.ic_data_rdata_i(ic_data_rdata),
.ic_tag_req_o (ic_tag_req),
.ic_tag_write_o (ic_tag_write),
.ic_tag_addr_o (ic_tag_addr),
.ic_tag_wdata_o (ic_tag_wdata),
.ic_tag_rdata_i (ic_tag_rdata),
.ic_data_req_o (ic_data_req),
.ic_data_write_o (ic_data_write),
.ic_data_addr_o (ic_data_addr),
.ic_data_wdata_o (ic_data_wdata),
.ic_data_rdata_i (ic_data_rdata),
.ic_scr_key_valid_i(scramble_key_valid_q),
.irq_software_i,
.irq_timer_i,
@ -299,9 +319,10 @@ module ibex_top import ibex_pkg::*; #(
`endif
.fetch_enable_i,
.alert_minor_o(core_alert_minor),
.alert_major_o(core_alert_major),
.core_busy_o (core_busy_d)
.alert_minor_o (core_alert_minor),
.alert_major_o (core_alert_major),
.icache_inval_o(icache_inval),
.core_busy_o (core_busy_d)
);
/////////////////////////////////
@ -373,6 +394,58 @@ module ibex_top import ibex_pkg::*; #(
);
end
///////////////////////////////
// Scrambling Infrastructure //
///////////////////////////////
if (ICacheScramble) begin : gen_scramble
// Scramble key valid starts with OTP returning new valid key and stays high
// until we request a new valid key.
assign scramble_key_valid_d = scramble_req_q ? scramble_key_valid_i :
icache_inval ? 1'b0 :
scramble_key_valid_q;
always_ff @(posedge clk_i or negedge rst_ni) begin
if (!rst_ni) begin
scramble_key_q <= RndCnstIbexKey;
scramble_nonce_q <= RndCnstIbexNonce;
end else if (scramble_key_valid_i) begin
scramble_key_q <= scramble_key_i;
scramble_nonce_q <= scramble_nonce_i;
end
end
always_ff @(posedge clk_i or negedge rst_ni) begin
if (!rst_ni) begin
scramble_key_valid_q <= 1'b1;
scramble_req_q <= '0;
end else begin
scramble_key_valid_q <= scramble_key_valid_d;
scramble_req_q <= scramble_req_d;
end
end
// Scramble key request starts with invalidate signal from ICache and stays high
// until we got a valid key.
assign scramble_req_d = scramble_req_q ? ~scramble_key_valid_i : icache_inval;
assign scramble_req_o = scramble_req_q;
end else begin : gen_noscramble
logic unused_scramble_inputs = scramble_key_valid_i & (|scramble_key_i) & (|RndCnstIbexKey) &
(|scramble_nonce_i) & (|RndCnstIbexNonce) & scramble_req_q &
icache_inval & scramble_key_valid_d & scramble_req_d;
assign scramble_req_d = 1'b0;
assign scramble_req_q = 1'b0;
assign scramble_req_o = 1'b0;
assign scramble_key_q = '0;
assign scramble_nonce_q = '0;
assign scramble_key_valid_q = 1'b1;
assign scramble_key_valid_d = 1'b1;
end
////////////////////////
// Rams Instantiation //
////////////////////////
@ -380,35 +453,72 @@ module ibex_top import ibex_pkg::*; #(
if (ICache) begin : gen_rams
for (genvar way = 0; way < IC_NUM_WAYS; way++) begin : gen_rams_inner
// Tag RAM instantiation
prim_ram_1p #(
.Width (TagSizeECC),
.Depth (IC_NUM_LINES),
.DataBitsPerMask(TagSizeECC)
prim_ram_1p_scr #(
.Width (TagSizeECC),
.Depth (IC_NUM_LINES),
.DataBitsPerMask (TagSizeECC),
.EnableParity (0),
.DiffWidth (TagSizeECC),
.NumAddrScrRounds (NumAddrScrRounds),
.NumDiffRounds (NumDiffRounds)
) tag_bank (
.clk_i (clk_i),
.req_i (ic_tag_req[way]),
.cfg_i (ram_cfg_i),
.write_i(ic_tag_write),
.wmask_i({TagSizeECC{1'b1}}),
.addr_i (ic_tag_addr),
.wdata_i(ic_tag_wdata),
.rdata_o(ic_tag_rdata[way])
.clk_i,
.rst_ni,
.key_valid_i (scramble_key_valid_q),
.key_i (scramble_key_q),
.nonce_i (scramble_nonce_q),
.req_i (ic_tag_req[way]),
.gnt_o (),
.write_i (ic_tag_write),
.addr_i (ic_tag_addr),
.wdata_i (ic_tag_wdata),
.wmask_i ({TagSizeECC{1'b1}}),
.intg_error_i(1'b0),
.rdata_o (ic_tag_rdata[way]),
.rvalid_o (),
.raddr_o (),
.rerror_o (),
.cfg_i (ram_cfg_i)
);
// Data RAM instantiation
prim_ram_1p #(
.Width (LineSizeECC),
.Depth (IC_NUM_LINES),
.DataBitsPerMask(LineSizeECC)
prim_ram_1p_scr #(
.Width (LineSizeECC),
.Depth (IC_NUM_LINES),
.DataBitsPerMask (LineSizeECC),
.ReplicateKeyStream (1),
.EnableParity (0),
.DiffWidth (LineSizeECC),
.NumAddrScrRounds (NumAddrScrRounds),
.NumDiffRounds (NumDiffRounds)
) data_bank (
.clk_i (clk_i),
.req_i (ic_data_req[way]),
.cfg_i (ram_cfg_i),
.write_i(ic_data_write),
.wmask_i({LineSizeECC{1'b1}}),
.addr_i (ic_data_addr),
.wdata_i(ic_data_wdata),
.rdata_o(ic_data_rdata[way])
.clk_i,
.rst_ni,
.key_valid_i (scramble_key_valid_q),
.key_i (scramble_key_q),
.nonce_i (scramble_nonce_q),
.req_i (ic_data_req[way]),
.gnt_o (),
.write_i (ic_data_write),
.addr_i (ic_data_addr),
.wdata_i (ic_data_wdata),
.wmask_i ({LineSizeECC{1'b1}}),
.intg_error_i(1'b0),
.rdata_o (ic_data_rdata[way]),
.rvalid_o (),
.raddr_o (),
.rerror_o (),
.cfg_i (ram_cfg_i)
);
end
@ -419,7 +529,11 @@ module ibex_top import ibex_pkg::*; #(
assign unused_ram_cfg = ram_cfg_i;
assign unused_ram_inputs = (|ic_tag_req) & ic_tag_write & (|ic_tag_addr) & (|ic_tag_wdata) &
(|ic_data_req) & ic_data_write & (|ic_data_addr) & (|ic_data_wdata);
(|ic_data_req) & ic_data_write & (|ic_data_addr) & (|ic_data_wdata) &
(|scramble_key_q) & (|scramble_nonce_q) & scramble_key_valid_q &
scramble_key_valid_d & (|scramble_nonce_q) &
(|NumAddrScrRounds);
assign ic_tag_rdata = '{default:'b0};
assign ic_data_rdata = '{default:'b0};
@ -469,6 +583,7 @@ module ibex_top import ibex_pkg::*; #(
ic_data_write,
ic_data_addr,
ic_data_wdata,
scramble_key_valid_i,
irq_software_i,
irq_timer_i,
irq_external_i,
@ -478,6 +593,7 @@ module ibex_top import ibex_pkg::*; #(
debug_req_i,
crash_dump_o,
fetch_enable_i,
icache_inval,
core_busy_d
});
@ -523,6 +639,7 @@ module ibex_top import ibex_pkg::*; #(
logic ic_data_write_local;
logic [IC_INDEX_W-1:0] ic_data_addr_local;
logic [LineSizeECC-1:0] ic_data_wdata_local;
logic scramble_key_valid_local;
logic irq_software_local;
logic irq_timer_local;
@ -535,6 +652,7 @@ module ibex_top import ibex_pkg::*; #(
crash_dump_t crash_dump_local;
logic fetch_enable_local;
logic icache_inval_local;
logic core_busy_local;
assign buf_in = {
@ -573,6 +691,7 @@ module ibex_top import ibex_pkg::*; #(
ic_data_write,
ic_data_addr,
ic_data_wdata,
scramble_key_valid_q,
irq_software_i,
irq_timer_i,
irq_external_i,
@ -582,6 +701,7 @@ module ibex_top import ibex_pkg::*; #(
debug_req_i,
crash_dump_o,
fetch_enable_i,
icache_inval,
core_busy_d
};
@ -621,6 +741,7 @@ module ibex_top import ibex_pkg::*; #(
ic_data_write_local,
ic_data_addr_local,
ic_data_wdata_local,
scramble_key_valid_local,
irq_software_local,
irq_timer_local,
irq_external_local,
@ -630,6 +751,7 @@ module ibex_top import ibex_pkg::*; #(
debug_req_local,
crash_dump_local,
fetch_enable_local,
icache_inval_local,
core_busy_local
} = buf_out;
@ -727,6 +849,7 @@ module ibex_top import ibex_pkg::*; #(
.ic_data_addr_i (ic_data_addr_local),
.ic_data_wdata_i (ic_data_wdata_local),
.ic_data_rdata_i (ic_data_rdata_local),
.ic_scr_key_valid_i (scramble_key_valid_local),
.irq_software_i (irq_software_local),
.irq_timer_i (irq_timer_local),
@ -741,6 +864,7 @@ module ibex_top import ibex_pkg::*; #(
.fetch_enable_i (fetch_enable_local),
.alert_minor_o (lockstep_alert_minor_local),
.alert_major_o (lockstep_alert_major_local),
.icache_inval_i (icache_inval_local),
.core_busy_i (core_busy_local),
.test_en_i (test_en_i),
.scan_rst_ni (scan_rst_ni)

View file

@ -24,6 +24,7 @@ module ibex_top_tracing import ibex_pkg::*; #(
parameter bit DbgTriggerEn = 1'b0,
parameter int unsigned DbgHwBreakNum = 1,
parameter bit SecureIbex = 1'b0,
parameter bit ICacheScramble = 1'b0,
parameter lfsr_seed_t RndCnstLfsrSeed = RndCnstLfsrSeedDefault,
parameter lfsr_perm_t RndCnstLfsrPerm = RndCnstLfsrPermDefault,
parameter int unsigned DmHaltAddr = 32'h1A110800,
@ -70,6 +71,12 @@ module ibex_top_tracing import ibex_pkg::*; #(
input logic [14:0] irq_fast_i,
input logic irq_nm_i, // non-maskeable interrupt
// Scrambling Interface
input logic scramble_key_valid_i,
input logic [SCRAMBLE_KEY_W-1:0] scramble_key_i,
input logic [SCRAMBLE_NONCE_W-1:0] scramble_nonce_i,
output logic scramble_req_o,
// Debug Interface
input logic debug_req_i,
output crash_dump_t crash_dump_o,
@ -145,6 +152,7 @@ module ibex_top_tracing import ibex_pkg::*; #(
.DbgHwBreakNum ( DbgHwBreakNum ),
.WritebackStage ( WritebackStage ),
.SecureIbex ( SecureIbex ),
.ICacheScramble ( ICacheScramble ),
.RndCnstLfsrSeed ( RndCnstLfsrSeed ),
.RndCnstLfsrPerm ( RndCnstLfsrPerm ),
.DmHaltAddr ( DmHaltAddr ),
@ -186,6 +194,11 @@ module ibex_top_tracing import ibex_pkg::*; #(
.irq_fast_i,
.irq_nm_i,
.scramble_key_valid_i,
.scramble_key_i,
.scramble_nonce_i,
.scramble_req_o,
.debug_req_i,
.crash_dump_o,