../src/lowrisc_ip_spi_device_0.1/rtl/spi_device.sv Cov: 100%

   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: // Serial Peripheral Interface (SPI) Device module.
   6: //
   7: //
   8: 
   9: `include "prim_assert.sv"
  10: 
  11: module spi_device #(
  12:   parameter int SramAw = 9, // 2kB, SRAM Width is DW
  13:   parameter int SramDw = 32
  14: ) (
  15:   input clk_i,
  16:   input rst_ni,
  17: 
  18:   // Register interface
  19:   input  tlul_pkg::tl_h2d_t tl_i,
  20:   output tlul_pkg::tl_d2h_t tl_o,
  21: 
  22:   // SPI Interface
  23:   input              cio_sck_i,
  24:   input              cio_csb_i,
  25:   output logic       cio_miso_o,
  26:   output logic       cio_miso_en_o,
  27:   input              cio_mosi_i,
  28: 
  29:   // Interrupts
  30:   output logic intr_rxf_o,         // RX FIFO Full
  31:   output logic intr_rxlvl_o,       // RX FIFO above level
  32:   output logic intr_txlvl_o,       // TX FIFO below level
  33:   output logic intr_rxerr_o,       // RX Frame error
  34:   output logic intr_rxoverflow_o,  // RX Async FIFO Overflow
  35:   output logic intr_txunderflow_o, // TX Async FIFO Underflow
  36: 
  37:   input scanmode_i
  38: );
  39: 
  40:   import spi_device_pkg::*;
  41:   import spi_device_reg_pkg::*;
  42: 
  43:   localparam int FifoWidth = $bits(spi_byte_t);
  44:   localparam int FifoDepth = 8; // 2 DWords
  45:   localparam int SDW = $clog2(SramDw/FifoWidth);
  46:   localparam int PtrW = SramAw + 1 + SDW;
  47:   localparam int AsFifoDepthW = $clog2(FifoDepth+1);
  48: 
  49:   logic clk_spi_in;   // clock for latch MOSI
  50:   logic clk_spi_out;  // clock for driving MISO
  51: 
  52:   spi_device_reg2hw_t reg2hw;
  53:   spi_device_hw2reg_t hw2reg;
  54: 
  55:   tlul_pkg::tl_h2d_t tl_sram_h2d [1];
  56:   tlul_pkg::tl_d2h_t tl_sram_d2h [1];
  57: 
  58:   // Dual-port SRAM Interface: Refer prim_ram_2p_wrapper.sv
  59:   logic              mem_a_req;
  60:   logic              mem_a_write;
  61:   logic [SramAw-1:0] mem_a_addr;
  62:   logic [SramDw-1:0] mem_a_wdata;
  63:   logic              mem_a_rvalid;
  64:   logic [SramDw-1:0] mem_a_rdata;
  65:   logic [1:0]        mem_a_rerror;
  66: 
  67:   logic              mem_b_req;
  68:   logic              mem_b_write;
  69:   logic [SramAw-1:0] mem_b_addr;
  70:   logic [SramDw-1:0] mem_b_wdata;
  71:   logic              mem_b_rvalid;
  72:   logic [SramDw-1:0] mem_b_rdata;
  73:   logic [1:0]        mem_b_rerror;
  74: 
  75:   /////////////////////
  76:   // Control signals //
  77:   /////////////////////
  78: 
  79:   logic cpol; // Clock polarity
  80:   logic cpha; // Phase : Not complete
  81:   logic txorder; // TX bitstream order: 0(bit 7 to 0), 1(bit 0 to 7)
  82:   logic rxorder; // RX bitstream order: 0(bit 7 to 0), 1(bit 0 to 7)
  83: 
  84:   logic abort;  // Abort current operations (txf only at this time)
  85:                 // Think how FW knows abort is done.
  86:   //logic abort_done; // TODO: Not implemented yet
  87: 
  88:   logic csb_syncd;
  89: 
  90:   logic rst_txfifo_n, rst_rxfifo_n;
  91:   logic rst_txfifo_reg, rst_rxfifo_reg;
  92: 
  93:   //spi_addr_size_e addr_size; // Not used in fwmode
  94:   spi_mode_e spi_mode;
  95:   //spi_byte_t fw_dummy_byte;
  96: 
  97:   logic intr_sram_rxf_full, intr_fwm_rxerr;
  98:   logic intr_fwm_rxlvl, rxlvl, rxlvl_d, intr_fwm_txlvl, txlvl, txlvl_d;
  99:   logic intr_fwm_rxoverflow, intr_fwm_txunderflow;
 100: 
 101:   // RX Async FIFO Signals
 102:   //  Write: SCK positive edge
 103:   logic      rxf_wvalid, rxf_wready;
 104:   spi_byte_t rxf_wdata;
 105:   logic      rxf_overflow;
 106:   //  Read: Main clock
 107:   logic      rxf_rvalid, rxf_rready;
 108:   spi_byte_t rxf_rdata;
 109:   logic      rxf_full_syncd;
 110: 
 111:   // TX Async FIFO Signals
 112:   //   Read: SCK negative edge
 113:   logic      txf_rvalid, txf_rready;
 114:   spi_byte_t txf_rdata;
 115:   logic      txf_underflow;
 116:   //   Write: Main clock
 117:   logic      txf_wvalid, txf_wready;
 118:   spi_byte_t txf_wdata;
 119:   logic      txf_empty_syncd;
 120: 
 121:   // SRAM FIFO control
 122:   typedef enum int {
 123:     FwModeRxFifo = 0,
 124:     FwModeTxFifo = 1
 125:   } fwm_fifo_e;
 126:   logic        [7:0] timer_v;   // Wait timer inside rxf control
 127:   logic   [PtrW-1:0] sram_rxf_rptr, sram_rxf_wptr;
 128:   logic   [PtrW-1:0] sram_txf_rptr, sram_txf_wptr;
 129:   logic   [PtrW-1:0] sram_rxf_depth, sram_txf_depth;
 130: 
 131:   logic [SramAw-1:0] sram_rxf_bindex, sram_txf_bindex;
 132:   logic [SramAw-1:0] sram_rxf_lindex, sram_txf_lindex;
 133:   logic        [1:0] fwm_sram_req;
 134:   logic [SramAw-1:0] fwm_sram_addr  [2];
 135:   logic              fwm_sram_write [2];
 136:   logic [SramDw-1:0] fwm_sram_wdata [2];
 137:   logic        [1:0] fwm_sram_gnt;
 138:   logic        [1:0] fwm_sram_rvalid;    // RXF doesn't use
 139:   logic [SramDw-1:0] fwm_sram_rdata [2]; // RXF doesn't use
 140:   logic        [1:0] fwm_sram_error [2];
 141: 
 142:   logic [AsFifoDepthW-1:0] as_txfifo_depth, as_rxfifo_depth;
 143: 
 144: 
 145:   //////////////////////////////////////////////////////////////////////
 146:   // Connect phase (between control signals above and register module //
 147:   //////////////////////////////////////////////////////////////////////
 148: 
 149:   assign cpol = reg2hw.cfg.cpol.q;
 150:   assign cpha = reg2hw.cfg.cpha.q;
 151:   assign txorder = reg2hw.cfg.tx_order.q;
 152:   assign rxorder = reg2hw.cfg.rx_order.q;
 153: 
 154:   assign rst_txfifo_reg = reg2hw.control.rst_txfifo.q;
 155:   assign rst_rxfifo_reg = reg2hw.control.rst_rxfifo.q;
 156: 
 157:   assign timer_v = reg2hw.cfg.timer_v.q;
 158: 
 159:   assign sram_rxf_bindex = reg2hw.rxf_addr.base.q[SDW+:SramAw];
 160:   assign sram_rxf_lindex = reg2hw.rxf_addr.limit.q[SDW+:SramAw];
 161:   assign sram_txf_bindex = reg2hw.txf_addr.base.q[SDW+:SramAw];
 162:   assign sram_txf_lindex = reg2hw.txf_addr.limit.q[SDW+:SramAw];
 163: 
 164:   assign sram_rxf_rptr = reg2hw.rxf_ptr.rptr.q[PtrW-1:0];
 165:   assign hw2reg.rxf_ptr.wptr.d = {{(16-PtrW){1'b0}}, sram_rxf_wptr};
 166:   assign hw2reg.rxf_ptr.wptr.de = 1'b1;
 167: 
 168:   assign sram_txf_wptr = reg2hw.txf_ptr.wptr.q[PtrW-1:0];
 169:   assign hw2reg.txf_ptr.rptr.d = {{(16-PtrW){1'b0}}, sram_txf_rptr};
 170:   assign hw2reg.txf_ptr.rptr.de = 1'b1;
 171: 
 172:   assign abort = reg2hw.control.abort.q;
 173:   assign hw2reg.status.abort_done.d  = 1'b1;
 174: 
 175:   assign hw2reg.status.rxf_empty.d = ~rxf_rvalid;
 176:   assign hw2reg.status.txf_full.d  = ~txf_wready;
 177: 
 178:   // SYNC logic required
 179:   assign hw2reg.status.rxf_full.d = rxf_full_syncd;
 180:   assign hw2reg.status.txf_empty.d = txf_empty_syncd;
 181: 
 182:   // CSb : after 2stage synchronizer
 183:   assign hw2reg.status.csb.d = csb_syncd;
 184:   prim_flop_2sync #(.Width(1)) u_sync_csb (
 185:     .clk_i,
 186:     .rst_ni,
 187:     .d(cio_csb_i),
 188:     .q(csb_syncd)
 189:   );
 190: 
 191:   logic rxf_full_q, txf_empty_q;
 192:   always_ff @(posedge clk_spi_in or negedge rst_ni) begin
 193:     if (!rst_ni) rxf_full_q <= 1'b0;
 194:     else         rxf_full_q <= ~rxf_wready;
 195:   end
 196:   always_ff @(posedge clk_spi_out or negedge rst_ni) begin
 197:     if (!rst_ni) txf_empty_q <= 1'b1;
 198:     else         txf_empty_q <= ~txf_rvalid;
 199:   end
 200:   prim_flop_2sync #(.Width(1)) u_sync_rxf (
 201:     .clk_i,
 202:     .rst_ni,
 203:     .d(rxf_full_q),
 204:     .q(rxf_full_syncd)
 205:   );
 206:   prim_flop_2sync #(.Width(1), .ResetValue(1'b1)) u_sync_txe (
 207:     .clk_i,
 208:     .rst_ni,
 209:     .d(txf_empty_q),
 210:     .q(txf_empty_syncd)
 211:   );
 212: 
 213:   assign spi_mode = spi_mode_e'(reg2hw.control.mode.q);
 214: 
 215:   // Async FIFO level
 216:   //  rx rdepth, tx wdepth to be in main clock domain
 217:   assign hw2reg.async_fifo_level.txlvl.d  = {{(8-AsFifoDepthW){1'b0}}, as_txfifo_depth};
 218:   assign hw2reg.async_fifo_level.rxlvl.d  = {{(8-AsFifoDepthW){1'b0}}, as_rxfifo_depth};
 219: 
 220:   // Interrupt
 221: 
 222:   // Edge
 223:   logic sram_rxf_full_q, fwm_rxerr_q;
 224:   logic sram_rxf_full  , fwm_rxerr  ;
 225: 
 226:   // TODO: Check if CE# deasserted in the middle of bit transfer
 227:   assign fwm_rxerr = 1'b0;
 228: 
 229:   always_ff @(posedge clk_i or negedge rst_ni) begin
 230:     if (!rst_ni) begin
 231:       sram_rxf_full_q <= 1'b0;
 232:       fwm_rxerr_q     <= 1'b0;
 233:     end else begin
 234:       sram_rxf_full_q <= sram_rxf_full;
 235:       fwm_rxerr_q     <= fwm_rxerr;
 236:     end
 237:   end
 238: 
 239:   // Interrupt
 240:   assign intr_sram_rxf_full = ~sram_rxf_full_q & sram_rxf_full;
 241:   assign intr_fwm_rxerr     = ~fwm_rxerr_q & fwm_rxerr;
 242: 
 243:   assign rxlvl_d = (sram_rxf_depth >= reg2hw.fifo_level.rxlvl.q[PtrW-1:0]) ;
 244:   assign txlvl_d = (sram_txf_depth <  reg2hw.fifo_level.txlvl.q[PtrW-1:0]) ;
 245: 
 246:   always_ff @(posedge clk_i or negedge rst_ni) begin
 247:     if (!rst_ni) begin
 248:       rxlvl <= 1'b0;
 249:       txlvl <= 1'b0;
 250:     end else begin
 251:       rxlvl <= rxlvl_d;
 252:       txlvl <= txlvl_d;
 253:     end
 254:   end
 255:   assign intr_fwm_rxlvl = ~rxlvl && rxlvl_d;
 256:   assign intr_fwm_txlvl = ~txlvl && txlvl_d;
 257: 
 258:   // rxf_overflow
 259:   //    Could trigger lint error for input clock.
 260:   //    It's unavoidable due to the characteristics of SPI intf
 261:   prim_pulse_sync u_rxf_overflow (
 262:     .clk_src_i   (clk_spi_in         ),
 263:     .rst_src_ni  (rst_ni             ),
 264:     .src_pulse_i (rxf_overflow       ),
 265:     .clk_dst_i   (clk_i              ),
 266:     .rst_dst_ni  (rst_ni             ),
 267:     .dst_pulse_o (intr_fwm_rxoverflow)
 268:   );
 269: 
 270:   // txf_underflow
 271:   //    Could trigger lint error for input clock.
 272:   //    It's unavoidable due to the characteristics of SPI intf
 273:   prim_pulse_sync u_txf_underflow (
 274:     .clk_src_i   (clk_spi_out         ),
 275:     .rst_src_ni  (rst_ni              ),
 276:     .src_pulse_i (txf_underflow       ),
 277:     .clk_dst_i   (clk_i               ),
 278:     .rst_dst_ni  (rst_ni              ),
 279:     .dst_pulse_o (intr_fwm_txunderflow)
 280:   );
 281: 
 282:   assign intr_rxlvl_o       = reg2hw.intr_enable.rxlvl.q       & reg2hw.intr_state.rxlvl.q;
 283:   assign intr_txlvl_o       = reg2hw.intr_enable.txlvl.q       & reg2hw.intr_state.txlvl.q;
 284:   assign intr_rxf_o         = reg2hw.intr_enable.rxf.q         & reg2hw.intr_state.rxf.q;
 285:   assign intr_rxerr_o       = reg2hw.intr_enable.rxerr.q       & reg2hw.intr_state.rxerr.q;
 286:   assign intr_rxoverflow_o  = reg2hw.intr_enable.rxoverflow.q  & reg2hw.intr_state.rxoverflow.q;
 287:   assign intr_txunderflow_o = reg2hw.intr_enable.txunderflow.q & reg2hw.intr_state.txunderflow.q;
 288: 
 289:   assign hw2reg.intr_state.rxf.d    = 1'b1;
 290:   assign hw2reg.intr_state.rxf.de   = intr_sram_rxf_full |
 291:                                       (reg2hw.intr_test.rxf.qe   & reg2hw.intr_test.rxf.q);
 292:   assign hw2reg.intr_state.rxerr.d  = 1'b1;
 293:   assign hw2reg.intr_state.rxerr.de = intr_fwm_rxerr |
 294:                                       (reg2hw.intr_test.rxerr.qe & reg2hw.intr_test.rxerr.q);
 295:   assign hw2reg.intr_state.rxlvl.d  = 1'b1;
 296:   assign hw2reg.intr_state.rxlvl.de = intr_fwm_rxlvl |
 297:                                       (reg2hw.intr_test.rxlvl.qe & reg2hw.intr_test.rxlvl.q);
 298:   assign hw2reg.intr_state.txlvl.d  = 1'b1;
 299:   assign hw2reg.intr_state.txlvl.de = intr_fwm_txlvl |
 300:                                       (reg2hw.intr_test.txlvl.qe & reg2hw.intr_test.txlvl.q);
 301:   assign hw2reg.intr_state.rxoverflow.d   = 1'b1;
 302:   assign hw2reg.intr_state.rxoverflow.de  = intr_fwm_rxoverflow |
 303:       (reg2hw.intr_test.rxoverflow.qe  & reg2hw.intr_test.rxoverflow.q);
 304:   assign hw2reg.intr_state.txunderflow.d  = 1'b1;
 305:   assign hw2reg.intr_state.txunderflow.de = intr_fwm_txunderflow |
 306:       (reg2hw.intr_test.txunderflow.qe & reg2hw.intr_test.txunderflow.q);
 307: 
 308:   //////////////////////////////
 309:   // // Clock & reset control //
 310:   //////////////////////////////
 311:   //  clk_spi cannot use glitch-free clock mux as clock switching in glitch-free
 312:   //  requires two clocks to propagate clock selection and enable but SPI clock
 313:   //  doesn't exist until it transmits data through MOSI
 314:   logic sck_n;
 315:   logic rst_spi_n;
 316: 
 317:   prim_clock_inverter u_clk_spi (.clk_i(cio_sck_i), .clk_no(sck_n), .scanmode_i);
 318:   assign clk_spi_in  = (cpha ^ cpol) ? sck_n    : cio_sck_i   ;
 319:   assign clk_spi_out = (cpha ^ cpol) ? cio_sck_i    : sck_n   ;
 320: 
 321:   assign rst_spi_n = (scanmode_i) ? rst_ni : rst_ni & ~cio_csb_i;
 322: 
 323:   assign rst_txfifo_n = (scanmode_i) ? rst_ni : rst_ni & ~rst_txfifo_reg;
 324:   assign rst_rxfifo_n = (scanmode_i) ? rst_ni : rst_ni & ~rst_rxfifo_reg;
 325: 
 326: 
 327:   /////////////
 328:   // FW Mode //
 329:   /////////////
 330:   spi_fwmode u_fwmode (
 331:     .clk_in_i     (clk_spi_in),
 332:     .rst_in_ni    (rst_spi_n),
 333: 
 334:     .clk_out_i    (clk_spi_out),
 335:     .rst_out_ni   (rst_spi_n),
 336: 
 337:     .cpha_i        (cpha),
 338:     .cfg_rxorder_i (rxorder),
 339:     .cfg_txorder_i (txorder),
 340: 
 341:     .mode_i        (spi_mode),
 342: 
 343:     .rx_wvalid_o   (rxf_wvalid),
 344:     .rx_wready_i   (rxf_wready),
 345:     .rx_data_o     (rxf_wdata),
 346: 
 347:     .tx_rvalid_i   (txf_rvalid),
 348:     .tx_rready_o   (txf_rready),
 349:     .tx_data_i     (txf_rdata),
 350: 
 351:     .rx_overflow_o  (rxf_overflow),
 352:     .tx_underflow_o (txf_underflow),
 353: 
 354:     // SPI signal
 355:     .csb_i         (cio_csb_i),
 356:     .mosi          (cio_mosi_i),
 357:     .miso          (cio_miso_o),
 358:     .miso_oe       (cio_miso_en_o)
 359:   );
 360: 
 361:   // FIFO: Connecting FwMode to SRAM CTRLs
 362:   prim_fifo_async #(
 363:     .Width (FifoWidth),
 364:     .Depth (FifoDepth)
 365:   ) u_rx_fifo (
 366:     .clk_wr_i     (clk_spi_in),
 367:     .rst_wr_ni    (rst_rxfifo_n),
 368: 
 369:     .clk_rd_i     (clk_i),
 370:     .rst_rd_ni    (rst_rxfifo_n),
 371: 
 372:     .wvalid       (rxf_wvalid),
 373:     .wready       (rxf_wready),
 374:     .wdata        (rxf_wdata),
 375: 
 376:     .rvalid       (rxf_rvalid),
 377:     .rready       (rxf_rready),
 378:     .rdata        (rxf_rdata),
 379: 
 380:     .wdepth       (),
 381:     .rdepth       (as_rxfifo_depth)
 382:   );
 383: 
 384:   prim_fifo_async #(
 385:     .Width (FifoWidth),
 386:     .Depth (FifoDepth)
 387:   ) u_tx_fifo (
 388:     .clk_wr_i     (clk_i),
 389:     .rst_wr_ni    (rst_txfifo_n),
 390: 
 391:     .clk_rd_i     (clk_spi_out),
 392:     .rst_rd_ni    (rst_txfifo_n),
 393: 
 394:     .wvalid       (txf_wvalid),
 395:     .wready       (txf_wready),
 396:     .wdata        (txf_wdata),
 397: 
 398:     .rvalid       (txf_rvalid),
 399:     .rready       (txf_rready),
 400:     .rdata        (txf_rdata),
 401: 
 402:     .wdepth       (as_txfifo_depth),
 403:     .rdepth       ()
 404:   );
 405: 
 406:   // RX Fifo control (FIFO Read port --> SRAM request)
 407:   spi_fwm_rxf_ctrl #(
 408:     .FifoDw (FifoWidth),
 409:     .SramAw (SramAw),
 410:     .SramDw (SramDw)
 411:   ) u_rxf_ctrl (
 412:     .clk_i,
 413:     .rst_ni,
 414: 
 415:     .base_index_i  (sram_rxf_bindex),
 416:     .limit_index_i (sram_rxf_lindex),
 417:     .timer_v      (timer_v),
 418:     .rptr         (sram_rxf_rptr),  // Given by FW
 419:     .wptr         (sram_rxf_wptr),  // to Register interface
 420:     .depth        (sram_rxf_depth),
 421:     .full         (sram_rxf_full),
 422: 
 423:     .fifo_valid  (rxf_rvalid),
 424:     .fifo_ready  (rxf_rready),
 425:     .fifo_rdata  (rxf_rdata),
 426: 
 427:     .sram_req    (fwm_sram_req   [FwModeRxFifo]),
 428:     .sram_write  (fwm_sram_write [FwModeRxFifo]),
 429:     .sram_addr   (fwm_sram_addr  [FwModeRxFifo]),
 430:     .sram_wdata  (fwm_sram_wdata [FwModeRxFifo]),
 431:     .sram_gnt    (fwm_sram_gnt   [FwModeRxFifo]),
 432:     .sram_rvalid (fwm_sram_rvalid[FwModeRxFifo]),
 433:     .sram_rdata  (fwm_sram_rdata [FwModeRxFifo]),
 434:     .sram_error  (fwm_sram_error [FwModeRxFifo])
 435:   );
 436: 
 437:   // TX Fifo control (SRAM read request --> FIFO write)
 438:   spi_fwm_txf_ctrl #(
 439:     .FifoDw (FifoWidth),
 440:     .SramAw (SramAw),
 441:     .SramDw (SramDw)
 442:   ) u_txf_ctrl (
 443:     .clk_i,
 444:     .rst_ni,
 445: 
 446:     .base_index_i  (sram_txf_bindex),
 447:     .limit_index_i (sram_txf_lindex),
 448: 
 449:     .abort        (abort),
 450:     .rptr         (sram_txf_rptr),  // Given by FW
 451:     .wptr         (sram_txf_wptr),  // to Register interface
 452:     .depth        (sram_txf_depth),
 453: 
 454:     .fifo_valid  (txf_wvalid),
 455:     .fifo_ready  (txf_wready),
 456:     .fifo_wdata  (txf_wdata),
 457: 
 458:     .sram_req    (fwm_sram_req   [FwModeTxFifo]),
 459:     .sram_write  (fwm_sram_write [FwModeTxFifo]),
 460:     .sram_addr   (fwm_sram_addr  [FwModeTxFifo]),
 461:     .sram_wdata  (fwm_sram_wdata [FwModeTxFifo]),
 462:     .sram_gnt    (fwm_sram_gnt   [FwModeTxFifo]),
 463:     .sram_rvalid (fwm_sram_rvalid[FwModeTxFifo]),
 464:     .sram_rdata  (fwm_sram_rdata [FwModeTxFifo]),
 465:     .sram_error  (fwm_sram_error [FwModeTxFifo])
 466:   );
 467: 
 468:   // Arbiter for FIFOs : Connecting between SRAM Ctrls and SRAM interface
 469:   prim_sram_arbiter #(
 470:     .N       (2),  // RXF, TXF
 471:     .SramDw (SramDw),
 472:     .SramAw (SramAw)   // 2kB
 473:   ) u_fwmode_arb (
 474:     .clk_i,
 475:     .rst_ni,
 476: 
 477:     .req          (fwm_sram_req),
 478:     .req_addr     (fwm_sram_addr),
 479:     .req_write    (fwm_sram_write),
 480:     .req_wdata    (fwm_sram_wdata),
 481:     .gnt          (fwm_sram_gnt),
 482: 
 483:     .rsp_rvalid   (fwm_sram_rvalid),
 484:     .rsp_rdata    (fwm_sram_rdata),
 485:     .rsp_error    (fwm_sram_error),
 486: 
 487:     .sram_req     (mem_b_req),
 488:     .sram_addr    (mem_b_addr),
 489:     .sram_write   (mem_b_write),
 490:     .sram_wdata   (mem_b_wdata),
 491: 
 492:     .sram_rvalid  (mem_b_rvalid),
 493:     .sram_rdata   (mem_b_rdata),
 494:     .sram_rerror  (mem_b_rerror)
 495:   );
 496: 
 497:   tlul_adapter_sram #(
 498:     .SramAw      (SramAw),
 499:     .SramDw      (SramDw),
 500:     .Outstanding (1),
 501:     .ByteAccess  (0)
 502:   ) u_tlul2sram (
 503:     .clk_i,
 504:     .rst_ni,
 505: 
 506:     .tl_i (tl_sram_h2d [0]),
 507:     .tl_o (tl_sram_d2h [0]),
 508: 
 509:     .req_o    (mem_a_req),
 510:     .gnt_i    (mem_a_req),  //Always grant when request
 511:     .we_o     (mem_a_write),
 512:     .addr_o   (mem_a_addr),
 513:     .wdata_o  (mem_a_wdata),
 514:     .wmask_o  (),           // Not used
 515:     .rdata_i  (mem_a_rdata),
 516:     .rvalid_i (mem_a_rvalid),
 517:     .rerror_i (mem_a_rerror)
 518:   );
 519: 
 520:   // SRAM Wrapper
 521:   prim_ram_2p_adv #(
 522:     .Depth (512),
 523:     .Width (SramDw),    // 32 x 512 --> 2kB
 524:     .DataBitsPerMask (1),
 525:     .CfgW  (8),
 526: 
 527:     .EnableECC           (1),
 528:     .EnableParity        (0),
 529:     .EnableInputPipeline (0),
 530:     .EnableOutputPipeline(0)
 531:   ) u_memory_2p (
 532:     .clk_i,
 533:     .rst_ni,
 534:     .a_req_i    (mem_a_req),
 535:     .a_write_i  (mem_a_write),
 536:     .a_addr_i   (mem_a_addr),
 537:     .a_wdata_i  (mem_a_wdata),
 538:     .a_wmask_i  ({SramDw{1'b1}}),
 539:     .a_rvalid_o (mem_a_rvalid),
 540:     .a_rdata_o  (mem_a_rdata),
 541:     .a_rerror_o (mem_a_rerror),
 542: 
 543:     .b_req_i    (mem_b_req),
 544:     .b_write_i  (mem_b_write),
 545:     .b_addr_i   (mem_b_addr),
 546:     .b_wdata_i  (mem_b_wdata),
 547:     .b_wmask_i  ({SramDw{1'b1}}),
 548:     .b_rvalid_o (mem_b_rvalid),
 549:     .b_rdata_o  (mem_b_rdata),
 550:     .b_rerror_o (mem_b_rerror),
 551: 
 552:     .cfg_i      ('0)
 553:   );
 554: 
 555:   // Register module
 556:   spi_device_reg_top u_reg (
 557:     .clk_i,
 558:     .rst_ni,
 559: 
 560:     .tl_i (tl_i),
 561:     .tl_o (tl_o),
 562: 
 563:     .tl_win_o (tl_sram_h2d),
 564:     .tl_win_i (tl_sram_d2h),
 565: 
 566:     .reg2hw,
 567:     .hw2reg,
 568: 
 569:     .devmode_i  (1'b1)
 570:   );
 571: 
 572:   // make sure scanmode_i is never X (including during reset)
 573:   `ASSERT_KNOWN(scanmodeKnown, scanmode_i, clk_i, 0)
 574:   `ASSERT_KNOWN(CioMisoEnOKnown, cio_miso_en_o)
 575: 
 576:   `ASSERT_KNOWN(IntrRxfOKnown,         intr_rxf_o        )
 577:   `ASSERT_KNOWN(IntrRxlvlOKnown,       intr_rxlvl_o      )
 578:   `ASSERT_KNOWN(IntrTxlvlOKnown,       intr_txlvl_o      )
 579:   `ASSERT_KNOWN(IntrRxerrOKnown,       intr_rxerr_o      )
 580:   `ASSERT_KNOWN(IntrRxoverflowOKnown,  intr_rxoverflow_o )
 581:   `ASSERT_KNOWN(IntrTxunderflowOKnown, intr_txunderflow_o)
 582: 
 583: endmodule
 584: