blob: 8e5c685c8716cf8ba2358331e56a1f920d78db6b [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);
// 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, 32'h0, 768, 0, 1'b0, 1'b0, 1'b1, 1'b0},
// OWNER_SW_CFG
'{Unbuffered, 32'h300, 768, 0, 1'b0, 1'b0, 1'b1, 1'b0},
// HW_CFG
'{Buffered, 32'h600, 176, 0, 1'b0, 1'b1, 1'b1, 1'b0},
// SECRET0
'{Buffered, 32'h6B0, 40, 0, 1'b1, 1'b1, 1'b1, 1'b1},
// SECRET1
'{Buffered, 32'h6D8, 88, 1, 1'b1, 1'b1, 1'b1, 1'b1},
// SECRET2
'{Buffered, 32'h730, 120, 2, 1'b1, 1'b1, 1'b1, 1'b1},
// LIFE_CYCLE
'{Buffered, 32'h7A8, 88, 0, 1'b0, 1'b0, 1'b0, 1'b0}
};
parameter int CreatorSwCfgIdx = 0;
parameter int OwnerSwCfgIdx = 1;
parameter int HwCfgIdx = 2;
parameter int Secret0Idx = 3;
parameter int Secret1Idx = 4;
parameter int Secret2Idx = 5;
parameter int LifeCycleIdx = 6;
// These are not "real partitions", but in terms of implementation it is convenient to
// add these at the end of certain arrays.
parameter int DaiIdx = 7;
parameter int LciIdx = 8;
///////////////////////////////
// Typedefs for LC Interface //
///////////////////////////////
// TODO: update this encoding and move to lc_ctrl_pkg
typedef enum logic [7:0] {
Value0 = 8'h 00,
Value1 = 8'h 6D,
Value2 = 8'h 94,
ValueF = 8'h FF
} lc_value_e;
// TODO: move to lc_ctrl_pkg
typedef enum logic [47:0] {
// GRP5 GRP4 GRP3 GRP2 GRP1 GRP0
LcStateRaw = {6{Value0}},
LcStateTest = {Value0, Value0, Value0, Value0, Value0, Value1},
LcStateDev = {Value0, Value0, Value2, Value2, Value1, Value1},
LcStateProd = {Value0, Value0, Value2, Value1, Value2, Value1},
LcStateProdEnd = {Value0, Value0, Value1, Value2, Value2, Value1},
LcStateRma = {Value1, Value1, Value2, ValueF, ValueF, Value1},
LcStateScrap = {6{ValueF}}
} lc_state_e;
typedef struct packed {
logic lc_state_valid;
lc_value_e [5:0] lc_state;
logic [7:0] id_state;
logic [7:0] test_state_cnt;
logic [31:0] test_unlock_token;
logic [31:0] test_exit_token;
logic [63:0] rma_unlock_token;
logic [7:0] test_unlock_cnt;
logic [7:0] test_exit_cnt;
logic [7:0] rma_unlock_cnt;
// this must be incremented upon each state change
// also, each invalid otp_program_cmd_e command will increment
// this counter.
logic [15:0] transition_cnt;
} otp_lc_data_t; // broadcast
// TODO: this should have maximum Hamming distance encoding
typedef enum logic [15:0] {
// state transitions
CmdGoToTestState = 16'h0001,
CmdGoToDevState = 16'h0002,
CmdGoToProdState = 16'h0003,
CmdGoToProdEndState = 16'h0004,
CmdGoToRmaState = 16'h0005,
CmdGoToScrapState = 16'h0006,
// counters
CmdIncrTestStateCnt = 16'h0007,
CmdIncrTestUnlockCnt = 16'h0008,
CmdIncrRmaUnlockCnt = 16'h0009,
CmdIncrTransitionCnt = 16'h000A
} otp_program_cmd_e;
typedef struct packed {
logic update;
otp_program_cmd_e command;
} lc_otp_program_req_t;
typedef struct packed {
logic done;
} lc_otp_program_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 KeyMgrKeyWidth = 256;
parameter int FlashKeyWidth = 128;
typedef struct packed {
logic valid;
logic [KeyMgrKeyWidth-1:0] key_share0;
logic [KeyMgrKeyWidth-1:0] key_share1;
} keymgr_key_t;
typedef struct packed {
logic valid;
logic [FlashKeyWidth-1:0] addr_key;
logic [FlashKeyWidth-1:0] data_key;
} flash_key_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