Philipp Wagner | 5c2d294 | 2020-06-22 11:34:00 +0100 | [diff] [blame] | 1 | // Copyright lowRISC contributors. |
| 2 | // Licensed under the Apache License, Version 2.0, see LICENSE for details. |
| 3 | // SPDX-License-Identifier: Apache-2.0 |
| 4 | |
| 5 | `include "prim_assert.sv" |
| 6 | |
| 7 | /** |
| 8 | * OpenTitan Big Number Accelerator (OTBN) |
| 9 | */ |
| 10 | module otbn |
| 11 | import prim_alert_pkg::*; |
| 12 | import otbn_pkg::*; |
Pirmin Vogel | 0193aba | 2020-08-17 15:10:57 +0200 | [diff] [blame] | 13 | import otbn_reg_pkg::*; |
| 14 | #( |
Pirmin Vogel | 69b55a8 | 2020-10-01 09:54:39 +0200 | [diff] [blame] | 15 | parameter regfile_e RegFile = RegFileFF, |
Pirmin Vogel | 0193aba | 2020-08-17 15:10:57 +0200 | [diff] [blame] | 16 | parameter logic [NumAlerts-1:0] AlertAsyncOn = {NumAlerts{1'b1}} |
| 17 | ) ( |
Philipp Wagner | 5c2d294 | 2020-06-22 11:34:00 +0100 | [diff] [blame] | 18 | input clk_i, |
| 19 | input rst_ni, |
| 20 | |
| 21 | input tlul_pkg::tl_h2d_t tl_i, |
| 22 | output tlul_pkg::tl_d2h_t tl_o, |
| 23 | |
| 24 | // Inter-module signals |
| 25 | output logic idle_o, |
| 26 | |
| 27 | // Interrupts |
| 28 | output logic intr_done_o, |
| 29 | output logic intr_err_o, |
| 30 | |
| 31 | // Alerts |
Pirmin Vogel | 0193aba | 2020-08-17 15:10:57 +0200 | [diff] [blame] | 32 | input prim_alert_pkg::alert_rx_t [NumAlerts-1:0] alert_rx_i, |
| 33 | output prim_alert_pkg::alert_tx_t [NumAlerts-1:0] alert_tx_o |
Philipp Wagner | 5c2d294 | 2020-06-22 11:34:00 +0100 | [diff] [blame] | 34 | |
| 35 | // CSRNG interface |
| 36 | // TODO: Needs to be connected to RNG distribution network (#2638) |
| 37 | ); |
| 38 | |
Philipp Wagner | 5c2d294 | 2020-06-22 11:34:00 +0100 | [diff] [blame] | 39 | import prim_util_pkg::vbits; |
| 40 | |
| 41 | // The OTBN_*_SIZE parameters are auto-generated by regtool and come from the |
| 42 | // bus window sizes; they are given in bytes. |
Michael Schaffner | 82a936e | 2020-07-13 16:52:38 -0700 | [diff] [blame] | 43 | localparam int ImemSizeByte = otbn_reg_pkg::OTBN_IMEM_SIZE; |
| 44 | localparam int DmemSizeByte = otbn_reg_pkg::OTBN_DMEM_SIZE; |
Philipp Wagner | 5c2d294 | 2020-06-22 11:34:00 +0100 | [diff] [blame] | 45 | |
Michael Schaffner | 82a936e | 2020-07-13 16:52:38 -0700 | [diff] [blame] | 46 | localparam int ImemAddrWidth = vbits(ImemSizeByte); |
| 47 | localparam int DmemAddrWidth = vbits(DmemSizeByte); |
Philipp Wagner | 5c2d294 | 2020-06-22 11:34:00 +0100 | [diff] [blame] | 48 | |
Stefan Wallentowitz | 7fe6abc | 2020-06-25 11:05:29 +0200 | [diff] [blame] | 49 | `ifdef OTBN_MODEL |
| 50 | localparam int OTBNModel = 1; |
| 51 | `else |
| 52 | localparam int OTBNModel = 0; |
| 53 | `endif |
| 54 | |
Philipp Wagner | 5c2d294 | 2020-06-22 11:34:00 +0100 | [diff] [blame] | 55 | logic start; |
| 56 | logic busy_d, busy_q; |
| 57 | logic done; |
| 58 | |
| 59 | logic err_valid; |
| 60 | logic [31:0] err_code; |
| 61 | |
| 62 | logic [ImemAddrWidth-1:0] start_addr; |
| 63 | |
| 64 | otbn_reg2hw_t reg2hw; |
| 65 | otbn_hw2reg_t hw2reg; |
| 66 | |
| 67 | // Bus device windows, as specified in otbn.hjson |
| 68 | typedef enum int { |
| 69 | TlWinImem = 0, |
| 70 | TlWinDmem = 1 |
| 71 | } tl_win_e; |
| 72 | |
| 73 | tlul_pkg::tl_h2d_t tl_win_h2d [2]; |
| 74 | tlul_pkg::tl_d2h_t tl_win_d2h [2]; |
| 75 | |
| 76 | |
| 77 | // Inter-module signals ====================================================== |
| 78 | |
| 79 | // TODO: Better define what "idle" means -- only the core, or also the |
| 80 | // register interface? |
| 81 | assign idle_o = ~busy_q | ~start; |
| 82 | |
| 83 | |
| 84 | // Interrupts ================================================================ |
| 85 | |
| 86 | prim_intr_hw #( |
| 87 | .Width(1) |
| 88 | ) u_intr_hw_done ( |
Timothy Chen | 4ab322a | 2020-09-11 10:50:50 -0700 | [diff] [blame] | 89 | .clk_i, |
| 90 | .rst_ni, |
Philipp Wagner | 5c2d294 | 2020-06-22 11:34:00 +0100 | [diff] [blame] | 91 | .event_intr_i (done), |
| 92 | .reg2hw_intr_enable_q_i (reg2hw.intr_enable.done.q), |
| 93 | .reg2hw_intr_test_q_i (reg2hw.intr_test.done.q), |
| 94 | .reg2hw_intr_test_qe_i (reg2hw.intr_test.done.qe), |
| 95 | .reg2hw_intr_state_q_i (reg2hw.intr_state.done.q), |
| 96 | .hw2reg_intr_state_de_o (hw2reg.intr_state.done.de), |
| 97 | .hw2reg_intr_state_d_o (hw2reg.intr_state.done.d), |
| 98 | .intr_o (intr_done_o) |
| 99 | ); |
| 100 | prim_intr_hw #( |
| 101 | .Width(1) |
| 102 | ) u_intr_hw_err ( |
Timothy Chen | 4ab322a | 2020-09-11 10:50:50 -0700 | [diff] [blame] | 103 | .clk_i, |
| 104 | .rst_ni, |
Philipp Wagner | 5c2d294 | 2020-06-22 11:34:00 +0100 | [diff] [blame] | 105 | .event_intr_i (err_valid), |
| 106 | .reg2hw_intr_enable_q_i (reg2hw.intr_enable.err.q), |
| 107 | .reg2hw_intr_test_q_i (reg2hw.intr_test.err.q), |
| 108 | .reg2hw_intr_test_qe_i (reg2hw.intr_test.err.qe), |
| 109 | .reg2hw_intr_state_q_i (reg2hw.intr_state.err.q), |
| 110 | .hw2reg_intr_state_de_o (hw2reg.intr_state.err.de), |
| 111 | .hw2reg_intr_state_d_o (hw2reg.intr_state.err.d), |
| 112 | .intr_o (intr_err_o) |
| 113 | ); |
| 114 | |
| 115 | |
| 116 | // Registers ================================================================= |
| 117 | |
| 118 | otbn_reg_top u_reg ( |
| 119 | .clk_i, |
| 120 | .rst_ni, |
| 121 | .tl_i, |
| 122 | .tl_o, |
| 123 | .tl_win_o (tl_win_h2d), |
| 124 | .tl_win_i (tl_win_d2h), |
| 125 | |
| 126 | .reg2hw, |
| 127 | .hw2reg, |
| 128 | |
Philipp Wagner | a59a076 | 2020-07-18 00:03:59 +0100 | [diff] [blame] | 129 | .devmode_i (1'b1) |
Philipp Wagner | 5c2d294 | 2020-06-22 11:34:00 +0100 | [diff] [blame] | 130 | ); |
| 131 | |
| 132 | // CMD register |
| 133 | assign start = reg2hw.cmd.start.qe & reg2hw.cmd.start.q; |
| 134 | |
| 135 | // STATUS register |
| 136 | assign hw2reg.status.busy.d = busy_q; |
| 137 | assign hw2reg.status.dummy.d = 1'b0; |
| 138 | |
| 139 | // ERR_CODE register |
| 140 | assign hw2reg.err_code.de = err_valid; |
| 141 | assign hw2reg.err_code.d = err_code; |
| 142 | |
| 143 | // START_ADDR register |
| 144 | assign start_addr = reg2hw.start_addr.q[ImemAddrWidth-1:0]; |
| 145 | |
| 146 | // Errors ==================================================================== |
| 147 | |
| 148 | // err_valid goes high if there is a new error this cycle. This causes the |
| 149 | // register block to take a new error code (stored as ERR_CODE) and triggers |
| 150 | // an interrupt. To ensure software on the host CPU only sees the first event |
| 151 | // in a series, err_valid is squashed if there is an existing error. Software |
| 152 | // should read the ERR_CODE register before clearing the interrupt to avoid |
| 153 | // race conditions. |
| 154 | assign err_valid = ~reg2hw.intr_state.err.q & |
| 155 | (1'b0); // TODO: OR error signals here. |
| 156 | |
| 157 | always_comb begin |
| 158 | err_code = ErrCodeNoError; |
| 159 | unique case (1'b1) |
| 160 | // TODO: Add more errors here. |
| 161 | |
| 162 | default: begin |
| 163 | err_code = ErrCodeNoError; |
| 164 | end |
| 165 | endcase |
| 166 | end |
| 167 | |
| 168 | // Instruction Memory (IMEM) ================================================= |
| 169 | |
Michael Schaffner | 82a936e | 2020-07-13 16:52:38 -0700 | [diff] [blame] | 170 | localparam int ImemSizeWords = ImemSizeByte / 4; |
| 171 | localparam int ImemIndexWidth = vbits(ImemSizeWords); |
Philipp Wagner | 5c2d294 | 2020-06-22 11:34:00 +0100 | [diff] [blame] | 172 | |
| 173 | // Access select to IMEM: core (1), or bus (0) |
| 174 | logic imem_access_core; |
| 175 | |
| 176 | logic imem_req; |
| 177 | logic imem_write; |
| 178 | logic [ImemIndexWidth-1:0] imem_index; |
| 179 | logic [31:0] imem_wdata; |
| 180 | logic [31:0] imem_wmask; |
| 181 | logic [31:0] imem_rdata; |
| 182 | logic imem_rvalid; |
| 183 | logic [1:0] imem_rerror; |
| 184 | |
| 185 | logic imem_req_core; |
| 186 | logic imem_write_core; |
| 187 | logic [ImemIndexWidth-1:0] imem_index_core; |
| 188 | logic [31:0] imem_wdata_core; |
Philipp Wagner | 5c2d294 | 2020-06-22 11:34:00 +0100 | [diff] [blame] | 189 | logic [31:0] imem_rdata_core; |
| 190 | logic imem_rvalid_core; |
| 191 | logic [1:0] imem_rerror_core; |
| 192 | |
| 193 | logic imem_req_bus; |
| 194 | logic imem_write_bus; |
| 195 | logic [ImemIndexWidth-1:0] imem_index_bus; |
| 196 | logic [31:0] imem_wdata_bus; |
| 197 | logic [31:0] imem_wmask_bus; |
| 198 | logic [31:0] imem_rdata_bus; |
| 199 | logic imem_rvalid_bus; |
| 200 | logic [1:0] imem_rerror_bus; |
| 201 | |
| 202 | logic [ImemAddrWidth-1:0] imem_addr_core; |
| 203 | assign imem_index_core = imem_addr_core[ImemAddrWidth-1:2]; |
| 204 | |
| 205 | logic [1:0] unused_imem_addr_core_wordbits; |
| 206 | assign unused_imem_addr_core_wordbits = imem_addr_core[1:0]; |
| 207 | |
| 208 | prim_ram_1p_adv #( |
| 209 | .Width (32), |
| 210 | .Depth (ImemSizeWords), |
| 211 | .DataBitsPerMask (32), // Write masks are not supported. |
| 212 | .CfgW (8) |
| 213 | ) u_imem ( |
| 214 | .clk_i, |
| 215 | .rst_ni, |
| 216 | .req_i (imem_req), |
| 217 | .write_i (imem_write), |
| 218 | .addr_i (imem_index), |
| 219 | .wdata_i (imem_wdata), |
| 220 | .wmask_i (imem_wmask), |
| 221 | .rdata_o (imem_rdata), |
| 222 | .rvalid_o (imem_rvalid), |
| 223 | .rerror_o (imem_rerror), |
| 224 | .cfg_i ('0) |
| 225 | ); |
| 226 | |
| 227 | // IMEM access from main TL-UL bus |
| 228 | logic imem_gnt_bus; |
| 229 | assign imem_gnt_bus = imem_req_bus & ~imem_access_core; |
| 230 | |
| 231 | tlul_adapter_sram #( |
| 232 | .SramAw (ImemIndexWidth), |
| 233 | .SramDw (32), |
| 234 | .Outstanding (1), |
| 235 | .ByteAccess (0), |
| 236 | .ErrOnRead (0) |
| 237 | ) u_tlul_adapter_sram_imem ( |
| 238 | .clk_i, |
| 239 | .rst_ni, |
| 240 | .tl_i (tl_win_h2d[TlWinImem]), |
| 241 | .tl_o (tl_win_d2h[TlWinImem]), |
| 242 | |
| 243 | .req_o (imem_req_bus ), |
| 244 | .gnt_i (imem_gnt_bus ), |
| 245 | .we_o (imem_write_bus ), |
| 246 | .addr_o (imem_index_bus ), |
| 247 | .wdata_o (imem_wdata_bus ), |
| 248 | .wmask_o (imem_wmask_bus ), |
| 249 | .rdata_i (imem_rdata_bus ), |
| 250 | .rvalid_i (imem_rvalid_bus), |
| 251 | .rerror_i (imem_rerror_bus) |
| 252 | ); |
| 253 | |
| 254 | // Mux core and bus access into IMEM |
| 255 | assign imem_access_core = busy_q; |
| 256 | |
| 257 | assign imem_req = imem_access_core ? imem_req_core : imem_req_bus; |
| 258 | assign imem_write = imem_access_core ? imem_write_core : imem_write_bus; |
| 259 | assign imem_index = imem_access_core ? imem_index_core : imem_index_bus; |
| 260 | assign imem_wdata = imem_access_core ? imem_wdata_core : imem_wdata_bus; |
| 261 | |
Rupert Swarbrick | d54a450 | 2020-07-10 12:06:53 +0100 | [diff] [blame] | 262 | // The instruction memory only supports 32b word writes, so we hardcode its |
| 263 | // wmask here. |
| 264 | // |
| 265 | // Since this could cause confusion if the bus tried to do a partial write |
| 266 | // (which wasn't caught in the TLUL adapter for some reason), we assert that |
| 267 | // the wmask signal from the bus is indeed '1 when it requests a write. We |
| 268 | // don't have the corresponding check for writes from the core because the |
| 269 | // core cannot perform writes (and has no imem_wmask_o port). |
Philipp Wagner | 5c2d294 | 2020-06-22 11:34:00 +0100 | [diff] [blame] | 270 | assign imem_wmask = 32'hFFFFFFFF; |
Philipp Wagner | 5c2d294 | 2020-06-22 11:34:00 +0100 | [diff] [blame] | 271 | `ASSERT(ImemWmaskBusIsFullWord_A, |
Rupert Swarbrick | d54a450 | 2020-07-10 12:06:53 +0100 | [diff] [blame] | 272 | imem_req_bus && imem_write_bus |-> imem_wmask_bus == 32'hFFFFFFFF) |
Philipp Wagner | 5c2d294 | 2020-06-22 11:34:00 +0100 | [diff] [blame] | 273 | |
| 274 | // Explicitly tie off bus interface during core operation to avoid leaking |
| 275 | // the currently executed instruction from IMEM through the bus |
| 276 | // unintentionally. |
| 277 | assign imem_rdata_bus = !imem_access_core ? imem_rdata : 32'b0; |
| 278 | assign imem_rdata_core = imem_rdata; |
| 279 | |
| 280 | assign imem_rvalid_bus = !imem_access_core ? imem_rvalid : 1'b0; |
| 281 | assign imem_rvalid_core = imem_access_core ? imem_rvalid : 1'b0; |
| 282 | |
| 283 | // Since rerror depends on rvalid we could save this mux, but could |
| 284 | // potentially leak rerror to the bus. Err on the side of caution. |
| 285 | assign imem_rerror_bus = !imem_access_core ? imem_rerror : 2'b00; |
| 286 | assign imem_rerror_core = imem_rerror; |
| 287 | |
| 288 | |
| 289 | // Data Memory (DMEM) ======================================================== |
| 290 | |
Michael Schaffner | 82a936e | 2020-07-13 16:52:38 -0700 | [diff] [blame] | 291 | localparam int DmemSizeWords = DmemSizeByte / (WLEN / 8); |
| 292 | localparam int DmemIndexWidth = vbits(DmemSizeWords); |
Philipp Wagner | 5c2d294 | 2020-06-22 11:34:00 +0100 | [diff] [blame] | 293 | |
| 294 | // Access select to DMEM: core (1), or bus (0) |
| 295 | logic dmem_access_core; |
| 296 | |
| 297 | logic dmem_req; |
| 298 | logic dmem_write; |
| 299 | logic [DmemIndexWidth-1:0] dmem_index; |
| 300 | logic [WLEN-1:0] dmem_wdata; |
| 301 | logic [WLEN-1:0] dmem_wmask; |
| 302 | logic [WLEN-1:0] dmem_rdata; |
| 303 | logic dmem_rvalid; |
| 304 | logic [1:0] dmem_rerror; |
| 305 | |
| 306 | logic dmem_req_core; |
| 307 | logic dmem_write_core; |
| 308 | logic [DmemIndexWidth-1:0] dmem_index_core; |
| 309 | logic [WLEN-1:0] dmem_wdata_core; |
| 310 | logic [WLEN-1:0] dmem_wmask_core; |
| 311 | logic [WLEN-1:0] dmem_rdata_core; |
| 312 | logic dmem_rvalid_core; |
| 313 | logic [1:0] dmem_rerror_core; |
| 314 | |
| 315 | logic dmem_req_bus; |
| 316 | logic dmem_write_bus; |
| 317 | logic [DmemIndexWidth-1:0] dmem_index_bus; |
| 318 | logic [WLEN-1:0] dmem_wdata_bus; |
| 319 | logic [WLEN-1:0] dmem_wmask_bus; |
| 320 | logic [WLEN-1:0] dmem_rdata_bus; |
| 321 | logic dmem_rvalid_bus; |
| 322 | logic [1:0] dmem_rerror_bus; |
| 323 | |
| 324 | logic [DmemAddrWidth-1:0] dmem_addr_core; |
| 325 | assign dmem_index_core = dmem_addr_core[DmemAddrWidth-1:DmemAddrWidth-DmemIndexWidth]; |
| 326 | |
| 327 | prim_ram_1p_adv #( |
| 328 | .Width (WLEN), |
| 329 | .Depth (DmemSizeWords), |
| 330 | .DataBitsPerMask (32), // 32b write masks for 32b word writes from bus |
| 331 | .CfgW (8) |
| 332 | ) u_dmem ( |
| 333 | .clk_i, |
| 334 | .rst_ni, |
| 335 | .req_i (dmem_req), |
| 336 | .write_i (dmem_write), |
| 337 | .addr_i (dmem_index), |
| 338 | .wdata_i (dmem_wdata), |
| 339 | .wmask_i (dmem_wmask), |
| 340 | .rdata_o (dmem_rdata), |
| 341 | .rvalid_o (dmem_rvalid), |
| 342 | .rerror_o (dmem_rerror), |
| 343 | .cfg_i ('0) |
| 344 | ); |
| 345 | |
| 346 | // DMEM access from main TL-UL bus |
| 347 | logic dmem_gnt_bus; |
| 348 | assign dmem_gnt_bus = dmem_req_bus & ~dmem_access_core; |
| 349 | |
| 350 | tlul_adapter_sram #( |
| 351 | .SramAw (DmemIndexWidth), |
| 352 | .SramDw (WLEN), |
| 353 | .Outstanding (1), |
| 354 | .ByteAccess (0), |
| 355 | .ErrOnRead (0) |
| 356 | ) u_tlul_adapter_sram_dmem ( |
| 357 | .clk_i, |
| 358 | .rst_ni, |
| 359 | |
| 360 | .tl_i (tl_win_h2d[TlWinDmem]), |
| 361 | .tl_o (tl_win_d2h[TlWinDmem]), |
| 362 | |
| 363 | .req_o (dmem_req_bus ), |
| 364 | .gnt_i (dmem_gnt_bus ), |
| 365 | .we_o (dmem_write_bus ), |
| 366 | .addr_o (dmem_index_bus ), |
| 367 | .wdata_o (dmem_wdata_bus ), |
| 368 | .wmask_o (dmem_wmask_bus ), |
| 369 | .rdata_i (dmem_rdata_bus ), |
| 370 | .rvalid_i (dmem_rvalid_bus), |
| 371 | .rerror_i (dmem_rerror_bus) |
| 372 | ); |
| 373 | |
| 374 | // Mux core and bus access into dmem |
| 375 | assign dmem_access_core = busy_q; |
| 376 | |
| 377 | assign dmem_req = dmem_access_core ? dmem_req_core : dmem_req_bus; |
| 378 | assign dmem_write = dmem_access_core ? dmem_write_core : dmem_write_bus; |
| 379 | assign dmem_wmask = dmem_access_core ? dmem_wmask_core : dmem_wmask_bus; |
| 380 | assign dmem_index = dmem_access_core ? dmem_index_core : dmem_index_bus; |
| 381 | assign dmem_wdata = dmem_access_core ? dmem_wdata_core : dmem_wdata_bus; |
| 382 | |
| 383 | // Explicitly tie off bus interface during core operation to avoid leaking |
| 384 | // DMEM data through the bus unintentionally. |
| 385 | assign dmem_rdata_bus = !dmem_access_core ? dmem_rdata : '0; |
| 386 | assign dmem_rdata_core = dmem_rdata; |
| 387 | |
| 388 | assign dmem_rvalid_bus = !dmem_access_core ? dmem_rvalid : 1'b0; |
| 389 | assign dmem_rvalid_core = dmem_access_core ? dmem_rvalid : 1'b0; |
| 390 | |
| 391 | // Since rerror depends on rvalid we could save this mux, but could |
| 392 | // potentially leak rerror to the bus. Err on the side of caution. |
| 393 | assign dmem_rerror_bus = !dmem_access_core ? dmem_rerror : 2'b00; |
| 394 | assign dmem_rerror_core = dmem_rerror; |
| 395 | |
| 396 | |
| 397 | // Alerts ==================================================================== |
| 398 | |
| 399 | logic [NumAlerts-1:0] alerts; |
| 400 | assign alerts[AlertImemUncorrectable] = imem_rerror[1]; |
| 401 | assign alerts[AlertDmemUncorrectable] = dmem_rerror[1]; |
| 402 | assign alerts[AlertRegUncorrectable] = 1'b0; // TODO: Implement |
| 403 | for (genvar i = 0; i < NumAlerts; i++) begin: gen_alert_tx |
| 404 | prim_alert_sender #( |
| 405 | .AsyncOn(AlertAsyncOn[i]) |
| 406 | ) i_prim_alert_sender ( |
| 407 | .clk_i, |
| 408 | .rst_ni, |
| 409 | .alert_i (alerts[i] ), |
| 410 | .alert_rx_i (alert_rx_i[i]), |
| 411 | .alert_tx_o (alert_tx_o[i]) |
| 412 | ); |
| 413 | end |
| 414 | |
| 415 | |
| 416 | // OTBN Core ================================================================= |
| 417 | |
| 418 | always_ff @(posedge clk_i or negedge rst_ni) begin |
| 419 | if (!rst_ni) begin |
| 420 | busy_q <= 1'b0; |
| 421 | end else begin |
| 422 | busy_q <= busy_d; |
| 423 | end |
| 424 | end |
| 425 | assign busy_d = (busy_q | start) & ~done; |
| 426 | |
Stefan Wallentowitz | 7fe6abc | 2020-06-25 11:05:29 +0200 | [diff] [blame] | 427 | if (OTBNModel) begin : gen_impl_model |
Rupert Swarbrick | 4c7b023 | 2020-09-23 17:19:56 +0100 | [diff] [blame] | 428 | localparam ImemScope = "..u_imem.u_mem.gen_generic.u_impl_generic"; |
| 429 | localparam DmemScope = "..u_dmem.u_mem.gen_generic.u_impl_generic"; |
Philipp Wagner | 5c2d294 | 2020-06-22 11:34:00 +0100 | [diff] [blame] | 430 | |
Stefan Wallentowitz | 7fe6abc | 2020-06-25 11:05:29 +0200 | [diff] [blame] | 431 | otbn_core_model #( |
| 432 | .DmemSizeByte(DmemSizeByte), |
| 433 | .ImemSizeByte(ImemSizeByte), |
| 434 | .DmemScope(DmemScope), |
Rupert Swarbrick | 913a483 | 2020-09-18 15:00:45 +0100 | [diff] [blame] | 435 | .ImemScope(ImemScope), |
| 436 | .StandaloneModel(1'b1) |
Stefan Wallentowitz | 7fe6abc | 2020-06-25 11:05:29 +0200 | [diff] [blame] | 437 | ) u_otbn_core_model ( |
| 438 | .clk_i, |
| 439 | .rst_ni, |
Philipp Wagner | 5c2d294 | 2020-06-22 11:34:00 +0100 | [diff] [blame] | 440 | |
Stefan Wallentowitz | 7fe6abc | 2020-06-25 11:05:29 +0200 | [diff] [blame] | 441 | .start_i (start), |
| 442 | .done_o (done), |
Philipp Wagner | 5c2d294 | 2020-06-22 11:34:00 +0100 | [diff] [blame] | 443 | |
Rupert Swarbrick | e2eb476 | 2020-09-08 14:40:18 +0100 | [diff] [blame] | 444 | .start_addr_i (start_addr) |
Stefan Wallentowitz | 7fe6abc | 2020-06-25 11:05:29 +0200 | [diff] [blame] | 445 | ); |
| 446 | end else begin : gen_impl_rtl |
| 447 | otbn_core #( |
Pirmin Vogel | 69b55a8 | 2020-10-01 09:54:39 +0200 | [diff] [blame] | 448 | .RegFile(RegFile), |
Stefan Wallentowitz | 7fe6abc | 2020-06-25 11:05:29 +0200 | [diff] [blame] | 449 | .DmemSizeByte(DmemSizeByte), |
| 450 | .ImemSizeByte(ImemSizeByte) |
| 451 | ) u_otbn_core ( |
| 452 | .clk_i, |
| 453 | .rst_ni, |
| 454 | |
| 455 | .start_i (start), |
| 456 | .done_o (done), |
| 457 | |
| 458 | .start_addr_i (start_addr), |
| 459 | |
| 460 | .imem_req_o (imem_req_core), |
| 461 | .imem_addr_o (imem_addr_core), |
| 462 | .imem_wdata_o (imem_wdata_core), |
| 463 | .imem_rdata_i (imem_rdata_core), |
| 464 | .imem_rvalid_i (imem_rvalid_core), |
| 465 | .imem_rerror_i (imem_rerror_core), |
| 466 | |
| 467 | .dmem_req_o (dmem_req_core), |
| 468 | .dmem_write_o (dmem_write_core), |
| 469 | .dmem_addr_o (dmem_addr_core), |
| 470 | .dmem_wdata_o (dmem_wdata_core), |
| 471 | .dmem_wmask_o (dmem_wmask_core), |
| 472 | .dmem_rdata_i (dmem_rdata_core), |
| 473 | .dmem_rvalid_i (dmem_rvalid_core), |
| 474 | .dmem_rerror_i (dmem_rerror_core) |
| 475 | ); |
| 476 | end |
Philipp Wagner | 5c2d294 | 2020-06-22 11:34:00 +0100 | [diff] [blame] | 477 | |
Rupert Swarbrick | d54a450 | 2020-07-10 12:06:53 +0100 | [diff] [blame] | 478 | // The core can never signal a write to IMEM |
| 479 | assign imem_write_core = 1'b0; |
Philipp Wagner | 5c2d294 | 2020-06-22 11:34:00 +0100 | [diff] [blame] | 480 | |
| 481 | // LFSR ====================================================================== |
| 482 | |
| 483 | // TODO: Potentially insert local LFSR, or use output from RNG distribution |
| 484 | // network directly, depending on availability. Revisit once CSRNG interface |
| 485 | // is known (#2638). |
| 486 | |
| 487 | |
| 488 | // Asserts =================================================================== |
| 489 | |
| 490 | // All outputs should be known value after reset |
| 491 | `ASSERT_KNOWN(TlODValidKnown_A, tl_o.d_valid) |
| 492 | `ASSERT_KNOWN(TlOAReadyKnown_A, tl_o.a_ready) |
| 493 | `ASSERT_KNOWN(IntrDoneOKnown_A, intr_done_o) |
| 494 | `ASSERT_KNOWN(IntrErrOKnown_A, intr_err_o) |
| 495 | `ASSERT_KNOWN(AlertTxOKnown_A, alert_tx_o) |
Philipp Wagner | b4c1c8b | 2020-09-17 15:53:40 +0100 | [diff] [blame] | 496 | `ASSERT_KNOWN(IdleOKnown_A, idle_o) |
Philipp Wagner | 5c2d294 | 2020-06-22 11:34:00 +0100 | [diff] [blame] | 497 | |
| 498 | endmodule |