blob: 5dda89fda41cac0b5695f067d4ff93cc77460e7f [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 otp_ctrl_env_pkg::*;
import otp_ctrl_test_pkg::*;
import otp_ctrl_reg_pkg::*;
import mem_bkdr_util_pkg::mem_bkdr_util;
// macro includes
`include "uvm_macros.svh"
`include "dv_macros.svh"
// TB base test ENV_T & CFG_T specification
//
// Specify the parameters for the otp_ctrl_base_test
// This will invoke the UVM registry and link this test type to
// the name 'otp_ctrl_base_test' as a test name passed by UVM_TESTNAME
//
// This is done explicitly only for the prim_pkg::ImplGeneric implementation
// since partner base tests inherit from otp_ctrl_base_test#(CFG_T, ENV_T) and
// specify directly (CFG_T, ENV_T) via the class extension and use a different
// UVM_TESTNAME
if (`PRIM_DEFAULT_IMPL == prim_pkg::ImplGeneric) begin : gen_spec_base_test_params
typedef otp_ctrl_base_test #(.CFG_T(otp_ctrl_env_cfg),
.ENV_T(otp_ctrl_env)) otp_ctrl_base_test_t;
end
wire clk, rst_n;
wire devmode;
wire otp_ctrl_pkg::flash_otp_key_req_t flash_req;
wire otp_ctrl_pkg::flash_otp_key_rsp_t flash_rsp;
wire otp_ctrl_pkg::otbn_otp_key_req_t otbn_req;
wire otp_ctrl_pkg::otbn_otp_key_rsp_t otbn_rsp;
wire otp_ctrl_pkg::sram_otp_key_req_t[NumSramKeyReqSlots-1:0] sram_req;
wire otp_ctrl_pkg::sram_otp_key_rsp_t[NumSramKeyReqSlots-1:0] sram_rsp;
wire [NUM_MAX_INTERRUPTS-1:0] interrupts;
wire intr_otp_operation_done, intr_otp_error;
// Output from close-source OTP, not checked in open-source env.
wire otp_ctrl_pkg::otp_ast_req_t ast_req;
wire [7:0] otp_obs_o;
tlul_pkg::tl_d2h_t prim_tl_o;
// interfaces
clk_rst_if clk_rst_if(.clk(clk), .rst_n(rst_n));
pins_if #(NUM_MAX_INTERRUPTS) intr_if(interrupts);
pins_if #(1) devmode_if(devmode);
// lc_otp interfaces
push_pull_if #(.HostDataWidth(LC_PROG_DATA_SIZE), .DeviceDataWidth(1))
lc_prog_if(.clk(clk), .rst_n(rst_n));
push_pull_if #(.DeviceDataWidth(SRAM_DATA_SIZE))
sram_if[NumSramKeyReqSlots](.clk(clk), .rst_n(rst_n));
push_pull_if #(.DeviceDataWidth(OTBN_DATA_SIZE)) otbn_if(.clk(clk), .rst_n(rst_n));
push_pull_if #(.DeviceDataWidth(FLASH_DATA_SIZE)) flash_addr_if(.clk(clk), .rst_n(rst_n));
push_pull_if #(.DeviceDataWidth(FLASH_DATA_SIZE)) flash_data_if(.clk(clk), .rst_n(rst_n));
tl_if tl_if(.clk(clk), .rst_n(rst_n));
tl_if prim_tl_if(.clk(clk), .rst_n(rst_n));
otp_ctrl_if otp_ctrl_if(.clk_i(clk), .rst_ni(rst_n));
`DV_ALERT_IF_CONNECT()
// edn_clk, edn_rst_n and edn_if are defined and driven in below macro
`DV_EDN_IF_CONNECT
assign otp_ctrl_if.lc_prog_req = lc_prog_if.req;
assign otp_ctrl_if.lc_prog_err = lc_prog_if.d_data;
// Assign to otp_ctrl_if for assertion checks.
assign otp_ctrl_if.lc_prog_ack = lc_prog_if.ack;
assign otp_ctrl_if.flash_acks = flash_data_if.ack;
assign otp_ctrl_if.otbn_ack = otbn_if.ack;
// This signal probes design's alert request to avoid additional logic for triggering alert and
// disable assertions.
// Alert checkings are done independently in otp_ctrl's scb.
// The correctness of this probed signal is checked in otp_ctrl's scb as well.
assign otp_ctrl_if.alert_reqs = dut.alerts[0] | dut.alerts[1];
// connected to interface
wire otp_ext_voltage_h = otp_ctrl_if.ext_voltage_h_io;
// dut
otp_ctrl dut (
.clk_i (clk ),
.rst_ni (rst_n ),
// edn
.clk_edn_i (edn_clk ),
.rst_edn_ni (edn_rst_n ),
.edn_o (edn_if[0].req ),
.edn_i ({edn_if[0].ack, edn_if[0].d_data}),
// bus interfaces
.core_tl_i (tl_if.h2d ),
.core_tl_o (tl_if.d2h ),
.prim_tl_i (prim_tl_if.h2d),
.prim_tl_o (prim_tl_if.d2h),
// interrupt
.intr_otp_operation_done_o (intr_otp_operation_done),
.intr_otp_error_o (intr_otp_error),
// alert
.alert_rx_i (alert_rx ),
.alert_tx_o (alert_tx ),
// ast
.obs_ctrl_i (otp_ctrl_if.obs_ctrl_i),
.otp_obs_o (otp_obs_o),
.otp_ast_pwr_seq_o (ast_req),
.otp_ast_pwr_seq_h_i (otp_ctrl_if.otp_ast_pwr_seq_h_i),
// pwrmgr
.pwr_otp_i (otp_ctrl_if.pwr_otp_init_i),
.pwr_otp_o ({otp_ctrl_if.pwr_otp_done_o, otp_ctrl_if.pwr_otp_idle_o}),
// lc
.lc_otp_vendor_test_i (otp_ctrl_if.otp_vendor_test_ctrl_i),
.lc_otp_vendor_test_o (otp_ctrl_if.otp_vendor_test_status_o),
.lc_otp_program_i ({lc_prog_if.req, lc_prog_if.h_data}),
.lc_otp_program_o ({lc_prog_if.d_data, lc_prog_if.ack}),
.lc_creator_seed_sw_rw_en_i (otp_ctrl_if.lc_creator_seed_sw_rw_en_i),
.lc_seed_hw_rd_en_i (otp_ctrl_if.lc_seed_hw_rd_en_i),
.lc_dft_en_i (otp_ctrl_if.lc_dft_en_i),
.lc_escalate_en_i (otp_ctrl_if.lc_escalate_en_i),
.lc_check_byp_en_i (otp_ctrl_if.lc_check_byp_en_i),
.otp_lc_data_o (otp_ctrl_if.lc_data_o),
// keymgr
.otp_keymgr_key_o (otp_ctrl_if.keymgr_key_o),
// flash
.flash_otp_key_i (flash_req),
.flash_otp_key_o (flash_rsp),
// sram
.sram_otp_key_i (sram_req),
.sram_otp_key_o (sram_rsp),
// otbn
.otbn_otp_key_i (otbn_req),
.otbn_otp_key_o (otbn_rsp),
.otp_hw_cfg_o (otp_ctrl_if.otp_hw_cfg_o),
.otp_ext_voltage_h_io (otp_ext_voltage_h),
//scan
.scan_en_i (otp_ctrl_if.scan_en_i),
.scan_rst_ni (otp_ctrl_if.scan_rst_ni),
.scanmode_i (otp_ctrl_if.scanmode_i),
// Test-related GPIO output
.cio_test_o (otp_ctrl_if.cio_test_o),
.cio_test_en_o (otp_ctrl_if.cio_test_en_o)
);
for (genvar i = 0; i < NumSramKeyReqSlots; i++) begin : gen_sram_pull_if
assign sram_req[i] = sram_if[i].req;
assign sram_if[i].ack = sram_rsp[i].ack;
assign sram_if[i].d_data = {sram_rsp[i].key, sram_rsp[i].nonce, sram_rsp[i].seed_valid};
assign otp_ctrl_if.sram_acks[i] = sram_rsp[i].ack;
initial begin
uvm_config_db#(virtual push_pull_if#(.DeviceDataWidth(SRAM_DATA_SIZE)))::set(null,
$sformatf("*env.m_sram_pull_agent[%0d]*", i), "vif", sram_if[i]);
end
end
assign otbn_req = otbn_if.req;
assign otbn_if.ack = otbn_rsp.ack;
assign otbn_if.d_data = {otbn_rsp.key, otbn_rsp.nonce, otbn_rsp.seed_valid};
assign flash_req = {flash_data_if.req, flash_addr_if.req};
assign flash_data_if.ack = flash_rsp.data_ack;
assign flash_addr_if.ack = flash_rsp.addr_ack;
assign flash_data_if.d_data = {flash_rsp.key, flash_rsp.seed_valid};
assign flash_addr_if.d_data = {flash_rsp.key, flash_rsp.seed_valid};
assign interrupts[OtpOperationDone] = intr_otp_operation_done;
assign interrupts[OtpErr] = intr_otp_error;
// Instantitate the memory backdoor util instance only for OS implementation
// Proprietary IP will instantiate their own backdoor util
if (`PRIM_DEFAULT_IMPL == prim_pkg::ImplGeneric) begin : gen_impl_generic
`define MEM_MODULE_PATH \
tb.dut.u_otp.gen_generic.u_impl_generic.u_prim_ram_1p_adv
`define MEM_ARRAY_PATH \
`MEM_MODULE_PATH.u_mem.gen_generic.u_impl_generic.mem
initial begin : mem_bkdr_util_gen
mem_bkdr_util m_mem_bkdr_util;
m_mem_bkdr_util = new(.name("mem_bkdr_util"),
.path(`DV_STRINGIFY(`MEM_ARRAY_PATH)),
.depth($size(`MEM_ARRAY_PATH)),
.n_bits($bits(`MEM_ARRAY_PATH)),
.err_detection_scheme(mem_bkdr_util_pkg::EccHamming_22_16));
uvm_config_db#(mem_bkdr_util)::set(null, "*.env", "mem_bkdr_util", m_mem_bkdr_util);
end : mem_bkdr_util_gen
`undef MEM_ARRAY_PATH
`undef MEM_MODULE_PATH
end : gen_impl_generic
initial begin
// DV forced otp_cmd_i to reach invalid state, thus violate the assertions
$assertoff(0, tb.dut.gen_partitions[3].gen_buffered.u_part_buf.OtpErrorState_A);
$assertoff(0, tb.dut.gen_partitions[4].gen_buffered.u_part_buf.OtpErrorState_A);
$assertoff(0, tb.dut.gen_partitions[5].gen_buffered.u_part_buf.OtpErrorState_A);
$assertoff(0, tb.dut.gen_partitions[6].gen_buffered.u_part_buf.OtpErrorState_A);
// 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#(virtual clk_rst_if)::set(null, "*.env",
"clk_rst_vif_otp_ctrl_prim_reg_block", clk_rst_if);
uvm_config_db#(virtual tl_if)::set(null, "*.env.m_tl_agent_otp_ctrl_core_reg_block*",
"vif", tl_if);
uvm_config_db#(virtual tl_if)::set(null, "*.env.m_tl_agent_otp_ctrl_prim_reg_block",
"vif", prim_tl_if);
uvm_config_db#(virtual push_pull_if#(.DeviceDataWidth(OTBN_DATA_SIZE)))::set(null,
"*env.m_otbn_pull_agent*", "vif", otbn_if);
uvm_config_db#(virtual push_pull_if#(.DeviceDataWidth(FLASH_DATA_SIZE)))::set(null,
"*env.m_flash_data_pull_agent*", "vif", flash_data_if);
uvm_config_db#(virtual push_pull_if#(.DeviceDataWidth(FLASH_DATA_SIZE)))::set(null,
"*env.m_flash_addr_pull_agent*", "vif", flash_addr_if);
uvm_config_db#(virtual push_pull_if#(.HostDataWidth(LC_PROG_DATA_SIZE), .DeviceDataWidth(1)))::
set(null, "*env.m_lc_prog_pull_agent*", "vif", lc_prog_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 otp_ctrl_if)::set(null, "*.env", "otp_ctrl_vif", otp_ctrl_if);
$timeformat(-12, 0, " ps", 12);
run_test();
end
endmodule