[otbn] Remove START_ADDR register

This commit removes the register from the spec and auto-generated
register model (otbn.hjson) and the RTL itself (otbn.sv). It also
removes it from the ISS, DIFs, SW driver and existing SW tests.

Signed-off-by: Rupert Swarbrick <rswarbrick@lowrisc.org>
diff --git a/hw/ip/otbn/data/otbn.hjson b/hw/ip/otbn/data/otbn.hjson
index 40a3804..1002d55 100644
--- a/hw/ip/otbn/data/otbn.hjson
+++ b/hw/ip/otbn/data/otbn.hjson
@@ -171,7 +171,7 @@
                   <td>EXECUTE</td>
                   <td>
                     Start the execution of the program stored in the
-                    instruction memory, starting at address !!START_ADDR.
+                    instruction memory, starting at address zero.
                   </td>
                 </tr>
                 <tr>
@@ -328,21 +328,6 @@
         }
       ]
     } // register : err_bits
-    { name: "START_ADDR",
-      desc: "Start byte address in the instruction memory",
-      swaccess: "wo",
-      hwaccess: "hro",
-      fields: [
-        { bits: "31:0",
-          name: "start_addr",
-          resval: 0,
-          desc: '''
-            Byte address in the instruction memory OTBN starts to execute from
-            when instructed to do so by issuing the EXECUTE command.
-          '''
-        }
-      ]
-    } // register : start_addr
     { name: "FATAL_ALERT_CAUSE",
       desc: '''
         Description of the error that caused a fatal alert.
diff --git a/hw/ip/otbn/doc/_index.md b/hw/ip/otbn/doc/_index.md
index 571db61..07aad55 100644
--- a/hw/ip/otbn/doc/_index.md
+++ b/hw/ip/otbn/doc/_index.md
@@ -569,7 +569,7 @@
 
 - OTBN transitions into the busy state, and reflects this by setting {{< regref "STATUS">}} to `BUSY_EXECUTE`.
 - The internal randomness source, which provides random numbers to the `URND` CSR and WSR, is re-seeded from the EDN.
-- The instruction at {{< regref "START_ADDR" >}} is fetched and executed.
+- The instruction at address zero is fetched and executed.
 - From this point on, all subsequent instructions are executed according to their semantics until either an {{< otbnInsnRef "ECALL" >}} instruction is executed, or an error is detected.
 - A [secure wipe of internal state](#design-details-secure-wipe-internal) is performed.
 - The {{< regref "ERR_BITS" >}} register is set to indicate either a successful execution (value `0`), or to indicate the error that was observed (a non-zero value).
diff --git a/hw/ip/otbn/dv/model/iss_wrapper.cc b/hw/ip/otbn/dv/model/iss_wrapper.cc
index 3ab371e..e8cec8c 100644
--- a/hw/ip/otbn/dv/model/iss_wrapper.cc
+++ b/hw/ip/otbn/dv/model/iss_wrapper.cc
@@ -341,9 +341,10 @@
   run_command(oss.str(), nullptr);
 }
 
-void ISSWrapper::start(uint32_t addr) {
+void ISSWrapper::start() {
   std::ostringstream oss;
-  oss << "start " << addr << "\n";
+  oss << "start "
+      << "\n";
   run_command(oss.str(), nullptr);
 
   // "Reset" our mirror of INSN_CNT. This gets zeroed on this cycle in the
diff --git a/hw/ip/otbn/dv/model/iss_wrapper.h b/hw/ip/otbn/dv/model/iss_wrapper.h
index 6850819..01965b9 100644
--- a/hw/ip/otbn/dv/model/iss_wrapper.h
+++ b/hw/ip/otbn/dv/model/iss_wrapper.h
@@ -39,8 +39,8 @@
   // Dump the contents of DMEM to a file
   void dump_d(const std::string &path) const;
 
-  // Jump to a new address and start running
-  void start(uint32_t addr);
+  // Jump to address zero and start running
+  void start();
 
   // Provide data for RND. ISS will stall when RND is read and RND data isn't
   // available
diff --git a/hw/ip/otbn/dv/model/otbn_core_model.sv b/hw/ip/otbn/dv/model/otbn_core_model.sv
index 2c17db2..8021ea8 100644
--- a/hw/ip/otbn/dv/model/otbn_core_model.sv
+++ b/hw/ip/otbn/dv/model/otbn_core_model.sv
@@ -26,9 +26,7 @@
   // Scope of an RTL OTBN implementation (for DPI). If empty, this is a "standalone" model, which
   // should update DMEM on completion. If not empty, we assume it's the scope for the top-level of a
   // real implementation running alongside and we check DMEM contents on completion.
-  parameter string DesignScope = "",
-
-  localparam int ImemAddrWidth = prim_util_pkg::vbits(ImemSizeByte)
+  parameter string DesignScope = ""
 )(
   input  logic  clk_i,
   input  logic  rst_ni,
@@ -38,8 +36,6 @@
 
   output err_bits_t err_bits_o, // valid when done_o is asserted
 
-  input  logic [ImemAddrWidth-1:0] start_addr_i, // start byte address in IMEM
-
   input logic            edn_rnd_data_valid_i, // provide RND data from EDN
   input logic [WLEN-1:0] edn_rnd_data_i,
   input logic            edn_urnd_data_valid_i, // URND reseed from EDN is valid
@@ -52,10 +48,6 @@
   localparam int ImemSizeWords = ImemSizeByte / 4;
   localparam int DmemSizeWords = DmemSizeByte / (WLEN / 8);
 
-  `ASSERT_INIT(StartAddr32_A, ImemAddrWidth <= 32)
-  logic [31:0] start_addr_32;
-  assign start_addr_32 = {{32 - ImemAddrWidth{1'b0}}, start_addr_i};
-
   // Work-around for Verilator. IEEE 1800-2017 says you should compare/assign to a chandle with
   // null. Verilator would prefer you to use zero: it treats null as a synonym of 1'b0 and chandle
   // as a synonym of bit [63:0], so comparing with null causes width mismatch errors.
@@ -109,7 +101,7 @@
     end else begin
       if (start_i | running | check_due) begin
         status <= otbn_model_step(model_handle,
-                                  start_i, start_addr_32,
+                                  start_i,
                                   status,
                                   edn_rnd_data_valid_i, edn_rnd_data_i,
                                   edn_urnd_data_valid_i,
diff --git a/hw/ip/otbn/dv/model/otbn_model.cc b/hw/ip/otbn/dv/model/otbn_model.cc
index 420c502..581b8e7 100644
--- a/hw/ip/otbn/dv/model/otbn_model.cc
+++ b/hw/ip/otbn/dv/model/otbn_model.cc
@@ -219,10 +219,8 @@
   return 0;
 }
 
-int OtbnModel::start(unsigned start_addr) {
+int OtbnModel::start() {
   const MemArea &imem = mem_util_.GetMemArea(true);
-  assert(start_addr % 4 == 0);
-  assert(start_addr / 4 < imem.GetSizeWords());
 
   ISSWrapper *iss = ensure_wrapper();
   if (!iss)
@@ -242,7 +240,7 @@
   try {
     iss->load_d(dfname);
     iss->load_i(ifname);
-    iss->start(start_addr);
+    iss->start();
   } catch (const std::runtime_error &err) {
     std::cerr << "Error when starting ISS: " << err.what() << "\n";
     return -1;
@@ -539,8 +537,8 @@
 
 void otbn_model_destroy(OtbnModel *model) { delete model; }
 
-unsigned otbn_model_step(OtbnModel *model, svLogic start, unsigned start_addr,
-                         unsigned status, svLogic edn_rnd_data_valid,
+unsigned otbn_model_step(OtbnModel *model, svLogic start, unsigned status,
+                         svLogic edn_rnd_data_valid,
                          svLogicVecVal *edn_rnd_data, /* logic [255:0] */
                          svLogic edn_urnd_data_valid,
                          svBitVecVal *insn_cnt /* bit [31:0] */,
@@ -572,7 +570,7 @@
 
   // Start the model if requested
   if (start) {
-    switch (model->start(start_addr)) {
+    switch (model->start()) {
       case 0:
         // All good
         status |= RUNNING_BIT;
diff --git a/hw/ip/otbn/dv/model/otbn_model.h b/hw/ip/otbn/dv/model/otbn_model.h
index 1941ca5..889e871 100644
--- a/hw/ip/otbn/dv/model/otbn_model.h
+++ b/hw/ip/otbn/dv/model/otbn_model.h
@@ -29,9 +29,9 @@
   // implementation too (which needs checking).
   bool has_rtl() const { return !design_scope_.empty(); }
 
-  // Start a new run with the model, writing IMEM/DMEM and jumping to the given
-  // start address. Returns 0 on success; -1 on failure.
-  int start(unsigned start_addr);
+  // Start a new run with the model, writing IMEM/DMEM and jumping to address
+  // zero. Returns 0 on success; -1 on failure.
+  int start();
 
   // Step once in the model. Returns 1 if the model has finished, 0 if not and
   // -1 on failure. If gen_trace is true, pass trace entries to the trace
diff --git a/hw/ip/otbn/dv/model/otbn_model_dpi.h b/hw/ip/otbn/dv/model/otbn_model_dpi.h
index dc25d7e..3031b28 100644
--- a/hw/ip/otbn/dv/model/otbn_model_dpi.h
+++ b/hw/ip/otbn/dv/model/otbn_model_dpi.h
@@ -52,10 +52,10 @@
 // the contents of DMEM from the ISS and inject them into the simulation
 // memory.
 //
-// If start is true, we start the model at start_addr and then step once (as
-// described above).
-unsigned otbn_model_step(OtbnModel *model, svLogic start, unsigned start_addr,
-                         unsigned status, svLogic edn_rnd_data_valid,
+// If start is true, we start the model and then step once (as described
+// above).
+unsigned otbn_model_step(OtbnModel *model, svLogic start, unsigned status,
+                         svLogic edn_rnd_data_valid,
                          svLogicVecVal *edn_rnd_data, /* logic [255:0] */
                          svLogic edn_urnd_data_valid,
                          svBitVecVal *insn_cnt /* bit [31:0] */,
diff --git a/hw/ip/otbn/dv/model/otbn_model_pkg.sv b/hw/ip/otbn/dv/model/otbn_model_pkg.sv
index 13e4e92..028d03e 100644
--- a/hw/ip/otbn/dv/model/otbn_model_pkg.sv
+++ b/hw/ip/otbn/dv/model/otbn_model_pkg.sv
@@ -19,7 +19,6 @@
   import "DPI-C" context function
     int unsigned otbn_model_step(chandle          model,
                                  logic            start,
-                                 int unsigned     start_addr,
                                  int unsigned     status,
                                  logic            edn_rnd_data_valid,
                                  logic [WLEN-1:0] edn_rnd_data,
diff --git a/hw/ip/otbn/dv/otbnsim/sim/state.py b/hw/ip/otbn/dv/otbnsim/sim/state.py
index 95117d0..ac306b5 100644
--- a/hw/ip/otbn/dv/otbnsim/sim/state.py
+++ b/hw/ip/otbn/dv/otbnsim/sim/state.py
@@ -166,7 +166,7 @@
         self._err_bits = 0
         self._urnd_reseed_complete = False
 
-        self.pc = self.get_start_addr()
+        self.pc = 0
 
         # Reset CSRs, WSRs, loop stack and call stack
         self.csrs = CSRFile()
@@ -174,15 +174,6 @@
         self.loop_stack = LoopStack()
         self.gprs.start()
 
-    def get_start_addr(self) -> int:
-        '''Get the start address of the processor.
-
-        Set the start address by writing the external register START_ADDR before
-        calling start(), and commiting the external register changes.
-
-        '''
-        return self.ext_regs.read('START_ADDR', True)
-
     def stop(self) -> None:
         '''Set flags to stop the processor and maybe abort the instruction.
 
diff --git a/hw/ip/otbn/dv/otbnsim/sim/stats.py b/hw/ip/otbn/dv/otbnsim/sim/stats.py
index 10be8e1..bc8bc4d 100644
--- a/hw/ip/otbn/dv/otbnsim/sim/stats.py
+++ b/hw/ip/otbn/dv/otbnsim/sim/stats.py
@@ -73,7 +73,7 @@
             if call_stack:
                 caller_func = call_stack[0]
             else:
-                caller_func = state_bc.get_start_addr()
+                caller_func = 0  # (start address)
 
             self.func_calls.append({
                 'call_site': pc,
diff --git a/hw/ip/otbn/dv/otbnsim/standalone.py b/hw/ip/otbn/dv/otbnsim/standalone.py
index 3f23b4e..d393146 100755
--- a/hw/ip/otbn/dv/otbnsim/standalone.py
+++ b/hw/ip/otbn/dv/otbnsim/standalone.py
@@ -44,7 +44,6 @@
     sim = OTBNSim()
     exp_end_addr = load_elf(sim, args.elf)
 
-    sim.state.ext_regs.write('START_ADDR', 0, False)
     sim.state.ext_regs.commit()
 
     sim.start()
diff --git a/hw/ip/otbn/dv/otbnsim/stepped.py b/hw/ip/otbn/dv/otbnsim/stepped.py
index 44f7f49..22f8355 100755
--- a/hw/ip/otbn/dv/otbnsim/stepped.py
+++ b/hw/ip/otbn/dv/otbnsim/stepped.py
@@ -12,7 +12,7 @@
 The integer arguments are read with Python's int() function, so should be
 prefixed with "0x" if they are hexadecimal.
 
-    start <addr>         Set the PC to <addr> and start OTBN
+    start                Set the PC to zero and start OTBN
 
     step                 Run one instruction. Print trace information to
                          stdout.
@@ -75,16 +75,10 @@
 
 def on_start(sim: OTBNSim, args: List[str]) -> Optional[OTBNSim]:
     '''Jump to an address given as the (only) argument and start running'''
-    if len(args) != 1:
-        raise ValueError('start expects exactly 1 argument. Got {}.'
-                         .format(args))
+    if len(args) != 0:
+        raise ValueError('start expects zero arguments. Got {}.'.format(args))
 
-    addr = read_word('addr', args[0], 32)
-    if addr & 3:
-        raise ValueError('start address must be word-aligned. Got {:#08x}.'
-                         .format(addr))
-    print('START {:#08x}'.format(addr))
-    sim.state.ext_regs.write('START_ADDR', addr, False)
+    print('START')
     sim.state.ext_regs.commit()
     sim.start()
 
diff --git a/hw/ip/otbn/dv/otbnsim/test/simple_test.py b/hw/ip/otbn/dv/otbnsim/test/simple_test.py
index ac8b6e5..c0f7e01 100644
--- a/hw/ip/otbn/dv/otbnsim/test/simple_test.py
+++ b/hw/ip/otbn/dv/otbnsim/test/simple_test.py
@@ -150,7 +150,7 @@
     # Run the simulation. We can just pass a list of commands to stdin, and
     # don't need to do anything clever to track what's going on.
     stepped_py = os.path.join(SIM_DIR, 'stepped.py')
-    commands = 'load_elf {}\nstart 0\nrun\nprint_regs\n'.format(elf_file)
+    commands = 'load_elf {}\nstart\nrun\nprint_regs\n'.format(elf_file)
     sim_proc = subprocess.run([stepped_py], check=True, input=commands,
                               stdout=subprocess.PIPE, universal_newlines=True)
 
diff --git a/hw/ip/otbn/dv/otbnsim/test/state_test.py b/hw/ip/otbn/dv/otbnsim/test/state_test.py
index 8908971..be5f8f1 100644
--- a/hw/ip/otbn/dv/otbnsim/test/state_test.py
+++ b/hw/ip/otbn/dv/otbnsim/test/state_test.py
@@ -18,7 +18,7 @@
     ecall
     """
 
-    sim = prepare_sim_for_asm_str(simple_asm, tmpdir, start_addr=4)
+    sim = prepare_sim_for_asm_str(simple_asm, tmpdir)
     sim.run(verbose=False, collect_stats=False)
 
     assert sim.state.ext_regs.read('ERR_BITS', False) == 0
@@ -33,12 +33,6 @@
     # STATUS must be IDLE
     assert sim.state.ext_regs.read('STATUS', False) == Status.IDLE
 
-    # START_ADDR should reflect the start address that was last written there
-    # when the simulation was started.
-    # START_ADDR is write-only from software; only reads from hardware reveal
-    # the actual value.
-    assert sim.state.ext_regs.read('START_ADDR', from_hw=True) == 4
-
 
 def test_ext_regs_err_bits_bad(tmpdir: py.path.local) -> None:
     '''Test an invalid instruction is reflected in ERR_BITS.'''
@@ -48,7 +42,7 @@
     ecall
     """
 
-    sim = prepare_sim_for_asm_str(invalid_jump_asm, tmpdir, start_addr=0)
+    sim = prepare_sim_for_asm_str(invalid_jump_asm, tmpdir)
     sim.run(verbose=False, collect_stats=False)
 
     assert sim.state.ext_regs.read('ERR_BITS', False) == ErrBits.BAD_INSN_ADDR
diff --git a/hw/ip/otbn/dv/otbnsim/test/stats_test.py b/hw/ip/otbn/dv/otbnsim/test/stats_test.py
index 7941196..53af579 100644
--- a/hw/ip/otbn/dv/otbnsim/test/stats_test.py
+++ b/hw/ip/otbn/dv/otbnsim/test/stats_test.py
@@ -23,12 +23,12 @@
 def _simulate_asm_file(asm_file: str, tmpdir: py.path.local) -> ExecutionStats:
     '''Run the OTBN simulator, collect statistics, and return them.'''
 
-    sim = testutil.prepare_sim_for_asm_file(asm_file, tmpdir, start_addr=0)
+    sim = testutil.prepare_sim_for_asm_file(asm_file, tmpdir)
     return _run_sim_for_stats(sim)
 
 
 def _simulate_asm_str(assembly: str, tmpdir: py.path.local) -> ExecutionStats:
-    sim = testutil.prepare_sim_for_asm_str(assembly, tmpdir, start_addr=0)
+    sim = testutil.prepare_sim_for_asm_str(assembly, tmpdir)
     return _run_sim_for_stats(sim)
 
 
diff --git a/hw/ip/otbn/dv/otbnsim/test/testutil.py b/hw/ip/otbn/dv/otbnsim/test/testutil.py
index c37c01f..44d83d7 100644
--- a/hw/ip/otbn/dv/otbnsim/test/testutil.py
+++ b/hw/ip/otbn/dv/otbnsim/test/testutil.py
@@ -32,7 +32,7 @@
     return elf_path
 
 
-def prepare_sim_for_asm_file(asm_file: str, tmpdir: py.path.local, start_addr: int = 0) -> OTBNSim:
+def prepare_sim_for_asm_file(asm_file: str, tmpdir: py.path.local) -> OTBNSim:
     '''Set up the simulation of a single assembly file.
 
     The returned simulation is ready to be run through the run() method.
@@ -44,13 +44,12 @@
     sim = OTBNSim()
     load_elf(sim, elf_file)
 
-    sim.state.ext_regs.write('START_ADDR', start_addr, False)
     sim.state.ext_regs.commit()
     sim.start()
     return sim
 
 
-def prepare_sim_for_asm_str(assembly: str, tmpdir: py.path.local, start_addr: int = 0) -> OTBNSim:
+def prepare_sim_for_asm_str(assembly: str, tmpdir: py.path.local) -> OTBNSim:
     '''Set up the simulation for an assembly snippet passed as string.
 
     The returned simulation is ready to be run through the run() method.
@@ -59,4 +58,4 @@
     with tempfile.NamedTemporaryFile('w', dir=tmpdir) as fp:
         fp.write(assembly)
         fp.flush()
-        return prepare_sim_for_asm_file(fp.name, tmpdir, start_addr)
+        return prepare_sim_for_asm_file(fp.name, tmpdir)
diff --git a/hw/ip/otbn/dv/rig/README.md b/hw/ip/otbn/dv/rig/README.md
index 245af17..94bf00a 100644
--- a/hw/ip/otbn/dv/rig/README.md
+++ b/hw/ip/otbn/dv/rig/README.md
@@ -24,10 +24,6 @@
 output should be stable for a fixed seed. If not specified, the seed
 is zero.
 
-To support testing with the `START_ADDR` register, which allows the
-host processor to control OTBN's reset address, there is a
-`--start-addr` parameter. By default this is zero.
-
 ### The size parameter
 
 The `--size` parameter is used to control how big the program grows. A
diff --git a/hw/ip/otbn/dv/rig/otbn-rig b/hw/ip/otbn/dv/rig/otbn-rig
index 0c5dbdb..9241186 100755
--- a/hw/ip/otbn/dv/rig/otbn-rig
+++ b/hw/ip/otbn/dv/rig/otbn-rig
@@ -60,7 +60,6 @@
     # Run the generator
     try:
         init_data, snippet, end_addr = gen_program(config,
-                                                   args.start_addr,
                                                    args.size,
                                                    insns_file)
     except RuntimeError as err:
@@ -156,8 +155,6 @@
     gen.add_argument('--size', type=int, default=100,
                      help=('Max number of instructions in stream. '
                            'Defaults to 100.'))
-    gen.add_argument('--start-addr', type=int, default=0,
-                     help='Reset address. Defaults to 0.')
     gen.add_argument('--config', type=str, default='default',
                      help='Configuration to use')
     gen.add_argument('--output', '-o',
diff --git a/hw/ip/otbn/dv/rig/rig/model.py b/hw/ip/otbn/dv/rig/rig/model.py
index 6389c83..7ec8f8a 100644
--- a/hw/ip/otbn/dv/rig/rig/model.py
+++ b/hw/ip/otbn/dv/rig/rig/model.py
@@ -182,7 +182,7 @@
     following the instruction stream to this point.
 
     '''
-    def __init__(self, dmem_size: int, reset_addr: int, fuel: int) -> None:
+    def __init__(self, dmem_size: int, fuel: int) -> None:
         assert fuel >= 0
         self.initial_fuel = fuel
         self.fuel = fuel
@@ -246,11 +246,12 @@
 
         # The current PC (the address of the next instruction that needs
         # generating)
-        self.pc = reset_addr
+        self.pc = 0
 
     def copy(self) -> 'Model':
         '''Return a deep copy of the model'''
-        ret = Model(self.dmem_size, self.pc, self.initial_fuel)
+        ret = Model(self.dmem_size, self.initial_fuel)
+        ret.pc = self.pc
         ret.fuel = self.fuel
         ret._known_regs = {n: regs.copy()
                            for n, regs in self._known_regs.items()}
diff --git a/hw/ip/otbn/dv/rig/rig/rig.py b/hw/ip/otbn/dv/rig/rig/rig.py
index ac4f2f3..c348994 100644
--- a/hw/ip/otbn/dv/rig/rig/rig.py
+++ b/hw/ip/otbn/dv/rig/rig/rig.py
@@ -16,14 +16,12 @@
 
 
 def gen_program(config: Config,
-                start_addr: int,
                 fuel: int,
                 insns_file: InsnsFile) -> Tuple[InitData, Snippet, int]:
     '''Generate a random program for OTBN
 
-    start_addr is the reset address (the value that should be programmed into
-    the START_ADDR register). fuel gives a rough upper bound for the number of
-    instructions that will be executed by the generated program.
+    fuel gives a rough upper bound for the number of instructions that will be
+    executed by the generated program.
 
     Returns (init_data, snippet, end_addr). init_data is a dict mapping (4-byte
     aligned) address to u32s that should be loaded into data memory before
@@ -39,11 +37,8 @@
     imem_lma, imem_size = mems['IMEM']
     dmem_lma, dmem_size = mems['DMEM']
 
-    assert start_addr <= imem_size - 4
-    assert start_addr & 3 == 0
-
     program = Program(imem_lma, imem_size, dmem_lma, dmem_size)
-    model = Model(dmem_size, start_addr, fuel)
+    model = Model(dmem_size, fuel)
 
     # Generate some initialised data to start with. Otherwise, it takes a while
     # before we start issuing loads (because we need stores to happen first).
diff --git a/hw/ip/otbn/dv/uvm/otbn_model_agent/otbn_model_if.sv b/hw/ip/otbn/dv/uvm/otbn_model_agent/otbn_model_if.sv
index 2931e40..8896856 100644
--- a/hw/ip/otbn/dv/uvm/otbn_model_agent/otbn_model_if.sv
+++ b/hw/ip/otbn/dv/uvm/otbn_model_agent/otbn_model_if.sv
@@ -14,7 +14,6 @@
 
   // Inputs to DUT
   logic                     start;        // Start the operation
-  logic [ImemAddrWidth-1:0] start_addr;   // Start byte address in IMEM
 
   // Outputs from DUT
   bit                       done;         // Operation done
@@ -36,14 +35,12 @@
     end
   endtask
 
-  // Start model by setting start and start_addr for a cycle. Waits until not in reset.
-  task automatic start_model(bit [ImemAddrWidth-1:0] start_addr);
+  // Start model by setting start for a cycle. Waits until not in reset.
+  task automatic start_model();
     wait(rst_ni);
     start = 1'b1;
-    start_addr = start_addr;
     @(posedge clk_i or negedge rst_ni);
     start = 1'b0;
-    start_addr = 'x;
   endtask
 
   // The err signal is asserted by the model if it fails to find the DUT or if it finds a mismatch
diff --git a/hw/ip/otbn/dv/uvm/tb.sv b/hw/ip/otbn/dv/uvm/tb.sv
index c841937..ea63270 100644
--- a/hw/ip/otbn/dv/uvm/tb.sv
+++ b/hw/ip/otbn/dv/uvm/tb.sv
@@ -187,8 +187,6 @@
 
     .err_bits_o   (),
 
-    .start_addr_i (model_if.start_addr),
-
     .edn_rnd_data_valid_i  (edn_rnd_data_valid),
     .edn_rnd_data_i        (dut.edn_rnd_data),
     .edn_urnd_data_valid_i (edn_urnd_data_valid),
diff --git a/hw/ip/otbn/dv/verilator/otbn_top_sim.sv b/hw/ip/otbn/dv/verilator/otbn_top_sim.sv
index 7a4bf5a..8f803ba 100644
--- a/hw/ip/otbn/dv/verilator/otbn_top_sim.sv
+++ b/hw/ip/otbn/dv/verilator/otbn_top_sim.sv
@@ -12,8 +12,6 @@
   parameter int ImemSizeByte = otbn_reg_pkg::OTBN_IMEM_SIZE;
   // Size of the data memory, in bytes
   parameter int DmemSizeByte = otbn_reg_pkg::OTBN_DMEM_SIZE;
-  // Start address of first instruction in IMem
-  parameter int ImemStartAddr = 32'h0;
 
   localparam int ImemAddrWidth = prim_util_pkg::vbits(ImemSizeByte);
   localparam int DmemAddrWidth = prim_util_pkg::vbits(DmemSizeByte);
@@ -70,8 +68,6 @@
 
     .err_bits_o             ( otbn_err_bits_d  ),
 
-    .start_addr_i           ( ImemStartAddr    ),
-
     .imem_req_o             ( imem_req         ),
     .imem_addr_o            ( imem_addr        ),
     .imem_wdata_o           (                  ),
@@ -288,8 +284,6 @@
     .start_i               ( otbn_start ),
     .done_o                ( otbn_model_done ),
 
-    .start_addr_i          ( ImemStartAddr ),
-
     .err_bits_o            ( otbn_model_err_bits ),
 
     .edn_rnd_data_valid_i  ( edn_rnd_data_valid ),
diff --git a/hw/ip/otbn/rtl/otbn.sv b/hw/ip/otbn/rtl/otbn.sv
index edcd78c..8f47349 100644
--- a/hw/ip/otbn/rtl/otbn.sv
+++ b/hw/ip/otbn/rtl/otbn.sv
@@ -93,8 +93,6 @@
 
   err_bits_t err_bits;
 
-  logic [ImemAddrWidth-1:0] start_addr;
-
   otbn_reg2hw_t reg2hw;
   otbn_hw2reg_t hw2reg;
 
@@ -637,11 +635,6 @@
   assign hw2reg.err_bits.lifecycle_escalation.de = done;
   assign hw2reg.err_bits.lifecycle_escalation.d = err_bits.lifecycle_escalation;
 
-  // START_ADDR register
-  assign start_addr = reg2hw.start_addr.q[ImemAddrWidth-1:0];
-  logic [top_pkg::TL_DW-ImemAddrWidth-1:0] unused_start_addr_bits;
-  assign unused_start_addr_bits = reg2hw.start_addr.q[top_pkg::TL_DW-1:ImemAddrWidth];
-
   // FATAL_ALERT_CAUSE register. The .de and .d values are equal for each bit, so that it can only
   // be set, not cleared.
   assign hw2reg.fatal_alert_cause.imem_intg_violation.de = imem_rerror;
@@ -799,8 +792,6 @@
 
       .err_bits_o (err_bits_model),
 
-      .start_addr_i (start_addr),
-
       .edn_rnd_data_valid_i  ( edn_rnd_data_valid ),
       .edn_rnd_data_i        ( edn_rnd_data ),
       .edn_urnd_data_valid_i ( edn_urnd_data_valid ),
@@ -829,8 +820,6 @@
 
       .err_bits_o             (err_bits_rtl),
 
-      .start_addr_i           (start_addr),
-
       .imem_req_o             (imem_req_core),
       .imem_addr_o            (imem_addr_core),
       .imem_wdata_o           (imem_wdata_core),
@@ -879,8 +868,6 @@
 
       .err_bits_o             (err_bits),
 
-      .start_addr_i           (start_addr),
-
       .imem_req_o             (imem_req_core),
       .imem_addr_o            (imem_addr_core),
       .imem_wdata_o           (imem_wdata_core),
diff --git a/hw/ip/otbn/rtl/otbn_controller.sv b/hw/ip/otbn/rtl/otbn_controller.sv
index 6da7c23..13c54a2 100644
--- a/hw/ip/otbn/rtl/otbn_controller.sv
+++ b/hw/ip/otbn/rtl/otbn_controller.sv
@@ -21,14 +21,12 @@
   input  logic  clk_i,
   input  logic  rst_ni,
 
-  input  logic  start_i, // start the processing at start_addr_i
+  input  logic  start_i, // start the processing at address zero
   output logic  done_o,  // processing done, signaled by ECALL or error occurring
   output logic  locked_o, // OTBN in locked state and must be reset to perform any further actions
 
   output err_bits_t err_bits_o, // valid when done_o is asserted
 
-  input  logic [ImemAddrWidth-1:0] start_addr_i,
-
   // Next instruction selection (to instruction fetch)
   output logic                     insn_fetch_req_valid_o,
   output logic [ImemAddrWidth-1:0] insn_fetch_req_addr_o,
@@ -257,7 +255,7 @@
     // `insn_fetch_req_valid_o` before any errors are considered.
     state_raw                = state_q;
     insn_fetch_req_valid_raw = 1'b0;
-    insn_fetch_req_addr_o    = start_addr_i;
+    insn_fetch_req_addr_o    = '0;
 
     // TODO: Harden state machine
     // TODO: Jumps/branches
@@ -266,7 +264,7 @@
         if (start_i) begin
           state_raw = OtbnStateRun;
 
-          insn_fetch_req_addr_o    = start_addr_i;
+          insn_fetch_req_addr_o    = '0;
           insn_fetch_req_valid_raw = 1'b1;
         end
       end
diff --git a/hw/ip/otbn/rtl/otbn_core.sv b/hw/ip/otbn/rtl/otbn_core.sv
index 29387ee..3f1210b 100644
--- a/hw/ip/otbn/rtl/otbn_core.sv
+++ b/hw/ip/otbn/rtl/otbn_core.sv
@@ -36,8 +36,6 @@
 
   output err_bits_t err_bits_o, // valid when done_o is asserted
 
-  input  logic [ImemAddrWidth-1:0] start_addr_i, // start byte address in IMEM
-
   // Instruction memory (IMEM)
   output logic                     imem_req_o,
   output logic [ImemAddrWidth-1:0] imem_addr_o,
@@ -174,26 +172,21 @@
   logic            urnd_advance;
   logic [WLEN-1:0] urnd_data;
 
-  logic                     controller_start;
-  logic [ImemAddrWidth-1:0] controller_start_addr;
+  logic        controller_start;
 
   logic        state_reset;
   logic [31:0] insn_cnt;
 
   // Start stop control start OTBN execution when requested and deals with any pre start or post
   // stop actions.
-  otbn_start_stop_control #(
-    .ImemSizeByte(ImemSizeByte)
-  ) u_otbn_start_stop_control (
+  otbn_start_stop_control u_otbn_start_stop_control (
     .clk_i,
     .rst_ni,
 
     .start_i,
-    .start_addr_i,
 
-    .controller_start_o      (controller_start),
-    .controller_start_addr_o (controller_start_addr),
-    .controller_done_i       (done_o),
+    .controller_start_o (controller_start),
+    .controller_done_i  (done_o),
 
     .urnd_reseed_req_o  (urnd_reseed_req),
     .urnd_reseed_busy_i (urnd_reseed_busy),
@@ -269,8 +262,6 @@
 
     .err_bits_o,
 
-    .start_addr_i (controller_start_addr),
-
     // Next instruction selection (to instruction fetch)
     .insn_fetch_req_addr_o  (insn_fetch_req_addr),
     .insn_fetch_req_valid_o (insn_fetch_req_valid),
diff --git a/hw/ip/otbn/rtl/otbn_reg_pkg.sv b/hw/ip/otbn/rtl/otbn_reg_pkg.sv
index 9fe76b4..c2df23b 100644
--- a/hw/ip/otbn/rtl/otbn_reg_pkg.sv
+++ b/hw/ip/otbn/rtl/otbn_reg_pkg.sv
@@ -46,10 +46,6 @@
   } otbn_reg2hw_cmd_reg_t;
 
   typedef struct packed {
-    logic [31:0] q;
-  } otbn_reg2hw_start_addr_reg_t;
-
-  typedef struct packed {
     logic        d;
     logic        de;
   } otbn_hw2reg_intr_state_reg_t;
@@ -138,12 +134,11 @@
 
   // Register -> HW type
   typedef struct packed {
-    otbn_reg2hw_intr_state_reg_t intr_state; // [48:48]
-    otbn_reg2hw_intr_enable_reg_t intr_enable; // [47:47]
-    otbn_reg2hw_intr_test_reg_t intr_test; // [46:45]
-    otbn_reg2hw_alert_test_reg_t alert_test; // [44:41]
-    otbn_reg2hw_cmd_reg_t cmd; // [40:32]
-    otbn_reg2hw_start_addr_reg_t start_addr; // [31:0]
+    otbn_reg2hw_intr_state_reg_t intr_state; // [16:16]
+    otbn_reg2hw_intr_enable_reg_t intr_enable; // [15:15]
+    otbn_reg2hw_intr_test_reg_t intr_test; // [14:13]
+    otbn_reg2hw_alert_test_reg_t alert_test; // [12:9]
+    otbn_reg2hw_cmd_reg_t cmd; // [8:0]
   } otbn_reg2hw_t;
 
   // HW -> register type
@@ -163,9 +158,8 @@
   parameter logic [BlockAw-1:0] OTBN_CMD_OFFSET = 16'h 10;
   parameter logic [BlockAw-1:0] OTBN_STATUS_OFFSET = 16'h 14;
   parameter logic [BlockAw-1:0] OTBN_ERR_BITS_OFFSET = 16'h 18;
-  parameter logic [BlockAw-1:0] OTBN_START_ADDR_OFFSET = 16'h 1c;
-  parameter logic [BlockAw-1:0] OTBN_FATAL_ALERT_CAUSE_OFFSET = 16'h 20;
-  parameter logic [BlockAw-1:0] OTBN_INSN_CNT_OFFSET = 16'h 24;
+  parameter logic [BlockAw-1:0] OTBN_FATAL_ALERT_CAUSE_OFFSET = 16'h 1c;
+  parameter logic [BlockAw-1:0] OTBN_INSN_CNT_OFFSET = 16'h 20;
 
   // Reset values for hwext registers and their fields
   parameter logic [0:0] OTBN_INTR_TEST_RESVAL = 1'h 0;
@@ -195,13 +189,12 @@
     OTBN_CMD,
     OTBN_STATUS,
     OTBN_ERR_BITS,
-    OTBN_START_ADDR,
     OTBN_FATAL_ALERT_CAUSE,
     OTBN_INSN_CNT
   } otbn_id_e;
 
   // Register width information to check illegal writes
-  parameter logic [3:0] OTBN_PERMIT [10] = '{
+  parameter logic [3:0] OTBN_PERMIT [9] = '{
     4'b 0001, // index[0] OTBN_INTR_STATE
     4'b 0001, // index[1] OTBN_INTR_ENABLE
     4'b 0001, // index[2] OTBN_INTR_TEST
@@ -209,9 +202,8 @@
     4'b 0001, // index[4] OTBN_CMD
     4'b 0001, // index[5] OTBN_STATUS
     4'b 0111, // index[6] OTBN_ERR_BITS
-    4'b 1111, // index[7] OTBN_START_ADDR
-    4'b 0001, // index[8] OTBN_FATAL_ALERT_CAUSE
-    4'b 1111  // index[9] OTBN_INSN_CNT
+    4'b 0001, // index[7] OTBN_FATAL_ALERT_CAUSE
+    4'b 1111  // index[8] OTBN_INSN_CNT
   };
 
 endpackage
diff --git a/hw/ip/otbn/rtl/otbn_reg_top.sv b/hw/ip/otbn/rtl/otbn_reg_top.sv
index 3c137e2..d51b695 100644
--- a/hw/ip/otbn/rtl/otbn_reg_top.sv
+++ b/hw/ip/otbn/rtl/otbn_reg_top.sv
@@ -187,8 +187,6 @@
   logic err_bits_bus_intg_violation_qs;
   logic err_bits_illegal_bus_access_qs;
   logic err_bits_lifecycle_escalation_qs;
-  logic start_addr_we;
-  logic [31:0] start_addr_wd;
   logic fatal_alert_cause_imem_intg_violation_qs;
   logic fatal_alert_cause_dmem_intg_violation_qs;
   logic fatal_alert_cause_reg_intg_violation_qs;
@@ -603,32 +601,6 @@
   );
 
 
-  // R[start_addr]: V(False)
-  prim_subreg #(
-    .DW      (32),
-    .SwAccess(prim_subreg_pkg::SwAccessWO),
-    .RESVAL  (32'h0)
-  ) u_start_addr (
-    .clk_i   (clk_i),
-    .rst_ni  (rst_ni),
-
-    // from register interface
-    .we     (start_addr_we),
-    .wd     (start_addr_wd),
-
-    // from internal hardware
-    .de     (1'b0),
-    .d      ('0),
-
-    // to internal hardware
-    .qe     (),
-    .q      (reg2hw.start_addr.q),
-
-    // to register interface (read)
-    .qs     ()
-  );
-
-
   // R[fatal_alert_cause]: V(False)
   //   F[imem_intg_violation]: 0:0
   prim_subreg #(
@@ -797,7 +769,7 @@
 
 
 
-  logic [9:0] addr_hit;
+  logic [8:0] addr_hit;
   always_comb begin
     addr_hit = '0;
     addr_hit[0] = (reg_addr == OTBN_INTR_STATE_OFFSET);
@@ -807,9 +779,8 @@
     addr_hit[4] = (reg_addr == OTBN_CMD_OFFSET);
     addr_hit[5] = (reg_addr == OTBN_STATUS_OFFSET);
     addr_hit[6] = (reg_addr == OTBN_ERR_BITS_OFFSET);
-    addr_hit[7] = (reg_addr == OTBN_START_ADDR_OFFSET);
-    addr_hit[8] = (reg_addr == OTBN_FATAL_ALERT_CAUSE_OFFSET);
-    addr_hit[9] = (reg_addr == OTBN_INSN_CNT_OFFSET);
+    addr_hit[7] = (reg_addr == OTBN_FATAL_ALERT_CAUSE_OFFSET);
+    addr_hit[8] = (reg_addr == OTBN_INSN_CNT_OFFSET);
   end
 
   assign addrmiss = (reg_re || reg_we) ? ~|addr_hit : 1'b0 ;
@@ -825,8 +796,7 @@
                (addr_hit[5] & (|(OTBN_PERMIT[5] & ~reg_be))) |
                (addr_hit[6] & (|(OTBN_PERMIT[6] & ~reg_be))) |
                (addr_hit[7] & (|(OTBN_PERMIT[7] & ~reg_be))) |
-               (addr_hit[8] & (|(OTBN_PERMIT[8] & ~reg_be))) |
-               (addr_hit[9] & (|(OTBN_PERMIT[9] & ~reg_be)))));
+               (addr_hit[8] & (|(OTBN_PERMIT[8] & ~reg_be)))));
   end
   assign intr_state_we = addr_hit[0] & reg_we & !reg_error;
 
@@ -846,10 +816,7 @@
 
   assign cmd_wd = reg_wdata[7:0];
   assign status_re = addr_hit[5] & reg_re & !reg_error;
-  assign start_addr_we = addr_hit[7] & reg_we & !reg_error;
-
-  assign start_addr_wd = reg_wdata[31:0];
-  assign insn_cnt_re = addr_hit[9] & reg_re & !reg_error;
+  assign insn_cnt_re = addr_hit[8] & reg_re & !reg_error;
 
   // Read data return
   always_comb begin
@@ -895,10 +862,6 @@
       end
 
       addr_hit[7]: begin
-        reg_rdata_next[31:0] = '0;
-      end
-
-      addr_hit[8]: begin
         reg_rdata_next[0] = fatal_alert_cause_imem_intg_violation_qs;
         reg_rdata_next[1] = fatal_alert_cause_dmem_intg_violation_qs;
         reg_rdata_next[2] = fatal_alert_cause_reg_intg_violation_qs;
@@ -907,7 +870,7 @@
         reg_rdata_next[5] = fatal_alert_cause_lifecycle_escalation_qs;
       end
 
-      addr_hit[9]: begin
+      addr_hit[8]: begin
         reg_rdata_next[31:0] = insn_cnt_qs;
       end
 
diff --git a/hw/ip/otbn/rtl/otbn_start_stop_control.sv b/hw/ip/otbn/rtl/otbn_start_stop_control.sv
index 3fa2ff8..e7262c5 100644
--- a/hw/ip/otbn/rtl/otbn_start_stop_control.sv
+++ b/hw/ip/otbn/rtl/otbn_start_stop_control.sv
@@ -16,21 +16,15 @@
 
 module otbn_start_stop_control
   import otbn_pkg::*;
-#(
-  // Size of the instruction memory, in bytes
-  parameter int ImemSizeByte = 4096,
-  localparam int ImemAddrWidth = prim_util_pkg::vbits(ImemSizeByte)
-) (
-  input  logic  clk_i,
-  input  logic  rst_ni,
+(
+  input  logic clk_i,
+  input  logic rst_ni,
 
-  input  logic                     start_i,
-  input  logic [ImemAddrWidth-1:0] start_addr_i,
+  input  logic start_i,
 
-  output logic                     controller_start_o,
-  output logic [ImemAddrWidth-1:0] controller_start_addr_o,
+  output logic controller_start_o,
 
-  input  logic                     controller_done_i,
+  input  logic controller_done_i,
 
   output logic urnd_reseed_req_o,
   input  logic urnd_reseed_busy_i,
@@ -41,9 +35,6 @@
 );
   otbn_start_stop_state_e state_q, state_d;
 
-  logic [ImemAddrWidth-1:0] start_addr_q;
-  logic start_addr_en;
-
   always_ff @(posedge clk_i or negedge rst_ni) begin
     if (!rst_ni) begin
       state_q <= OtbnStartStopStateHalt;
@@ -52,16 +43,9 @@
     end
   end
 
-  always_ff @(posedge clk_i) begin
-    if (start_addr_en) begin
-      start_addr_q <= start_addr_i;
-    end
-  end
-
   always_comb begin
     urnd_reseed_req_o = 1'b0;
     urnd_advance_o    = 1'b0;
-    start_addr_en     = 1'b0;
     state_d           = state_q;
     ispr_init_o       = 1'b0;
     state_reset_o     = 1'b0;
@@ -69,7 +53,6 @@
     unique case(state_q)
       OtbnStartStopStateHalt: begin
         if (start_i) begin
-          start_addr_en     = 1'b1;
           urnd_reseed_req_o = 1'b1;
           ispr_init_o       = 1'b1;
           state_reset_o     = 1'b1;
@@ -99,5 +82,4 @@
                       OtbnStartStopStateUrndRefresh,
                       OtbnStartStopStateRunning})
 
-  assign controller_start_addr_o = start_addr_q;
 endmodule
diff --git a/sw/device/lib/dif/dif_otbn.c b/sw/device/lib/dif/dif_otbn.c
index f5f3a6e..a8bd777 100644
--- a/sw/device/lib/dif/dif_otbn.c
+++ b/sw/device/lib/dif/dif_otbn.c
@@ -220,18 +220,6 @@
   return kDifOtbnOk;
 }
 
-dif_otbn_result_t dif_otbn_set_start_addr(const dif_otbn_t *otbn,
-                                          unsigned int start_addr) {
-  if (otbn == NULL || start_addr % sizeof(uint32_t) != 0 ||
-      start_addr >= OTBN_IMEM_SIZE_BYTES) {
-    return kDifOtbnBadArg;
-  }
-
-  mmio_region_write32(otbn->base_addr, OTBN_START_ADDR_REG_OFFSET, start_addr);
-
-  return kDifOtbnOk;
-}
-
 dif_otbn_result_t dif_otbn_write_cmd(const dif_otbn_t *otbn,
                                      dif_otbn_cmd_t cmd) {
   if (otbn == NULL) {
diff --git a/sw/device/lib/dif/dif_otbn.h b/sw/device/lib/dif/dif_otbn.h
index 1a99118..b972319 100644
--- a/sw/device/lib/dif/dif_otbn.h
+++ b/sw/device/lib/dif/dif_otbn.h
@@ -251,17 +251,6 @@
                                      dif_otbn_interrupt_t irq_type);
 
 /**
- * Set the start address of the execution.
- *
- * @param otbn OTBN instance.
- * @param start_addr The IMEM byte address to start the execution at.
- * @return `kDifOtbnBadArg` if `otbn` is `NULL` or `start_addr` is invalid,
- *         `kDifOtbnOk` otherwise.
- */
-dif_otbn_result_t dif_otbn_set_start_addr(const dif_otbn_t *otbn,
-                                          unsigned int start_addr);
-
-/**
  * Start an operation by issuing a command.
  *
  * @param otbn OTBN instance.
diff --git a/sw/device/lib/dif/dif_otbn_unittest.cc b/sw/device/lib/dif/dif_otbn_unittest.cc
index b7dc556..c6c67f6 100644
--- a/sw/device/lib/dif/dif_otbn_unittest.cc
+++ b/sw/device/lib/dif/dif_otbn_unittest.cc
@@ -199,36 +199,6 @@
   EXPECT_EQ(dif_otbn_irq_force(&dif_otbn_, kDifOtbnInterruptDone), kDifOtbnOk);
 }
 
-class SetStartAddrTest : public OtbnTest {};
-
-TEST_F(SetStartAddrTest, NullArgs) {
-  EXPECT_EQ(dif_otbn_set_start_addr(nullptr, 0), kDifOtbnBadArg);
-}
-
-TEST_F(SetStartAddrTest, BadStartAddress) {
-  // Must be 4-byte aligned.
-  EXPECT_EQ(dif_otbn_set_start_addr(&dif_otbn_, 1), kDifOtbnBadArg);
-
-  EXPECT_EQ(dif_otbn_set_start_addr(&dif_otbn_, 2), kDifOtbnBadArg);
-
-  // Valid addresses (ignoring alignment): 0 .. (OTBN_IMEM_SIZE_BYTES - 1)
-  EXPECT_EQ(dif_otbn_set_start_addr(&dif_otbn_, OTBN_IMEM_SIZE_BYTES),
-            kDifOtbnBadArg);
-
-  EXPECT_EQ(dif_otbn_set_start_addr(&dif_otbn_, OTBN_IMEM_SIZE_BYTES + 32),
-            kDifOtbnBadArg);
-}
-
-TEST_F(SetStartAddrTest, Success) {
-  // Test assumption.
-  ASSERT_GE(OTBN_IMEM_SIZE_BYTES, 8);
-
-  // Write start address.
-  EXPECT_WRITE32(OTBN_START_ADDR_REG_OFFSET, 4);
-
-  EXPECT_EQ(dif_otbn_set_start_addr(&dif_otbn_, 4), kDifOtbnOk);
-}
-
 class WriteCmdTest : public OtbnTest {};
 
 TEST_F(WriteCmdTest, NullArgs) {
diff --git a/sw/device/lib/runtime/otbn.c b/sw/device/lib/runtime/otbn.c
index b1de75b..6aee26f 100644
--- a/sw/device/lib/runtime/otbn.c
+++ b/sw/device/lib/runtime/otbn.c
@@ -12,20 +12,6 @@
  */
 const int kOtbnWlenBytes = 256 / 8;
 
-otbn_result_t otbn_func_ptr_to_imem_addr(const otbn_t *ctx, otbn_ptr_t ptr,
-                                         uint32_t *imem_addr_otbn) {
-  uintptr_t ptr_addr = (uintptr_t)ptr;
-  uintptr_t app_imem_start_addr = (uintptr_t)ctx->app.imem_start;
-  uintptr_t app_imem_end_addr = (uintptr_t)ctx->app.imem_end;
-
-  if (imem_addr_otbn == NULL || ptr == NULL || ctx == NULL ||
-      ptr_addr < app_imem_start_addr || ptr_addr > app_imem_end_addr) {
-    return kOtbnBadArg;
-  }
-  *imem_addr_otbn = ptr_addr - app_imem_start_addr;
-  return kOtbnOk;
-}
-
 otbn_result_t otbn_data_ptr_to_dmem_addr(const otbn_t *ctx, otbn_ptr_t ptr,
                                          uint32_t *dmem_addr_otbn) {
   uintptr_t ptr_addr = (uintptr_t)ptr;
@@ -106,21 +92,11 @@
   return kOtbnOk;
 }
 
-otbn_result_t otbn_call_function(otbn_t *ctx, otbn_ptr_t func) {
+otbn_result_t otbn_execute(otbn_t *ctx) {
   if (ctx == NULL || !ctx->app_is_loaded) {
     return kOtbnBadArg;
   }
 
-  uint32_t func_imem_addr;
-  otbn_result_t result = otbn_func_ptr_to_imem_addr(ctx, func, &func_imem_addr);
-  if (result != kOtbnOk) {
-    return result;
-  }
-
-  if (dif_otbn_set_start_addr(&ctx->dif, func_imem_addr) != kDifOtbnOk) {
-    return kOtbnError;
-  }
-
   if (dif_otbn_write_cmd(&ctx->dif, kDifOtbnCmdExecute) != kDifOtbnOk) {
     return kOtbnError;
   }
diff --git a/sw/device/lib/runtime/otbn.h b/sw/device/lib/runtime/otbn.h
index 0017ca3..abf25bd 100644
--- a/sw/device/lib/runtime/otbn.h
+++ b/sw/device/lib/runtime/otbn.h
@@ -177,18 +177,14 @@
 otbn_result_t otbn_load_app(otbn_t *ctx, const otbn_app_t app);
 
 /**
- * Calls a function on OTBN.
+ * Starts the OTBN execute operation.
  *
- * Set the entry point (start address) of OTBN to the desired function, and
- * starts the OTBN operation.
- *
- * Use `otbn_busy_wait_for_done()` to wait for the function call to complete.
+ * Use `otbn_busy_wait_for_done()` to wait for execution to complete.
  *
  * @param ctx The context object.
- * @param func The function to be called.
  * @return The result of the operation.
  */
-otbn_result_t otbn_call_function(otbn_t *ctx, otbn_ptr_t func);
+otbn_result_t otbn_execute(otbn_t *ctx);
 
 /**
  * Busy waits for OTBN to be done with the current operation.
@@ -237,19 +233,6 @@
 otbn_result_t otbn_zero_data_memory(otbn_t *ctx);
 
 /**
- * Gets the address in OTBN instruction memory referenced by `ptr`.
- *
- * @param ctx The context object.
- * @param ptr The pointer to convert.
- * @param[out] imem_addr_otbn The address of the function in OTBN's instruction
- *                            memory.
- * @return The result of the operation; #kOtbnBadArg if `ptr` is not in the
- *         instruction memory space of the currently loaded application.
- */
-otbn_result_t otbn_func_ptr_to_imem_addr(const otbn_t *ctx, otbn_ptr_t ptr,
-                                         uint32_t *imem_addr_otbn);
-
-/**
  * Gets the address in OTBN data memory referenced by `ptr`.
  *
  * @param ctx The context object.
diff --git a/sw/device/silicon_creator/lib/drivers/otbn.c b/sw/device/silicon_creator/lib/drivers/otbn.c
index c467e2b..286c504 100644
--- a/sw/device/silicon_creator/lib/drivers/otbn.c
+++ b/sw/device/silicon_creator/lib/drivers/otbn.c
@@ -59,16 +59,8 @@
   return kErrorOk;
 }
 
-rom_error_t otbn_start(uint32_t start_addr) {
-  // TODO: Update to use alignment utility functions.
-  // https://github.com/lowRISC/opentitan/issues/6112
-  if (start_addr % sizeof(uint32_t) != 0 || start_addr >= kOtbnIMemSizeBytes) {
-    return kErrorOtbnInvalidArgument;
-  }
-
-  abs_mmio_write32(kBase + OTBN_START_ADDR_REG_OFFSET, start_addr);
+rom_error_t otbn_execute(void) {
   abs_mmio_write32(kBase + OTBN_CMD_REG_OFFSET, kOtbnCmdExecute);
-
   return kErrorOk;
 }
 
diff --git a/sw/device/silicon_creator/lib/drivers/otbn.h b/sw/device/silicon_creator/lib/drivers/otbn.h
index 4be57f0..ea5205f 100644
--- a/sw/device/silicon_creator/lib/drivers/otbn.h
+++ b/sw/device/silicon_creator/lib/drivers/otbn.h
@@ -46,13 +46,12 @@
 } otbn_status_t;
 
 /**
- * Start the execution of the application loaded into OTBN at the start address.
+ * Start the execution of the application loaded into OTBN
  *
- * @param start_addr The IMEM byte address to start the execution at.
  * @return `kErrorOtbInvalidArgument` if `start_addr` is invalid, `kErrorOk`
  *         otherwise.
  */
-rom_error_t otbn_start(uint32_t start_addr);
+rom_error_t otbn_execute(void);
 
 /**
  * Is OTBN busy executing an application?
diff --git a/sw/device/silicon_creator/lib/drivers/otbn_unittest.cc b/sw/device/silicon_creator/lib/drivers/otbn_unittest.cc
index fb9adfb..9f035c1 100644
--- a/sw/device/silicon_creator/lib/drivers/otbn_unittest.cc
+++ b/sw/device/silicon_creator/lib/drivers/otbn_unittest.cc
@@ -25,28 +25,14 @@
 
 class StartTest : public OtbnTest {};
 
-TEST_F(StartTest, BadStartAddress) {
-  // Must be 4-byte aligned.
-  EXPECT_EQ(otbn_start(1), kErrorOtbnInvalidArgument);
-  EXPECT_EQ(otbn_start(2), kErrorOtbnInvalidArgument);
-
-  // Valid addresses (ignoring alignment): 0 .. (OTBN_IMEM_SIZE_BYTES - 1)
-  EXPECT_EQ(otbn_start(OTBN_IMEM_SIZE_BYTES), kErrorOtbnInvalidArgument);
-
-  EXPECT_EQ(otbn_start(OTBN_IMEM_SIZE_BYTES + 32), kErrorOtbnInvalidArgument);
-}
-
 TEST_F(StartTest, Success) {
   // Test assumption.
   static_assert(OTBN_IMEM_SIZE_BYTES >= 8, "OTBN IMEM size too small.");
 
-  // Write start address.
-  EXPECT_ABS_WRITE32(base_ + OTBN_START_ADDR_REG_OFFSET, 4);
-
-  // Set EXECUTE command.
+  // Send EXECUTE command.
   EXPECT_ABS_WRITE32(base_ + OTBN_CMD_REG_OFFSET, kOtbnCmdExecute);
 
-  EXPECT_EQ(otbn_start(4), kErrorOk);
+  EXPECT_EQ(otbn_execute(), kErrorOk);
 }
 
 class IsBusyTest : public OtbnTest {};
diff --git a/sw/device/tests/otbn_ecdsa_p256_test.c b/sw/device/tests/otbn_ecdsa_p256_test.c
index cedc80b..2ffdb68 100644
--- a/sw/device/tests/otbn_ecdsa_p256_test.c
+++ b/sw/device/tests/otbn_ecdsa_p256_test.c
@@ -33,7 +33,6 @@
  */
 
 OTBN_DECLARE_APP_SYMBOLS(p256_ecdsa);
-OTBN_DECLARE_PTR_SYMBOL(p256_ecdsa, start);
 
 OTBN_DECLARE_PTR_SYMBOL(p256_ecdsa, dptr_msg);
 OTBN_DECLARE_PTR_SYMBOL(p256_ecdsa, dptr_r);
@@ -53,8 +52,6 @@
 OTBN_DECLARE_PTR_SYMBOL(p256_ecdsa, x_r);
 
 static const otbn_app_t kOtbnAppP256Ecdsa = OTBN_APP_T_INIT(p256_ecdsa);
-static const otbn_ptr_t kOtbnAppP256EcdsaFuncStart =
-    OTBN_PTR_T_INIT(p256_ecdsa, start);
 
 static const otbn_ptr_t kOtbnVarDptrMsg = OTBN_PTR_T_INIT(p256_ecdsa, dptr_msg);
 static const otbn_ptr_t kOtbnVarDptrR = OTBN_PTR_T_INIT(p256_ecdsa, dptr_r);
@@ -180,7 +177,7 @@
                                kOtbnVarD) == kOtbnOk);
 
   // Call OTBN to perform operation, and wait for it to complete.
-  CHECK(otbn_call_function(otbn_ctx, kOtbnAppP256EcdsaFuncStart) == kOtbnOk);
+  CHECK(otbn_execute(otbn_ctx) == kOtbnOk);
   CHECK(otbn_busy_wait_for_done(otbn_ctx) == kOtbnOk);
 
   // Read back results.
@@ -229,7 +226,7 @@
                                kOtbnVarY) == kOtbnOk);
 
   // Call OTBN to perform operation, and wait for it to complete.
-  CHECK(otbn_call_function(otbn_ctx, kOtbnAppP256EcdsaFuncStart) == kOtbnOk);
+  CHECK(otbn_execute(otbn_ctx) == kOtbnOk);
   CHECK(otbn_busy_wait_for_done(otbn_ctx) == kOtbnOk);
 
   // Read back results.
diff --git a/sw/device/tests/otbn_randomness_test.c b/sw/device/tests/otbn_randomness_test.c
index 6af0d73..3cf5647 100644
--- a/sw/device/tests/otbn_randomness_test.c
+++ b/sw/device/tests/otbn_randomness_test.c
@@ -13,14 +13,12 @@
 #include "hw/top_earlgrey/sw/autogen/top_earlgrey.h"
 
 OTBN_DECLARE_APP_SYMBOLS(randomness);
-OTBN_DECLARE_PTR_SYMBOL(randomness, main);
 OTBN_DECLARE_PTR_SYMBOL(randomness, rv);
 OTBN_DECLARE_PTR_SYMBOL(randomness, fail_idx);
 OTBN_DECLARE_PTR_SYMBOL(randomness, rnd_out);
 OTBN_DECLARE_PTR_SYMBOL(randomness, urnd_out);
 
 static const otbn_app_t kOtbnAppCfiTest = OTBN_APP_T_INIT(randomness);
-static const otbn_ptr_t kFuncMain = OTBN_PTR_T_INIT(randomness, main);
 static const otbn_ptr_t kVarRv = OTBN_PTR_T_INIT(randomness, rv);
 static const otbn_ptr_t kVarFailIdx = OTBN_PTR_T_INIT(randomness, fail_idx);
 static const otbn_ptr_t kVarRndOut = OTBN_PTR_T_INIT(randomness, rnd_out);
@@ -50,7 +48,7 @@
   CHECK(otbn_init(&otbn_ctx, otbn_config) == kOtbnOk);
   CHECK(otbn_load_app(&otbn_ctx, kOtbnAppCfiTest) == kOtbnOk);
 
-  CHECK(otbn_call_function(&otbn_ctx, kFuncMain) == kOtbnOk);
+  CHECK(otbn_execute(&otbn_ctx) == kOtbnOk);
   CHECK(otbn_busy_wait_for_done(&otbn_ctx) == kOtbnOk);
 
   // Check for successful test execution (self-reported).
diff --git a/sw/device/tests/otbn_rsa_test.c b/sw/device/tests/otbn_rsa_test.c
index 19ad929..96e29b6 100644
--- a/sw/device/tests/otbn_rsa_test.c
+++ b/sw/device/tests/otbn_rsa_test.c
@@ -67,7 +67,6 @@
 static const bool kTestRsaGreater1k = false;
 
 OTBN_DECLARE_APP_SYMBOLS(rsa);
-OTBN_DECLARE_PTR_SYMBOL(rsa, start);
 OTBN_DECLARE_PTR_SYMBOL(rsa, mode);
 OTBN_DECLARE_PTR_SYMBOL(rsa, n_limbs);
 OTBN_DECLARE_PTR_SYMBOL(rsa, in);
@@ -76,7 +75,6 @@
 OTBN_DECLARE_PTR_SYMBOL(rsa, exp);
 
 static const otbn_app_t kOtbnAppRsa = OTBN_APP_T_INIT(rsa);
-static const otbn_ptr_t kOtbnFuncRsaStart = OTBN_PTR_T_INIT(rsa, start);
 static const otbn_ptr_t kOtbnVarRsaMode = OTBN_PTR_T_INIT(rsa, mode);
 static const otbn_ptr_t kOtbnVarRsaNLimbs = OTBN_PTR_T_INIT(rsa, n_limbs);
 static const otbn_ptr_t kOtbnVarRsaIn = OTBN_PTR_T_INIT(rsa, in);
@@ -127,7 +125,7 @@
         kOtbnOk);
 
   // Call OTBN to perform operation, and wait for it to complete.
-  CHECK(otbn_call_function(otbn_ctx, kOtbnFuncRsaStart) == kOtbnOk);
+  CHECK(otbn_execute(otbn_ctx) == kOtbnOk);
   CHECK(otbn_busy_wait_for_done(otbn_ctx) == kOtbnOk);
 
   // Read back results.
@@ -171,7 +169,7 @@
         kOtbnOk);
 
   // Call OTBN to perform operation
-  CHECK(otbn_call_function(otbn_ctx, kOtbnFuncRsaStart) == kOtbnOk);
+  CHECK(otbn_execute(otbn_ctx) == kOtbnOk);
   CHECK(otbn_busy_wait_for_done(otbn_ctx) == kOtbnOk);
 
   // Read back results.
diff --git a/sw/device/tests/otbn_smoketest.c b/sw/device/tests/otbn_smoketest.c
index ed49dbe..873e634 100644
--- a/sw/device/tests/otbn_smoketest.c
+++ b/sw/device/tests/otbn_smoketest.c
@@ -13,17 +13,12 @@
 #include "hw/top_earlgrey/sw/autogen/top_earlgrey.h"
 
 OTBN_DECLARE_APP_SYMBOLS(barrett384);
-OTBN_DECLARE_PTR_SYMBOL(barrett384, wrap_barrett384);
 
 static const otbn_app_t kAppBarrett = OTBN_APP_T_INIT(barrett384);
-static const otbn_ptr_t kFuncWrapBarrett384 =
-    OTBN_PTR_T_INIT(barrett384, wrap_barrett384);
 
 OTBN_DECLARE_APP_SYMBOLS(err_test);
-OTBN_DECLARE_PTR_SYMBOL(err_test, err_test);
 
 static const otbn_app_t kAppErrTest = OTBN_APP_T_INIT(err_test);
-static const otbn_ptr_t kFuncWrapErrTest = OTBN_PTR_T_INIT(err_test, err_test);
 
 const test_config_t kTestConfig;
 
@@ -108,7 +103,7 @@
   CHECK(dif_otbn_dmem_write(&otbn_ctx->dif, /*offset_bytes=*/320, &u,
                             sizeof(u)) == kDifOtbnOk);
 
-  CHECK(otbn_call_function(otbn_ctx, kFuncWrapBarrett384) == kOtbnOk);
+  CHECK(otbn_execute(otbn_ctx) == kOtbnOk);
   CHECK(otbn_busy_wait_for_done(otbn_ctx) == kOtbnOk);
 
   // Reading back result (c).
@@ -136,7 +131,7 @@
 static void test_err_test(otbn_t *otbn_ctx) {
   CHECK(otbn_load_app(otbn_ctx, kAppErrTest) == kOtbnOk);
 
-  CHECK(otbn_call_function(otbn_ctx, kFuncWrapErrTest) == kOtbnOk);
+  CHECK(otbn_execute(otbn_ctx) == kOtbnOk);
   CHECK(otbn_busy_wait_for_done(otbn_ctx) == kOtbnOperationFailed);
 
   check_otbn_err_bits(otbn_ctx, kDifOtbnErrBitsBadDataAddr);