From 8364a5de0b75e228d5ff575ae604e4d88eec5ff2 Mon Sep 17 00:00:00 2001 From: Adrian Lees Date: Wed, 5 Apr 2023 23:43:12 +0100 Subject: [PATCH] [chip_tb] Integrate usbdpi into chip tb Initial integration of usbdpi model into chip dvsim/tb; usbdev_test is up and running Simple chip_sw_usbdev_dpi_vseq created but incomplete. Include workaround for mmio32 routines reading X from usbdev. Added pull up resistors in diff receiver; driven by usbdev_aon_wake module in pinmux. Signed-off-by: Adrian Lees --- hw/dv/dpi/usbdpi/usbdpi.c | 27 +-- hw/dv/dpi/usbdpi/usbdpi.h | 1 + hw/dv/dpi/usbdpi/usbdpi.sv | 50 ++++-- hw/dv/sv/usb20_agent/usb20_usbdpi.core | 16 ++ hw/dv/sv/usb20_agent/usb20_usbdpi.sv | 162 ++++++++++++++++++ .../rtl/prim_generic_usb_diff_rx.sv | 10 +- hw/top_earlgrey/data/chip_testplan.hjson | 7 + hw/top_earlgrey/dv/chip_sim.core | 2 + hw/top_earlgrey/dv/chip_sim_cfg.hjson | 9 + hw/top_earlgrey/dv/env/chip_env.core | 1 + .../dv/env/seq_lib/chip_sw_usbdev_dpi_vseq.sv | 18 ++ .../dv/env/seq_lib/chip_vseq_list.sv | 1 + hw/top_earlgrey/dv/tb/tb.sv | 9 + sw/device/lib/dif/dif_usbdev.c | 10 ++ sw/device/lib/testing/pinmux_testutils.c | 24 +++ sw/device/tests/BUILD | 1 + sw/device/tests/usbdev_test.c | 5 - 17 files changed, 314 insertions(+), 39 deletions(-) create mode 100644 hw/dv/sv/usb20_agent/usb20_usbdpi.core create mode 100644 hw/dv/sv/usb20_agent/usb20_usbdpi.sv create mode 100644 hw/top_earlgrey/dv/env/seq_lib/chip_sw_usbdev_dpi_vseq.sv diff --git a/hw/dv/dpi/usbdpi/usbdpi.c b/hw/dv/dpi/usbdpi/usbdpi.c index 8c3c9c5b55123e..b82c0445885ca2 100644 --- a/hw/dv/dpi/usbdpi/usbdpi.c +++ b/hw/dv/dpi/usbdpi/usbdpi.c @@ -62,7 +62,8 @@ static void setDeviceConfiguration(usbdpi_ctx_t *ctx, uint8_t config); static void setTestStatus(usbdpi_ctx_t *ctx, uint32_t status, const char *msg); // Change DP and DN outputs from host -static uint32_t set_driving(usbdpi_ctx_t *ctx, uint32_t d2p, uint32_t newval); +static uint32_t set_driving(usbdpi_ctx_t *ctx, uint32_t d2p, uint32_t newval, + bool p2d_oe); // Try to send OUT transfer. Optionally expect Status packet (eg. ACK|NAK) in // response @@ -181,6 +182,7 @@ void usbdpi_device_to_host(void *ctx_void, const svBitVecVal *usb_d2p) { "drives\n", ctx->frame, ctx->tick_bits, st_states[ctx->state], hs_states[ctx->hostSt]); + // TODO: stop the test break; // Device to host transmission; collect the bits @@ -193,14 +195,13 @@ void usbdpi_device_to_host(void *ctx_void, const svBitVecVal *usb_d2p) { case ST_IDLE: // Nothing to do + ctx->state = ST_GET; break; default: assert(!"Invalid/unknown state"); break; } - - ctx->state = ST_GET; } else { if (ctx->state == ST_GET) { ctx->state = ST_IDLE; @@ -1046,8 +1047,9 @@ void testUnimplEp(usbdpi_ctx_t *ctx, uint8_t pid, uint8_t device, } } -// Change DP and DN outputs from host -uint32_t set_driving(usbdpi_ctx_t *ctx, uint32_t d2p, uint32_t newval) { +// Change host outputs +uint32_t set_driving(usbdpi_ctx_t *ctx, uint32_t d2p, uint32_t newval, + bool p2d_oe) { // Always maintain the current state of VBUS uint32_t driving = ctx->driving & P2D_SENSE; if (d2p & D2P_DNPU) { @@ -1064,6 +1066,10 @@ uint32_t set_driving(usbdpi_ctx_t *ctx, uint32_t d2p, uint32_t newval) { driving |= P2D_DN; } } + // Enable host output drivers? + if (p2d_oe) { + driving |= P2D_OE; + } return driving; } @@ -1286,7 +1292,7 @@ uint8_t usbdpi_host_to_device(void *ctx_void, const svBitVecVal *usb_d2p) { case ST_SYNC: dat = ((USB_SYNC & ctx->bit)) ? P2D_DP : P2D_DN; - ctx->driving = set_driving(ctx, d2p, dat); + ctx->driving = set_driving(ctx, d2p, dat, true); force_stat = 1; ctx->bit <<= 1; if (ctx->bit == 0x100) { @@ -1307,7 +1313,7 @@ uint8_t usbdpi_host_to_device(void *ctx_void, const svBitVecVal *usb_d2p) { ctx->linebits = (ctx->linebits << 1); } else if (ctx->byte >= sending->num_bytes) { ctx->state = ST_EOP; - ctx->driving = set_driving(ctx, d2p, 0); // SE0 + ctx->driving = set_driving(ctx, d2p, 0, true); // SE0 ctx->bit = 1; force_stat = 1; } else { @@ -1329,19 +1335,20 @@ uint8_t usbdpi_host_to_device(void *ctx_void, const svBitVecVal *usb_d2p) { } break; case ST_EOP0: - ctx->driving = set_driving(ctx, d2p, 0); // SE0 + ctx->driving = set_driving(ctx, d2p, 0, true); // SE0 ctx->state = ST_EOP; break; case ST_EOP: // SE0 SE0 J if (ctx->bit == 4) { - ctx->driving = set_driving(ctx, d2p, P2D_DP); // J + ctx->driving = set_driving(ctx, d2p, P2D_DP, true); // J } if (ctx->bit == 8) { usbdpi_transfer_t *sending = ctx->sending; assert(sending); // Stop driving: host pulldown to SE0 unless there is a pullup on DP - ctx->driving = set_driving(ctx, d2p, (d2p & D2P_PU) ? P2D_DP : 0); + ctx->driving = + set_driving(ctx, d2p, (d2p & D2P_PU) ? P2D_DP : 0, false); if (ctx->byte == sending->data_start) { ctx->bit = 1; ctx->state = ST_SYNC; diff --git a/hw/dv/dpi/usbdpi/usbdpi.h b/hw/dv/dpi/usbdpi/usbdpi.h index eb2be17868603f..18fb351403bf94 100644 --- a/hw/dv/dpi/usbdpi/usbdpi.h +++ b/hw/dv/dpi/usbdpi/usbdpi.h @@ -81,6 +81,7 @@ typedef uint32_t svBitVecVal; #define P2D_DN 2 #define P2D_DP 4 #define P2D_D 8 +#define P2D_OE 0x10 /* Remember these go LSB first */ diff --git a/hw/dv/dpi/usbdpi/usbdpi.sv b/hw/dv/dpi/usbdpi/usbdpi.sv index 67309933d27058..4fe801b13f4c78 100644 --- a/hw/dv/dpi/usbdpi/usbdpi.sv +++ b/hw/dv/dpi/usbdpi/usbdpi.sv @@ -11,14 +11,16 @@ module usbdpi #( parameter string NAME = "usb0", - parameter LOG_LEVEL = 1 + parameter int LOG_LEVEL = 1 )( input logic clk_i, input logic rst_ni, input logic clk_48MHz_i, + output logic dp_en_p2d, output logic dp_p2d, input logic dp_d2p, input logic dp_en_d2p, + output logic dn_en_p2d, output logic dn_p2d, input logic dn_d2p, input logic dn_en_d2p, @@ -52,7 +54,6 @@ module usbdpi #( initial begin ctx = usbdpi_create(NAME, LOG_LEVEL); - sense_p2d = 1'b0; end final begin @@ -146,7 +147,7 @@ module usbdpi #( // Test steps typedef enum bit [6:0] { - STEP_BUS_RESET = 0, + STEP_BUS_RESET = 7'h0, STEP_SET_DEVICE_ADDRESS, STEP_GET_DEVICE_DESCRIPTOR, STEP_GET_CONFIG_DESCRIPTOR, @@ -169,13 +170,13 @@ module usbdpi #( STEP_ENDPT_UNIMPL_IN, STEP_DEVICE_UK_SETUP, STEP_IDLE_START, - STEP_IDLE_END = STEP_IDLE_START + 4, + STEP_IDLE_END = STEP_IDLE_START + 7'h4, // usbdev_stream_test - STEP_STREAM_SERVICE = 'h20, + STEP_STREAM_SERVICE = 7'h20, // Disconnect the device and stop - STEP_BUS_DISCONNECT = 'h7f + STEP_BUS_DISCONNECT = 7'h7f } usbdpi_test_step_t; // Make usb_monitor diagnostic information viewable in waveforms @@ -212,22 +213,33 @@ module usbdpi #( assign d2p = {dp_d2p, dp_en_d2p, dn_d2p, dn_en_d2p, d_d2p, d_en_d2p, se0_d2p, tx_use_d_se0_d2p, pullupdp_d2p, pullupdn_d2p, rx_enable}; - always_ff @(posedge clk_48MHz_i) begin - if (!sense_p2d || pullup_detect) begin - automatic byte p2d = usbdpi_host_to_device(ctx, d2p); - d_last <= d_p2d; - dp_int <= p2d[2]; - dn_int <= p2d[1]; - sense_p2d <= p2d[0]; - unused_dummy <= |p2d[7:4]; - d2p_r <= d2p; - if (d2p_r != d2p) begin - usbdpi_device_to_host(ctx, d2p); - end - end else begin // if (pullup_detect) + always_ff @(posedge clk_48MHz_i or negedge rst_ni) begin + if (!rst_ni) begin + sense_p2d <= 1'b0; + dp_en_p2d <= 1'b0; + dn_en_p2d <= 1'b0; d_last <= 0; dp_int <= 0; dn_int <= 0; + end else begin + if (!sense_p2d || pullup_detect) begin + automatic byte p2d = usbdpi_host_to_device(ctx, d2p); + d_last <= d_p2d; + dp_en_p2d <= p2d[4]; + dn_en_p2d <= p2d[4]; + dp_int <= p2d[2]; + dn_int <= p2d[1]; + sense_p2d <= p2d[0]; + unused_dummy <= |p2d[7:5]; + d2p_r <= d2p; + if (d2p_r != d2p) begin + usbdpi_device_to_host(ctx, d2p); + end + end else begin + d_last <= 0; + dp_int <= 0; + dn_int <= 0; + end end end diff --git a/hw/dv/sv/usb20_agent/usb20_usbdpi.core b/hw/dv/sv/usb20_agent/usb20_usbdpi.core new file mode 100644 index 00000000000000..45a148c8a76d9f --- /dev/null +++ b/hw/dv/sv/usb20_agent/usb20_usbdpi.core @@ -0,0 +1,16 @@ +CAPI=2: +# Copyright lowRISC contributors. +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 +name: "lowrisc:dv:usb20_usbdpi:0.1" +description: "USB20-USBDPI" + +filesets: + files_rtl: + files: + - usb20_usbdpi.sv: { file_type: systemVerilogSource } + +targets: + default: + filesets: + - files_rtl diff --git a/hw/dv/sv/usb20_agent/usb20_usbdpi.sv b/hw/dv/sv/usb20_agent/usb20_usbdpi.sv new file mode 100644 index 00000000000000..2b868cc818bb35 --- /dev/null +++ b/hw/dv/sv/usb20_agent/usb20_usbdpi.sv @@ -0,0 +1,162 @@ +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +module usb20_usbdpi ( + input clk_i, + input rst_ni, + + // VBUS/SENSE is driven high to activate/power the device. + output usb_sense_o, + + // Bidirectional, differential bus. + inout usb_p, + inout usb_n +); + + // Functioning sketch of integration of USBDPI model into dv top-level tb + // as a connectivity and function test for ASIC + + // This module integrates the existing `usbdpi` module into the DV chip test + // bench, reconstructing the two unidirectional buses and driver enables that + // the DPI model requires for its operation, using just the bare bidirectional + // USB signals. + // + // Nomenclature notes: + // dp (or p) and dn (or n) are the two signals of the differential USB + // d2p means device to DPI + // p2d means DPI to device + + // VBUS/SENSE output from DPI + wire usb_sense_p2d; + // DPI driver enables + wire usb_dp_en_p2d; + wire usb_dn_en_p2d; + // DPI driver outputs + wire usb_dp_p2d; + wire usb_dn_p2d; + + assign usb_sense_o = usb_sense_p2d; + + // Weak pull downs so that we can detect the presence of the device, and we + // also prevent Z triggering 'X assertions' in usbdev + assign (weak0, weak1) usb_p = 1'b0; + assign (weak0, weak1) usb_n = 1'b0; + // Tri-stated output drivers + assign (strong0, strong1) usb_p = usb_dp_en_p2d ? usb_dp_p2d : 1'bZ; + assign (strong0, strong1) usb_n = usb_dn_en_p2d ? usb_dn_p2d : 1'bZ; + + /////////////////////////////////////////////////////////////////////////// + // Simple detection of pull up assertion indicating device presence; + // we simply respond to the first line to be pulled high by the device after + // VSENSE assertion, without regard for proper USB 2.0 timing + /////////////////////////////////////////////////////////////////////////// + logic usb_pullupdp_d2p; + logic usb_pullupdn_d2p; + + // Has either pull up been asserted by the device? + wire usb_pullup_detect = usb_pullupdp_d2p | usb_pullupdn_d2p; + + always_ff @(posedge clk_i or negedge rst_ni) begin + if (!rst_ni) begin + usb_pullupdp_d2p <= 1'b0; + usb_pullupdn_d2p <= 1'b0; + end else if (usb_sense_p2d && !usb_pullup_detect) begin + // Is the FS device pulling DP high? + if (usb_p === 1'b1) begin + usb_pullupdp_d2p <= 1'b1; + end + // Is the FS device pulling DN high, implying that it has been configured + // to perform pin-flipping? + if (usb_n === 1'b1) begin + usb_pullupdn_d2p <= 1'b1; + end + end + end + + /////////////////////////////////////////////////////////////////////////// + // Basic activity detection; DPI model indicates whether it is driving, + // but for the device we must detect a departure from the bus Idle state + /////////////////////////////////////////////////////////////////////////// + logic usb_dp_en_d2p_last; + logic usb_dn_en_d2p_last; + logic usb_dp_en_d2p; + logic usb_dn_en_d2p; + + always_comb begin + usb_dp_en_d2p = usb_dp_en_d2p_last; + usb_dn_en_d2p = usb_dn_en_d2p_last; + // Detect transmission start of DPI or device + if (usb_dp_en_p2d || (!usb_dp_en_d2p && usb_p != 1'b1)) begin + usb_dp_en_d2p = !usb_dp_en_p2d; + end + if (usb_dn_en_p2d || (!usb_dn_en_d2p && usb_n != 1'b0)) begin + usb_dn_en_d2p = !usb_dn_en_p2d; + end + end + + // Count of SE0 cycles (1/4 bit intervals). This is just an approximate + // detection of EOP for the purpose of ascertaining when the device is + // relinquishing the bus; it will also count during bus resets. + logic [2:0] se0_cnt; + always @(posedge clk_i or negedge rst_ni) begin + if (!rst_ni) begin + se0_cnt <= 'b0; + end else if (usb_p === 1'b0 && usb_n === 1'b0) begin + se0_cnt <= se0_cnt + 1'b1; + end else begin + se0_cnt <= 'b0; + end + end + + // Assume that the device is driving if the DPI model is not + always_ff @(posedge clk_i or negedge rst_ni) begin + if (!rst_ni) begin + usb_dp_en_d2p_last <= 1'b0; + usb_dn_en_d2p_last <= 1'b0; + end else if (usb_sense_p2d & usb_pullup_detect) begin + // Detect the end of EOP when the device has been transmitting + if (&{usb_dp_en_d2p_last, se0_cnt}) begin + usb_dp_en_d2p_last <= 1'b0; + end else begin + usb_dp_en_d2p_last <= usb_dp_en_d2p; + end + // Detect the end of EOP when the device has been transmitting + if ({usb_dn_en_d2p_last, se0_cnt}) begin + usb_dn_en_d2p_last <= 1'b0; + end else begin + usb_dn_en_d2p_last <= usb_dn_en_d2p; + end + end + end + + // USB DPI + usbdpi u_usbdpi ( + .clk_i (clk_i), + .rst_ni (rst_ni), + .clk_48MHz_i (clk_i), + + .sense_p2d (usb_sense_p2d), + .pullupdp_d2p (usb_pullupdp_d2p), + .pullupdn_d2p (usb_pullupdn_d2p), + + .dp_en_p2d (usb_dp_en_p2d), + .dp_p2d (usb_dp_p2d), + .dp_d2p (usb_p), + .dp_en_d2p (usb_dp_en_d2p), + + .dn_en_p2d (usb_dn_en_p2d), + .dn_p2d (usb_dn_p2d), + .dn_d2p (usb_n), + .dn_en_d2p (usb_dn_en_d2p), + + // ASIC communicates via true differential signaling + .d_p2d (), + .d_d2p (1'b0), // not used + .d_en_d2p (1'b0), + .se0_d2p (1'b0), // not used + .rx_enable_d2p (1'b0), + .tx_use_d_se0_d2p(1'b0) + ); + +endmodule diff --git a/hw/ip/prim_generic/rtl/prim_generic_usb_diff_rx.sv b/hw/ip/prim_generic/rtl/prim_generic_usb_diff_rx.sv index def212ac0aa0a8..b94d39cdc2ba28 100644 --- a/hw/ip/prim_generic/rtl/prim_generic_usb_diff_rx.sv +++ b/hw/ip/prim_generic/rtl/prim_generic_usb_diff_rx.sv @@ -10,8 +10,8 @@ module prim_generic_usb_diff_rx #( parameter int CalibW = 32 ) ( - input wire input_pi, // differential input - input wire input_ni, // differential input + inout input_pi, // differential input + inout input_ni, // differential input input input_en_i, // input buffer enable input core_pok_h_i, // core power indication at VCC level input pullup_p_en_i, // pullup enable for P @@ -35,9 +35,9 @@ module prim_generic_usb_diff_rx #( assign unused_pullup_p_en = pullup_p_en_i; assign unused_pullup_n_en = pullup_n_en_i; `else - // pullup / pulldown termination - assign (weak0, weak1) input_p = pullup_p_en_i ? 1'b1 : 1'bz; - assign (weak0, weak1) input_n = pullup_n_en_i ? 1'b1 : 1'bz; + // pullup termination + assign (weak0, pull1) input_pi = pullup_p_en_i ? 1'b1 : 1'bz; + assign (weak0, pull1) input_ni = pullup_n_en_i ? 1'b1 : 1'bz; `endif assign input_o = (input_en_i) ? input_p & ~input_n : 1'b0; diff --git a/hw/top_earlgrey/data/chip_testplan.hjson b/hw/top_earlgrey/data/chip_testplan.hjson index 0efb7286c3fb7e..4d26427835a077 100644 --- a/hw/top_earlgrey/data/chip_testplan.hjson +++ b/hw/top_earlgrey/data/chip_testplan.hjson @@ -298,6 +298,13 @@ } // USB (pre-verified IP) integration tests: + { + name: chip_sw_usbdev_dpi + desc: '''Sketch of USBDPI integration. + ''' + stage: V2 + tests: ["chip_sw_usbdev_dpi"] + } { name: chip_sw_usb_fs_tx_rx desc: '''Verify the transmission of single-ended data over the USB at full speed. As a part of diff --git a/hw/top_earlgrey/dv/chip_sim.core b/hw/top_earlgrey/dv/chip_sim.core index 9341a4f3a28fd7..e2f61b3b415bef 100644 --- a/hw/top_earlgrey/dv/chip_sim.core +++ b/hw/top_earlgrey/dv/chip_sim.core @@ -28,6 +28,8 @@ filesets: - lowrisc:dv:sw_test_status - lowrisc:dv:sw_logger_if - lowrisc:dv:mem_bkdr_util + - lowrisc:dv_dpi:usbdpi + - lowrisc:dv:usb20_usbdpi files: - tb/chip_hier_macros.svh: {is_include_file: true} - autogen/tb__xbar_connect.sv: {is_include_file: true} diff --git a/hw/top_earlgrey/dv/chip_sim_cfg.hjson b/hw/top_earlgrey/dv/chip_sim_cfg.hjson index cac301d553597b..98c9f435c18ddf 100644 --- a/hw/top_earlgrey/dv/chip_sim_cfg.hjson +++ b/hw/top_earlgrey/dv/chip_sim_cfg.hjson @@ -527,6 +527,15 @@ "+test_timeout_ns=80_000_000"] run_timeout_mins: 180 } + { + name: chip_sw_usbdev_dpi + uvm_test_seq: chip_sw_usbdev_dpi_vseq + sw_images: ["//sw/device/tests:usbdev_test:1"] + en_run_modes: ["sw_test_mode_test_rom"] + run_opts: ["+uart_idx=0", "+calibrate_usb_clk=1"] + run_timeout_mins: 120 + reseed: 1 + } { name: chip_sw_inject_scramble_seed uvm_test_seq: chip_sw_inject_scramble_seed_vseq diff --git a/hw/top_earlgrey/dv/env/chip_env.core b/hw/top_earlgrey/dv/env/chip_env.core index 1d4dc89858b6aa..13feab5ade1b4b 100644 --- a/hw/top_earlgrey/dv/env/chip_env.core +++ b/hw/top_earlgrey/dv/env/chip_env.core @@ -121,6 +121,7 @@ filesets: - seq_lib/chip_sw_entropy_src_fuse_vseq.sv: {is_include_file: true} - seq_lib/chip_sw_csrng_lc_hw_debug_en_vseq.sv: {is_include_file: true} - seq_lib/chip_sw_usb_ast_clk_calib_vseq.sv: {is_include_file: true} + - seq_lib/chip_sw_usbdev_dpi_vseq.sv: {is_include_file: true} - seq_lib/chip_sw_i2c_tx_rx_vseq.sv: {is_include_file: true} - seq_lib/chip_sw_i2c_host_tx_rx_vseq.sv: {is_include_file: true} - seq_lib/chip_sw_spi_device_tpm_vseq.sv: {is_include_file: true} diff --git a/hw/top_earlgrey/dv/env/seq_lib/chip_sw_usbdev_dpi_vseq.sv b/hw/top_earlgrey/dv/env/seq_lib/chip_sw_usbdev_dpi_vseq.sv new file mode 100644 index 00000000000000..8d638003e8d9d6 --- /dev/null +++ b/hw/top_earlgrey/dv/env/seq_lib/chip_sw_usbdev_dpi_vseq.sv @@ -0,0 +1,18 @@ +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +class chip_sw_usbdev_dpi_vseq extends chip_sw_base_vseq; + `uvm_object_utils(chip_sw_usbdev_dpi_vseq) + + `uvm_object_new + + virtual task body(); + super.body(); + + // We need to release the tb weak pull up on DP, otherwise usbdev appears + // to be connected much too soon + cfg.chip_vif.cfg_default_weak_pulls_on_dios(0); + endtask + +endclass : chip_sw_usbdev_dpi_vseq diff --git a/hw/top_earlgrey/dv/env/seq_lib/chip_vseq_list.sv b/hw/top_earlgrey/dv/env/seq_lib/chip_vseq_list.sv index d55145702b9021..2fa03faf539667 100644 --- a/hw/top_earlgrey/dv/env/seq_lib/chip_vseq_list.sv +++ b/hw/top_earlgrey/dv/env/seq_lib/chip_vseq_list.sv @@ -76,6 +76,7 @@ `include "chip_sw_entropy_src_fuse_vseq.sv" `include "chip_sw_csrng_lc_hw_debug_en_vseq.sv" `include "chip_sw_usb_ast_clk_calib_vseq.sv" +`include "chip_sw_usbdev_dpi_vseq.sv" `include "chip_sw_i2c_tx_rx_vseq.sv" `include "chip_sw_i2c_host_tx_rx_vseq.sv" `include "chip_sw_i2c_device_tx_rx_vseq.sv" diff --git a/hw/top_earlgrey/dv/tb/tb.sv b/hw/top_earlgrey/dv/tb/tb.sv index 8aaf51c182235a..20f3ae708b419d 100644 --- a/hw/top_earlgrey/dv/tb/tb.sv +++ b/hw/top_earlgrey/dv/tb/tb.sv @@ -162,6 +162,15 @@ module tb; bit en_sim_sram = 1'b1; wire sel_sim_sram = !dut.chip_if.stub_cpu & en_sim_sram; + // Instantiate & connect the USB DPI model for top-level testing. + usb20_usbdpi u_usb20_usbdpi ( + .clk_i (dut.chip_if.usb_clk), + .rst_ni (dut.chip_if.usb_rst_n), + .usb_sense_o (dut.chip_if.mios[top_earlgrey_pkg::MioPadIoc7]), + .usb_p (dut.chip_if.dios[top_earlgrey_pkg::DioPadUsbP]), + .usb_n (dut.chip_if.dios[top_earlgrey_pkg::DioPadUsbN]) + ); + sim_sram u_sim_sram ( .clk_i (sel_sim_sram ? `CPU_HIER.clk_i : 1'b0), .rst_ni (`CPU_HIER.rst_ni), diff --git a/sw/device/lib/dif/dif_usbdev.c b/sw/device/lib/dif/dif_usbdev.c index 3e5105ff7a3696..f42b72f8700a3f 100644 --- a/sw/device/lib/dif/dif_usbdev.c +++ b/sw/device/lib/dif/dif_usbdev.c @@ -220,6 +220,16 @@ dif_result_t dif_usbdev_configure(const dif_usbdev_t *usbdev, return kDifError; } + // TODO: in dvsim the packet memory contents are uninitialized and there is + // an 'X' checker on the TL-UL bus meaning that we cannot read/write a partial + // word + for (uint8_t id = 0U; id < USBDEV_NUM_BUFFERS; id++) { + static const uint8_t zeros[USBDEV_MAX_PACKET_SIZE]; + uint32_t buffer_addr = get_buffer_addr(id, 0); + mmio_region_memcpy_to_mmio32(usbdev->base_addr, buffer_addr, zeros, + USBDEV_MAX_PACKET_SIZE); + } + // Check enum fields. if (!dif_is_valid_toggle(config.have_differential_receiver) || !dif_is_valid_toggle(config.use_tx_d_se0) || diff --git a/sw/device/lib/testing/pinmux_testutils.c b/sw/device/lib/testing/pinmux_testutils.c index 8cc6689d20e12f..9beea99984b72d 100644 --- a/sw/device/lib/testing/pinmux_testutils.c +++ b/sw/device/lib/testing/pinmux_testutils.c @@ -62,6 +62,30 @@ void pinmux_testutils_init(dif_pinmux_t *pinmux) { // Configure UART1 TX output to connect to MIO pad IOB5 CHECK_DIF_OK(dif_pinmux_output_select(pinmux, kTopEarlgreyPinmuxMioOutIob5, kTopEarlgreyPinmuxOutselUart1Tx)); + + // Configure a higher drive strength for the USB_P and USB_N pads because we + // must the pad drivers must be capable of overpowering the 'pull' signal + // strength of the internal pull ups in the differential receiver. + // + // 'pull' strength is required because at the host end of the USB, there + // are 'weak' pull downs, allowing it to detect device presence when it + // applies its pull up. + // strong PAD driver > internal pull up > weak pull down at host + // + // Normally the pull up on USB_P will be asserted, but we may be employing + // 'pin flipping' and instead choose to apply the _N pull up. + if (kDeviceType == kDeviceSimDV) { + dif_pinmux_pad_attr_t out_attr; + dif_pinmux_pad_attr_t in_attr = { + .slew_rate = 0, .drive_strength = 1, .flags = 0}; + + CHECK_DIF_OK( + dif_pinmux_pad_write_attrs(pinmux, kTopEarlgreyDirectPadsUsbdevUsbDp, + kDifPinmuxPadKindDio, in_attr, &out_attr)); + CHECK_DIF_OK( + dif_pinmux_pad_write_attrs(pinmux, kTopEarlgreyDirectPadsUsbdevUsbDn, + kDifPinmuxPadKindDio, in_attr, &out_attr)); + } #endif // Configure USBDEV SENSE outputs to be high-Z (IOC7) diff --git a/sw/device/tests/BUILD b/sw/device/tests/BUILD index 5b9ca5a01ece7c..0bf597af726695 100644 --- a/sw/device/tests/BUILD +++ b/sw/device/tests/BUILD @@ -1941,6 +1941,7 @@ opentitan_functest( targets = [ "verilator", "cw310_test_rom", + "dv", ], verilator = verilator_params( timeout = "long", diff --git a/sw/device/tests/usbdev_test.c b/sw/device/tests/usbdev_test.c index 2ffffc599e5103..a73ef9fc7b051f 100644 --- a/sw/device/tests/usbdev_test.c +++ b/sw/device/tests/usbdev_test.c @@ -98,11 +98,6 @@ static void usb_receipt_callback(uint8_t c) { OTTF_DEFINE_TEST_CONFIG(); bool test_main(void) { - CHECK(kDeviceType == kDeviceSimVerilator || kDeviceType == kDeviceFpgaCw310, - "This test is not expected to run on platforms other than the " - "Verilator simulation or CW310 FPGA. It needs the USB DPI model " - "or host application."); - LOG_INFO("Running USBDEV test"); CHECK_DIF_OK(dif_pinmux_init(