Skip to content

Commit

Permalink
[sram_ctrl] Minor alignment of init and key request behavior
Browse files Browse the repository at this point in the history
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 <[email protected]>
  • Loading branch information
msfschaffner committed Mar 7, 2024
1 parent 27c5e5d commit 5e6f05a
Show file tree
Hide file tree
Showing 3 changed files with 16 additions and 8 deletions.
5 changes: 3 additions & 2 deletions hw/ip/sram_ctrl/data/sram_ctrl.hjson
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand All @@ -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.
'''
},
]
Expand Down
5 changes: 3 additions & 2 deletions hw/ip/sram_ctrl/doc/registers.md
Original file line number Diff line number Diff line change
Expand Up @@ -165,15 +165,16 @@ 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
be blocked until [`STATUS.SCR_KEY_VALID`](#status) has been set to 1. If [`STATUS.SCR_KEY_VALID`](#status) was already 1
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.
Expand Down
14 changes: 10 additions & 4 deletions hw/ip/sram_ctrl/rtl/sram_ctrl.sv
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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;

Expand Down

0 comments on commit 5e6f05a

Please sign in to comment.