blob: 1a71054299679761bd634dd2fbd34d9eeec053e3 [file] [log] [blame]
// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
//
package otp_ctrl_pkg;
import prim_util_pkg::vbits;
import otp_ctrl_reg_pkg::*;
////////////////////////
// General Parameters //
////////////////////////
parameter int NumPart = 7;
parameter int NumPartWidth = vbits(NumPart);
// This defines the width of the check timers and LFSR
parameter int TimerWidth = 40;
// TODO: may need to tune this and make sure that this encoding not optimized away.
// Redundantly encoded and complementary values are used to for signalling to the partition
// controller FSMs and the DAI whether a partition is locked or not. Any other value than
// "Unlocked" is interpreted as "Locked" in those FSMs.
typedef enum logic [7:0] {
Unlocked = 8'h5A,
Locked = 8'hA5
} access_e;
// Partition access type
typedef struct packed {
access_e read_lock;
access_e write_lock;
} part_access_t;
parameter int DaiCmdWidth = 3;
typedef enum logic [DaiCmdWidth-1:0] {
DaiRead = 3'b001,
DaiWrite = 3'b010,
DaiDigest = 3'b100
} dai_cmd_e;
//////////////////////////////////////
// Typedefs for OTP Macro Interface //
//////////////////////////////////////
// OTP-macro specific
parameter int OtpWidth = 16;
parameter int OtpAddrWidth = OtpByteAddrWidth - $clog2(OtpWidth/8);
parameter int OtpDepth = 2**OtpAddrWidth;
parameter int OtpCmdWidth = 2;
parameter int OtpSizeWidth = 2; // Allows to transfer up to 4 native OTP words at once.
parameter int OtpErrWidth = 4;
parameter int OtpIfWidth = 2**OtpSizeWidth*OtpWidth;
// Number of Byte address bits to cut off in order to get the native OTP word address.
parameter int OtpAddrShift = OtpByteAddrWidth - OtpAddrWidth;
typedef enum logic [OtpCmdWidth-1:0] {
OtpRead = 2'b00,
OtpWrite = 2'b01,
OtpInit = 2'b11
} prim_otp_cmd_e;
typedef enum logic [OtpErrWidth-1:0] {
NoErr = 4'h0,
OtpCmdInvErr = 4'h1,
OtpInitErr = 4'h2,
OtpReadCorrErr = 4'h3,
OtpReadUncorrErr = 4'h4,
OtpReadErr = 4'h5,
OtpWriteBlankErr = 4'h6,
OtpWriteErr = 4'h7,
CmdInvErr = 4'h8,
AccessErr = 4'h9,
ParityErr = 4'hA,
IntegErr = 4'hB,
CnstyErr = 4'hC,
FsmErr = 4'hD,
EscErr = 4'hE
} otp_err_e;
/////////////////////////////////
// Typedefs for OTP Scrambling //
/////////////////////////////////
parameter int ScrmblKeyWidth = 128;
parameter int ScrmblBlockWidth = 64;
parameter int DigestBlockWidth = 64;
parameter int NumPresentRounds = 31;
parameter int ScrmblBlockHalfWords = ScrmblBlockWidth / OtpWidth;
typedef enum logic [2:0] {
Decrypt,
Encrypt,
LoadShadow,
Digest,
DigestInit,
DigestFinalize
} otp_scrmbl_cmd_e;
// NOTE: THESE CONSTANTS HAVE TO BE REPLACED BEFORE TAPING OUT.
// TODO(#2229): need to put mechanism in place to manage these constants.
// Global netlist constants for OTP scrambling and digest calculation.
// Sample values below have been obtained from random.org
parameter int NumScrmblKeys = 3;
parameter int NumDigestSets = 5;
parameter int ConstSelWidth = (NumScrmblKeys > NumDigestSets) ?
vbits(NumScrmblKeys) :
vbits(NumDigestSets);
parameter logic [ScrmblKeyWidth-1:0] OtpKey [NumScrmblKeys] = '{
128'h047288e1a65c839dae610bbbdf8c4525,
128'h38fe59a71a91a65636573a6513784e3b,
128'h4f48dcc45ace0770e9135bda73e56344
};
// Note: digest set 0 is used for computing the partition digests. Constants at
// higher indices are used to compute the scrambling keys.
parameter logic [ScrmblKeyWidth-1:0] OtpDigestConst [NumDigestSets] = '{
128'h9d40106e2dc2346ec96d61f0cc5295c7,
128'hafed2aa5c3284c01d71103edab1d8953,
128'h8a14fe0c08f8a3a190dd32c05f208474,
128'h9e6fac4ba15a3bce29d05a3e9e2d0846,
128'h3a0c6051392e00ef24073627319555b8
};
parameter logic [ScrmblBlockWidth-1:0] OtpDigestIV [NumDigestSets] = '{
64'ha5af72c1b813aec4,
64'h5d7aacd1db316407,
64'hd0ec83b7fe6ae2ae,
64'hc2993a0ea64e312d,
64'h899aac2ab7d91479
};
typedef enum logic [ConstSelWidth-1:0] {
StandardMode,
ChainedMode
} otp_digest_mode_e;
////////////////////////
// Partition Metadata //
////////////////////////
typedef enum logic {
Unbuffered,
Buffered
} part_variant_e;
typedef struct packed {
part_variant_e variant;
// Offset and size within the OTP array, in Bytes.
logic [OtpByteAddrWidth-1:0] offset;
logic [OtpByteAddrWidth-1:0] size;
// Key index to use for scrambling.
logic [ConstSelWidth-1:0] key_idx;
// Attributes
logic scrambled; // Whether the partition is scrambled
logic hw_digest; // Whether the partition has a hardware digest
logic write_lock; // Whether the partition is write lockable (via digest)
logic read_lock; // Whether the partition is read lockable (via digest)
} part_info_t;
// TODO: need to parse this somehow from an hjson
localparam part_info_t PartInfo [NumPart] = '{
// Variant | offset | size | key_idx | scrambled | HW digest | write_lock | read_lock
// CREATOR_SW_CFG
'{Unbuffered, 11'h0, 768, 0, 1'b0, 1'b0, 1'b1, 1'b0},
// OWNER_SW_CFG
'{Unbuffered, 11'h300, 768, 0, 1'b0, 1'b0, 1'b1, 1'b0},
// HW_CFG
'{Buffered, 11'h600, 176, 0, 1'b0, 1'b1, 1'b1, 1'b0},
// SECRET0
'{Buffered, 11'h6B0, 40, 0, 1'b1, 1'b1, 1'b1, 1'b1},
// SECRET1
'{Buffered, 11'h6D8, 88, 1, 1'b1, 1'b1, 1'b1, 1'b1},
// SECRET2
'{Buffered, 11'h730, 120, 2, 1'b1, 1'b1, 1'b1, 1'b1},
// LIFE_CYCLE
'{Buffered, 11'h7A8, 88, 0, 1'b0, 1'b0, 1'b0, 1'b0}
};
typedef enum {
CreatorSwCfgIdx,
OwnerSwCfgIdx,
HwCfgIdx,
Secret0Idx,
Secret1Idx,
Secret2Idx,
LifeCycleIdx,
// These are not "real partitions", but in terms of implementation it is convenient to
// add these at the end of certain arrays.
DaiIdx,
LciIdx,
KdiIdx,
// Number of agents is the last idx+1.
NumAgentsIdx
} part_idx_e;
parameter int NumAgents = int'(NumAgentsIdx);
parameter int NumHwCfgBits = PartInfo[HwCfgIdx].size*8;
////////////////////////
// Typedefs for CSRNG //
////////////////////////
// Unidirectional input type for LFSR reseeding.
typedef struct packed {
logic en;
logic [31:0] data;
} edn_otp_up_t;
// Bidirectional entropy requests for scramble key derivation.
typedef struct packed {
logic req;
} otp_edn_req_t;
typedef struct packed {
logic ack;
logic [31:0] data;
} otp_edn_rsp_t;
///////////////////////////////
// Typedefs for LC Interface //
///////////////////////////////
// TODO: move all these definitions to the lc_ctrl_pkg
parameter int LcValueWidth = OtpWidth;
parameter int LcTokenWidth = 128;
parameter int NumLcStateValues = 12;
parameter int LcStateWidth = NumLcStateValues * LcValueWidth;
parameter int NumLcCountValues = 32;
typedef enum logic [LcValueWidth-1:0] {
Blk = 16'h0000, // blank
Set = 16'hF5FA // programmed
} lc_value_e;
typedef enum logic [LcStateWidth-1:0] {
LcStRaw = {NumLcStateValues{Blk}},
LcStTestUnlocked0 = {Blk, Blk, Blk, Blk, Blk, Blk, Blk, Blk, Blk, Blk, Blk, Set},
LcStTestLocked0 = {Blk, Blk, Blk, Blk, Blk, Blk, Blk, Blk, Blk, Blk, Set, Set},
LcStTestUnlocked1 = {Blk, Blk, Blk, Blk, Blk, Blk, Blk, Blk, Blk, Set, Set, Set},
LcStTestLocked1 = {Blk, Blk, Blk, Blk, Blk, Blk, Blk, Blk, Set, Set, Set, Set},
LcStTestUnlocked2 = {Blk, Blk, Blk, Blk, Blk, Blk, Blk, Set, Set, Set, Set, Set},
LcStTestLocked2 = {Blk, Blk, Blk, Blk, Blk, Blk, Set, Set, Set, Set, Set, Set},
LcStTestUnlocked3 = {Blk, Blk, Blk, Blk, Blk, Set, Set, Set, Set, Set, Set, Set},
LcStDev = {Blk, Blk, Blk, Blk, Set, Set, Set, Set, Set, Set, Set, Set},
LcStProd = {Blk, Blk, Blk, Set, Blk, Set, Set, Set, Set, Set, Set, Set},
LcStProdEnd = {Blk, Blk, Set, Blk, Blk, Set, Set, Set, Set, Set, Set, Set},
LcStRma = {Set, Set, Blk, Set, Set, Set, Set, Set, Set, Set, Set, Set},
LcStScrap = {NumLcStateValues{Set}}
} lc_state_e;
typedef struct packed {
logic state_valid;
logic test_token_valid;
logic rma_token_valid;
logic id_state_valid;
lc_state_e state;
lc_value_e [NumLcCountValues-1:0] count;
logic [LcTokenWidth-1:0] test_unlock_token;
logic [LcTokenWidth-1:0] test_exit_token;
logic [LcTokenWidth-1:0] rma_token;
lc_value_e id_state;
} otp_lc_data_t;
typedef struct packed {
logic req;
lc_state_e state_diff;
lc_value_e [NumLcCountValues-1:0] count_diff;
} lc_otp_program_req_t;
typedef struct packed {
logic err;
logic ack;
} lc_otp_program_rsp_t;
// RAW unlock token hashing request.
typedef struct packed {
logic req;
logic [LcTokenWidth-1:0] token_input;
} lc_otp_token_req_t;
typedef struct packed {
logic ack;
logic [LcTokenWidth-1:0] hashed_token;
} lc_otp_token_rsp_t;
// TODO: move this to the LC ctrl package
typedef enum logic [2:0] {
On = 3'b101,
Off = 3'b000
} lc_tx_e;
// TODO: move this to the LC ctrl package
typedef struct packed {
lc_tx_e state;
} lc_tx_t;
////////////////////////////////
// Typedefs for Key Broadcast //
////////////////////////////////
parameter int FlashKeySeedWidth = 256;
parameter int SramKeySeedWidth = 128;
parameter int KeyMgrKeyWidth = 256;
parameter int FlashKeyWidth = 128;
parameter int SramKeyWidth = 128;
parameter int SramNonceWidth = 64;
parameter int OtbnKeyWidth = 128;
parameter int OtbnNonceWidth = 256;
typedef struct packed {
logic valid;
logic [KeyMgrKeyWidth-1:0] key_share0;
logic [KeyMgrKeyWidth-1:0] key_share1;
} otp_keymgr_key_t;
typedef struct packed {
logic req;
} flash_otp_key_req_t;
typedef struct packed {
logic req;
} sram_otp_key_req_t;
typedef struct packed {
logic req;
} otbn_otp_key_req_t;
typedef struct packed {
logic ack;
logic [FlashKeyWidth-1:0] addr_key;
logic [FlashKeyWidth-1:0] data_key;
} flash_otp_key_rsp_t;
typedef struct packed {
logic ack;
logic [SramKeyWidth-1:0] key;
logic [SramNonceWidth-1:0] nonce;
} sram_otp_key_rsp_t;
typedef struct packed {
logic ack;
logic [OtbnKeyWidth-1:0] key;
logic [OtbnNonceWidth-1:0] nonce;
} otbn_otp_key_rsp_t;
////////////////////////////////
// Power/Reset Ctrl Interface //
////////////////////////////////
typedef struct packed {
logic init;
} pwr_otp_init_req_t;
typedef struct packed {
logic done;
} pwr_otp_init_rsp_t;
typedef struct packed {
logic idle;
} otp_pwr_state_t;
endpackage : otp_ctrl_pkg