blob: acd7876218b467a34c39cde45205be20790eb522 [file] [log] [blame]
// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
`include "prim_assert.sv"
package otbn_pkg;
// Global Constants ==============================================================================
// Data path width for BN (wide) instructions, in bits.
parameter int WLEN = 256;
// "Extended" WLEN: the size of the datapath with added integrity bits
parameter int ExtWLEN = WLEN * 39 / 32;
// Width of base (32b) data path with added integrity bits
parameter int BaseIntgWidth = 39;
// Number of 32-bit words per WLEN
parameter int BaseWordsPerWLEN = WLEN / 32;
// Number of flag groups
parameter int NFlagGroups = 2;
// Width of the GPR index/address
parameter int GprAw = 5;
// Number of General Purpose Registers (GPRs)
parameter int NGpr = 2 ** GprAw;
// Width of the WDR index/address
parameter int WdrAw = 5;
// Number of Wide Data Registers (WDRs)
parameter int NWdr = 2 ** WdrAw;
// Width of entropy input
parameter int EdnDataWidth = 256;
parameter int SideloadKeyWidth = 384;
parameter int unsigned LoopStackDepth = 8;
// Zero word in the implemented ECC scheme. If changing the ECC scheme, this has to be changed,
// and vice-versa.
localparam logic [BaseIntgWidth-1:0] EccZeroWord = prim_secded_pkg::SecdedInv3932ZeroWord;
localparam logic [ExtWLEN-1:0] EccWideZeroWord = {BaseWordsPerWLEN{EccZeroWord}};
// Size of DMEM scratch area. The total DMEM size is OTBN_DMEM_SIZE + DmemScratchSizeByte. Note
// that some of the Python tooling depends on this parameter (it needs to know the full DMEM size,
// but regtool only gives it OTBN_DMEM_SIZE). If changing this, you'll also need to edit
// _DmemScratchSizeBytes in util/shared/mem_layout.py
parameter int DmemScratchSizeByte = 1024;
// Toplevel constants ============================================================================
parameter int AlertFatal = 0;
parameter int AlertRecov = 1;
// Register file implementation selection enum.
typedef enum integer {
RegFileFF = 0, // Generic flip-flop based implementation
RegFileFPGA = 1 // FPGA implmentation, does infer RAM primitives.
} regfile_e;
// Command to execute. See the CMD register description in otbn.hjson for details.
typedef enum logic [7:0] {
CmdExecute = 8'hd8,
CmdSecWipeDmem = 8'hc3,
CmdSecWipeImem = 8'h1e
} cmd_e;
// Status register values. See the STATUS register description in otbn.hjson for details.
typedef enum logic [7:0] {
StatusIdle = 8'h00,
StatusBusyExecute = 8'h01,
StatusBusySecWipeDmem = 8'h02,
StatusBusySecWipeImem = 8'h03,
StatusBusySecWipeInt = 8'h04,
StatusLocked = 8'hFF
} status_e;
function automatic logic is_busy_status(status_e status);
return status inside {StatusBusyExecute,
StatusBusySecWipeDmem,
StatusBusySecWipeImem,
StatusBusySecWipeInt};
endfunction
// Error bits
//
// Note: These errors are duplicated in other places. If updating them here, update those too.
typedef struct packed {
logic fatal_software;
logic lifecycle_escalation;
logic illegal_bus_access;
logic bad_internal_state;
logic bus_intg_violation;
logic reg_intg_violation;
logic dmem_intg_violation;
logic imem_intg_violation;
logic rnd_fips_chk_fail;
logic rnd_rep_chk_fail;
logic key_invalid;
logic loop;
logic illegal_insn;
logic call_stack;
logic bad_insn_addr;
logic bad_data_addr;
} err_bits_t;
// Wrappers for classifying bad internal states
typedef struct packed {
logic alu_bignum_err;
logic mac_bignum_err;
logic ispr_bignum_err;
logic controller_err;
logic rf_err;
logic rd_err;
} predec_err_t;
typedef struct packed {
logic spr_urnd_acks;
logic spr_rnd_acks;
logic spr_secwipe_reqs;
logic mubi_rma_err;
logic mubi_urnd_err;
logic state_err;
} start_stop_bad_int_t;
typedef struct packed {
logic loop_hw_cnt_err;
logic loop_hw_stack_cnt_err;
logic loop_hw_intg_err;
logic rf_base_call_stack_err;
logic spr_secwipe_acks;
logic state_err;
logic controller_mubi_err;
} controller_bad_int_t;
typedef struct packed {
logic imem_gnt_missed_err;
logic dmem_gnt_missed_err;
} missed_gnt_t;
typedef struct packed {
logic rf_base_intg_err;
logic rf_bignum_intg_err;
logic mod_ispr_intg_err;
logic acc_ispr_intg_err;
logic loop_stack_addr_intg_err;
logic insn_fetch_intg_err;
} internal_intg_err_t;
// All the error signals that can be generated directly from the controller. Note that this is
// organised to include every software error (including 'call_stack', which actually gets fed in
// from the base register file)
typedef struct packed {
logic fatal_software;
logic bad_internal_state;
logic reg_intg_violation;
logic key_invalid;
logic loop;
logic illegal_insn;
logic call_stack;
logic bad_insn_addr;
logic bad_data_addr;
} controller_err_bits_t;
// All the error signals that can be generated somewhere inside otbn_core
typedef struct packed {
logic fatal_software;
logic bad_internal_state;
logic reg_intg_violation;
logic dmem_intg_violation;
logic imem_intg_violation;
logic rnd_fips_chk_fail;
logic rnd_rep_chk_fail;
logic key_invalid;
logic loop;
logic illegal_insn;
logic call_stack;
logic bad_insn_addr;
logic bad_data_addr;
} core_err_bits_t;
// The error signals that are generated outside of otbn_core
typedef struct packed {
logic lifecycle_escalation;
logic illegal_bus_access;
logic bad_internal_state;
logic bus_intg_violation;
} non_core_err_bits_t;
// Constants =====================================================================================
typedef enum logic {
InsnSubsetBase = 1'b0, // Base (RV32/Narrow) Instruction Subset
InsnSubsetBignum = 1'b1 // Big Number (BN/Wide) Instruction Subset
} insn_subset_e;
// Opcodes (field [6:0] in the instruction), matching the RISC-V specification for the base
// instruction subset.
typedef enum logic [6:0] {
InsnOpcodeBaseLoad = 7'h03,
InsnOpcodeBaseMemMisc = 7'h0f,
InsnOpcodeBaseOpImm = 7'h13,
InsnOpcodeBaseStore = 7'h23,
InsnOpcodeBaseOp = 7'h33,
InsnOpcodeBaseLui = 7'h37,
InsnOpcodeBaseBranch = 7'h63,
InsnOpcodeBaseJalr = 7'h67,
InsnOpcodeBaseJal = 7'h6f,
InsnOpcodeBaseSystem = 7'h73,
InsnOpcodeBignumMisc = 7'h0B,
InsnOpcodeBignumArith = 7'h2B,
InsnOpcodeBignumMulqacc = 7'h3B,
InsnOpcodeBignumBaseMisc = 7'h7B
} insn_opcode_e;
typedef enum logic [3:0] {
AluOpBaseAdd,
AluOpBaseSub,
AluOpBaseXor,
AluOpBaseOr,
AluOpBaseAnd,
AluOpBaseNot,
AluOpBaseSra,
AluOpBaseSrl,
AluOpBaseSll
} alu_op_base_e;
typedef enum logic [3:0] {
AluOpBignumAdd,
AluOpBignumAddc,
AluOpBignumAddm,
AluOpBignumSub,
AluOpBignumSubb,
AluOpBignumSubm,
AluOpBignumRshi,
AluOpBignumXor,
AluOpBignumOr,
AluOpBignumAnd,
AluOpBignumNot,
AluOpBignumNone
} alu_op_bignum_e;
typedef enum logic [1:0] {
AluOpLogicXor = 2'h0,
AluOpLogicOr = 2'h1,
AluOpLogicAnd = 2'h2,
AluOpLogicNot = 2'h3
} alu_op_logic_e;
typedef enum logic {
ComparisonOpBaseEq,
ComparisonOpBaseNeq
} comparison_op_base_e;
// Operand a source selection
typedef enum logic [1:0] {
OpASelRegister = 'd0,
OpASelZero = 'd1,
OpASelCurrPc = 'd2
} op_a_sel_e;
// Operand b source selection
typedef enum logic {
OpBSelRegister = 'd0,
OpBSelImmediate = 'd1
} op_b_sel_e;
// Immediate b selection for base ISA
typedef enum logic [2:0] {
ImmBaseBI,
ImmBaseBS,
ImmBaseBB,
ImmBaseBU,
ImmBaseBJ,
ImmBaseBL,
ImmBaseBX
} imm_b_sel_base_e;
// Shift amount select for bignum ISA
typedef enum logic [1:0] {
ShamtSelBignumA,
ShamtSelBignumS,
ShamtSelBignumZero
} shamt_sel_bignum_e;
// Regfile write data selection
typedef enum logic [2:0] {
RfWdSelEx,
RfWdSelNextPc,
RfWdSelLsu,
RfWdSelIspr,
RfWdSelIncr,
RfWdSelMac,
RfWdSelMovSel
} rf_wd_sel_e;
// Control and Status Registers (CSRs)
parameter int CsrNumWidth = 12;
typedef enum logic [CsrNumWidth-1:0] {
// Address ranges follow the RISC-V Privileged Specification v1.11
// 0x7C0-0x7FF Custom read/write
CsrFg0 = 12'h7C0,
CsrFg1 = 12'h7C1,
CsrFlags = 12'h7C8,
CsrMod0 = 12'h7D0,
CsrMod1 = 12'h7D1,
CsrMod2 = 12'h7D2,
CsrMod3 = 12'h7D3,
CsrMod4 = 12'h7D4,
CsrMod5 = 12'h7D5,
CsrMod6 = 12'h7D6,
CsrMod7 = 12'h7D7,
CsrRndPrefetch = 12'h7D8,
// 0xFC0-0xFFF Custom read-only
CsrRnd = 12'hFC0,
CsrUrnd = 12'hFC1
} csr_e;
// Wide Special Purpose Registers (WSRs)
parameter int NWsr = 8; // Number of WSRs
parameter int WsrNumWidth = $clog2(NWsr);
typedef enum logic [WsrNumWidth-1:0] {
WsrMod = 'd0,
WsrRnd = 'd1,
WsrUrnd = 'd2,
WsrAcc = 'd3,
WsrKeyS0L = 'd4,
WsrKeyS0H = 'd5,
WsrKeyS1L = 'd6,
WsrKeyS1H = 'd7
} wsr_e;
// Internal Special Purpose Registers (ISPRs)
// CSRs and WSRs have some overlap into what they map into. ISPRs are the actual registers in the
// design which CSRs and WSRs are mapped on to.
parameter int NIspr = 9;
parameter int IsprNumWidth = $clog2(NIspr);
typedef enum logic [IsprNumWidth-1:0] {
IsprMod = 'd0,
IsprRnd = 'd1,
IsprAcc = 'd2,
IsprFlags = 'd3,
IsprUrnd = 'd4,
IsprKeyS0L = 'd5,
IsprKeyS0H = 'd6,
IsprKeyS1L = 'd7,
IsprKeyS1H = 'd8
} ispr_e;
typedef logic [$clog2(NFlagGroups)-1:0] flag_group_t;
typedef struct packed {
logic Z;
logic L;
logic M;
logic C;
} flags_t;
localparam int FlagsWidth = $bits(flags_t);
typedef enum logic [$clog2(FlagsWidth)-1:0] {
FlagC = 'd0,
FlagM = 'd1,
FlagL = 'd2,
FlagZ = 'd3
} flag_e;
// Structures for decoded instructions, grouped into three:
// - insn_dec_shared_t - Anything that applies to both bignum and base microarchitecture
// - insn_dec_base_t - Anything that only applies to the base side microarchitecture
// - insn_dec_bignum_t - Anything that only applies to bignum side microarchitecture
typedef struct packed {
insn_subset_e subset;
logic ecall_insn;
logic ld_insn;
logic st_insn;
logic branch_insn;
logic jump_insn;
logic loop_insn;
logic ispr_rd_insn;
logic ispr_wr_insn;
logic ispr_rs_insn;
} insn_dec_shared_t;
typedef struct packed {
logic [4:0] d; // Destination register
logic [4:0] a; // First source register
logic [4:0] b; // Second source register
logic [31:0] i; // Immediate
alu_op_base_e alu_op;
comparison_op_base_e comparison_op;
op_a_sel_e op_a_sel;
op_b_sel_e op_b_sel;
logic rf_ren_a;
logic rf_ren_b;
logic rf_we;
rf_wd_sel_e rf_wdata_sel;
logic [11:0] loop_bodysize;
logic loop_immediate;
} insn_dec_base_t;
typedef struct packed {
logic [WdrAw-1:0] d; // Destination register
logic [WdrAw-1:0] a; // First source register
logic [WdrAw-1:0] b; // Second source register
logic [WLEN-1:0] i; // Immediate
logic rf_a_indirect; // Indirect lookup, bignum register index a comes from
// base register a read
logic rf_b_indirect; // Indirect lookup, bignum register index b comes from
// base register b read
logic rf_d_indirect; // Indirect lookup, bignum register index d comes from
// base register b read using d in this struct
logic d_inc; // Increment destination register index in base
// register file
logic a_inc; // Increment source register index a in base register
// file
logic a_wlen_word_inc; // Increment source register a in base register file
// by WLEN word size
logic b_inc; // Increment source register index b in base register
// file
// Shifting only applies to a subset of ALU operations
logic [$clog2(WLEN)-1:0] alu_shift_amt; // Shift amount
logic alu_shift_right; // Shift right if set otherwise left
flag_group_t alu_flag_group;
flag_e alu_sel_flag;
logic alu_flag_en;
logic mac_flag_en;
alu_op_bignum_e alu_op;
op_b_sel_e alu_op_b_sel;
logic [1:0] mac_op_a_qw_sel;
logic [1:0] mac_op_b_qw_sel;
logic mac_wr_hw_sel_upper;
logic [1:0] mac_pre_acc_shift;
logic mac_zero_acc;
logic mac_shift_out;
logic mac_en;
logic rf_we;
rf_wd_sel_e rf_wdata_sel;
logic rf_ren_a;
logic rf_ren_b;
logic sel_insn;
} insn_dec_bignum_t;
typedef struct packed {
logic [NWdr-1:0] rf_ren_a;
logic [NWdr-1:0] rf_ren_b;
logic [NWdr-1:0] rf_we;
} rf_predec_bignum_t;
typedef struct packed {
logic adder_x_en;
logic x_res_operand_a_sel;
logic adder_y_op_a_en;
logic shift_mod_sel;
logic adder_y_op_shifter_en;
logic shifter_a_en;
logic shifter_b_en;
logic shift_right;
logic [$clog2(WLEN)-1:0] shift_amt;
logic logic_a_en;
logic logic_shifter_en;
logic [3:0] logic_res_sel;
} alu_predec_bignum_t;
typedef struct packed {
logic [NIspr-1:0] ispr_rd_en;
logic [NIspr-1:0] ispr_wr_en;
} ispr_predec_bignum_t;
typedef struct packed {
logic op_en;
logic acc_rd_en;
} mac_predec_bignum_t;
typedef struct packed {
logic call_stack_pop;
logic call_stack_push;
logic branch_insn;
logic jump_insn;
logic loop_insn;
} ctrl_flow_predec_t;
typedef struct packed {
alu_op_base_e op;
logic [31:0] operand_a;
logic [31:0] operand_b;
} alu_base_operation_t;
typedef struct packed {
comparison_op_base_e op;
logic [31:0] operand_a;
logic [31:0] operand_b;
} alu_base_comparison_t;
typedef struct packed {
alu_op_bignum_e op;
logic [WLEN-1:0] operand_a;
logic [WLEN-1:0] operand_b;
logic shift_right;
logic [$clog2(WLEN)-1:0] shift_amt;
flag_group_t flag_group;
flag_e sel_flag;
logic alu_flag_en;
logic mac_flag_en;
} alu_bignum_operation_t;
typedef struct packed {
logic [WLEN-1:0] operand_a;
logic [WLEN-1:0] operand_b;
logic [1:0] operand_a_qw_sel;
logic [1:0] operand_b_qw_sel;
logic wr_hw_sel_upper;
logic [1:0] pre_acc_shift_imm;
logic zero_acc;
logic shift_acc;
} mac_bignum_operation_t;
// Encoding generated with:
// $ ./util/design/sparse-fsm-encode.py -d 3 -m 4 -n 5 \
// -s 5799399942 --language=sv
//
// Hamming distance histogram:
//
// 0: --
// 1: --
// 2: --
// 3: |||||||||||||||||||| (66.67%)
// 4: |||||||||| (33.33%)
// 5: --
//
// Minimum Hamming distance: 3
// Maximum Hamming distance: 4
// Minimum Hamming weight: 1
// Maximum Hamming weight: 4
localparam int StateControllerWidth = 5;
typedef enum logic [StateControllerWidth-1:0] {
OtbnStateHalt = 5'b00100,
OtbnStateRun = 5'b01010,
OtbnStateStall = 5'b10011,
OtbnStateLocked = 5'b11101
} otbn_state_e;
// States for start_stop_controller
// Encoding generated with:
// Encoding generated with:
// $ ./util/design/sparse-fsm-encode.py -d 3 -m 9 -n 7 \
// -s 573771984 --language=sv
//
// Hamming distance histogram:
//
// 0: --
// 1: --
// 2: --
// 3: |||||||||||||||||||| (44.44%)
// 4: |||||||||||||||||| (41.67%)
// 5: | (2.78%)
// 6: | (2.78%)
// 7: ||| (8.33%)
//
// Minimum Hamming distance: 3
// Maximum Hamming distance: 7
// Minimum Hamming weight: 1
// Maximum Hamming weight: 6
//
localparam int StateStartStopWidth = 7;
typedef enum logic [StateStartStopWidth-1:0] {
OtbnStartStopStateInitial = 7'b1010011,
OtbnStartStopStateHalt = 7'b1111001,
OtbnStartStopStateUrndRefresh = 7'b0000110,
OtbnStartStopStateRunning = 7'b1001000,
OtbnStartStopSecureWipeWdrUrnd = 7'b0101100,
OtbnStartStopSecureWipeAccModBaseUrnd = 7'b0010000,
OtbnStartStopSecureWipeAllZero = 7'b0110101,
OtbnStartStopSecureWipeComplete = 7'b0001011,
OtbnStartStopStateLocked = 7'b1101111
} otbn_start_stop_state_e;
// Encoding generated with:
// $ ./util/design/sparse-fsm-encode.py -d 3 -m 4 -n 5 \
// -s 2298830978 --language=sv
//
// Hamming distance histogram:
//
// 0: --
// 1: --
// 2: --
// 3: |||||||||||||||||||| (66.67%)
// 4: |||||||||| (33.33%)
// 5: --
//
// Minimum Hamming distance: 3
// Maximum Hamming distance: 4
// Minimum Hamming weight: 1
// Maximum Hamming weight: 4
//
localparam int StateScrambleCtrlWidth = 5;
typedef enum logic [StateScrambleCtrlWidth-1:0] {
ScrambleCtrlIdle = 5'b10011,
ScrambleCtrlDmemReq = 5'b11110,
ScrambleCtrlImemReq = 5'b01000,
ScrambleCtrlError = 5'b00101
} scramble_ctrl_state_e;
// URNG PRNG default seed.
// These parameters have been generated with
// $ ./util/design/gen-lfsr-seed.py --width 256 --seed 2840984437 --prefix "Urnd"
parameter int UrndPrngWidth = 256;
typedef logic [UrndPrngWidth-1:0] urnd_prng_seed_t;
parameter urnd_prng_seed_t RndCnstUrndPrngSeedDefault =
256'h84ddfadaf7e1134d70aa1c59de6197ff25a4fe335d095f1e2cba89acbe4a07e9;
parameter otp_ctrl_pkg::otbn_key_t RndCnstOtbnKeyDefault =
128'h14e8cecae3040d5e12286bb3cc113298;
parameter otp_ctrl_pkg::otbn_nonce_t RndCnstOtbnNonceDefault =
64'hf79780bc735f3843;
typedef logic [63:0] otbn_dmem_nonce_t;
typedef logic [63:0] otbn_imem_nonce_t;
endpackage