blob: ef161c86dc24c9645e0e2783e50005bc0e16db74 [file] [log] [blame]
// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
//
module tb;
// dep packages
import uvm_pkg::*;
import dv_utils_pkg::*;
import spi_host_env_pkg::*;
import spi_host_test_pkg::*;
import spi_host_reg_pkg::*;
import lc_ctrl_pkg::*;
import spi_device_pkg::passthrough_req_t;
import spi_device_pkg::passthrough_rsp_t;
// macro includes
`include "uvm_macros.svh"
`include "dv_macros.svh"
wire clk, rst_n;
wire devmode;
wire [NUM_MAX_INTERRUPTS-1:0] interrupts;
wire [3:0] si_pulldown;
wire [3:0] so_pulldown;
lc_tx_t scanmode_i;
logic cio_sck_o;
logic cio_sck_en_o;
logic [NumCS-1:0] cio_csb_o;
logic [NumCS-1:0] cio_csb_en_o;
logic [3:0] cio_sd_o;
logic [3:0] cio_sd_en_o;
logic [3:0] cio_sd_i;
logic intr_error;
logic intr_event;
passthrough_req_t passthrough_i;
passthrough_rsp_t passthrough_o;
// interfaces
clk_rst_if clk_rst_if(.clk(clk), .rst_n(rst_n));
pins_if #(1) devmode_if(devmode);
pins_if #(NUM_MAX_INTERRUPTS) intr_if(.pins(interrupts));
tl_if tl_if(.clk(clk), .rst_n(rst_n));
spi_if spi_if(.rst_n(rst_n));
spi_passthrough_if spi_passthrough_if(.rst_n(rst_n));
`DV_ALERT_IF_CONNECT()
// dut
spi_host dut (
.clk_i (clk),
.rst_ni (rst_n),
// tl i/f
.tl_i (tl_if.h2d),
.tl_o (tl_if.d2h),
// alerts
.alert_rx_i (alert_rx),
.alert_tx_o (alert_tx),
// spi i/o
.cio_sck_o (cio_sck_o),
.cio_sck_en_o (cio_sck_en_o),
.cio_csb_o (cio_csb_o),
.cio_csb_en_o (cio_csb_en_o),
.cio_sd_o (cio_sd_o),
.cio_sd_en_o (cio_sd_en_o),
.cio_sd_i (cio_sd_i),
// passthrough i/o
.passthrough_i (passthrough_i),
.passthrough_o (passthrough_o),
// intr i/f
.intr_error_o (intr_error),
.intr_spi_event_o (intr_event)
);
assign passthrough_i.passthrough_en = spi_passthrough_if.passthrough_en;
assign passthrough_i.sck_en = spi_passthrough_if.sck_en;
assign passthrough_i.csb_en = spi_passthrough_if.csb_en;
assign passthrough_i.s_en = spi_passthrough_if.s_en;
assign passthrough_i.csb = spi_passthrough_if.csb;
assign passthrough_i.sck = spi_passthrough_if.sck;
assign passthrough_i.s = spi_passthrough_if.is;
assign spi_passthrough_if.os = passthrough_o.s;
assign spi_passthrough_if.cio_sck_o = cio_sck_o;
assign spi_passthrough_if.cio_sck_en_o = cio_sck_en_o;
assign spi_passthrough_if.cio_csb_o = cio_csb_o;
assign spi_passthrough_if.cio_csb_en_o = cio_csb_en_o;
assign spi_passthrough_if.cio_sd_en_o = cio_sd_en_o;
assign spi_passthrough_if.cio_sd_o = cio_sd_o;
assign cio_sd_i = spi_passthrough_if.passthrough_en ? spi_passthrough_if.cio_sd_i : si_pulldown;
// configure spi_if i/o
assign spi_if.sck = (cio_sck_en_o) ? cio_sck_o : 1'bz;
for (genvar i = 0; i < 4; i++) begin : gen_tri_state
pullup (weak1) pd_in_i (si_pulldown[i]);
pullup (weak1) pd_out_i (so_pulldown[i]);
assign spi_if.sio[i] = (cio_sd_en_o[i]) ? cio_sd_o[i] : 'z;
assign (highz0, pull1) spi_if.sio[i] = !cio_sd_en_o[i];
assign si_pulldown[i] = spi_if.sio[i];
assign spi_if.csb[i] = (i < NumCS && cio_csb_en_o[i]) ? cio_csb_o[i] : 1'b1;
end
assign interrupts[SpiHostError] = intr_error;
assign interrupts[SpiHostEvent] = intr_event;
initial begin
// drive clk and rst_n from clk_if
clk_rst_if.set_active();
uvm_config_db#(virtual clk_rst_if)::set(null, "*.env", "clk_rst_vif", clk_rst_if);
uvm_config_db#(intr_vif)::set(null, "*.env", "intr_vif", intr_if);
uvm_config_db#(devmode_vif)::set(null, "*.env", "devmode_vif", devmode_if);
uvm_config_db#(virtual spi_passthrough_if)::set(null, "*.env", "spi_passthrough_vif",
spi_passthrough_if);
uvm_config_db#(virtual tl_if)::set(null, "*.env.m_tl_agent*", "vif", tl_if);
uvm_config_db#(virtual spi_if)::set(null, "*.env.m_spi_agent*", "vif", spi_if);
$timeformat(-12, 0, " ps", 12);
run_test();
end
`ASSERT(Sck_A, passthrough_i.passthrough_en -> passthrough_i.sck == cio_sck_o, clk, !rst_n)
`ASSERT(Sck_En_A,passthrough_i.passthrough_en -> passthrough_i.sck_en == cio_sck_en_o,
clk, !rst_n)
`ASSERT(Csb_A, passthrough_i.passthrough_en -> passthrough_i.csb == cio_csb_o, clk, !rst_n)
`ASSERT(Csb_En_A,passthrough_i.passthrough_en -> passthrough_i.csb_en == cio_csb_en_o,
clk, !rst_n)
`ASSERT(S_En_A, passthrough_i.passthrough_en -> passthrough_i.s_en == cio_sd_en_o, clk, !rst_n)
`ASSERT(Sd_O_A, passthrough_i.passthrough_en -> passthrough_i.s == cio_sd_o, clk, !rst_n)
`ASSERT(Sd_I_A, passthrough_i.passthrough_en -> passthrough_o.s == cio_sd_i, clk, !rst_n)
endmodule