| // 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: "RndCnstUrndLfsrSeed", |
| type: "otbn_pkg::urnd_lfsr_seed_t", |
| desc: ''' |
| Default seed of the PRNG used for URND. |
| ''' |
| randcount: "256", |
| randtype: "data" |
| }, |
| { name: "RndCnstUrndChunkLfsrPerm", |
| type: "otbn_pkg::urnd_chunk_lfsr_perm_t", |
| desc: ''' |
| Permutation applied to the LFSR chunks of the PRNG used for URND. |
| ''' |
| randcount: "64", |
| randtype: "perm" |
| }, |
| { 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" |
| }, |
| ], |
| |
| 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. |
| ''', |
| swaccess: "ro", |
| hwaccess: "hwo", |
| 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." |
| } |
| |
| // 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: "illegal_bus_access" |
| resval: 0, |
| desc: "An `ILLEGAL_BUS_ACCESS` error was observed." |
| } |
| { bits: "21", |
| name: "lifecycle_escalation" |
| resval: 0, |
| desc: "A `LIFECYCLE_ESCALATION` error was observed." |
| } |
| { bits: "22", |
| 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: "illegal_bus_access" |
| resval: 0, |
| desc: "A `ILLEGAL_BUS_ACCESS` error was observed." |
| } |
| { bits: "5", |
| name: "lifecycle_escalation" |
| resval: 0, |
| desc: "A `LIFECYCLE_ESCALATION` error was observed." |
| } |
| { bits: "6", |
| 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. |
| ''', |
| hwext: "true", |
| swaccess: "ro", |
| hwaccess: "hwo", |
| fields: [ |
| { bits: "31:0", |
| name: "insn_cnt", |
| resval: 0, |
| desc: ''' |
| The number of executed instructions. |
| ''' |
| } |
| ] |
| } |
| { 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. |
| ''' |
| swaccess: "rw", |
| hwaccess: "hrw", |
| fields: [ |
| { bits: "31:0", |
| name: "checksum", |
| resval: 0, |
| desc: "Checksum accumulator" |
| } |
| ] |
| } |
| |
| // 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: "1024", // 4 kB |
| 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. |
| ''' |
| } |
| } |
| ] |
| } |