blob: 88399a25ec79da48eda6c9541ee6523adbc2805f [file] [log] [blame]
// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
{ name: "otbn"
clocking: [
{clock: "clk_i", reset: "rst_ni", idle: "idle_o", primary: true},
{clock: "clk_edn_i", reset: "rst_edn_ni", idle: "idle_o"},
{clock: "clk_otp_i", reset: "rst_otp_ni", idle: "idle_otp_o"}
]
bus_interfaces: [
{ protocol: "tlul", direction: "device" }
],
param_list: [
{ name: "Stub",
type: "bit",
default: "0",
desc: "Stub out the core of Otbn logic"
local: "false",
expose: "true"
},
{ name: "RegFile",
type: "otbn_pkg::regfile_e",
default: "otbn_pkg::RegFileFF",
desc: "Selection of the register file implementation. See otbn_pkg.sv."
local: "false",
expose: "true"
},
{ name: "RndCnstUrndPrngSeed",
type: "otbn_pkg::urnd_prng_seed_t",
desc: '''
Default seed of the PRNG used for URND.
'''
randcount: "256",
randtype: "data"
},
{ name: "RndCnstOtbnKey",
type: "otp_ctrl_pkg::otbn_key_t",
desc: '''
Compile-time random reset value for IMem/DMem scrambling key.
'''
randcount: "128",
randtype: "data"
},
{ name: "RndCnstOtbnNonce",
type: "otp_ctrl_pkg::otbn_nonce_t",
desc: '''
Compile-time random reset value for IMem/DMem scrambling nonce.
'''
randcount: "64",
randtype: "data"
},
]
interrupt_list: [
{ name: "done"
desc: "OTBN has completed the operation."
}
]
alert_list: [
{ name: "fatal"
desc: "A fatal error. Fatal alerts are non-recoverable and will be asserted until a hard reset."
}
{ name: "recov"
desc: "A recoverable error. Just sent once (as the processor stops)."
}
]
inter_signal_list: [
// Key request to OTP
{ struct: "otbn_otp_key"
type: "req_rsp"
name: "otbn_otp_key"
act: "req"
default: "'0"
package: "otp_ctrl_pkg"
},
// EDN interface for RND
{ struct: "edn"
type: "req_rsp"
name: "edn_rnd"
act: "req"
package: "edn_pkg"
},
// EDN interface for URND
{ struct: "edn"
type: "req_rsp"
name: "edn_urnd"
act: "req"
package: "edn_pkg"
},
// OTBN is not performing any operation and can be clock/power-gated. One
// idle for each clock domain (see assignments in "clocking" dictionary above).
{ name: "idle",
type: "uni",
struct: "logic",
width: "1",
act: "req",
},
{ name: "idle_otp",
type: "uni",
struct: "logic",
width: "1",
act: "req",
},
// ram configuration
{ struct: "ram_1p_cfg",
package: "prim_ram_1p_pkg",
type: "uni",
name: "ram_cfg",
act: "rcv"
},
// Lifecycle escalation
{ struct: "lc_tx"
type: "uni"
name: "lc_escalate_en"
act: "rcv"
default: "lc_ctrl_pkg::Off"
package: "lc_ctrl_pkg"
},
// Key sideload
{ struct: "otbn_key_req"
type: "uni"
name: "keymgr_key"
act: "rcv"
package: "keymgr_pkg"
},
],
countermeasures: [
{ name: "BUS.INTEGRITY",
desc: "End-to-end bus integrity scheme."
}
{ name: "SCRAMBLE.KEY.SIDELOAD",
desc: "The scrambling key is sideloaded from OTP and thus unreadable by SW."
}
]
regwidth: "32"
registers: [
// The magic values for EXECUTE, SEC_WIPE_DMEM and SEC_WIPE_IMEM in the CMD
// register below were generated with the sparse-fsm-encode.py script:
//
// util/design/sparse-fsm-encode.py -d 4 -m 3 -n 8 --avoid-zero -s 1
//
// and have a hamming distance of at least 4 from one another and the zero
// word.
{ name: "CMD"
desc: '''
Command Register
A command initiates an OTBN operation. While performing the operation,
OTBN is busy; the !!STATUS register reflects that.
All operations signal their completion by raising the done
interrupt; alternatively, software may poll the !!STATUS register.
Writes are ignored if OTBN is not idle.
Unrecognized commands are ignored.
''',
swaccess: "wo",
hwaccess: "hro",
hwext: "true",
hwqe: "true",
fields: [
{ bits: "7:0"
name: "cmd"
resval: 0,
desc: '''
The operation to perform.
<table>
<thead>
<tr>
<th>Value</th>
<th>Name</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>0xd8</td>
<td>EXECUTE</td>
<td>
Starts the execution of the program stored in the
instruction memory, starting at address zero.
</td>
</tr>
<tr>
<td>0xc3</td>
<td>SEC_WIPE_DMEM</td>
<td>Securely removes all contents from the data memory.</td>
</tr>
<tr>
<td>0x1e</td>
<td>SEC_WIPE_IMEM</td>
<td>
Securely removes all contents from the instruction memory.
</td>
</tr>
</tbody>
</table>
'''
tags: [
// Don't write this field in the automated CSR tests; the commands
// are tested in more controlled form.
"excl:CsrAllTests:CsrExclWrite"
]
}
],
}
{ name: "CTRL",
desc: "Control Register",
hwext: "true",
swaccess: "rw",
hwaccess: "hrw",
hwqe: "true",
fields: [
{ bits: "0",
name: "software_errs_fatal",
resval: 0,
desc: '''
Controls the reaction to software errors.
When set software errors produce fatal errors, rather than
recoverable errors.
Writes are ignored if OTBN is not idle.
'''
}
],
}
{ name: "STATUS",
desc: "Status Register",
swaccess: "ro",
hwaccess: "hwo",
fields: [
{ bits: "7:0",
name: "status",
resval: 0,
// Note: Keep the list of status codes in sync with status_e in
// otbn_pkg.sv.
desc: '''
Indicates the current operational state OTBN is in.
All BUSY values represent an operation started by a write to the
!!CMD register.
<table>
<thead>
<tr>
<th>Value</th>
<th>Name</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>0x00</td>
<td>IDLE</td>
<td>OTBN is idle: it is not performing any action.</td>
</tr>
<tr>
<td>0x01</td>
<td>BUSY_EXECUTE</td>
<td>OTBN is busy executing software.</td>
</tr>
<tr>
<td>0x02</td>
<td>BUSY_SEC_WIPE_DMEM</td>
<td>OTBN is busy securely wiping the data memory.</td>
</tr>
<tr>
<td>0x03</td>
<td>BUSY_SEC_WIPE_IMEM</td>
<td>OTBN is busy securely wiping the instruction memory.</td>
</tr>
<tr>
<td>0xFF</td>
<td>LOCKED</td>
<td>
OTBN is locked as reaction to a fatal error, and must be
reset to unlock it again. See also the the section
"Reaction to Fatal Errors".
</td>
</tr>
</tbody>
</table>
'''
tags: [
// Don't write this field in the automated CSR tests. Despite this being RO for software
// (so you might think we couldn't write it), the csr_hw_reset test does write this by
// by default (using a backdoor access). The idea of that test is to write bogus values
// to registers, reset the block and then check that everything has its reset value.
// Doing this causes various assertions to fire and it isn't really necessary: we
// already have strong checks between this register and the output of the model.
"excl:CsrAllTests:CsrExclWrite"
]
}
]
}
{ name: "ERR_BITS",
desc: '''
Operation Result Register
Describes the errors detected during an operation.
Refer to the "List of Errors" section for a detailed description of the
errors.
The host CPU can clear this register when OTBN is not running,
by writing any value. Write attempts while OTBN is running are ignored.
''',
swaccess: "rw",
hwaccess: "hrw",
hwext: "true",
hwqe: "true",
tags: [
// Don't write this register in the automated CSR tests;
"excl:CsrAllTests:CsrExclWrite"
],
fields: [
// Software errors
{ bits: "0",
name: "bad_data_addr"
resval: 0,
desc: "A `BAD_DATA_ADDR` error was observed."
}
{ bits: "1",
name: "bad_insn_addr"
resval: 0,
desc: "A `BAD_INSN_ADDR` error was observed."
}
{ bits: "2",
resval: 0,
name: "call_stack"
desc: "A `CALL_STACK` error was observed."
}
{ bits: "3",
resval: 0,
name: "illegal_insn"
desc: "An `ILLEGAL_INSN` error was observed."
}
{ bits: "4",
name: "loop"
resval: 0,
desc: "A `LOOP` error was observed."
}
{ bits: "5",
name: "key_invalid"
resval: 0,
desc: "A `KEY_INVALID` error was observed."
}
// Fatal errors. Keep in sync with list in FATAL_ALERT_CAUSE.
{ bits: "16",
name: "imem_intg_violation"
resval: 0,
desc: "A `IMEM_INTG_VIOLATION` error was observed."
}
{ bits: "17",
name: "dmem_intg_violation"
resval: 0,
desc: "A `DMEM_INTG_VIOLATION` error was observed."
}
{ bits: "18",
name: "reg_intg_violation"
resval: 0,
desc: "A `REG_INTG_VIOLATION` error was observed."
}
{ bits: "19",
name: "bus_intg_violation"
resval: 0,
desc: "A `BUS_INTG_VIOLATION` error was observed."
}
{ bits: "20",
name: "bad_internal_state",
resval: 0,
desc: "A `BAD_INTERNAL_STATE` error was observed."
}
{ bits: "21",
name: "illegal_bus_access"
resval: 0,
desc: "An `ILLEGAL_BUS_ACCESS` error was observed."
}
{ bits: "22",
name: "lifecycle_escalation"
resval: 0,
desc: "A `LIFECYCLE_ESCALATION` error was observed."
}
{ bits: "23",
name: "fatal_software"
resval: 0,
desc: "A `FATAL_SOFTWARE` error was observed."
}
]
}
{ name: "FATAL_ALERT_CAUSE",
desc: '''
Fatal Alert Cause Register
Describes any errors that led to a fatal alert.
A fatal error puts OTBN in locked state; the value of this register
does not change until OTBN is reset.
Refer to the "List of Errors" section for a detailed description of the
errors.
'''
swaccess: "ro",
hwaccess: "hwo",
fields: [
// Keep the list in sync with the fatal errors in ERR_BITS.
{ bits: "0",
name: "imem_intg_violation",
resval: 0,
desc: "A `IMEM_INTG_VIOLATION` error was observed."
}
{ bits: "1",
name: "dmem_intg_violation",
resval: 0,
desc: "A `DMEM_INTG_VIOLATION` error was observed."
}
{ bits: "2",
name: "reg_intg_violation",
resval: 0,
desc: "A `REG_INTG_VIOLATION` error was observed."
}
{ bits: "3",
name: "bus_intg_violation",
resval: 0,
desc: "A `BUS_INTG_VIOLATION` error was observed."
}
{ bits: "4",
name: "bad_internal_state",
resval: 0,
desc: "A `BAD_INTERNAL_STATE` error was observed."
}
{ bits: "5",
name: "illegal_bus_access"
resval: 0,
desc: "A `ILLEGAL_BUS_ACCESS` error was observed."
}
{ bits: "6",
name: "lifecycle_escalation"
resval: 0,
desc: "A `LIFECYCLE_ESCALATION` error was observed."
}
{ bits: "7",
name: "fatal_software"
resval: 0,
desc: "A `FATAL_SOFTWARE` error was observed."
}
]
}
{ name: "INSN_CNT",
desc: '''
Instruction Count Register
Returns the number of instructions executed in the current or last
operation. The counter saturates at 2^32-1 and is reset to 0 at the
start of a new operation.
Only the EXECUTE operation counts instructions; for all other operations
this register remains at 0. Instructions triggering an error do not
count towards the total.
Always reads as 0 if OTBN is locked.
The host CPU can clear this register when OTBN is not running,
by writing any value. Write attempts while OTBN is running are ignored.
''',
swaccess: "rw",
hwaccess: "hrw",
hwext: "true",
hwqe: "true",
fields: [
{ bits: "31:0",
name: "insn_cnt",
resval: 0,
desc: '''
The number of executed instructions.
'''
tags: [
// Don't write this field in the automated CSR tests;
"excl:CsrAllTests:CsrExclWrite"
]
}
]
}
{ name: "LOAD_CHECKSUM",
desc: '''
A 32-bit CRC checksum of data written to memory
See the "Memory Load Integrity" section of the manual for full details.
'''
hwext: "true",
hwqe: "true",
swaccess: "rw",
hwaccess: "hrw",
tags: [
// Don't write this register in the automated CSR tests;
"excl:CsrAllTests:CsrExclWrite"
],
fields: [
{ bits: "31:0",
name: "checksum",
resval: 0,
desc: "Checksum accumulator"
tags: [
// Don't read this field in any of the automated CSR tests (they
// will predict the value wrongly because they don't know that it
// updates on memory writes)
"excl:CsrAllTests:CsrExclAll"
]
}
]
}
// Give IMEM and DMEM 16 KiB address space, each, to allow for easy expansion
// of the actual IMEM and DMEM sizes without changing the address map.
{ skipto: "0x4000" }
// Imem size (given as `items` below) must be a power of two.
{ window: {
name: "IMEM",
items: "1024", // 4 kB
swaccess: "rw",
data-intg-passthru: "true",
byte-write: "false",
desc: '''
Instruction Memory Access
The instruction memory may only be accessed through this window
while OTBN is idle.
If OTBN is busy or locked, read accesses return 0 and write accesses
are ignored.
If OTBN is busy, any access additionally triggers an
ILLEGAL_BUS_ACCESS fatal error.
'''
}
}
{ skipto: "0x8000" }
// Dmem size (given as `items` below) must be a power of two.
{ window: {
name: "DMEM",
items: "512", // 2 kB visible over the bus
swaccess: "rw",
data-intg-passthru: "true",
byte-write: "false",
desc: '''
Data Memory Access
The data memory may only be accessed through this window while OTBN
is idle.
If OTBN is busy or locked, read accesses return 0 and write accesses
are ignored.
If OTBN is busy, any access additionally triggers an
ILLEGAL_BUS_ACCESS fatal error.
Note that DMEM is actually 4kiB in size, but only the first 2kiB of
the memory is visible through this register interface.
'''
}
}
]
}