From 5e6f05ab70854e11bd7912e10691e16baad5d246 Mon Sep 17 00:00:00 2001 From: Michael Schaffner Date: Tue, 5 Mar 2024 17:14:37 -0800 Subject: [PATCH] [sram_ctrl] Minor alignment of init and key request behavior Previously, it was possible to re-request a new key while a memory init was ongoing. This can result in problematic behavior since the init done indication would still be set to true afterwards, which is misleading since part of the array has then been initialized with the a different key. This patch changes that and ignores key requests that are issued while a memory initialization is pending. On a similar note, it was possible to re-trigger a memory initialization while one was already ongoing, causing the existing initialization to restart. This is now also changed so that initialization requests are ignored while an initialization is still pending. Signed-off-by: Michael Schaffner --- hw/ip/sram_ctrl/data/sram_ctrl.hjson | 5 +++-- hw/ip/sram_ctrl/doc/registers.md | 5 +++-- hw/ip/sram_ctrl/rtl/sram_ctrl.sv | 14 ++++++++++---- 3 files changed, 16 insertions(+), 8 deletions(-) diff --git a/hw/ip/sram_ctrl/data/sram_ctrl.hjson b/hw/ip/sram_ctrl/data/sram_ctrl.hjson index 1e12ef296aaf8..b223825eca856 100644 --- a/hw/ip/sram_ctrl/data/sram_ctrl.hjson +++ b/hw/ip/sram_ctrl/data/sram_ctrl.hjson @@ -366,7 +366,7 @@ before triggering a key renewal, hardware will automatically clear that status bit such that software can poll its status. Note that requesting a new scrambling key takes ~200 OTP cycles, which translates to ~800 CPU cycles (OTP runs at 24MHz, CPU runs at 100MHz). Note that writing 1 to this register while - a key request is pending has no effect. + a key request or a memory initialization request is already pending has no effect. ''' }, { bits: "1", @@ -376,7 +376,8 @@ The init mechanism uses an LFSR that is seeded with a part of the nonce supplied when requesting a scrambling key. Once seeded, the memory is initialized with pseudo-random data pulled from the LFSR. Note that !!CTRL.RENEW_SCR_KEY takes priority when writing 1 to both !!CTRL.RENEW_SCR_KEY and !!CTRL.INIT with the same write transaction. - This means that the key request will complete first, followed by SRAM initialization. + This means that the key request will complete first, followed by SRAM initialization. Note that writing 1 to this register while + an init request is already pending has no effect. ''' }, ] diff --git a/hw/ip/sram_ctrl/doc/registers.md b/hw/ip/sram_ctrl/doc/registers.md index ed28ed308e98e..8504937afd650 100644 --- a/hw/ip/sram_ctrl/doc/registers.md +++ b/hw/ip/sram_ctrl/doc/registers.md @@ -165,7 +165,8 @@ Write 1 to request memory init. The init mechanism uses an LFSR that is seeded with a part of the nonce supplied when requesting a scrambling key. Once seeded, the memory is initialized with pseudo-random data pulled from the LFSR. Note that [`CTRL.RENEW_SCR_KEY`](#ctrl) takes priority when writing 1 to both [`CTRL.RENEW_SCR_KEY`](#ctrl) and [`CTRL.INIT`](#ctrl) with the same write transaction. -This means that the key request will complete first, followed by SRAM initialization. +This means that the key request will complete first, followed by SRAM initialization. Note that writing 1 to this register while +an init request is already pending has no effect. ### CTRL . RENEW_SCR_KEY Write 1 to request a new scrambling key from OTP. After writing to this register, SRAM transactions will @@ -173,7 +174,7 @@ be blocked until [`STATUS.SCR_KEY_VALID`](#status) has been set to 1. If [`STATU before triggering a key renewal, hardware will automatically clear that status bit such that software can poll its status. Note that requesting a new scrambling key takes ~200 OTP cycles, which translates to ~800 CPU cycles (OTP runs at 24MHz, CPU runs at 100MHz). Note that writing 1 to this register while -a key request is pending has no effect. +a key request or a memory initialization request is already pending has no effect. ## SCR_KEY_ROTATED Clearable SRAM key request status. diff --git a/hw/ip/sram_ctrl/rtl/sram_ctrl.sv b/hw/ip/sram_ctrl/rtl/sram_ctrl.sv index 4cf5588f76cdb..c9564b8a96fe4 100644 --- a/hw/ip/sram_ctrl/rtl/sram_ctrl.sv +++ b/hw/ip/sram_ctrl/rtl/sram_ctrl.sv @@ -205,10 +205,12 @@ module sram_ctrl // A write to the init register reloads the LFSR seed, resets the init counter and // sets init_q to flag a pending initialization request. - logic init_trig; - assign init_trig = reg2hw.ctrl.init.q & reg2hw.ctrl.init.qe; + logic init_trig, init_q; + assign init_trig = reg2hw.ctrl.init.q && + reg2hw.ctrl.init.qe && + !init_q; // Ignore new requests while memory init is already pending. - logic init_d, init_q, init_done; + logic init_d, init_done; assign init_d = (init_done) ? 1'b0 : (init_trig) ? 1'b1 : init_q; @@ -262,7 +264,11 @@ module sram_ctrl // the req/ack protocol as described in more details here: // https://docs.opentitan.org/hw/ip/otp_ctrl/doc/index.html#interfaces-to-sram-and-otbn-scramblers logic key_req, key_ack; - assign key_req = reg2hw.ctrl.renew_scr_key.q & reg2hw.ctrl.renew_scr_key.qe; + assign key_req = reg2hw.ctrl.renew_scr_key.q && + reg2hw.ctrl.renew_scr_key.qe && + !key_req_pending_q && // Ignore new requests while a request is already pending. + !init_q; // Ignore new requests while memory init is already pending. + assign key_req_pending_d = (key_req) ? 1'b1 : (key_ack) ? 1'b0 : key_req_pending_q;