| // 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." | 
 |     } | 
 |   ] | 
 |  | 
 |   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", | 
 |       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. | 
 |         ''' | 
 |       } | 
 |     } | 
 |   ] | 
 | } |