Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[chip_tb] Integrate usbdpi into chip tb #18063

Merged
merged 1 commit into from
Apr 28, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 17 additions & 10 deletions hw/dv/dpi/usbdpi/usbdpi.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand All @@ -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;
Expand Down Expand Up @@ -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) {
Expand All @@ -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;
}

Expand Down Expand Up @@ -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) {
Expand All @@ -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 {
Expand All @@ -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;
Expand Down
1 change: 1 addition & 0 deletions hw/dv/dpi/usbdpi/usbdpi.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 */

Expand Down
51 changes: 32 additions & 19 deletions hw/dv/dpi/usbdpi/usbdpi.sv
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,17 @@

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,
input logic enable,
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,
Expand Down Expand Up @@ -52,7 +55,6 @@ module usbdpi #(

initial begin
ctx = usbdpi_create(NAME, LOG_LEVEL);
sense_p2d = 1'b0;
end

final begin
Expand Down Expand Up @@ -146,7 +148,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,
Expand All @@ -169,13 +171,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
Expand Down Expand Up @@ -212,22 +214,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 if (enable) 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

Expand Down
49 changes: 46 additions & 3 deletions hw/dv/sv/usb20_agent/usb20_if.sv
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,53 @@
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0

interface usb20_if ();
interface usb20_if (
input clk_i,
input rst_ni,

// interface pins
output wire usb_vbus,
inout wire usb_p,
inout wire usb_n
);

// debug signals
// This interface presently serves just to connect/disconnect the USB DPI
// model to/from the ASIC pins. In time it may be extended to support a DV
// block-level USB 2.0 agent.

// Clock and reset not presently required
wire unused_clk = clk_i;
wire unused_rst_n = rst_ni;

// 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;

// Are our drivers connected?
bit connected = 0;

// Enable/disable the output drivers
function automatic void enable_driver(bit enabled);
connected = enabled;
endfunction

assign usb_vbus = connected ? usb_sense_p2d : 1'bZ;

// 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 = connected ? 1'b0 : 1'bZ;
assign (weak0, weak1) usb_n = connected ? 1'b0 : 1'bZ;
// Tri-stated output drivers
assign (strong0, strong1) usb_p = (connected & usb_dp_en_p2d) ? usb_dp_p2d : 1'bZ;
assign (strong0, strong1) usb_n = (connected & usb_dn_en_p2d) ? usb_dn_p2d : 1'bZ;

endinterface
21 changes: 21 additions & 0 deletions hw/dv/sv/usb20_agent/usb20_usbdpi.core
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
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_if.sv: { file_type: systemVerilogSource }
- usb20_usbdpi.sv: { file_type: systemVerilogSource }
a-will marked this conversation as resolved.
Show resolved Hide resolved

files_dv:
depend:
- lowrisc:dv_dpi:usbdpi

targets:
default:
filesets:
- files_rtl
Loading