Go
back
172
173 1/1 assign payload_notempty = payload_depth != '0;
Tests: T1 T2 T3
174
175 /////////////////////
176 // Control signals //
177 /////////////////////
178
179 logic txorder; // TX bitstream order: 0(bit 7 to 0), 1(bit 0 to 7)
180 logic rxorder; // RX bitstream order: 0(bit 7 to 0), 1(bit 0 to 7)
181
182 logic sys_csb_syncd;
183
184 spi_mode_e spi_mode;
185 logic cfg_addr_4b_en;
186 logic cmd_sync_addr_4b_en;
187
188 // Address 3B/ 4B tracker related signals
189 //
190 // EN4B/ EX4B change internal status by HW. If SW is involved into the
191 // process, the latency is long. As EN4B/ EX4B commands do not assert BUSY
192 // bit, the host system issues next read commands without any delays. SW
193 // process latency cannot meet the requirement.
194 //
195 // `spid_addr_4b` submodule processes the broadcasting signal
196 // `cfg_addr_4b_en`. The command parser recognizes the commands and triggers
197 // the `spid_addr_4b` submodule to change the internal status.
198 //
199 // The opcodes of the commands SW may configure via CMD_INFO_EN4B,
200 // CMD_INFO_EX4B.
201 logic cmd_en4b_pulse, cmd_ex4b_pulse;
202
203 // SPI S2P signals
204 // io_mode: Determine s2p/p2s behavior.
205 // io_mode is changed at the negedge of SPI_CLK (based on the SPI protocol).
206 // sub_iomode originates from the clk_spi_in domain, with flop values that
207 // may have changed based on the input of SPI. The sub_iomode is selected
208 // and sampled on the clk_spi_out domain.
209 io_mode_e io_mode, io_mode_outclk;
210 io_mode_e sub_iomode[IoModeEnd];
211 logic s2p_data_valid;
212 spi_byte_t s2p_data;
213
214 logic p2s_valid;
215 spi_byte_t p2s_data;
216 logic p2s_sent;
217
218 logic sub_p2s_valid[IoModeEnd];
219 spi_byte_t sub_p2s_data[IoModeEnd];
220 logic sub_p2s_sent[IoModeEnd];
221
222 // Read commands related signals
223 logic [31:0] readbuf_addr_sck;
224 logic [31:0] readbuf_addr_busclk;
225
226 // CMD interface
227 sel_datapath_e cmd_dp_sel, cmd_only_dp_sel;
228
229 // Mailbox in Passthrough needs to take SPI if readcmd hits mailbox address
230 logic intercept_en, intercept_en_out;
231
232 logic cfg_mailbox_en;
233 logic [31:0] mailbox_addr;
234
235 // Intercept
236 typedef struct packed {
237 logic status;
238 logic jedec;
239 logic sfdp;
240 logic mbx;
241 } intercept_t;
242 intercept_t cfg_intercept_en;
243 intercept_t intercept; // Assume signals
244
245 // Threshold value of a buffer in bytes
246 logic [BufferAw:0] readbuf_threshold;
247
248 // Synchronous clear of read buffer tracking.
249 logic readbuf_clr;
250
251 // Passthrouth config signals
252 logic [255:0] cmd_filter;
253
254 logic [31:0] addr_swap_mask;
255 logic [31:0] addr_swap_data;
256
257 logic [31:0] payload_swap_mask;
258 logic [31:0] payload_swap_data;
259
260 // Additional 2-stage read pipeline configuration
261 logic cmd_read_pipeline_sel;
262
263 // Command Info structure
264 cmd_info_t [NumTotalCmdInfo-1:0] cmd_info;
265 // Broadcasted cmd_info. cmdparse compares the opcode up to CmdInfoReadCmdEnd
266 // and latches the cmd_info and broadcast to submodules
267 cmd_info_t cmd_info_broadcast;
268 logic [CmdInfoIdxW-1:0] cmd_info_idx_broadcast;
269 // Combinatorial output of selected cmd_info, to be used with modules that
270 // need the values before the 8th posedge of the command.
271 cmd_info_t cmd_only_info_broadcast;
272 logic [CmdInfoIdxW-1:0] cmd_only_info_idx_broadcast;
273
274 // Synchronization pulse indicating that the 8th bit of the command is
275 // arriving. This is used to time the transfer of some data to/from the sys
276 // domain.
277 logic cmd_sync_pulse;
278
279 // CSb edge detector in the system clock and SPI input clock
280 // SYS clock assertion can be detected but no usage for the event yet.
281 // SPI clock de-assertion cannot be detected as no SCK at the time is given.
282 logic sys_csb_deasserted_pulse;
283
284 // Important status bits for tracking in the upload module
285 logic cmd_sync_status_busy;
286 logic cmd_sync_status_wel;
287 logic sck_status_busy;
288
289 // Read Status input and broadcast
290 logic sck_status_busy_set; // set by HW (upload)
291 logic csb_status_busy_broadcast; // from spid_status
292
293 // WREN / WRDI HW signal
294 logic sck_status_wr_set;
295 logic sck_status_wr_clr;
296
297 // Jedec ID
298 jedec_cfg_t jedec_cfg;
299
300 // Interrupts in Flash mode
301 logic intr_upload_cmdfifo_not_empty, intr_upload_payload_not_empty;
302 logic intr_upload_payload_overflow;
303 logic intr_readbuf_watermark, intr_readbuf_flip;
304 logic flash_sck_readbuf_watermark, flash_sck_readbuf_flip;
305
306 // TPM ===============================================================
307 // Interface
308 logic tpm_mosi, tpm_miso, tpm_miso_en;
309 1/1 assign tpm_mosi = cio_sd_i[0];
Tests: T3 T5 T6
310
311 // Return-by-HW registers
312 logic [8*spi_device_reg_pkg::NumLocality-1:0] tpm_access;
313 logic [31:0] tpm_int_enable;
314 logic [7:0] tpm_int_vector;
315 logic [31:0] tpm_int_status;
316 logic [31:0] tpm_intf_capability;
317 logic [31:0] tpm_status;
318 logic [31:0] tpm_did_vid;
319 logic [7:0] tpm_rid;
320
321 // Buffer and FIFO signals
322 sram_l2m_t tpm_sram_l2m;
323 sram_m2l_t tpm_sram_m2l;
324 logic tpm_cmdaddr_rvalid, tpm_cmdaddr_rready;
325 logic [31:0] tpm_cmdaddr_rdata;
326 logic tpm_rdfifo_wvalid, tpm_rdfifo_wready;
327 logic [TpmRdFifoWidth-1:0] tpm_rdfifo_wdata;
328 logic tpm_event_rdfifo_cmd_end;
329 logic tpm_event_rdfifo_drop;
330
331 tpm_cap_t tpm_cap;
332
333 // TPM CFG
334 logic cfg_tpm_en, cfg_tpm_mode, cfg_tpm_hw_reg_dis;
335 logic cfg_tpm_invalid_locality, cfg_tpm_reg_chk_dis;
336
337 // TPM_STATUS
338 logic tpm_status_cmdaddr_notempty;
339 logic tpm_status_wrfifo_pending;
340 logic tpm_status_wrfifo_release;
341 logic tpm_status_rdfifo_aborted;
342
343 // TPM ---------------------------------------------------------------
344
345 /////////////////
346 // CSb Buffers //
347 /////////////////
348 // Split the CSB into multiple explicit buffers. One for reset, two for each
349 // clock domains.
350 logic clk_csb_buf, rst_csb_buf, sys_csb, sck_csb;
351 prim_buf #(
352 .Width (4)
353 ) u_csb_buf (
354 .in_i ({4{cio_csb_i}}),
355 .out_o ({clk_csb_buf, rst_csb_buf, sys_csb, sck_csb})
356 );
357
358 // Split TPM CSB into explicit reset and data.
359 logic rst_tpm_csb_buf, sys_tpm_csb_buf, sck_tpm_csb_buf;
360 logic sys_tpm_csb_syncd; // synchronized prior to be connected to reg
361 prim_buf #(
362 .Width (3)
363 ) u_tpm_csb_buf (
364 .in_i ({3{cio_tpm_csb_i}}),
365 .out_o ({rst_tpm_csb_buf, sys_tpm_csb_buf, sck_tpm_csb_buf})
366 );
367
368 //////////////////////////////////////////////////////////////////////
369 // Connect phase (between control signals above and register module //
370 //////////////////////////////////////////////////////////////////////
371
372 1/1 assign txorder = reg2hw.cfg.tx_order.q;
Tests: T1 T2 T3
373 1/1 assign rxorder = reg2hw.cfg.rx_order.q;
Tests: T1 T2 T3
374
375 // CSb : after 2stage synchronizer
376 1/1 assign hw2reg.status.csb.d = sys_csb_syncd;
Tests: T1 T2 T3
377 1/1 assign hw2reg.status.tpm_csb.d = sys_tpm_csb_syncd;
Tests: T1 T2 T3
378
379 1/1 assign spi_mode = spi_mode_e'(reg2hw.control.mode.q);
Tests: T1 T2 T3
380
381 prim_edge_detector #(
382 .Width (2),
383 .EnSync(1'b 0)
384 ) u_intr_upload_edge (
385 .clk_i,
386 .rst_ni,
387
388 .d_i ({payload_notempty, payload_overflow}),
389 .q_sync_o (),
390 .q_posedge_pulse_o ({intr_upload_payload_not_empty,
391 intr_upload_payload_overflow}),
392 .q_negedge_pulse_o ()
393 );
394 1/1 assign intr_upload_cmdfifo_not_empty = cmdfifo_set_pulse;
Tests: T1 T2 T3
395
396 prim_intr_hw #(.Width(1)) u_intr_cmdfifo_not_empty (
397 .clk_i,
398 .rst_ni,
399 .event_intr_i (intr_upload_cmdfifo_not_empty ),
400 .reg2hw_intr_enable_q_i (reg2hw.intr_enable.upload_cmdfifo_not_empty.q),
401 .reg2hw_intr_test_q_i (reg2hw.intr_test.upload_cmdfifo_not_empty.q ),
402 .reg2hw_intr_test_qe_i (reg2hw.intr_test.upload_cmdfifo_not_empty.qe ),
403 .reg2hw_intr_state_q_i (reg2hw.intr_state.upload_cmdfifo_not_empty.q ),
404 .hw2reg_intr_state_d_o (hw2reg.intr_state.upload_cmdfifo_not_empty.d ),
405 .hw2reg_intr_state_de_o (hw2reg.intr_state.upload_cmdfifo_not_empty.de),
406 .intr_o (intr_upload_cmdfifo_not_empty_o )
407 );
408
409 prim_intr_hw #(.Width(1)) u_intr_payload_not_empty (
410 .clk_i,
411 .rst_ni,
412 .event_intr_i (intr_upload_payload_not_empty ),
413 .reg2hw_intr_enable_q_i (reg2hw.intr_enable.upload_payload_not_empty.q),
414 .reg2hw_intr_test_q_i (reg2hw.intr_test.upload_payload_not_empty.q ),
415 .reg2hw_intr_test_qe_i (reg2hw.intr_test.upload_payload_not_empty.qe ),
416 .reg2hw_intr_state_q_i (reg2hw.intr_state.upload_payload_not_empty.q ),
417 .hw2reg_intr_state_d_o (hw2reg.intr_state.upload_payload_not_empty.d ),
418 .hw2reg_intr_state_de_o (hw2reg.intr_state.upload_payload_not_empty.de),
419 .intr_o (intr_upload_payload_not_empty_o )
420 );
421
422 prim_intr_hw #(.Width(1)) u_intr_payload_overflow (
423 .clk_i,
424 .rst_ni,
425 .event_intr_i (intr_upload_payload_overflow ),
426 .reg2hw_intr_enable_q_i (reg2hw.intr_enable.upload_payload_overflow.q),
427 .reg2hw_intr_test_q_i (reg2hw.intr_test.upload_payload_overflow.q ),
428 .reg2hw_intr_test_qe_i (reg2hw.intr_test.upload_payload_overflow.qe ),
429 .reg2hw_intr_state_q_i (reg2hw.intr_state.upload_payload_overflow.q ),
430 .hw2reg_intr_state_d_o (hw2reg.intr_state.upload_payload_overflow.d ),
431 .hw2reg_intr_state_de_o (hw2reg.intr_state.upload_payload_overflow.de),
432 .intr_o (intr_upload_payload_overflow_o )
433 );
434
435
436 prim_pulse_sync u_flash_readbuf_watermark_pulse_sync (
437 .clk_src_i (clk_spi_in_buf ),
438 .rst_src_ni (rst_ni ),
439 .src_pulse_i (flash_sck_readbuf_watermark),
440 .clk_dst_i (clk_i ),
441 .rst_dst_ni (rst_ni ),
442 .dst_pulse_o (intr_readbuf_watermark )
443 );
444 prim_intr_hw #(.Width(1)) u_intr_readbuf_watermark (
445 .clk_i,
446 .rst_ni,
447 .event_intr_i (intr_readbuf_watermark ),
448 .reg2hw_intr_enable_q_i (reg2hw.intr_enable.readbuf_watermark.q),
449 .reg2hw_intr_test_q_i (reg2hw.intr_test.readbuf_watermark.q ),
450 .reg2hw_intr_test_qe_i (reg2hw.intr_test.readbuf_watermark.qe ),
451 .reg2hw_intr_state_q_i (reg2hw.intr_state.readbuf_watermark.q ),
452 .hw2reg_intr_state_d_o (hw2reg.intr_state.readbuf_watermark.d ),
453 .hw2reg_intr_state_de_o (hw2reg.intr_state.readbuf_watermark.de),
454 .intr_o (intr_readbuf_watermark_o )
455 );
456
457 prim_pulse_sync u_flash_readbuf_flip_pulse_sync (
458 .clk_src_i (clk_spi_in_buf ),
459 .rst_src_ni (rst_ni ),
460 .src_pulse_i (flash_sck_readbuf_flip),
461 .clk_dst_i (clk_i ),
462 .rst_dst_ni (rst_ni ),
463 .dst_pulse_o (intr_readbuf_flip )
464 );
465 prim_intr_hw #(.Width(1)) u_intr_readbuf_flip (
466 .clk_i,
467 .rst_ni,
468 .event_intr_i (intr_readbuf_flip ),
469 .reg2hw_intr_enable_q_i (reg2hw.intr_enable.readbuf_flip.q),
470 .reg2hw_intr_test_q_i (reg2hw.intr_test.readbuf_flip.q ),
471 .reg2hw_intr_test_qe_i (reg2hw.intr_test.readbuf_flip.qe ),
472 .reg2hw_intr_state_q_i (reg2hw.intr_state.readbuf_flip.q ),
473 .hw2reg_intr_state_d_o (hw2reg.intr_state.readbuf_flip.d ),
474 .hw2reg_intr_state_de_o (hw2reg.intr_state.readbuf_flip.de),
475 .intr_o (intr_readbuf_flip_o )
476 );
477
478 prim_intr_hw #(
479 .Width (1 ),
480 .IntrT ("Status")
481 ) u_intr_tpm_cmdaddr_notempty (
482 .clk_i,
483 .rst_ni,
484 .event_intr_i (tpm_status_cmdaddr_notempty ),
485 .reg2hw_intr_enable_q_i (reg2hw.intr_enable.tpm_header_not_empty.q),
486 .reg2hw_intr_test_q_i (reg2hw.intr_test.tpm_header_not_empty.q ),
487 .reg2hw_intr_test_qe_i (reg2hw.intr_test.tpm_header_not_empty.qe ),
488 .reg2hw_intr_state_q_i (reg2hw.intr_state.tpm_header_not_empty.q ),
489 .hw2reg_intr_state_d_o (hw2reg.intr_state.tpm_header_not_empty.d ),
490 .hw2reg_intr_state_de_o (hw2reg.intr_state.tpm_header_not_empty.de),
491 .intr_o (intr_tpm_header_not_empty_o )
492 );
493
494 prim_intr_hw #(
495 .Width (1 ),
496 .IntrT ("Event")
497 ) u_intr_tpm_rdfifo_cmd_end (
498 .clk_i,
499 .rst_ni,
500 .event_intr_i (tpm_event_rdfifo_cmd_end ),
501 .reg2hw_intr_enable_q_i (reg2hw.intr_enable.tpm_rdfifo_cmd_end.q),
502 .reg2hw_intr_test_q_i (reg2hw.intr_test.tpm_rdfifo_cmd_end.q ),
503 .reg2hw_intr_test_qe_i (reg2hw.intr_test.tpm_rdfifo_cmd_end.qe ),
504 .reg2hw_intr_state_q_i (reg2hw.intr_state.tpm_rdfifo_cmd_end.q ),
505 .hw2reg_intr_state_d_o (hw2reg.intr_state.tpm_rdfifo_cmd_end.d ),
506 .hw2reg_intr_state_de_o (hw2reg.intr_state.tpm_rdfifo_cmd_end.de),
507 .intr_o (intr_tpm_rdfifo_cmd_end_o )
508 );
509
510 prim_intr_hw #(
511 .Width (1 ),
512 .IntrT ("Event")
513 ) u_intr_tpm_rdfifo_drop (
514 .clk_i,
515 .rst_ni,
516 .event_intr_i (tpm_event_rdfifo_drop ),
517 .reg2hw_intr_enable_q_i (reg2hw.intr_enable.tpm_rdfifo_drop.q),
518 .reg2hw_intr_test_q_i (reg2hw.intr_test.tpm_rdfifo_drop.q ),
519 .reg2hw_intr_test_qe_i (reg2hw.intr_test.tpm_rdfifo_drop.qe ),
520 .reg2hw_intr_state_q_i (reg2hw.intr_state.tpm_rdfifo_drop.q ),
521 .hw2reg_intr_state_d_o (hw2reg.intr_state.tpm_rdfifo_drop.d ),
522 .hw2reg_intr_state_de_o (hw2reg.intr_state.tpm_rdfifo_drop.de),
523 .intr_o (intr_tpm_rdfifo_drop_o )
524 );
525 // SPI Flash commands registers
526
527 1/1 assign cfg_intercept_en = '{
Tests: T1 T2 T3
528 status: reg2hw.intercept_en.status.q,
529 jedec: reg2hw.intercept_en.jedec.q,
530 sfdp: reg2hw.intercept_en.sfdp.q,
531 mbx: reg2hw.intercept_en.mbx.q
532 };
533 logic unused_cfg_intercept_en;
534 1/1 assign unused_cfg_intercept_en = ^cfg_intercept_en;
Tests: T1 T2 T3
535
536 1/1 assign hw2reg.last_read_addr.d = readbuf_addr_busclk;
Tests: T1 T2 T3
537
538 always_ff @(posedge clk_i or negedge rst_ni) begin
539 1/1 if (!rst_ni) begin
Tests: T1 T2 T3
540 1/1 readbuf_addr_busclk <= '0;
Tests: T1 T2 T3
541 1/1 end else if (sys_csb_deasserted_pulse) begin
Tests: T1 T2 T3
542 1/1 readbuf_addr_busclk <= readbuf_addr_sck;
Tests: T6 T9 T10
543 end
MISSING_ELSE
544 end
545
546 // Jedec ID
547 1/1 assign jedec_cfg = '{ num_cc: reg2hw.jedec_cc.num_cc.q,
Tests: T1 T2 T3
548 cc: reg2hw.jedec_cc.cc.q,
549 jedec_id: reg2hw.jedec_id.mf.q,
550 device_id: reg2hw.jedec_id.id.q
551 };
552
553 1/1 assign readbuf_threshold = reg2hw.read_threshold.q[BufferAw:0];
Tests: T1 T2 T3
554 1/1 assign readbuf_clr = reg2hw.control.flash_read_buffer_clr.q;
Tests: T1 T2 T3
555 assign hw2reg.control.flash_read_buffer_clr.d = '0;
556 assign hw2reg.control.flash_read_buffer_clr.de = 1'b1;
557
558 localparam int unsigned MailboxAw = $clog2(SramMailboxDepth*SramDw/8);
559 1/1 assign cfg_mailbox_en = reg2hw.cfg.mailbox_en.q;
Tests: T1 T2 T3
560 1/1 assign mailbox_addr = { reg2hw.mailbox_addr.q[31:MailboxAw],
Tests: T1 T2 T3
561 {MailboxAw{1'b0}}
562 };
563 logic unused_mailbox_addr;
564 1/1 assign unused_mailbox_addr = ^reg2hw.mailbox_addr.q[MailboxAw-1:0];
Tests: T1 T2 T3
565
566 // Passthrough config: value shall be stable while SPI transaction is active
567 //assign cmd_filter = reg2hw.cmd_filter.q;
568 always_comb begin
569 1/1 for (int unsigned i = 0 ; i < 256 ; i++) begin
Tests: T1 T2 T3
570 1/1 cmd_filter[i] = reg2hw.cmd_filter[i].q;
Tests: T1 T2 T3
571 end
572 end
573
574 1/1 assign addr_swap_mask = reg2hw.addr_swap_mask.q;
Tests: T1 T2 T3
575 1/1 assign addr_swap_data = reg2hw.addr_swap_data.q;
Tests: T1 T2 T3
576
577 // payload_swap_mask and _data are big-endian to calculate easily.
578 assign payload_swap_mask = {<<8{reg2hw.payload_swap_mask.q}};
579 assign payload_swap_data = {<<8{reg2hw.payload_swap_data.q}};
580
581 // Connect command info
582 always_comb begin
583 1/1 for (int unsigned i = 0 ; i < spi_device_reg_pkg::NumCmdInfo ; i++) begin
Tests: T1 T2 T3
584 1/1 cmd_info[i] = '{
Tests: T1 T2 T3
585 valid: reg2hw.cmd_info[i].valid.q,
586 opcode: reg2hw.cmd_info[i].opcode.q,
587 addr_mode: addr_mode_e'(reg2hw.cmd_info[i].addr_mode.q),
588 addr_swap_en: reg2hw.cmd_info[i].addr_swap_en.q,
589 mbyte_en: reg2hw.cmd_info[i].mbyte_en.q,
590 dummy_en: reg2hw.cmd_info[i].dummy_en.q,
591 dummy_size: reg2hw.cmd_info[i].dummy_size.q,
592 payload_en: reg2hw.cmd_info[i].payload_en.q,
593 payload_dir: payload_dir_e'(reg2hw.cmd_info[i].payload_dir.q),
594 payload_swap_en: reg2hw.cmd_info[i].payload_swap_en.q,
595 read_pipeline_mode: read_pipeline_mode_e'(reg2hw.cmd_info[i].read_pipeline_mode.q),
596 upload: reg2hw.cmd_info[i].upload.q,
597 busy: reg2hw.cmd_info[i].busy.q
598 };
599 end
600
601 // Manual addition to cmd_info list
602 // Default Input mode
603 1/1 for (int unsigned i = CmdInfoReserveEnd + 1; i < NumTotalCmdInfo; i++) begin
Tests: T1 T2 T3
604 1/1 cmd_info[i] = CmdInfoInput;
Tests: T1 T2 T3
605 end
606
607 // Hand crafted command information slots
608 1/1 cmd_info[CmdInfoEn4B].valid = reg2hw.cmd_info_en4b.valid.q;
Tests: T1 T2 T3
609 1/1 cmd_info[CmdInfoEn4B].opcode = reg2hw.cmd_info_en4b.opcode.q;
Tests: T1 T2 T3
610
611 1/1 cmd_info[CmdInfoEx4B].valid = reg2hw.cmd_info_ex4b.valid.q;
Tests: T1 T2 T3
612 1/1 cmd_info[CmdInfoEx4B].opcode = reg2hw.cmd_info_ex4b.opcode.q;
Tests: T1 T2 T3
613
614 1/1 cmd_info[CmdInfoWrEn].valid = reg2hw.cmd_info_wren.valid.q;
Tests: T1 T2 T3
615 1/1 cmd_info[CmdInfoWrEn].opcode = reg2hw.cmd_info_wren.opcode.q;
Tests: T1 T2 T3
616
617 1/1 cmd_info[CmdInfoWrDi].valid = reg2hw.cmd_info_wrdi.valid.q;
Tests: T1 T2 T3
618 1/1 cmd_info[CmdInfoWrDi].opcode = reg2hw.cmd_info_wrdi.opcode.q;
Tests: T1 T2 T3
619
620 end
621
622 ///////////////////////////
623 // Clock & reset control //
624 ///////////////////////////
625 logic sck_n;
626 logic rst_spi_n;
627 prim_mubi_pkg::mubi4_t [ScanModeUseLast-1:0] scanmode;
628
629 prim_mubi4_sync #(
630 .NumCopies(int'(ScanModeUseLast)),
631 .AsyncOn(0) // clock/reset below is only used for SVAs.
632 ) u_scanmode_sync (
633 .clk_i,
634 .rst_ni,
635 .mubi_i(scanmode_i),
636 .mubi_o(scanmode)
637 );
638
639 prim_clock_inv #(
640 .NoFpgaBufG(1'b1)
641 ) u_clk_spi (
642 .clk_i(cio_sck_i),
643 .clk_no(sck_n),
644 .scanmode_i(prim_mubi_pkg::mubi4_test_true_strict(scanmode[ClkInvSel]))
645 );
646
647 1/1 assign sck_monitor_o = cio_sck_i;
Tests: T1 T2 T3
648 1/1 assign clk_spi_in = cio_sck_i;
Tests: T1 T2 T3
649 1/1 assign clk_spi_out = sck_n;
Tests: T1 T2 T3
650
651 prim_clock_mux2 #(
652 .NoFpgaBufG(1'b1)
653 ) u_clk_spi_in_mux (
654 .clk0_i(clk_spi_in),
655 .clk1_i(scan_clk_i),
656 .sel_i(prim_mubi_pkg::mubi4_test_true_strict(scanmode[ClkMuxSel]) | mbist_en_i),
657 .clk_o(clk_spi_in_muxed)
658 );
659
660 prim_clock_buf #(
661 .RegionSel(1'b1)
662 ) u_clk_spi_in_buf(
663 .clk_i (clk_spi_in_muxed),
664 .clk_o (clk_spi_in_buf)
665 );
666
667 prim_clock_mux2 #(
668 .NoFpgaBufG(1'b1)
669 ) u_clk_spi_out_mux (
670 .clk0_i(clk_spi_out),
671 .clk1_i(scan_clk_i),
672 .sel_i(prim_mubi_pkg::mubi4_test_true_strict(scanmode[ClkMuxSel])),
673 .clk_o(clk_spi_out_muxed)
674 );
675
676 prim_clock_buf #(
677 .RegionSel(1'b1)
678 ) u_clk_spi_out_buf(
679 .clk_i (clk_spi_out_muxed),
680 .clk_o (clk_spi_out_buf)
681 );
682
683 // CSb muxed to scan clock
684 prim_clock_mux2 #(
685 .NoFpgaBufG(1'b 1)
686 ) u_clk_csb_mux (
687 .clk0_i (clk_csb_buf),
688 .clk1_i (scan_clk_i ),
689 .sel_i (prim_mubi_pkg::mubi4_test_true_strict(scanmode[ClkMuxSel])),
690 .clk_o (clk_csb_muxed)
691 );
692
693 prim_clock_buf #(
694 .NoFpgaBuf (1'b 1)
695 ) u_clk_csb_buf (
696 .clk_i (clk_csb_muxed),
697 .clk_o (clk_csb )
698 );
699
700 prim_clock_mux2 #(
701 .NoFpgaBufG(1'b1)
702 ) u_csb_rst_scan_mux (
703 .clk0_i(rst_ni & ~rst_csb_buf),
704 .clk1_i(scan_rst_ni),
705 .sel_i(prim_mubi_pkg::mubi4_test_true_strict(scanmode[CsbRstMuxSel])),
706 .clk_o(rst_spi_n)
707 );
708
709 logic rst_spi_in_n, rst_spi_out_sync_n, rst_spi_out_n;
710 1/1 assign rst_spi_in_n = rst_spi_n;
Tests: T1 T2 T3
711
712 // Synchronizes reset de-assertion to safely occur in the outclk domain.
713 prim_flop #(
714 .Width (1),
715 .ResetValue (1'b0)
716 ) u_rst_spi_out_sync (
717 .clk_i (clk_spi_in_buf),
718 .rst_ni(rst_spi_n),
719 .d_i (1'b1),
720 .q_o (rst_spi_out_sync_n)
721 );
722
723 prim_clock_mux2 #(
724 .NoFpgaBufG(1'b1)
725 ) u_csb_rst_out_scan_mux (
726 .clk0_i(rst_spi_out_sync_n),
727 .clk1_i(scan_rst_ni),
728 .sel_i(prim_mubi_pkg::mubi4_test_true_strict(scanmode[CsbRstMuxSel])),
729 .clk_o(rst_spi_out_n)
730 );
731
732 logic tpm_rst_in_n, tpm_rst_out_sync_n, tpm_rst_out_n, sys_tpm_rst_n;
733
734 prim_clock_mux2 #(
735 .NoFpgaBufG(1'b1)
736 ) u_tpm_csb_rst_scan_mux (
737 .clk0_i (rst_ni & ~rst_tpm_csb_buf),
738 .clk1_i (scan_rst_ni),
739 .sel_i (prim_mubi_pkg::mubi4_test_true_strict(scanmode[TpmRstSel])),
740 .clk_o (tpm_rst_in_n)
741 );
742
743 // Synchronizes reset de-assertion to safely occur in the outclk domain.
744 prim_flop #(
745 .Width (1),
746 .ResetValue (1'b0)
747 ) u_tpm_rst_out_sync (
748 .clk_i (clk_spi_in_buf),
749 .rst_ni(tpm_rst_in_n),
750 .d_i (1'b1),
751 .q_o (tpm_rst_out_sync_n)
752 );
753
754 prim_clock_mux2 #(
755 .NoFpgaBufG(1'b1)
756 ) u_tpm_rst_out_scan_mux (
757 .clk0_i (tpm_rst_out_sync_n),
758 .clk1_i (scan_rst_ni),
759 .sel_i (prim_mubi_pkg::mubi4_test_true_strict(scanmode[TpmRstSel])),
760 .clk_o (tpm_rst_out_n)
761 );
762
763 // TPM Read FIFO uses TPM CSb as a reset.
764 // The write port is clocked at SYS_CLK. Metastability may occur as CSb may
765 // be asserted, de-asserted independent of SYS_CLK. This reset synchronizer
766 // (sync to SYS_CLK), may delay the reset signal by 2 SYS_CLK when TPM_CSb
767 // is de-asserted.
768 prim_rst_sync #(
769 .ActiveHigh (1'b 0),
770 .SkipScan (1'b 0)
771 ) u_tpm_csb_rst_sync (
772 .clk_i,
773 .d_i (tpm_rst_in_n),
774 .q_o (sys_tpm_rst_n),
775
776 .scan_rst_ni,
777 .scanmode_i (scanmode[TpmRstSel])
778 );
779
780 // CSb edge on the system clock
781 spid_csb_sync u_spid_csb_sync (
782 .clk_i,
783 .rst_ni,
784 .sck_i (clk_spi_in_buf),
785 .sck_pulse_en_i (1'b1),
786 .csb_i (clk_csb),
787 .csb_deasserted_pulse_o (sys_csb_deasserted_pulse)
788 );
789
790 prim_flop_2sync #(
791 .Width (1)
792 ) u_sys_csb_syncd (
793 .clk_i,
794 .rst_ni,
795 .d_i (sys_csb),
796 .q_o (sys_csb_syncd)
797 );
798
799 // TPM CSb 2FF sync to SYS_CLK
800 prim_flop_2sync #(
801 .Width (1 ),
802 .ResetValue (1'b 1)
803 ) u_sys_tpm_csb_sync (
804 .clk_i,
805 .rst_ni,
806
807 .d_i (sys_tpm_csb_buf),
808 .q_o (sys_tpm_csb_syncd)
809 );
810
811 //////////////////////////////
812 // SPI_DEVICE mode selector //
813 //////////////////////////////
814 // This logic chooses appropriate signals based on input SPI_DEVICE mode.
815 // Assume spi_mode does not change dynamically
816
817 // io_mode to spi_s2p io_mode should be affected at the negedge of SPI_CLK
818 // based on SPI protocol. the internal io_mode signal is generated by SPI
819 // input signals. So, the io_mode should be latched at clk_spi_out to not
820 // introduce the timing loop.
821 //
822 // example: cmdparse triggers sel_dp at 8th beat of CMD bit.
823 // -> readcmd activates, it also changes IoMode if opcode is DualIO
824 // or QuadIO commands
825 // -> changed io_mode affects spi_s2p module, which again affects
826 // cmdparse module.
827 always_ff @(posedge clk_spi_out_buf or negedge rst_spi_out_n) begin
828 2/2 if (!rst_spi_out_n) io_mode_outclk <= SingleIO;
Tests: T1 T2 T3 | T1 T2 T3
829 1/1 else io_mode_outclk <= io_mode;
Tests: T6 T9 T10
830 end
831
832 // SCK clock domain MUX for SRAM access for Flash and Passthrough
833 always_comb begin
834 1/1 flash_sram_l2m = '{ default: '0 };
Tests: T1 T2 T3
835
836 1/1 for (int unsigned i = IoModeCmdParse ; i < IoModeEnd ; i++) begin
Tests: T1 T2 T3
837 1/1 sub_sram_m2l[i] = '{
Tests: T1 T2 T3
838 rvalid: 1'b 0,
839 rdata: '0,
840 rerror: '{uncorr: 1'b 0, corr: 1'b 0}
841 };
842 end
843
844 1/1 unique case (cmd_dp_sel)
Tests: T1 T2 T3
845 DpReadCmd, DpReadSFDP: begin
846 // SRAM:: Remember this has glitch
847 // switch should happen only when clock gate is disabled.
848 1/1 flash_sram_l2m = sub_sram_l2m[IoModeReadCmd];
Tests: T12 T15 T16
849 1/1 sub_sram_m2l[IoModeReadCmd] = flash_sram_m2l;
Tests: T12 T15 T16
850 end
851
852 DpUpload: begin
853 1/1 flash_sram_l2m = sub_sram_l2m[IoModeUpload];
Tests: T20 T60 T50
854 1/1 sub_sram_m2l[IoModeUpload] = flash_sram_m2l;
Tests: T20 T60 T50
855 end
856
857 default: begin
858 if (cmd_only_dp_sel == DpUpload) begin
859 // Be ready to upload commands on the 8th command bit, when directed
860 flash_sram_l2m = sub_sram_l2m[IoModeUpload];
861 sub_sram_m2l[IoModeUpload] = flash_sram_m2l;
862 end else begin
863 // DpNone, DpReadStatus, DpReadJEDEC
864 flash_sram_l2m = '{default: '0 };
865 end
866 end
867 endcase
868 end
869
870 always_comb begin
871 // SRAM comb logic is in SCK clock domain
872 1/1 mem_b_l2m = '{ default: '0 };
Tests: T1 T2 T3
873
874 1/1 flash_sram_m2l = '{
Tests: T1 T2 T3
875 rvalid: 1'b 0,
876 rdata: '0,
877 rerror: '{uncorr: 1'b 0, corr: 1'b 0}
878 };
879 1/1 tpm_sram_m2l = '{
Tests: T1 T2 T3
880 rvalid: 1'b 0,
881 rdata: '0,
882 rerror: '{uncorr: 1'b 0, corr: 1'b 0}
883 };
884
885 1/1 if (!sck_csb && ((spi_mode == FlashMode) || (spi_mode == PassThrough))) begin
Tests: T1 T2 T3
886 1/1 mem_b_l2m = flash_sram_l2m;
Tests: T1 T6 T9
887 1/1 flash_sram_m2l = mem_b_m2l;
Tests: T1 T6 T9
888 1/1 end else if (cfg_tpm_en) begin
Tests: T1 T2 T3
889 1/1 mem_b_l2m = tpm_sram_l2m;
Tests: T3 T5 T38
890 1/1 tpm_sram_m2l = mem_b_m2l;
Tests: T3 T5 T38
891 end
MISSING_ELSE
892 end
893
894 // inverted SCK clock domain MUX for IO Mode and P2S
895 always_comb begin
896 1/1 io_mode = SingleIO;
Tests: T1 T2 T3
897 1/1 p2s_valid = 1'b 0;
Tests: T1 T2 T3
898 1/1 p2s_data = 8'h 0;
Tests: T1 T2 T3
899 1/1 sub_p2s_sent = '{default: 1'b 0};
Tests: T1 T2 T3
900
901 1/1 unique case (spi_mode)
Tests: T1 T2 T3
902 FlashMode, PassThrough: begin
903 1/1 unique case (cmd_dp_sel)
Tests: T1 T2 T3
904 DpNone: begin
905 1/1 io_mode = sub_iomode[IoModeCmdParse];
Tests: T1 T2 T3
906
907 1/1 sub_p2s_sent[IoModeCmdParse] = p2s_sent;
Tests: T1 T2 T3
908
909 end
910 DpReadCmd, DpReadSFDP: begin
911 1/1 io_mode = sub_iomode[IoModeReadCmd];
Tests: T12 T15 T16
912
913 1/1 p2s_valid = sub_p2s_valid[IoModeReadCmd];
Tests: T12 T15 T16
914 1/1 p2s_data = sub_p2s_data[IoModeReadCmd];
Tests: T12 T15 T16
915 1/1 sub_p2s_sent[IoModeReadCmd] = p2s_sent;
Tests: T12 T15 T16
916 end
917 DpReadStatus: begin
918 1/1 io_mode = sub_iomode[IoModeStatus];
Tests: T20 T55 T60
919
920 1/1 p2s_valid = sub_p2s_valid[IoModeStatus];
Tests: T20 T55 T60
921 1/1 p2s_data = sub_p2s_data[IoModeStatus];
Tests: T20 T55 T60
922 1/1 sub_p2s_sent[IoModeStatus] = p2s_sent;
Tests: T20 T55 T60
923
924 end
925
926 DpReadJEDEC: begin
927 1/1 io_mode = sub_iomode[IoModeJedec];
Tests: T91 T50 T62
928
929 1/1 p2s_valid = sub_p2s_valid[IoModeJedec];
Tests: T91 T50 T62
930 1/1 p2s_data = sub_p2s_data[IoModeJedec];
Tests: T91 T50 T62
931 1/1 sub_p2s_sent[IoModeJedec] = p2s_sent;
Tests: T91 T50 T62
932 end
933
934 DpUpload: begin
935 1/1 io_mode = sub_iomode[IoModeUpload];
Tests: T20 T60 T50
936
937 1/1 p2s_valid = sub_p2s_valid[IoModeUpload];
Tests: T20 T60 T50
938 1/1 p2s_data = sub_p2s_data[IoModeUpload];
Tests: T20 T60 T50
939 1/1 sub_p2s_sent[IoModeUpload] = p2s_sent;
Tests: T20 T60 T50
940 end
941 // DpUnknown:
942 default: begin
943 io_mode = sub_iomode[IoModeCmdParse];
944
945 sub_p2s_sent[IoModeCmdParse] = p2s_sent;
946 end
947 endcase
948 end
949
950 default: begin
951 io_mode = SingleIO;
952 end
953 endcase
954 end
955 `ASSERT_KNOWN(SpiModeKnown_A, spi_mode)
956
957 // Add 2-cycle delay to flash read data when requested.
958 // This mechanism should only be deployed on read commands with dummy cycles,
959 // so omit delaying the output enable.
960 logic [3:0] internal_sd_stg1_d, internal_sd_stg1_q;
961 logic [3:0] internal_sd_stg2_d, internal_sd_stg2_q;
962 logic [3:0] internal_sd_en_stg1, internal_sd_en_stg2;
963 logic intercept_en_stg1, intercept_en_stg2;
964 1/1 assign internal_sd_stg1_d = internal_sd;
Tests: T1 T2 T3
965 1/1 assign internal_sd_stg2_d = internal_sd_stg1_q;
Tests: T1 T2 T3
966
967 prim_flop #(
968 .Width ($bits(internal_sd_stg1_d)),
969 .ResetValue ('0)
970 ) u_read_pipe_stg1 (
971 .clk_i (clk_spi_out_buf),
972 .rst_ni (rst_spi_out_n),
973 .d_i (internal_sd_stg1_d),
974 .q_o (internal_sd_stg1_q)
975 );
976
977 prim_flop #(
978 .Width ($bits(internal_sd_stg2_d)),
979 .ResetValue ('0)
980 ) u_read_pipe_stg2 (
981 .clk_i (clk_spi_out_buf),
982 .rst_ni (rst_spi_out_n),
983 .d_i (internal_sd_stg2_d),
984 .q_o (internal_sd_stg2_q)
985 );
986
987 prim_flop #(
988 .Width ($bits(internal_sd_en)),
989 .ResetValue ('0)
990 ) u_read_en_pipe_stg1 (
991 .clk_i (clk_spi_out_buf),
992 .rst_ni (rst_spi_out_n),
993 .d_i (internal_sd_en),
994 .q_o (internal_sd_en_stg1)
995 );
996
997 prim_flop #(
998 .Width ($bits(internal_sd_en_stg1)),
999 .ResetValue ('0)
1000 ) u_read_en_pipe_stg2 (
1001 .clk_i (clk_spi_out_buf),
1002 .rst_ni (rst_spi_out_n),
1003 .d_i (internal_sd_en_stg1),
1004 .q_o (internal_sd_en_stg2)
1005 );
1006
1007 prim_flop #(
1008 .Width (1),
1009 .ResetValue ('0)
1010 ) u_read_intercept_pipe_stg1 (
1011 .clk_i (clk_spi_out_buf),
1012 .rst_ni (rst_spi_out_n),
1013 .d_i (intercept_en),
1014 .q_o (intercept_en_stg1)
1015 );
1016
1017 prim_flop #(
1018 .Width (1),
1019 .ResetValue ('0)
1020 ) u_read_intercept_pipe_stg2 (
1021 .clk_i (clk_spi_out_buf),
1022 .rst_ni (rst_spi_out_n),
1023 .d_i (intercept_en_stg1),
1024 .q_o (intercept_en_stg2)
1025 );
1026
1027 always_comb begin
1028 1/1 if (cmd_read_pipeline_sel) begin
Tests: T1 T2 T3
1029 1/1 internal_sd_out = internal_sd_stg2_q;
Tests: T12 T15 T16
1030 1/1 internal_sd_en_out = internal_sd_en_stg2;
Tests: T12 T15 T16
1031 1/1 intercept_en_out = intercept_en_stg2;
Tests: T12 T15 T16
1032 end else begin
1033 1/1 internal_sd_out = internal_sd;
Tests: T1 T2 T3
1034 1/1 internal_sd_en_out = internal_sd_en;
Tests: T1 T2 T3
1035 1/1 intercept_en_out = intercept_en;
Tests: T1 T2 T3
1036 end
1037 end
1038
1039
1040 always_comb begin
1041 1/1 cio_sd_o = internal_sd_out;
Tests: T1 T2 T3
1042 1/1 cio_sd_en_o = internal_sd_en_out;
Tests: T1 T2 T3
1043
1044 1/1 if (cfg_tpm_en && !sck_tpm_csb_buf) begin : miso_tpm
Tests: T1 T2 T3
1045 // TPM transaction is on-going. MOSI, MISO is being used by TPM
1046 1/1 cio_sd_o = {2'b 00, tpm_miso, 1'b 0};
Tests: T3 T5 T13
1047 1/1 cio_sd_en_o = {2'b 00, tpm_miso_en, 1'b 0};
Tests: T3 T5 T13
1048
1049 end else begin : spi_out_flash_passthrough
1050 // SPI Flash, Passthrough modes
1051 1/1 unique case (spi_mode)
Tests: T1 T2 T3
1052 FlashMode: begin
1053 1/1 cio_sd_o = internal_sd_out;
Tests: T1 T2 T3
1054 1/1 cio_sd_en_o = internal_sd_en_out;
Tests: T1 T2 T3
1055 end
1056
1057 PassThrough: begin
1058 1/1 if (intercept_en_out) begin
Tests: T6 T9 T10
1059 1/1 cio_sd_o = internal_sd_out;
Tests: T20 T39 T55
1060 1/1 cio_sd_en_o = internal_sd_en_out;
Tests: T20 T39 T55
1061 end else begin
1062 1/1 cio_sd_o = passthrough_sd;
Tests: T6 T9 T10
1063 1/1 cio_sd_en_o = passthrough_sd_en;
Tests: T6 T9 T10
1064 end
1065 end
1066
1067 default: begin
1068 cio_sd_o = internal_sd;
1069 cio_sd_en_o = internal_sd_en;
1070 end
1071 endcase
1072 end
1073 end
1074
1075 // Assume `intercept` is registered (SPI_IN).
1076 // passthrough assumed signal shall be registered in (SPI_OUT)
1077 always_ff @(posedge clk_spi_out_buf or negedge rst_spi_out_n) begin
1078 2/2 if (!rst_spi_out_n) intercept_en <= 1'b 0;
Tests: T1 T2 T3 | T1 T2 T3
1079 1/1 else intercept_en <= |intercept;
Tests: T6 T9 T10
1080 end
1081 // intercept_en shall not be de-asserted except mailbox
1082 `ASSUME(InterceptLevel_M,
1083 $rose(|{intercept.status, intercept.jedec, intercept.sfdp}) |=>
1084 ##1 $stable(intercept_en) until !rst_spi_out_n,
1085 clk_spi_out_buf, !rst_spi_out_n)
1086
1087 ////////////////////////////
1088 // SPI Serial to Parallel //
1089 ////////////////////////////
1090 spi_s2p u_s2p (
1091 .clk_i (clk_spi_in_buf),
1092 .rst_ni (rst_spi_in_n),
1093
1094 // SPI interface
1095 .s_i (cio_sd_i),
1096
1097 .data_valid_o (s2p_data_valid),
1098 .data_o (s2p_data ),
1099
1100 // Config (changed dynamically)
1101 .order_i (rxorder),
1102 .io_mode_i (io_mode_outclk)
1103 );
1104
1105 spi_p2s u_p2s (
1106 .clk_i (clk_spi_out_buf),
1107 .rst_ni (rst_spi_out_n),
1108
1109 .data_valid_i (p2s_valid),
1110 .data_i (p2s_data),
1111 .data_sent_o (p2s_sent),
1112
1113 .csb_i (sck_csb),
1114 .s_en_o (internal_sd_en),
1115 .s_o (internal_sd),
1116
1117 .order_i (txorder),
1118 .io_mode_i (io_mode_outclk)
1119 );
1120
1121 ////////////////////
1122 // SPI Flash Mode //
1123 ////////////////////
1124
1125 spi_cmdparse u_cmdparse (
1126 .clk_i (clk_spi_in_buf),
1127 .rst_ni (rst_spi_in_n),
1128
1129 .data_valid_i (s2p_data_valid),
1130 .data_i (s2p_data),
1131
1132 .spi_mode_i (spi_mode),
1133
1134 .cmd_info_i (cmd_info),
1135
1136 .sck_status_busy_i(sck_status_busy),
1137
1138 .io_mode_o (sub_iomode[IoModeCmdParse]),
1139
1140 .sel_dp_o (cmd_dp_sel),
1141 .cmd_only_sel_dp_o (cmd_only_dp_sel),
1142 .cmd_info_o (cmd_info_broadcast),
1143 .cmd_info_idx_o (cmd_info_idx_broadcast),
1144 .cmd_only_info_o (cmd_only_info_broadcast),
1145 .cmd_only_info_idx_o (cmd_only_info_idx_broadcast),
1146 .cmd_sync_pulse_o (cmd_sync_pulse),
1147
1148 .cmd_read_pipeline_sel_o (cmd_read_pipeline_sel),
1149
1150 .cfg_intercept_en_status_i (cfg_intercept_en.status),
1151 .cfg_intercept_en_jedec_i (cfg_intercept_en.jedec),
1152 .cfg_intercept_en_sfdp_i (cfg_intercept_en.sfdp),
1153
1154 .intercept_status_o (intercept.status),
1155 .intercept_jedec_o (intercept.jedec),
1156 .intercept_sfdp_o (intercept.sfdp),
1157
1158 // Not used for now
1159 .cmd_config_req_o (),
1160 .cmd_config_idx_o ()
1161 );
1162
1163 spi_readcmd u_readcmd (
1164 .clk_i (clk_spi_in_buf),
1165 .rst_ni (rst_spi_in_n),
1166
1167 .clk_out_i (clk_spi_out_buf),
1168 .rst_out_ni (rst_spi_out_n),
1169
1170 .sys_clk_i (clk_i),
1171 .sys_rst_ni (rst_ni),
1172
1173 .sel_dp_i (cmd_dp_sel),
1174
1175 // SRAM interface
1176 .sram_l2m_o (sub_sram_l2m[IoModeReadCmd]),
1177 .sram_m2l_i (sub_sram_m2l[IoModeReadCmd]),
1178
1179 // S2P
1180 .s2p_valid_i (s2p_data_valid),
1181 .s2p_byte_i (s2p_data),
1182
1183 // P2S
1184 .p2s_valid_o (sub_p2s_valid [IoModeReadCmd]),
1185 .p2s_byte_o (sub_p2s_data [IoModeReadCmd]),
1186 .p2s_sent_i (sub_p2s_sent [IoModeReadCmd]),
1187
1188 .spi_mode_i (spi_mode),
1189
1190 .cmd_info_i (cmd_info_broadcast),
1191 .cmd_info_idx_i (cmd_info_idx_broadcast),
1192
1193 .readbuf_threshold_i (readbuf_threshold),
1194 .sys_readbuf_clr_i (readbuf_clr),
1195
1196 .addr_4b_en_i (cfg_addr_4b_en),
1197
1198 .mailbox_en_i (cfg_mailbox_en ),
1199 .cfg_intercept_en_mbx_i (cfg_intercept_en.mbx),
1200
1201 .mailbox_addr_i (mailbox_addr ),
1202 .mailbox_assumed_o (intercept.mbx ),
1203
1204 .readbuf_address_o (readbuf_addr_sck),
1205
1206 .io_mode_o (sub_iomode [IoModeReadCmd]),
1207
1208 .sck_read_watermark_o (flash_sck_readbuf_watermark),
1209 .sck_read_flip_o (flash_sck_readbuf_flip)
1210 );
1211
1212 // Begin: Read Status ==============================================
1213 logic readstatus_qe;
1214 logic [23:0] readstatus_q;
1215 logic [23:0] readstatus_d;
1216
1217 1/1 assign readstatus_qe = reg2hw.flash_status.busy.qe &&
Tests: T9 T12 T15
1218 reg2hw.flash_status.wel.qe &&
1219 reg2hw.flash_status.status.qe;
1220 1/1 assign readstatus_q = { reg2hw.flash_status.status.q,
Tests: T1 T2 T3
1221 reg2hw.flash_status.wel.q,
1222 reg2hw.flash_status.busy.q
1223 };
1224 1/1 assign hw2reg.flash_status.busy.d = readstatus_d[0];
Tests: T1 T2 T3
1225 1/1 assign hw2reg.flash_status.wel.d = readstatus_d[1];
Tests: T1 T2 T3
1226 1/1 assign hw2reg.flash_status.status.d = readstatus_d[23:2];
Tests: T1 T2 T3
1227
1228 1/1 assign sck_status_wr_set = (cmd_only_dp_sel == DpWrEn);
Tests: T1 T2 T3
1229 1/1 assign sck_status_wr_clr = (cmd_only_dp_sel == DpWrDi);
Tests: T1 T2 T3
1230
1231 logic flash_status_sync_fifo_clr;
1232 1/1 assign flash_status_sync_fifo_clr = reg2hw.control.flash_status_fifo_clr.q;
Tests: T1 T2 T3
1233 assign hw2reg.control.flash_status_fifo_clr.d = '0;
1234 assign hw2reg.control.flash_status_fifo_clr.de = 1'b1;
1235
1236 spid_status u_spid_status (
1237 .clk_i (clk_spi_in_buf),
1238 .rst_ni (rst_spi_in_n),
1239
1240 .clk_out_i (clk_spi_out_buf),
1241 .rst_out_ni (rst_spi_out_n),
1242
1243 .clk_csb_i (clk_csb),
1244
1245 .sys_clk_i (clk_i),
1246 .sys_rst_ni (rst_ni),
1247
1248 .sys_csb_deasserted_pulse_i (sys_csb_deasserted_pulse),
1249
1250 .sys_update_clr_i(flash_status_sync_fifo_clr),
1251
1252 .sys_status_we_i (readstatus_qe),
1253 .sys_status_i (readstatus_q),
1254 .sys_status_o (readstatus_d),
1255
1256 .sel_dp_i (cmd_dp_sel),
1257 .cmd_info_i (cmd_info_broadcast),
1258 .cmd_info_idx_i (cmd_info_idx_broadcast),
1259
1260 .outclk_p2s_valid_o (sub_p2s_valid[IoModeStatus]),
1261 .outclk_p2s_byte_o (sub_p2s_data[IoModeStatus]),
1262 .outclk_p2s_sent_i (sub_p2s_sent[IoModeStatus]),
1263
1264 .io_mode_o (sub_iomode[IoModeStatus]),
1265
1266 .inclk_busy_set_i (sck_status_busy_set), // SCK domain
1267
1268 .inclk_we_set_i (sck_status_wr_set),
1269 .inclk_we_clr_i (sck_status_wr_clr),
1270
1271 .inclk_status_commit_i (s2p_data_valid),
1272 .cmd_sync_status_busy_o (cmd_sync_status_busy),
1273 .cmd_sync_status_wel_o (cmd_sync_status_wel),
1274 .sck_status_busy_o (sck_status_busy),
1275 .csb_busy_broadcast_o (csb_status_busy_broadcast), // SCK domain
1276 .scan_rst_ni,
1277 .scanmode_i (scanmode[StatusFifoRstSel])
1278 );
1279
1280 // Tie unused
1281 logic unused_sub_sram_status;
1282 0/1 ==> assign unused_sub_sram_status = ^{
1283 sub_sram_l2m[IoModeStatus],
1284 sub_sram_m2l[IoModeStatus]
1285 };
1286 assign sub_sram_l2m[IoModeStatus] = '0;
1287
1288 // End: Read Status ------------------------------------------------
1289
1290 spid_jedec u_jedec (
1291 .clk_i (clk_spi_in_buf),
1292 .rst_ni (rst_spi_in_n),
1293
1294 .clk_out_i (clk_spi_out_buf),
1295 .rst_out_ni (rst_spi_out_n),
1296
1297 .cmd_sync_pulse_i (cmd_sync_pulse),
1298
1299 .sys_jedec_i (jedec_cfg),
1300
1301 .io_mode_o (sub_iomode[IoModeJedec]),
1302
1303 .sel_dp_i (cmd_dp_sel),
1304 .cmd_info_i (cmd_info_broadcast),
1305 .cmd_info_idx_i (cmd_info_idx_broadcast),
1306
1307 .outclk_p2s_valid_o (sub_p2s_valid[IoModeJedec]),
1308 .outclk_p2s_byte_o (sub_p2s_data[IoModeJedec]),
1309 .outclk_p2s_sent_i (sub_p2s_sent[IoModeJedec])
1310 );
1311 // Tie unused
1312 logic unused_sub_sram_jedec;
1313 0/1 ==> assign unused_sub_sram_jedec = ^{
1314 sub_sram_l2m[IoModeJedec],
1315 sub_sram_m2l[IoModeJedec]
1316 };
1317 assign sub_sram_l2m[IoModeJedec] = '0;
1318
1319 // Begin: Upload ===================================================
1320 spid_upload #(
1321 .CmdFifoBaseAddr (SramCmdFifoIdx),
1322 .CmdFifoDepth (SramCmdFifoDepth),
1323 .AddrFifoBaseAddr (SramAddrFifoIdx),
1324 .AddrFifoDepth (SramAddrFifoDepth),
1325 .PayloadBaseAddr (SramPayloadIdx),
1326 .PayloadDepth (SramPayloadDepth),
1327
1328 .SpiByte ($bits(spi_byte_t))
1329 ) u_upload (
1330 .clk_i (clk_spi_in_buf),
1331 .rst_ni (rst_spi_in_n),
1332
1333 .sys_clk_i (clk_i),
1334 .sys_rst_ni (rst_ni),
1335
1336 .clk_csb_i (clk_csb),
1337
1338 .sel_dp_i (cmd_dp_sel),
1339 .cmd_only_sel_dp_i (cmd_only_dp_sel),
1340
1341 .sck_sram_o (sub_sram_l2m[IoModeUpload]),
1342 .sck_sram_i (sub_sram_m2l[IoModeUpload]),
1343
1344 .sys_cmdfifo_sram_o (sys_sram_l2m[SysSramCmdFifo]),
1345 .sys_cmdfifo_sram_i (sys_sram_m2l[SysSramCmdFifo]),
1346 .sys_cmdfifo_gnt_i (sys_sram_gnt[SysSramCmdFifo]),
1347
1348 .sys_addrfifo_sram_o (sys_sram_l2m[SysSramAddrFifo]),
1349 .sys_addrfifo_sram_i (sys_sram_m2l[SysSramAddrFifo]),
1350 .sys_addrfifo_gnt_i (sys_sram_gnt[SysSramAddrFifo]),
1351
1352 // SYS clock FIFO interface
1353 .sys_cmdfifo_rvalid_o (cmdfifo_rvalid),
1354 .sys_cmdfifo_rready_i (cmdfifo_rready),
1355 .sys_cmdfifo_rdata_o (cmdfifo_rdata),
1356
1357 .sys_addrfifo_rvalid_o (addrfifo_rvalid),
1358 .sys_addrfifo_rready_i (addrfifo_rready),
1359 .sys_addrfifo_rdata_o (addrfifo_rdata),
1360
1361 // Interface: SPI to Parallel
1362 .s2p_valid_i (s2p_data_valid),
1363 .s2p_byte_i (s2p_data),
1364
1365 // Interface: Parallel to SPI
1366 .p2s_valid_o (sub_p2s_valid[IoModeUpload]),
1367 .p2s_data_o (sub_p2s_data [IoModeUpload]),
1368 .p2s_sent_i (sub_p2s_sent [IoModeUpload]),
1369
1370 .spi_mode_i (spi_mode),
1371
1372 .cmd_sync_cfg_addr_4b_en_i (cmd_sync_addr_4b_en),
1373 .cmd_sync_status_wel_i (cmd_sync_status_wel),
1374 .cmd_sync_status_busy_i (cmd_sync_status_busy),
1375
1376 .cmd_only_info_i (cmd_only_info_broadcast),
1377 .cmd_only_info_idx_i (cmd_only_info_idx_broadcast),
1378
1379 .io_mode_o (sub_iomode[IoModeUpload]),
1380
1381 .set_busy_o (sck_status_busy_set),
1382
1383 .sys_cmdfifo_set_o (cmdfifo_set_pulse),
1384 .sys_cmdfifo_notempty_o (cmdfifo_notempty),
1385 .sys_cmdfifo_full_o (), // not used
1386 .sys_addrfifo_notempty_o (addrfifo_notempty),
1387 .sys_addrfifo_full_o (), // not used
1388 .sys_payload_overflow_o (payload_overflow),
1389
1390 .sys_cmdfifo_depth_o (cmdfifo_depth),
1391 .sys_addrfifo_depth_o (addrfifo_depth),
1392 .sys_payload_depth_o (payload_depth),
1393 .sys_payload_start_idx_o (payload_start_idx)
1394 );
1395 // FIFO connect
1396 1/1 assign cmdfifo_rready = reg2hw.upload_cmdfifo.data.re;
Tests: T20 T60 T50
1397 1/1 assign hw2reg.upload_cmdfifo.data.d = cmdfifo_rdata[7:0];
Tests: T1 T2 T3
1398 1/1 assign hw2reg.upload_cmdfifo.busy.d = cmdfifo_rdata[13];
Tests: T1 T2 T3
1399 1/1 assign hw2reg.upload_cmdfifo.wel.d = cmdfifo_rdata[14];
Tests: T1 T2 T3
1400 1/1 assign hw2reg.upload_cmdfifo.addr4b_mode.d = cmdfifo_rdata[15];
Tests: T1 T2 T3
1401 logic unused_cmdfifo_re;
1402 1/1 assign unused_cmdfifo_re = ^{reg2hw.upload_cmdfifo.busy.re,
Tests: T20 T60 T50
1403 reg2hw.upload_cmdfifo.wel.re,
1404 reg2hw.upload_cmdfifo.addr4b_mode.re};
1405 logic unused_cmdfifo_q;
1406 1/1 assign unused_cmdfifo_q = ^{reg2hw.upload_cmdfifo.data.q,
Tests: T1 T2 T3
1407 reg2hw.upload_cmdfifo.busy.q,
1408 reg2hw.upload_cmdfifo.wel.q,
1409 reg2hw.upload_cmdfifo.addr4b_mode.q,
1410 cmdfifo_rdata[12:8],
1411 cmdfifo_rvalid};
1412
1413 1/1 assign addrfifo_rready = reg2hw.upload_addrfifo.re;
Tests: T20 T50 T62
1414 1/1 assign hw2reg.upload_addrfifo.d = addrfifo_rdata;
Tests: T1 T2 T3
1415 logic unused_addrfifo_q;
1416 1/1 assign unused_addrfifo_q = ^{reg2hw.upload_addrfifo.q, addrfifo_rvalid};
Tests: T1 T2 T3
1417
1418 // Connect UPLOAD_STATUS
1419 assign hw2reg.upload_status.cmdfifo_depth.de = 1'b1;
1420 1/1 assign hw2reg.upload_status.cmdfifo_depth.d = cmdfifo_depth;
Tests: T1 T2 T3
1421
1422 assign hw2reg.upload_status.cmdfifo_notempty.de = 1'b1;
1423 1/1 assign hw2reg.upload_status.cmdfifo_notempty.d = cmdfifo_notempty;
Tests: T1 T2 T3
1424
1425 assign hw2reg.upload_status.addrfifo_depth.de = 1'b 1;
1426 1/1 assign hw2reg.upload_status.addrfifo_depth.d = addrfifo_depth;
Tests: T1 T2 T3
1427
1428 assign hw2reg.upload_status.addrfifo_notempty.de = 1'b 1;
1429 1/1 assign hw2reg.upload_status.addrfifo_notempty.d = addrfifo_notempty;
Tests: T1 T2 T3
1430
1431 assign hw2reg.upload_status2.payload_depth.de = 1'b 1;
1432 1/1 assign hw2reg.upload_status2.payload_depth.d = payload_depth;
Tests: T1 T2 T3
1433
1434 assign hw2reg.upload_status2.payload_start_idx.de = 1'b 1;
1435 1/1 assign hw2reg.upload_status2.payload_start_idx.d = payload_start_idx;
Tests: T1 T2 T3
1436 `ASSERT_INIT(PayloadStartIdxWidthMatch_A,
1437 $bits(hw2reg.upload_status2.payload_start_idx.d) == PayloadIdxW)
1438
1439 // End: Upload ---------------------------------------------------
1440
1441 // Begin: Address 3B/4B Tracker ====================================
1442 1/1 assign cmd_en4b_pulse = cmd_only_dp_sel == DpEn4B;
Tests: T1 T2 T3
1443 1/1 assign cmd_ex4b_pulse = cmd_only_dp_sel == DpEx4B;
Tests: T1 T2 T3
1444 spid_addr_4b u_spid_addr_4b (
1445 .sys_clk_i (clk_i ),
1446 .sys_rst_ni (rst_ni),
1447
1448 .spi_clk_i (clk_spi_in_buf),
1449
1450 .cmd_sync_pulse_i (cmd_sync_pulse),
1451
1452 .reg2hw_addr_mode_addr_4b_en_q_i (reg2hw.addr_mode.addr_4b_en.q),
1453 .reg2hw_addr_mode_addr_4b_en_qe_i (reg2hw.addr_mode.addr_4b_en.qe),
1454 .hw2reg_addr_mode_pending_d_o (hw2reg.addr_mode.pending.d),
1455 .hw2reg_addr_mode_addr_4b_en_d_o (hw2reg.addr_mode.addr_4b_en.d),
1456
1457 .spi_cfg_addr_4b_en_o (cfg_addr_4b_en), // broadcast
1458 .cmd_sync_cfg_addr_4b_en_o (cmd_sync_addr_4b_en), // early output for upload
1459
1460 .spi_addr_4b_set_i (cmd_en4b_pulse), // EN4B command
1461 .spi_addr_4b_clr_i (cmd_ex4b_pulse) // EX4B command
1462 );
1463 // End: Address 3B/4B Tracker ------------------------------------
1464
1465 /////////////////////
1466 // SPI Passthrough //
1467 /////////////////////
1468
1469 // Passthrough block
1470 // signal: sys_csb_syncd -> sysclock 2FF CSb
1471 // signal: sys_busy -> output of u_status readstatus_d[0]
1472 // set by CSb deassertion pulse & BUSY(SCK)
1473 // clr by CSb = 1 & SW writing 0
1474 //
1475 // NOTE: there will be a gap between the actual assertion of CSb and the CSb
1476 // syncd event visible in the u_status BUSY logic (2FF @ SYS_CLK). So,
1477 // there's chance that the SW may clear the BUSY right at the CSb
1478 // assertion event. If that happens, passthrough block may set during SPI
1479 // transaction. The behavior of the SPI_DEVICE in this scenario is
1480 // undeterminstic.
1481 logic passthrough_block;
1482 1/1 assign passthrough_block = csb_status_busy_broadcast;
Tests: T1 T2 T3
1483
1484 spi_passthrough u_passthrough (
1485 .clk_i (clk_spi_in_buf),
1486 .rst_ni (rst_spi_in_n),
1487 .clk_out_i (clk_spi_out_buf),
1488 .rst_out_ni(rst_spi_out_n),
1489
1490 .cfg_cmd_filter_i (cmd_filter),
1491
1492 .cfg_addr_mask_i (addr_swap_mask),
1493 .cfg_addr_value_i (addr_swap_data),
1494
1495 .cfg_payload_mask_i (payload_swap_mask),
1496 .cfg_payload_data_i (payload_swap_data),
1497
1498 .cfg_addr_4b_en_i (cfg_addr_4b_en),
1499
1500 .cmd_info_i (cmd_info),
1501
1502 .spi_mode_i (spi_mode),
1503
1504 // Control: BUSY block
1505 .passthrough_block_i (passthrough_block),
1506
1507 // Host SPI
1508 .host_sck_i (cio_sck_i),
1509 .host_csb_i (cio_csb_i),
1510 .host_s_i (cio_sd_i),
1511 .host_s_o (passthrough_sd),
1512 .host_s_en_o (passthrough_sd_en),
1513
1514 // Passthrough to SPI_HOST HWIP
1515 .passthrough_o,
1516 .passthrough_i,
1517
1518 .event_cmd_filtered_o ()
1519 );
1520
1521 //////////////////
1522 // TPM over SPI //
1523 //////////////////
1524 // Instance of spi_tpm
1525 spi_tpm #(
1526 // CmdAddrFifoDepth
1527 .EnLocality (1)
1528 ) u_spi_tpm (
1529 .clk_in_i (clk_spi_in_buf ),
1530 .clk_out_i (clk_spi_out_buf),
1531 .rst_ni (tpm_rst_in_n ),
1532 .rst_out_ni(tpm_rst_out_n),
1533
1534 .sys_clk_i (clk_i),
1535 .sys_rst_ni(rst_ni ),
1536
1537 .sys_tpm_rst_ni(sys_tpm_rst_n),
1538
1539 .csb_i (sck_tpm_csb_buf), // used as data only
1540 .mosi_i (tpm_mosi ),
1541 .miso_o (tpm_miso ),
1542 .miso_en_o (tpm_miso_en ),
1543
1544 .tpm_cap_o (tpm_cap),
1545 .cfg_tpm_en_i (cfg_tpm_en ),
1546 .cfg_tpm_mode_i (cfg_tpm_mode ),
1547 .cfg_tpm_hw_reg_dis_i (cfg_tpm_hw_reg_dis ),
1548 .cfg_tpm_reg_chk_dis_i (cfg_tpm_reg_chk_dis ),
1549 .cfg_tpm_invalid_locality_i (cfg_tpm_invalid_locality),
1550
1551 .sys_access_reg_i (tpm_access ),
1552 .sys_int_enable_reg_i (tpm_int_enable ),
1553 .sys_int_vector_reg_i (tpm_int_vector ),
1554 .sys_int_status_reg_i (tpm_int_status ),
1555 .sys_intf_capability_reg_i (tpm_intf_capability),
1556 .sys_status_reg_i (tpm_status ),
1557 .sys_id_reg_i (tpm_did_vid ),
1558 .sys_rid_reg_i (tpm_rid ),
1559
1560 .sck_sram_o (tpm_sram_l2m),
1561 .sck_sram_i (tpm_sram_m2l),
1562 .sys_sram_o (sys_sram_l2m[SysSramTpmRdFifo]),
1563 .sys_sram_i (sys_sram_m2l[SysSramTpmRdFifo]),
1564 .sys_sram_gnt_i (sys_sram_gnt[SysSramTpmRdFifo]),
1565
1566 .sys_cmdaddr_rvalid_o (tpm_cmdaddr_rvalid),
1567 .sys_cmdaddr_rdata_o (tpm_cmdaddr_rdata ),
1568 .sys_cmdaddr_rready_i (tpm_cmdaddr_rready),
1569
1570 .sys_rdfifo_wvalid_i (tpm_rdfifo_wvalid ),
1571 .sys_rdfifo_wdata_i (tpm_rdfifo_wdata ),
1572 .sys_rdfifo_wready_o (tpm_rdfifo_wready ),
1573 .sys_rdfifo_cmd_end_o (tpm_event_rdfifo_cmd_end),
1574 .sys_tpm_rdfifo_drop_o(tpm_event_rdfifo_drop ),
1575
1576 .sys_wrfifo_release_i(tpm_status_wrfifo_release),
1577
1578 .sys_cmdaddr_notempty_o (tpm_status_cmdaddr_notempty),
1579 .sys_wrfifo_pending_o (tpm_status_wrfifo_pending),
1580 .sys_rdfifo_aborted_o (tpm_status_rdfifo_aborted)
1581 );
1582
1583 // Register connection
1584 // TPM_CAP:
1585 0/1 ==> assign hw2reg.tpm_cap = '{
1586 rev: '{ de: 1'b 1, d: tpm_cap.rev },
1587 locality: '{ de: 1'b 1, d: tpm_cap.locality },
1588 max_wr_size: '{ de: 1'b 1, d: tpm_cap.max_wr_size },
1589 max_rd_size: '{ de: 1'b 1, d: tpm_cap.max_rd_size }
1590 };
1591
1592 // CFG:
1593 1/1 assign cfg_tpm_en = reg2hw.tpm_cfg.en.q;
Tests: T1 T2 T3
1594 1/1 assign cfg_tpm_mode = reg2hw.tpm_cfg.tpm_mode.q;
Tests: T1 T2 T3
1595 1/1 assign cfg_tpm_hw_reg_dis = reg2hw.tpm_cfg.hw_reg_dis.q;
Tests: T1 T2 T3
1596 1/1 assign cfg_tpm_reg_chk_dis = reg2hw.tpm_cfg.tpm_reg_chk_dis.q;
Tests: T1 T2 T3
1597 1/1 assign cfg_tpm_invalid_locality = reg2hw.tpm_cfg.invalid_locality.q;
Tests: T1 T2 T3
1598
1599 // STATUS:
1600 1/1 assign hw2reg.tpm_status = '{
Tests: T1 T2 T3
1601 rdfifo_aborted: '{ d: tpm_status_rdfifo_aborted },
1602 wrfifo_pending: '{ d: tpm_status_wrfifo_pending },
1603 cmdaddr_notempty: '{ d: tpm_status_cmdaddr_notempty }
1604 };
1605
1606 // wrfifo_release is RW0C
1607 1/1 assign tpm_status_wrfifo_release = reg2hw.tpm_status.wrfifo_pending.qe &
Tests: T1 T2 T3
1608 ~reg2hw.tpm_status.wrfifo_pending.q;
1609
1610 // Return-by-HW registers:
1611 // TPM_ACCESS_x, TPM_STS_x, TPM_INT_ENABLE, TPM_INT_VECTOR,
1612 // TPM_INT_STATUS, TPM_INTF_CAPABILITY, TPM_DID_VID, TPM_RID
1613 for (genvar i = 0 ; i < spi_device_reg_pkg::NumLocality ; i++) begin : g_tpm_access
1614 5/5 assign tpm_access[8*i+:8] = reg2hw.tpm_access[i].q;
Tests: T1 T2 T3 | T1 T2 T3 | T1 T2 T3 | T1 T2 T3 | T1 T2 T3
1615 end : g_tpm_access
1616
1617 1/1 assign tpm_int_enable = reg2hw.tpm_int_enable.q;
Tests: T1 T2 T3
1618 1/1 assign tpm_int_vector = reg2hw.tpm_int_vector.q;
Tests: T1 T2 T3
1619 1/1 assign tpm_int_status = reg2hw.tpm_int_status.q;
Tests: T1 T2 T3
1620 1/1 assign tpm_intf_capability = reg2hw.tpm_intf_capability.q;
Tests: T1 T2 T3
1621 1/1 assign tpm_status = reg2hw.tpm_sts.q;
Tests: T1 T2 T3
1622 1/1 assign tpm_did_vid = { reg2hw.tpm_did_vid.did.q ,
Tests: T1 T2 T3
1623 reg2hw.tpm_did_vid.vid.q };
1624 1/1 assign tpm_rid = reg2hw.tpm_rid.q;
Tests: T1 T2 T3
1625
1626 // Command / Address Buffer
1627 logic unused_tpm_cmdaddr;
1628 1/1 assign unused_tpm_cmdaddr = ^{tpm_cmdaddr_rvalid, reg2hw.tpm_cmd_addr};
Tests: T1 T2 T3
1629
1630 1/1 assign tpm_cmdaddr_rready = reg2hw.tpm_cmd_addr.cmd.re;
Tests: T5 T14 T29
1631 1/1 assign hw2reg.tpm_cmd_addr = '{
Tests: T1 T2 T3
1632 addr: tpm_cmdaddr_rdata[23: 0],
1633 cmd: tpm_cmdaddr_rdata[31:24]
1634 };
1635
1636 // Read FIFO (write by SW)
1637 logic unused_tpm_rdfifo;
1638 1/1 assign unused_tpm_rdfifo= tpm_rdfifo_wready;
Tests: T1 T2 T3
1639
1640 1/1 assign tpm_rdfifo_wvalid = reg2hw.tpm_read_fifo.qe;
Tests: T5 T14 T29
1641 1/1 assign tpm_rdfifo_wdata = reg2hw.tpm_read_fifo.q;
Tests: T1 T2 T3
1642
1643 // END: TPM over SPI --------------------------------------------------------
1644
1645 ////////////////////
1646 // Common modules //
1647 ////////////////////
1648
1649 logic [SramDw-1:0] sys_sram_l2m_fw_wmask[2];
1650 1/1 assign tl_sram_egress_h2d = tl_sram_h2d[SPI_DEVICE_EGRESS_BUFFER_IDX];
Tests: T1 T2 T3
1651 1/1 assign tl_sram_d2h[SPI_DEVICE_EGRESS_BUFFER_IDX] = tl_sram_egress_d2h;
Tests: T1 T2 T3
1652 1/1 assign tl_sram_ingress_h2d = tl_sram_h2d[SPI_DEVICE_INGRESS_BUFFER_IDX];
Tests: T1 T2 T3
1653 1/1 assign tl_sram_d2h[SPI_DEVICE_INGRESS_BUFFER_IDX] = tl_sram_ingress_d2h;
Tests: T1 T2 T3
1654
1655 tlul_adapter_sram #(
1656 .SramAw (SramAw),
1657 .SramDw (SramDw),
1658 .Outstanding (1),
1659 .ErrOnRead (1), // write-only memory window
1660 .ByteAccess (0)
1661 ) u_tlul2sram_egress (
1662 .clk_i,
1663 .rst_ni,
1664
1665 .tl_i (tl_sram_egress_h2d),
1666 .tl_o (tl_sram_egress_d2h),
1667 .en_ifetch_i (prim_mubi_pkg::MuBi4False),
1668 .req_o (sys_sram_l2m[SysSramFwEgress].req),
1669 .req_type_o (),
1670 .gnt_i (sys_sram_fw_gnt[SPI_DEVICE_EGRESS_BUFFER_IDX]),
1671 .we_o (sys_sram_l2m[SysSramFwEgress].we),
1672 .addr_o (sys_sram_l2m[SysSramFwEgress].addr),
1673 .wdata_o (sys_sram_l2m[SysSramFwEgress].wdata),
1674 .wmask_o (sys_sram_l2m_fw_wmask[SPI_DEVICE_EGRESS_BUFFER_IDX]), // Not used
1675 .intg_error_o (),
1676 .rdata_i (sys_sram_m2l[SysSramFwEgress].rdata),
1677 .rvalid_i (sys_sram_m2l[SysSramFwEgress].rvalid),
1678 .rerror_i (sys_sram_m2l[SysSramFwEgress].rerror),
1679 .compound_txn_in_progress_o (),
1680 .readback_en_i (prim_mubi_pkg::MuBi4False),
1681 .readback_error_o (),
1682 .wr_collision_i (1'b0),
1683 .write_pending_i (1'b0)
1684 );
1685
1686 tlul_adapter_sram #(
1687 .SramAw (SramAw),
1688 .SramDw (SramDw),
1689 .Outstanding (1),
1690 .ErrOnWrite (1), // read-only memory window
1691 .ByteAccess (0)
1692 ) u_tlul2sram_ingress (
1693 .clk_i,
1694 .rst_ni,
1695
1696 .tl_i (tl_sram_ingress_h2d),
1697 .tl_o (tl_sram_ingress_d2h),
1698 .en_ifetch_i (prim_mubi_pkg::MuBi4False),
1699 .req_o (sys_sram_l2m[SysSramFwIngress].req),
1700 .req_type_o (),
1701 .gnt_i (sys_sram_fw_gnt[SPI_DEVICE_INGRESS_BUFFER_IDX]),
1702 .we_o (sys_sram_l2m[SysSramFwIngress].we),
1703 .addr_o (sys_sram_l2m[SysSramFwIngress].addr),
1704 .wdata_o (sys_sram_l2m[SysSramFwIngress].wdata),
1705 .wmask_o (sys_sram_l2m_fw_wmask[SPI_DEVICE_INGRESS_BUFFER_IDX]), // Not used
1706 .intg_error_o (),
1707 .rdata_i (sys_sram_m2l[SysSramFwIngress].rdata),
1708 .rvalid_i (sys_sram_m2l[SysSramFwIngress].rvalid),
1709 .rerror_i (sys_sram_m2l[SysSramFwIngress].rerror),
1710 .compound_txn_in_progress_o (),
1711 .readback_en_i (prim_mubi_pkg::MuBi4False),
1712 .readback_error_o (),
1713 .wr_collision_i (1'b0),
1714 .write_pending_i (1'b0)
1715 );
1716 1/1 assign sys_sram_l2m[SysSramFwEgress].wstrb =
Tests: T1 T2 T3
1717 sram_mask2strb(sys_sram_l2m_fw_wmask[SPI_DEVICE_EGRESS_BUFFER_IDX]);
1718 1/1 assign sys_sram_l2m[SysSramFwIngress].wstrb =
Tests: T1 T2 T3
1719 sram_mask2strb(sys_sram_l2m_fw_wmask[SPI_DEVICE_INGRESS_BUFFER_IDX]);
1720
1721 logic sys_sram_hw_req;
1722 always_comb begin
1723 1/1 sys_sram_hw_req = 1'b0;
Tests: T1 T2 T3
1724 1/1 for (int unsigned i = 0; i < SysSramEnd; i++) begin
Tests: T1 T2 T3
1725 1/1 if ((i != SysSramFwEgress) && (i != SysSramFwIngress)) begin
Tests: T1 T2 T3
1726 1/1 sys_sram_hw_req |= sys_sram_l2m[i].req;
Tests: T1 T2 T3
1727 end
MISSING_ELSE
1728 end
1729 end
1730
1731 always_comb begin
1732 1/1 for (int unsigned i = 0; i < SysSramEnd; i++) begin
Tests: T1 T2 T3
1733 1/1 sys_sram_req[i] = sys_sram_l2m[i].req;
Tests: T1 T2 T3
1734 end
1735 1/1 if (sys_sram_hw_req) begin
Tests: T1 T2 T3
1736 // Fixed low priority. (Discussed in #10065)
1737 // When HW requests the SRAM access, lower the SW requests (and grant)
1738 1/1 sys_sram_req[SysSramFwEgress] = 1'b0;
Tests: T5 T14 T20
1739 1/1 sys_sram_fw_gnt[SPI_DEVICE_EGRESS_BUFFER_IDX] = 1'b0;
Tests: T5 T14 T20
1740 1/1 sys_sram_req[SysSramFwIngress] = 1'b0;
Tests: T5 T14 T20
1741 1/1 sys_sram_fw_gnt[SPI_DEVICE_INGRESS_BUFFER_IDX] = 1'b0;
Tests: T5 T14 T20
1742 end else begin
1743 1/1 sys_sram_fw_gnt[SPI_DEVICE_EGRESS_BUFFER_IDX] = sys_sram_gnt[SysSramFwEgress];
Tests: T1 T2 T3
1744 1/1 sys_sram_fw_gnt[SPI_DEVICE_INGRESS_BUFFER_IDX] = sys_sram_gnt[SysSramFwIngress];
Tests: T1 T2 T3
1745 end
1746 end
1747
1748 for (genvar i = 0 ; i < SysSramEnd ; i++) begin : g_sram_connect
1749 5/5 assign sys_sram_addr [i] = sys_sram_l2m[i].addr;
Tests: T1 T2 T3 | T1 T2 T3 | T1 T2 T3 | T1 T2 T3 | T1 T2 T3
1750 2/5 ==> assign sys_sram_write [i] = sys_sram_l2m[i].we;
Tests: T1 T2 T3 | T1 T2 T3
1751 3/5 ==> assign sys_sram_wdata [i] = sys_sram_l2m[i].wdata;
Tests: T1 T2 T3 | T1 T2 T3 | T1 T2 T3
1752 2/5 ==> assign sys_sram_wmask [i] = sram_strb2mask(sys_sram_l2m[i].wstrb);
Tests: T1 T2 T3 | T1 T2 T3
1753
1754 5/5 assign sys_sram_m2l[i].rvalid = sys_sram_rvalid[i];
Tests: T1 T2 T3 | T1 T2 T3 | T1 T2 T3 | T1 T2 T3 | T1 T2 T3
1755 5/5 assign sys_sram_m2l[i].rdata = sys_sram_rdata[i];
Tests: T4 T5 T25 | T4 T5 T25 | T4 T5 T25 | T4 T5 T25 | T4 T5 T25
1756 5/5 assign sys_sram_m2l[i].rerror = sys_sram_rerror[i];
Tests: T1 T2 T3 | T1 T2 T3 | T1 T2 T3 | T1 T2 T3 | T1 T2 T3
1757
1758 // There is only ever a single source of requests on the SYS port (SW), so
1759 // requests should always be granted.
1760 `ASSERT(ReqAlwaysAccepted_A, sys_sram_req[i] |-> sys_sram_gnt[i])
1761 end : g_sram_connect
1762
1763 prim_sram_arbiter #(
1764 .N (SysSramEnd),
1765 .SramDw (SramDw),
1766 .SramAw (SramAw),
1767
1768 .EnMask (1'b 1)
1769 ) u_sys_sram_arbiter (
1770 .clk_i,
1771 .rst_ni,
1772
1773 .req_i (sys_sram_req),
1774 .req_addr_i (sys_sram_addr),
1775 .req_write_i (sys_sram_write),
1776 .req_wdata_i (sys_sram_wdata),
1777 .req_wmask_i (sys_sram_wmask),
1778 .gnt_o (sys_sram_gnt),
1779
1780 .rsp_rvalid_o (sys_sram_rvalid),
1781 .rsp_rdata_o (sys_sram_rdata),
1782 .rsp_error_o (sys_sram_rerror),
1783
1784 .sram_req_o (mem_a_req),
1785 .sram_addr_o (mem_a_addr),
1786 .sram_write_o (mem_a_write),
1787 .sram_wdata_o (mem_a_wdata),
1788 .sram_wmask_o (mem_a_wmask),
1789 .sram_rvalid_i (mem_a_rvalid),
1790 .sram_rdata_i (mem_a_rdata),
1791 .sram_rerror_i (mem_a_rerror)
1792 );
1793
1794 // SRAM Wrapper
1795 // The SRAM should only be reset if both modes are inactive.
1796 logic spi_dpram_rst_n;
1797 1/1 assign spi_dpram_rst_n = tpm_rst_in_n | rst_spi_in_n;
Tests: T1 T2 T3
1798
1799 1/1 assign mem_b_req = mem_b_l2m.req;
Tests: T1 T2 T3
1800 1/1 assign mem_b_write = mem_b_l2m.we;
Tests: T1 T2 T3
1801 1/1 assign mem_b_addr = mem_b_l2m.addr;
Tests: T1 T2 T3
1802 1/1 assign mem_b_wdata = mem_b_l2m.wdata;
Tests: T1 T2 T3
1803 1/1 assign mem_b_wmask = sram_strb2mask(mem_b_l2m.wstrb);
Tests: T1 T2 T3
1804
1805 1/1 assign mem_b_m2l.rvalid = mem_b_rvalid;
Tests: T1 T2 T3
1806 1/1 assign mem_b_m2l.rdata = mem_b_rdata;
Tests: T5 T12 T14
1807 1/1 assign mem_b_m2l.rerror = mem_b_rerror;
Tests: T1 T2 T3
1808
1809 spid_dpram #(
1810 .SramType (SramType),
1811 .EnableECC (0),
1812 .EnableParity (1),
1813 .EnableInputPipeline (0),
1814 .EnableOutputPipeline(0)
1815 ) u_spid_dpram (
1816 .clk_sys_i (clk_i),
1817 .rst_sys_ni (rst_ni),
1818
1819 .clk_spi_i (clk_spi_in_buf),
1820 .rst_spi_ni (spi_dpram_rst_n),
1821
1822 .sys_req_i (mem_a_req),
1823 .sys_write_i (mem_a_write),
1824 .sys_addr_i (mem_a_addr),
1825 .sys_wdata_i (mem_a_wdata),
1826 .sys_wmask_i (mem_a_wmask),
1827 .sys_rvalid_o (mem_a_rvalid),
1828 .sys_rdata_o (mem_a_rdata),
1829 .sys_rerror_o (mem_a_rerror),
1830
1831 .spi_req_i (mem_b_req),
1832 .spi_write_i (mem_b_write),
1833 .spi_addr_i (mem_b_addr),
1834 .spi_wdata_i (mem_b_wdata),
1835 .spi_wmask_i (mem_b_wmask),
1836 .spi_rvalid_o (mem_b_rvalid),
1837 .spi_rdata_o (mem_b_rdata),
1838 .spi_rerror_o (mem_b_rerror),
1839
1840 .cfg_i (ram_cfg_i)
1841 );
1842
1843 // Register module
1844 logic [NumAlerts-1:0] alert_test, alerts;
1845 spi_device_reg_top u_reg (
1846 .clk_i,
1847 .rst_ni,
1848
1849 .tl_i (tl_i),
1850 .tl_o (tl_o),
1851
1852 .tl_win_o (tl_sram_h2d),
1853 .tl_win_i (tl_sram_d2h),
1854
1855 .reg2hw,
1856 .hw2reg,
1857
1858 // SEC_CM: BUS.INTEGRITY
1859 .intg_err_o (alerts[0])
1860 );
1861
1862 // Alerts
1863 1/1 assign alert_test = {
Tests: T1 T2 T3