[usbdev] Add capability for swapping D+/D-

The two pins can now be swapped/flipped based on a PINFLIP bit in the
PHY_CONFIG register. This is useful if the D+/D- pins are mapped to
the SBU1/SBU2 pins of USB-C.

Signed-off-by: Pirmin Vogel <vogelpi@lowrisc.org>
diff --git a/hw/ip/usbdev/data/usbdev.hjson b/hw/ip/usbdev/data/usbdev.hjson
index b00e2ff..9044314 100644
--- a/hw/ip/usbdev/data/usbdev.hjson
+++ b/hw/ip/usbdev/data/usbdev.hjson
@@ -18,7 +18,8 @@
   ],
   available_output_list: [
     { name: "se0", desc: "USB single-ended zero link state" }
-    { name: "pullup", desc: "USB pullup control" }
+    { name: "dp_pullup", desc: "USB D+ pullup control" }
+    { name: "dn_pullup", desc: "USB D- pullup control" }
     { name: "tx_mode_se", desc: "USB single-ended transmit mode control" }
     { name: "suspend", desc: "USB link suspend state" }
   ],
@@ -519,6 +520,16 @@
                 0: USB power not present, 1: present.
                 '''
         }
+        {
+          bits: "5",
+          resval: "0",
+          name: "pinflip",
+          desc: '''
+                Flip the D+/D- pins.
+                Particularly useful if D+/D- are mapped to SBU1/SBU2 pins of USB-C.
+
+                '''
+        }
       ]
     }
 
diff --git a/hw/ip/usbdev/doc/_index.md b/hw/ip/usbdev/doc/_index.md
index 482928d..b917eb2 100644
--- a/hw/ip/usbdev/doc/_index.md
+++ b/hw/ip/usbdev/doc/_index.md
@@ -21,6 +21,7 @@
 - Support for Bulk, Control, Interrupt and Isochronous endpoints and transactions
 - Streaming possible through software
 - Interrupts for packet reception and transmission
+- Flippable D+/D- pins, configurable via software, useful if it helps routing the PCB or if D+/D- are mapped to SBU1/SBU2 pins of USB-C
 
 Isochronous transfers larger than 64 bytes are currently not supported.
 This feature might be added in a later version of this IP.
@@ -111,11 +112,11 @@
 
 The USB device features the following non-data pins.
 
-|  External Pins | Internal Signals | Notes |
-|----------------|------------------|-------|
-| sense (VBUS)   | sense_i          | The sense pin indicates the presence of VBUS from the USB host. |
-| [pullup]       | pullup_o         | When the pullup_o asserts a 1.5k pullup resistor should be connected to D+. This can be done inside the chip or with an external pin. A permanently connected resistor can also be used. |
-| [suspend]      | suspend_o        | The suspend pin indicates to the USB transceiver that a constant idle has been detected on the link and the device is in the Suspend state (see Section 7.1.7.6 of the [USB 2.0 specification](https://www.usb.org/document-library/usb-20-specification)). |
+|  External Pins | Internal Signals         | Notes |
+|----------------|--------------------------|-------|
+| sense (VBUS)   | sense_i                  | The sense pin indicates the presence of VBUS from the USB host. |
+| [pullup]       | dp_pullup_o, dn_pullup_o | When dp_pullup_o or dn_pullup_o asserts a 1.5k pullup resistor should be connected to D+ or D-, respectively. This can be done inside the chip or with an external pin. A permanently connected resistor could be used if the pin flip feature is not needed, but this is not recommended because there is then no way to force the device to appear to unplug. Only one of the pullup signals can be asserted at any time. The selection is based on the `pinflip` bit in {{< regref "phy_config" >}}. Because this is a Full-Speed device the resistor must be on the D+ pin, so when `pinflip` is zero, dp_pullup_o is used. |
+| [suspend]      | suspend_o                | The suspend pin indicates to the USB transceiver that a constant idle has been detected on the link and the device is in the Suspend state (see Section 7.1.7.6 of the [USB 2.0 specification](https://www.usb.org/document-library/usb-20-specification)). |
 
 The USB host will identify itself to the device by enabling the 5V VBUS power.
 It may do a hard reset of a port by removing and reasserting VBUS (the Linux driver will do this when it finds a port in an inconsistent state or a port that generates errors during enumeration).
@@ -124,11 +125,17 @@
 Note that this may require a resistor divider or (for USB-C where VBUS can be up to 20V) active level translation to an acceptable voltage for the input pin.
 
 A Full-Speed device identifies itself by providing a 1.5k pullup resistor (to 3.3V) on the D+ line.
-The IP block produces a signal `pullup_o` that is asserted when this resistor should be presented.
+The IP block produces a signal `dp_pullup_o` that is asserted when this resistor should be presented.
 This signal will be asserted whenever the interface is enabled.
 In an FPGA implementation, this signal can drive a 3.3V output pin that is driven high when the signal is asserted and set high impedance when the signal is deasserted, and the output pin used to drive a 1.5k resistor connected on the board to the D+ line.
 Alternatively, it can be used to enable an internal 1.5k pullup on the D+ pin.
 
+This USB device supports the flipping of D+/D-.
+If the `pinflip` bit in {{< regref "phy_config" >}} is set, the data pins are flipped internally, meaning the 1.5k pullup resistor needs to be on the external D- line.
+To control the pullup on the D- line, this USB device features `dn_pullup_o` signal.
+Of the two pullup signals `dp_pullup_o` and `dn_pullup_o`, only one can be enabled at any time.
+As this is a Full-Speed device, `dp_pullup_o`, i.e., the pullup on D+ is used by default (`pinflip` equals zero).
+
 
 ## Hardware Interfaces
 
diff --git a/hw/ip/usbdev/dv/tb/tb.sv b/hw/ip/usbdev/dv/tb/tb.sv
index 9b46e94..64ba40f 100644
--- a/hw/ip/usbdev/dv/tb/tb.sv
+++ b/hw/ip/usbdev/dv/tb/tb.sv
@@ -63,8 +63,10 @@
 
     .cio_se0_o            (),
     .cio_se0_en_o         (),
-    .cio_pullup_o         (),
-    .cio_pullup_en_o      (),
+    .cio_dp_pullup_o      (),
+    .cio_dp_pullup_en_o   (),
+    .cio_dn_pullup_o      (),
+    .cio_dn_pullup_en_o   (),
     .cio_tx_mode_se_o     (),
     .cio_tx_mode_se_en_o  (),
     .cio_suspend_o        (),
diff --git a/hw/ip/usbdev/rtl/usbdev.sv b/hw/ip/usbdev/rtl/usbdev.sv
index 6195800..48810a8 100644
--- a/hw/ip/usbdev/rtl/usbdev.sv
+++ b/hw/ip/usbdev/rtl/usbdev.sv
@@ -34,8 +34,10 @@
   input  logic       cio_sense_i,
   output logic       cio_se0_o,
   output logic       cio_se0_en_o,
-  output logic       cio_pullup_o,
-  output logic       cio_pullup_en_o,
+  output logic       cio_dp_pullup_o,
+  output logic       cio_dp_pullup_en_o,
+  output logic       cio_dn_pullup_o,
+  output logic       cio_dn_pullup_en_o,
   output logic       cio_suspend_o,
   output logic       cio_suspend_en_o,
   output logic       cio_tx_mode_se_o,
@@ -864,8 +866,9 @@
     .rst_ni                 (rst_ni),
     .clk_usb_48mhz_i        (clk_usb_48mhz_i),
     .rst_usb_48mhz_ni       (rst_usb_48mhz_ni),
-    .rx_differential_mode_i (reg2hw.phy_config.rx_differential_mode),
-    .tx_differential_mode_i (reg2hw.phy_config.tx_differential_mode),
+    .rx_differential_mode_i (reg2hw.phy_config.rx_differential_mode.q),
+    .tx_differential_mode_i (reg2hw.phy_config.tx_differential_mode.q),
+    .pinflip_i              (reg2hw.phy_config.pinflip.q),
     .sys_reg2hw_config_i    (reg2hw.phy_config),
     .sys_usb_sense_o        (hw2reg.usbstat.sense.d),
 
@@ -880,7 +883,8 @@
     .cio_usb_oe_o           (cio_oe),
     .cio_usb_tx_mode_se_o   (cio_tx_mode_se_o),
     .cio_usb_sense_i        (cio_sense_i),
-    .cio_usb_pullup_en_o    (cio_pullup_en_o),
+    .cio_usb_dp_pullup_en_o (cio_dp_pullup_en_o),
+    .cio_usb_dn_pullup_en_o (cio_dn_pullup_en_o),
     .cio_usb_suspend_o      (cio_suspend_o),
 
     // Internal interface
@@ -909,6 +913,7 @@
   assign cio_tx_mode_se_en_o = 1'b1;
 
   // Pullup
-  assign cio_pullup_o        = 1'b1;
+  assign cio_dp_pullup_o     = 1'b1;
+  assign cio_dn_pullup_o     = 1'b1;
 
 endmodule
diff --git a/hw/ip/usbdev/rtl/usbdev_iomux.sv b/hw/ip/usbdev/rtl/usbdev_iomux.sv
index 2142bb2..a7300ef 100644
--- a/hw/ip/usbdev/rtl/usbdev_iomux.sv
+++ b/hw/ip/usbdev/rtl/usbdev_iomux.sv
@@ -3,11 +3,11 @@
 // Licensed under the Apache License, Version 2.0, see LICENSE for details.
 // SPDX-License-Identifier: Apache-2.0
 //
-//  USB IO Mux
+// USB IO Mux
 //
-//  Muxes the USB IO signals from: register access, differential signaling,
-//  single-ended signaling. The incomming signals are also muxed and synchronized
-//  to the corresponding clock domain.
+// Muxes the USB IO signals from register access, differential signaling, single-ended signaling
+// and swaps D+/D- if configured. The incomming signals are also muxed and synchronized to the
+// corresponding clock domain.
 
 module usbdev_iomux
   import usbdev_reg_pkg::*;
@@ -20,6 +20,7 @@
   // Configuration (quasi-static)
   input  logic                          rx_differential_mode_i,
   input  logic                          tx_differential_mode_i,
+  input  logic                          pinflip_i,
 
   // Register interface (system clk)
   input  usbdev_reg2hw_phy_config_reg_t sys_reg2hw_config_i,
@@ -38,7 +39,8 @@
 
   output logic                          cio_usb_tx_mode_se_o,
   input  logic                          cio_usb_sense_i,
-  output logic                          cio_usb_pullup_en_o,
+  output logic                          cio_usb_dp_pullup_en_o,
+  output logic                          cio_usb_dn_pullup_en_o,
   output logic                          cio_usb_suspend_o,
 
   // Internal USB Interface (usb clk)
@@ -62,7 +64,7 @@
   // CDCs //
   //////////
 
-  // USB pins sense (to sysclk)
+  // USB sense pin (to sysclk)
   prim_flop_2sync #(
     .Width (1)
   ) cdc_io_to_sys (
@@ -90,53 +92,57 @@
               usb_pwr_sense_o})
   );
 
-  ///////////////////////////////
-  // USB output pins drive mux //
-  ///////////////////////////////
-  always_comb begin : proc_drive_out
+  ////////////////////////
+  // USB output pin mux //
+  ////////////////////////
+
+  // D+/D- can be swapped based on a config register.
+  assign cio_usb_d_o            = pinflip_i ? ~usb_tx_d_i     : usb_tx_d_i;
+  assign cio_usb_dp_pullup_en_o = pinflip_i ? 1'b0            : usb_pullup_en_i;
+  assign cio_usb_dn_pullup_en_o = pinflip_i ? usb_pullup_en_i : 1'b0;
+
+  always_comb begin : proc_diff_se_mux_out
     // Defaults
     cio_usb_dn_o           = 1'b0;
     cio_usb_dp_o           = 1'b0;
 
-    // Signals from the peripheral core
-    cio_usb_pullup_en_o    = usb_pullup_en_i;
-    cio_usb_suspend_o      = usb_suspend_i;
-
+    // The single-ended signals are only driven in single-ended mode.
     if (tx_differential_mode_i) begin
-      // Differential mode
+      // Differential TX mode
       cio_usb_tx_mode_se_o   = 1'b0;
 
     end else begin
-      // Single-ended mode
+      // Single-ended TX mode
       cio_usb_tx_mode_se_o   = 1'b1;
       if (usb_tx_se0_i) begin
         cio_usb_dp_o = 1'b0;
         cio_usb_dn_o = 1'b0;
       end else begin
-        cio_usb_dp_o = usb_tx_d_i;
-        cio_usb_dn_o = !usb_tx_d_i;
+        cio_usb_dp_o = pinflip_i ? ~usb_tx_d_i :  usb_tx_d_i;
+        cio_usb_dn_o = pinflip_i ?  usb_tx_d_i : ~usb_tx_d_i;
       end
     end
   end
 
   // It would be possible to insert explicit controllability muxes here.
   // For now, we just pass the signal through
-  assign cio_usb_d_o   = usb_tx_d_i;
-  assign cio_usb_se0_o = usb_tx_se0_i;
-  assign cio_usb_oe_o  = usb_tx_oe_i;
+  assign cio_usb_oe_o      = usb_tx_oe_i;
+  assign cio_usb_se0_o     = usb_tx_se0_i;
+  assign cio_usb_suspend_o = usb_suspend_i;
 
   ///////////////////////
   // USB input pin mux //
   ///////////////////////
 
-  // Note that while transmitting, the receive (p2d) line must be fixed.
-  // Otherwise you are trying to regenerate the bit clock from the bit
-  // clock you are regenerating, rather than just holding the phase.
-  assign usb_rx_dp = (usb_tx_oe_i) ? 1'b1 : cio_usb_dp;
-  assign usb_rx_dn = (usb_tx_oe_i) ? 1'b0 : cio_usb_dn;
-  assign usb_rx_d  = (usb_tx_oe_i) ? 1'b1 : cio_usb_d;
+  // Note that while transmitting, we fix the receive line to 1. If the receive line isn't fixed,
+  // we are trying to regenerate the bit clock from the bit clock we are regenerating, rather than
+  // just holding the phase.
+  // D+/D- can be swapped based on a config register.
+  assign usb_rx_dp = usb_tx_oe_i ? 1'b1 : (pinflip_i ?  cio_usb_dn : cio_usb_dp);
+  assign usb_rx_dn = usb_tx_oe_i ? 1'b0 : (pinflip_i ?  cio_usb_dp : cio_usb_dn);
+  assign usb_rx_d  = usb_tx_oe_i ? 1'b1 : (pinflip_i ? ~cio_usb_d  : cio_usb_d);
 
-  always_comb begin : proc_mux_data_input
+  always_comb begin : proc_diff_se_mux_in
     usb_rx_se0_o = ~usb_rx_dp & ~usb_rx_dn;
 
     if (rx_differential_mode_i) begin
@@ -150,7 +156,7 @@
   end
 
   // Power sense mux
-  always_comb begin : proc_mux_pwr_input
+  always_comb begin : proc_mux_pwr_sense
     if (sys_reg2hw_config_i.override_pwr_sense_en.q) begin
       async_pwr_sense = sys_reg2hw_config_i.override_pwr_sense_val.q;
     end else begin
diff --git a/hw/ip/usbdev/rtl/usbdev_reg_pkg.sv b/hw/ip/usbdev/rtl/usbdev_reg_pkg.sv
index 3dc471e..afdaf1e 100644
--- a/hw/ip/usbdev/rtl/usbdev_reg_pkg.sv
+++ b/hw/ip/usbdev/rtl/usbdev_reg_pkg.sv
@@ -266,6 +266,9 @@
     struct packed {
       logic        q;
     } override_pwr_sense_val;
+    struct packed {
+      logic        q;
+    } pinflip;
   } usbdev_reg2hw_phy_config_reg_t;
 
 
@@ -411,19 +414,19 @@
   // Register to internal design logic //
   ///////////////////////////////////////
   typedef struct packed {
-    usbdev_reg2hw_intr_state_reg_t intr_state; // [343:328]
-    usbdev_reg2hw_intr_enable_reg_t intr_enable; // [327:312]
-    usbdev_reg2hw_intr_test_reg_t intr_test; // [311:280]
-    usbdev_reg2hw_usbctrl_reg_t usbctrl; // [279:272]
-    usbdev_reg2hw_avbuffer_reg_t avbuffer; // [271:266]
-    usbdev_reg2hw_rxfifo_reg_t rxfifo; // [265:245]
-    usbdev_reg2hw_rxenable_setup_mreg_t [11:0] rxenable_setup; // [244:233]
-    usbdev_reg2hw_rxenable_out_mreg_t [11:0] rxenable_out; // [232:221]
-    usbdev_reg2hw_stall_mreg_t [11:0] stall; // [220:209]
-    usbdev_reg2hw_configin_mreg_t [11:0] configin; // [208:41]
-    usbdev_reg2hw_iso_mreg_t [11:0] iso; // [40:29]
-    usbdev_reg2hw_data_toggle_clear_mreg_t [11:0] data_toggle_clear; // [28:5]
-    usbdev_reg2hw_phy_config_reg_t phy_config; // [4:0]
+    usbdev_reg2hw_intr_state_reg_t intr_state; // [344:329]
+    usbdev_reg2hw_intr_enable_reg_t intr_enable; // [328:313]
+    usbdev_reg2hw_intr_test_reg_t intr_test; // [312:281]
+    usbdev_reg2hw_usbctrl_reg_t usbctrl; // [280:273]
+    usbdev_reg2hw_avbuffer_reg_t avbuffer; // [272:267]
+    usbdev_reg2hw_rxfifo_reg_t rxfifo; // [266:246]
+    usbdev_reg2hw_rxenable_setup_mreg_t [11:0] rxenable_setup; // [245:234]
+    usbdev_reg2hw_rxenable_out_mreg_t [11:0] rxenable_out; // [233:222]
+    usbdev_reg2hw_stall_mreg_t [11:0] stall; // [221:210]
+    usbdev_reg2hw_configin_mreg_t [11:0] configin; // [209:42]
+    usbdev_reg2hw_iso_mreg_t [11:0] iso; // [41:30]
+    usbdev_reg2hw_data_toggle_clear_mreg_t [11:0] data_toggle_clear; // [29:6]
+    usbdev_reg2hw_phy_config_reg_t phy_config; // [5:0]
   } usbdev_reg2hw_t;
 
   ///////////////////////////////////////
diff --git a/hw/ip/usbdev/rtl/usbdev_reg_top.sv b/hw/ip/usbdev/rtl/usbdev_reg_top.sv
index 8960d08..6ff72f7 100644
--- a/hw/ip/usbdev/rtl/usbdev_reg_top.sv
+++ b/hw/ip/usbdev/rtl/usbdev_reg_top.sv
@@ -640,6 +640,9 @@
   logic phy_config_override_pwr_sense_val_qs;
   logic phy_config_override_pwr_sense_val_wd;
   logic phy_config_override_pwr_sense_val_we;
+  logic phy_config_pinflip_qs;
+  logic phy_config_pinflip_wd;
+  logic phy_config_pinflip_we;
 
   // Register instances
   // R[intr_state]: V(False)
@@ -5292,6 +5295,32 @@
   );
 
 
+  //   F[pinflip]: 5:5
+  prim_subreg #(
+    .DW      (1),
+    .SWACCESS("RW"),
+    .RESVAL  (1'h0)
+  ) u_phy_config_pinflip (
+    .clk_i   (clk_i    ),
+    .rst_ni  (rst_ni  ),
+
+    // from register interface
+    .we     (phy_config_pinflip_we),
+    .wd     (phy_config_pinflip_wd),
+
+    // from internal hardware
+    .de     (1'b0),
+    .d      ('0  ),
+
+    // to internal hardware
+    .qe     (),
+    .q      (reg2hw.phy_config.pinflip.q ),
+
+    // to register interface (read)
+    .qs     (phy_config_pinflip_qs)
+  );
+
+
 
 
   logic [25:0] addr_hit;
@@ -5910,6 +5939,9 @@
   assign phy_config_override_pwr_sense_val_we = addr_hit[25] & reg_we & ~wr_err;
   assign phy_config_override_pwr_sense_val_wd = reg_wdata[4];
 
+  assign phy_config_pinflip_we = addr_hit[25] & reg_we & ~wr_err;
+  assign phy_config_pinflip_wd = reg_wdata[5];
+
   // Read data return
   always_comb begin
     reg_rdata_next = '0;
@@ -6178,6 +6210,7 @@
         reg_rdata_next[2] = phy_config_eop_single_bit_qs;
         reg_rdata_next[3] = phy_config_override_pwr_sense_en_qs;
         reg_rdata_next[4] = phy_config_override_pwr_sense_val_qs;
+        reg_rdata_next[5] = phy_config_pinflip_qs;
       end
 
       default: begin
diff --git a/hw/ip/usbuart/rtl/usbuart_core.sv b/hw/ip/usbuart/rtl/usbuart_core.sv
index 7aa686a..c4f8a1a 100644
--- a/hw/ip/usbuart/rtl/usbuart_core.sv
+++ b/hw/ip/usbuart/rtl/usbuart_core.sv
@@ -414,6 +414,7 @@
   usbdev_reg_pkg::usbdev_reg2hw_phy_config_reg_t     usb_phy_config;
   assign usb_phy_config.rx_differential_mode.q   = 1'b0;
   assign usb_phy_config.tx_differential_mode.q   = 1'b0;
+  assign usb_phy_config.pinflip.q                = 1'b0;
   assign usb_phy_config.eop_single_bit.q         = 1'b1;
   assign usb_phy_config.override_pwr_sense_en.q  = 1'b0;
   assign usb_phy_config.override_pwr_sense_val.q = 1'b0;
@@ -425,7 +426,7 @@
     .rst_usb_48mhz_ni       ( rst_usb_48mhz_ni       ),
     .rx_differential_mode_i ( 1'b0                   ),
     .tx_differential_mode_i ( 1'b0                   ),
-
+    .pinflip_i              ( 1'b0                   ),
     .sys_reg2hw_config_i    (                        ),
     .sys_usb_sense_o        ( sys_usb_sense          ),
 
@@ -439,7 +440,8 @@
     .cio_usb_oe_o           ( cio_usb_oe_o           ),
     .cio_usb_tx_mode_se_o   (                        ),
     .cio_usb_sense_i        ( cio_usb_sense_i        ),
-    .cio_usb_pullup_en_o    ( cio_usb_pullup_en_o    ),
+    .cio_usb_dp_pullup_en_o ( cio_usb_pullup_en_o    ),
+    .cio_usb_dn_pullup_en_o (                        ),
     .cio_usb_suspend_o      (                        ),
 
     .usb_rx_d_o             ( usb_rx_d               ),
diff --git a/hw/top_earlgrey/data/autogen/top_earlgrey.gen.hjson b/hw/top_earlgrey/data/autogen/top_earlgrey.gen.hjson
index 5fac8d6..48d8cb6 100644
--- a/hw/top_earlgrey/data/autogen/top_earlgrey.gen.hjson
+++ b/hw/top_earlgrey/data/autogen/top_earlgrey.gen.hjson
@@ -1368,7 +1368,12 @@
           type: output
         }
         {
-          name: pullup
+          name: dp_pullup
+          width: 1
+          type: output
+        }
+        {
+          name: dn_pullup
           width: 1
           type: output
         }
@@ -2916,7 +2921,7 @@
         name: usbdev
         pad:
         [
-          ChC[0..7]
+          ChC[0..8]
         ]
       }
     ]
@@ -3039,7 +3044,7 @@
         ]
       }
       {
-        name: usbdev_pullup
+        name: usbdev_dp_pullup
         width: 1
         type: output
         module_name: usbdev
@@ -3052,7 +3057,7 @@
         ]
       }
       {
-        name: usbdev_tx_mode_se
+        name: usbdev_dn_pullup
         width: 1
         type: output
         module_name: usbdev
@@ -3065,7 +3070,7 @@
         ]
       }
       {
-        name: usbdev_suspend
+        name: usbdev_tx_mode_se
         width: 1
         type: output
         module_name: usbdev
@@ -3078,9 +3083,9 @@
         ]
       }
       {
-        name: usbdev_d
+        name: usbdev_suspend
         width: 1
-        type: inout
+        type: output
         module_name: usbdev
         pad:
         [
@@ -3091,7 +3096,7 @@
         ]
       }
       {
-        name: usbdev_dp
+        name: usbdev_d
         width: 1
         type: inout
         module_name: usbdev
@@ -3104,7 +3109,7 @@
         ]
       }
       {
-        name: usbdev_dn
+        name: usbdev_dp
         width: 1
         type: inout
         module_name: usbdev
@@ -3116,6 +3121,19 @@
           }
         ]
       }
+      {
+        name: usbdev_dn
+        width: 1
+        type: inout
+        module_name: usbdev
+        pad:
+        [
+          {
+            name: ChC
+            index: 8
+          }
+        ]
+      }
     ]
     inputs: []
     outputs: []
diff --git a/hw/top_earlgrey/data/pins_artys7.xdc b/hw/top_earlgrey/data/pins_artys7.xdc
index e60fe40..cc6e9c3 100644
--- a/hw/top_earlgrey/data/pins_artys7.xdc
+++ b/hw/top_earlgrey/data/pins_artys7.xdc
@@ -55,11 +55,11 @@
 ## PMOD Header JB
 set_property -dict { PACKAGE_PIN P17   IOSTANDARD LVCMOS33 DRIVE 8 SLEW FAST } [get_ports { IO_USB_DP0 }]; #IO_L9P_T1_DQS_14 Sch=jb_p[1]
 set_property -dict { PACKAGE_PIN P18   IOSTANDARD LVCMOS33 DRIVE 8 SLEW FAST } [get_ports { IO_USB_DN0 }]; #IO_L9N_T1_DQS_D13_14 Sch=jb_n[1]
-set_property -dict { PACKAGE_PIN R18   IOSTANDARD LVCMOS33 } [get_ports { IO_USB_PULLUP0 }]; #IO_L10P_T1_D14_14 Sch=jb_p[2]
+set_property -dict { PACKAGE_PIN R18   IOSTANDARD LVCMOS33 } [get_ports { IO_USB_DPPULLUP0 }]; #IO_L10P_T1_D14_14 Sch=jb_p[2]
 set_property -dict { PACKAGE_PIN T18   IOSTANDARD LVCMOS33 } [get_ports { IO_USB_SENSE0 }]; #IO_L10N_T1_D15_14 Sch=jb_n[2]
 #set_property -dict { PACKAGE_PIN P14   IOSTANDARD LVCMOS33 } [get_ports { jb[4] }]; #IO_L11P_T1_SRCC_14 Sch=jb_p[3]
 #set_property -dict { PACKAGE_PIN P15   IOSTANDARD LVCMOS33 } [get_ports { jb[5] }]; #IO_L11N_T1_SRCC_14 Sch=jb_n[3]
-#set_property -dict { PACKAGE_PIN N15   IOSTANDARD LVCMOS33 } [get_ports { jb[6] }]; #IO_L12P_T1_MRCC_14 Sch=jb_p[4]
+set_property -dict { PACKAGE_PIN N15   IOSTANDARD LVCMOS33 } [get_ports { IO_USB_DNPULLUP0 }]; #IO_L12P_T1_MRCC_14 Sch=jb_p[4]
 #set_property -dict { PACKAGE_PIN P16   IOSTANDARD LVCMOS33 } [get_ports { jb[7] }]; #IO_L12N_T1_MRCC_14 Sch=jb_n[4]
 
 ## PMOD Header JC
diff --git a/hw/top_earlgrey/data/pins_nexysvideo.xdc b/hw/top_earlgrey/data/pins_nexysvideo.xdc
index 005f23e..4d71ebf 100644
--- a/hw/top_earlgrey/data/pins_nexysvideo.xdc
+++ b/hw/top_earlgrey/data/pins_nexysvideo.xdc
@@ -124,11 +124,11 @@
 ## Pmod header JB
 set_property -dict { PACKAGE_PIN V9    IOSTANDARD LVCMOS33 DRIVE 8 SLEW FAST } [get_ports { IO_USB_DP0 }]; #IO_L21P_T3_DQS_34 Sch=jb_p[1]
 set_property -dict { PACKAGE_PIN V8    IOSTANDARD LVCMOS33 DRIVE 8 SLEW FAST } [get_ports { IO_USB_DN0 }]; #IO_L21N_T3_DQS_34 Sch=jb_n[1]
-set_property -dict { PACKAGE_PIN V7    IOSTANDARD LVCMOS33 } [get_ports { IO_USB_PULLUP0 }]; #IO_L19P_T3_34 Sch=jb_p[2]
+set_property -dict { PACKAGE_PIN V7    IOSTANDARD LVCMOS33 } [get_ports { IO_USB_DPPULLUP0 }]; #IO_L19P_T3_34 Sch=jb_p[2]
 set_property -dict { PACKAGE_PIN W7    IOSTANDARD LVCMOS33 } [get_ports { IO_USB_SENSE0 }]; #IO_L19N_T3_VREF_34 Sch=jb_n[2]
 #set_property -dict { PACKAGE_PIN W9    IOSTANDARD LVCMOS33 DRIVE 8 SLEW FAST } [get_ports { IO_USB_DP1 }]; #IO_L24P_T3_34 Sch=jb_p[3]
 #set_property -dict { PACKAGE_PIN Y9    IOSTANDARD LVCMOS33 DRIVE 8 SLEW FAST } [get_ports { IO_USB_DN1 }]; #IO_L24N_T3_34 Sch=jb_n[3]
-#set_property -dict { PACKAGE_PIN Y8    IOSTANDARD LVCMOS33 } [get_ports { IO_USB_PULLUP1 }]; #IO_L23P_T3_34 Sch=jb_p[4]
+set_property -dict { PACKAGE_PIN Y8    IOSTANDARD LVCMOS33 } [get_ports { IO_USB_DNPULLUP0 }]; #IO_L23P_T3_34 Sch=jb_p[4]
 #set_property -dict { PACKAGE_PIN Y7    IOSTANDARD LVCMOS33 } [get_ports { IO_USB_SENSE1 }]; #IO_L23N_T3_34 Sch=jb_n[4]
 
 
diff --git a/hw/top_earlgrey/data/top_earlgrey.hjson b/hw/top_earlgrey/data/top_earlgrey.hjson
index b9c54fe..07aa2b6 100644
--- a/hw/top_earlgrey/data/top_earlgrey.hjson
+++ b/hw/top_earlgrey/data/top_earlgrey.hjson
@@ -367,7 +367,7 @@
       //{ name: "uart.tx", pad: ["ChA[0]"]},
       { name: "uart", pad: ["ChA[0..1]"]},
       // { name: "dio_module.signal_input", pad: ["ChA[31]"] }
-      { name: "usbdev", pad: ["ChC[0..7]"]},
+      { name: "usbdev", pad: ["ChC[0..8]"]},
     ],
 
     // Multiplexing IO modules. The in/out ports of the modules below are
diff --git a/hw/top_earlgrey/dv/tb/tb.sv b/hw/top_earlgrey/dv/tb/tb.sv
index bff8eb7..8c32271 100644
--- a/hw/top_earlgrey/dv/tb/tb.sv
+++ b/hw/top_earlgrey/dv/tb/tb.sv
@@ -37,7 +37,7 @@
   wire bootstrap;
   wire [7:0] io_dps;
 
-  wire usb_dp0, usb_dn0, usb_sense0, usb_pullup0;
+  wire usb_dp0, usb_dn0, usb_sense0, usb_dppullup0, usb_dnpullup0;
 
   wire uart_rx, uart_tx;
 
@@ -85,7 +85,8 @@
     .IO_USB_DP0       (usb_dp0),
     .IO_USB_DN0       (usb_dn0),
     .IO_USB_SENSE0    (usb_sense0),
-    .IO_USB_PULLUP0   (usb_pullup0),
+    .IO_USB_DNPULLUP0 (usb_dppullup0),
+    .IO_USB_DPPULLUP0 (usb_dnpullup0),
 
     // GPIO x 16 interface
     .IO_GP0           (gpio_pins[0 ]),
diff --git a/hw/top_earlgrey/ip/padctrl/data/autogen/padctrl.hjson b/hw/top_earlgrey/ip/padctrl/data/autogen/padctrl.hjson
index 9207cf8..932166d 100644
--- a/hw/top_earlgrey/ip/padctrl/data/autogen/padctrl.hjson
+++ b/hw/top_earlgrey/ip/padctrl/data/autogen/padctrl.hjson
@@ -25,7 +25,7 @@
     { name: "NDioPads",
       desc: "Number of dedicated IO pads",
       type: "int",
-      default: "14",
+      default: "15",
       local: "true"
     },
     { name: "NMioPads",
diff --git a/hw/top_earlgrey/ip/padctrl/rtl/autogen/padctrl_reg_pkg.sv b/hw/top_earlgrey/ip/padctrl/rtl/autogen/padctrl_reg_pkg.sv
index a5166af..0ec0e6b 100644
--- a/hw/top_earlgrey/ip/padctrl/rtl/autogen/padctrl_reg_pkg.sv
+++ b/hw/top_earlgrey/ip/padctrl/rtl/autogen/padctrl_reg_pkg.sv
@@ -7,7 +7,7 @@
 package padctrl_reg_pkg;
 
   // Param list
-  parameter int NDioPads = 14;
+  parameter int NDioPads = 15;
   parameter int NMioPads = 32;
   parameter int AttrDw = 8;
 
@@ -38,7 +38,7 @@
   // Register to internal design logic //
   ///////////////////////////////////////
   typedef struct packed {
-    padctrl_reg2hw_dio_pads_mreg_t [13:0] dio_pads; // [413:288]
+    padctrl_reg2hw_dio_pads_mreg_t [14:0] dio_pads; // [422:288]
     padctrl_reg2hw_mio_pads_mreg_t [31:0] mio_pads; // [287:0]
   } padctrl_reg2hw_t;
 
@@ -46,7 +46,7 @@
   // Internal design logic to register //
   ///////////////////////////////////////
   typedef struct packed {
-    padctrl_hw2reg_dio_pads_mreg_t [13:0] dio_pads; // [367:256]
+    padctrl_hw2reg_dio_pads_mreg_t [14:0] dio_pads; // [375:256]
     padctrl_hw2reg_mio_pads_mreg_t [31:0] mio_pads; // [255:0]
   } padctrl_hw2reg_t;
 
@@ -89,7 +89,7 @@
     4'b 1111, // index[ 1] PADCTRL_DIO_PADS0
     4'b 1111, // index[ 2] PADCTRL_DIO_PADS1
     4'b 1111, // index[ 3] PADCTRL_DIO_PADS2
-    4'b 0011, // index[ 4] PADCTRL_DIO_PADS3
+    4'b 0111, // index[ 4] PADCTRL_DIO_PADS3
     4'b 1111, // index[ 5] PADCTRL_MIO_PADS0
     4'b 1111, // index[ 6] PADCTRL_MIO_PADS1
     4'b 1111, // index[ 7] PADCTRL_MIO_PADS2
diff --git a/hw/top_earlgrey/ip/padctrl/rtl/autogen/padctrl_reg_top.sv b/hw/top_earlgrey/ip/padctrl/rtl/autogen/padctrl_reg_top.sv
index 278e2d6..c77b0d6 100644
--- a/hw/top_earlgrey/ip/padctrl/rtl/autogen/padctrl_reg_top.sv
+++ b/hw/top_earlgrey/ip/padctrl/rtl/autogen/padctrl_reg_top.sv
@@ -130,6 +130,10 @@
   logic [7:0] dio_pads3_attr13_wd;
   logic dio_pads3_attr13_we;
   logic dio_pads3_attr13_re;
+  logic [7:0] dio_pads3_attr14_qs;
+  logic [7:0] dio_pads3_attr14_wd;
+  logic dio_pads3_attr14_we;
+  logic dio_pads3_attr14_re;
   logic [7:0] mio_pads0_attr0_qs;
   logic [7:0] mio_pads0_attr0_wd;
   logic mio_pads0_attr0_we;
@@ -524,6 +528,22 @@
   );
 
 
+  // F[attr14]: 23:16
+  prim_subreg_ext #(
+    .DW    (8)
+  ) u_dio_pads3_attr14 (
+    .re     (dio_pads3_attr14_re),
+    // qualified with register enable
+    .we     (dio_pads3_attr14_we & regen_qs),
+    .wd     (dio_pads3_attr14_wd),
+    .d      (hw2reg.dio_pads[14].d),
+    .qre    (),
+    .qe     (reg2hw.dio_pads[14].qe),
+    .q      (reg2hw.dio_pads[14].q ),
+    .qs     (dio_pads3_attr14_qs)
+  );
+
+
 
 
   // Subregister 0 of Multireg mio_pads
@@ -1162,6 +1182,10 @@
   assign dio_pads3_attr13_wd = reg_wdata[15:8];
   assign dio_pads3_attr13_re = addr_hit[4] && reg_re;
 
+  assign dio_pads3_attr14_we = addr_hit[4] & reg_we & ~wr_err;
+  assign dio_pads3_attr14_wd = reg_wdata[23:16];
+  assign dio_pads3_attr14_re = addr_hit[4] && reg_re;
+
   assign mio_pads0_attr0_we = addr_hit[5] & reg_we & ~wr_err;
   assign mio_pads0_attr0_wd = reg_wdata[7:0];
   assign mio_pads0_attr0_re = addr_hit[5] && reg_re;
@@ -1322,6 +1346,7 @@
       addr_hit[4]: begin
         reg_rdata_next[7:0] = dio_pads3_attr12_qs;
         reg_rdata_next[15:8] = dio_pads3_attr13_qs;
+        reg_rdata_next[23:16] = dio_pads3_attr14_qs;
       end
 
       addr_hit[5]: begin
diff --git a/hw/top_earlgrey/ip/pinmux/data/autogen/pinmux.hjson b/hw/top_earlgrey/ip/pinmux/data/autogen/pinmux.hjson
index f17bb91..9577bcb 100644
--- a/hw/top_earlgrey/ip/pinmux/data/autogen/pinmux.hjson
+++ b/hw/top_earlgrey/ip/pinmux/data/autogen/pinmux.hjson
@@ -81,7 +81,7 @@
     { name: "NDioPads",
       desc: "Number of dedicated IO pads",
       type: "int",
-      default: "14",
+      default: "15",
       local: "true"
     },
     { name: "NWkupDetect",
diff --git a/hw/top_earlgrey/ip/pinmux/rtl/autogen/pinmux_reg_pkg.sv b/hw/top_earlgrey/ip/pinmux/rtl/autogen/pinmux_reg_pkg.sv
index 6044089..e575020 100644
--- a/hw/top_earlgrey/ip/pinmux/rtl/autogen/pinmux_reg_pkg.sv
+++ b/hw/top_earlgrey/ip/pinmux/rtl/autogen/pinmux_reg_pkg.sv
@@ -10,7 +10,7 @@
   parameter int NMioPeriphIn = 32;
   parameter int NMioPeriphOut = 32;
   parameter int NMioPads = 32;
-  parameter int NDioPads = 14;
+  parameter int NDioPads = 15;
   parameter int NWkupDetect = 8;
   parameter int WkupCntWidth = 8;
 
@@ -77,10 +77,10 @@
   // Register to internal design logic //
   ///////////////////////////////////////
   typedef struct packed {
-    pinmux_reg2hw_periph_insel_mreg_t [31:0] periph_insel; // [657:466]
-    pinmux_reg2hw_mio_outsel_mreg_t [31:0] mio_outsel; // [465:274]
-    pinmux_reg2hw_mio_out_sleep_val_mreg_t [31:0] mio_out_sleep_val; // [273:210]
-    pinmux_reg2hw_dio_out_sleep_val_mreg_t [13:0] dio_out_sleep_val; // [209:168]
+    pinmux_reg2hw_periph_insel_mreg_t [31:0] periph_insel; // [660:469]
+    pinmux_reg2hw_mio_outsel_mreg_t [31:0] mio_outsel; // [468:277]
+    pinmux_reg2hw_mio_out_sleep_val_mreg_t [31:0] mio_out_sleep_val; // [276:213]
+    pinmux_reg2hw_dio_out_sleep_val_mreg_t [14:0] dio_out_sleep_val; // [212:168]
     pinmux_reg2hw_wkup_detector_en_mreg_t [7:0] wkup_detector_en; // [167:160]
     pinmux_reg2hw_wkup_detector_mreg_t [7:0] wkup_detector; // [159:120]
     pinmux_reg2hw_wkup_detector_cnt_th_mreg_t [7:0] wkup_detector_cnt_th; // [119:56]
@@ -92,7 +92,7 @@
   // Internal design logic to register //
   ///////////////////////////////////////
   typedef struct packed {
-    pinmux_hw2reg_dio_out_sleep_val_mreg_t [13:0] dio_out_sleep_val; // [35:8]
+    pinmux_hw2reg_dio_out_sleep_val_mreg_t [14:0] dio_out_sleep_val; // [37:8]
     pinmux_hw2reg_wkup_cause_mreg_t [7:0] wkup_cause; // [7:0]
   } pinmux_hw2reg_t;
 
diff --git a/hw/top_earlgrey/ip/pinmux/rtl/autogen/pinmux_reg_top.sv b/hw/top_earlgrey/ip/pinmux/rtl/autogen/pinmux_reg_top.sv
index 35f8ea3..bf3bc9f 100644
--- a/hw/top_earlgrey/ip/pinmux/rtl/autogen/pinmux_reg_top.sv
+++ b/hw/top_earlgrey/ip/pinmux/rtl/autogen/pinmux_reg_top.sv
@@ -418,6 +418,10 @@
   logic [1:0] dio_out_sleep_val_out13_wd;
   logic dio_out_sleep_val_out13_we;
   logic dio_out_sleep_val_out13_re;
+  logic [1:0] dio_out_sleep_val_out14_qs;
+  logic [1:0] dio_out_sleep_val_out14_wd;
+  logic dio_out_sleep_val_out14_we;
+  logic dio_out_sleep_val_out14_re;
   logic wkup_detector_en_en0_qs;
   logic wkup_detector_en_en0_wd;
   logic wkup_detector_en_en0_we;
@@ -3401,6 +3405,22 @@
   );
 
 
+  // F[out14]: 29:28
+  prim_subreg_ext #(
+    .DW    (2)
+  ) u_dio_out_sleep_val_out14 (
+    .re     (dio_out_sleep_val_out14_re),
+    // qualified with register enable
+    .we     (dio_out_sleep_val_out14_we & regen_qs),
+    .wd     (dio_out_sleep_val_out14_wd),
+    .d      (hw2reg.dio_out_sleep_val[14].d),
+    .qre    (),
+    .qe     (reg2hw.dio_out_sleep_val[14].qe),
+    .q      (reg2hw.dio_out_sleep_val[14].q ),
+    .qs     (dio_out_sleep_val_out14_qs)
+  );
+
+
 
 
   // Subregister 0 of Multireg wkup_detector_en
@@ -5255,6 +5275,10 @@
   assign dio_out_sleep_val_out13_wd = reg_wdata[27:26];
   assign dio_out_sleep_val_out13_re = addr_hit[17] && reg_re;
 
+  assign dio_out_sleep_val_out14_we = addr_hit[17] & reg_we & ~wr_err;
+  assign dio_out_sleep_val_out14_wd = reg_wdata[29:28];
+  assign dio_out_sleep_val_out14_re = addr_hit[17] && reg_re;
+
   assign wkup_detector_en_en0_we = addr_hit[18] & reg_we & ~wr_err;
   assign wkup_detector_en_en0_wd = reg_wdata[0];
 
@@ -5598,6 +5622,7 @@
         reg_rdata_next[23:22] = dio_out_sleep_val_out11_qs;
         reg_rdata_next[25:24] = dio_out_sleep_val_out12_qs;
         reg_rdata_next[27:26] = dio_out_sleep_val_out13_qs;
+        reg_rdata_next[29:28] = dio_out_sleep_val_out14_qs;
       end
 
       addr_hit[18]: begin
diff --git a/hw/top_earlgrey/rtl/autogen/top_earlgrey.sv b/hw/top_earlgrey/rtl/autogen/top_earlgrey.sv
index 7b1f1c5..f6b694d 100644
--- a/hw/top_earlgrey/rtl/autogen/top_earlgrey.sv
+++ b/hw/top_earlgrey/rtl/autogen/top_earlgrey.sv
@@ -30,9 +30,9 @@
   output logic [31:0] mio_out_o,
   output logic [31:0] mio_oe_o,
   // Dedicated I/O
-  input        [13:0] dio_in_i,
-  output logic [13:0] dio_out_o,
-  output logic [13:0] dio_oe_o,
+  input        [14:0] dio_in_i,
+  output logic [14:0] dio_out_o,
+  output logic [14:0] dio_oe_o,
 
   // pad attributes to padring
   output logic[padctrl_reg_pkg::NMioPads-1:0]
@@ -124,9 +124,9 @@
   logic [31:0] mio_p2d;
   logic [31:0] mio_d2p;
   logic [31:0] mio_d2p_en;
-  logic [13:0] dio_p2d;
-  logic [13:0] dio_d2p;
-  logic [13:0] dio_d2p_en;
+  logic [14:0] dio_p2d;
+  logic [14:0] dio_d2p;
+  logic [14:0] dio_d2p_en;
   // uart
   logic        cio_uart_rx_p2d;
   logic        cio_uart_tx_d2p;
@@ -160,8 +160,10 @@
   logic        cio_usbdev_dn_p2d;
   logic        cio_usbdev_se0_d2p;
   logic        cio_usbdev_se0_en_d2p;
-  logic        cio_usbdev_pullup_d2p;
-  logic        cio_usbdev_pullup_en_d2p;
+  logic        cio_usbdev_dp_pullup_d2p;
+  logic        cio_usbdev_dp_pullup_en_d2p;
+  logic        cio_usbdev_dn_pullup_d2p;
+  logic        cio_usbdev_dn_pullup_en_d2p;
   logic        cio_usbdev_tx_mode_se_d2p;
   logic        cio_usbdev_tx_mode_se_en_d2p;
   logic        cio_usbdev_suspend_d2p;
@@ -778,8 +780,10 @@
       // Output
       .cio_se0_o           (cio_usbdev_se0_d2p),
       .cio_se0_en_o        (cio_usbdev_se0_en_d2p),
-      .cio_pullup_o        (cio_usbdev_pullup_d2p),
-      .cio_pullup_en_o     (cio_usbdev_pullup_en_d2p),
+      .cio_dp_pullup_o     (cio_usbdev_dp_pullup_d2p),
+      .cio_dp_pullup_en_o  (cio_usbdev_dp_pullup_en_d2p),
+      .cio_dn_pullup_o     (cio_usbdev_dn_pullup_d2p),
+      .cio_dn_pullup_en_o  (cio_usbdev_dn_pullup_en_d2p),
       .cio_tx_mode_se_o    (cio_usbdev_tx_mode_se_d2p),
       .cio_tx_mode_se_en_o (cio_usbdev_tx_mode_se_en_d2p),
       .cio_suspend_o       (cio_usbdev_suspend_d2p),
@@ -949,15 +953,16 @@
   // Dedicated IO connections
   // Input-only DIOs have no d2p signals
   assign dio_d2p = {
-    1'b0, // DIO13: cio_spi_device_sck
-    1'b0, // DIO12: cio_spi_device_csb
-    1'b0, // DIO11: cio_spi_device_mosi
-    cio_spi_device_miso_d2p, // DIO10
-    1'b0, // DIO9: cio_uart_rx
-    cio_uart_tx_d2p, // DIO8
-    1'b0, // DIO7: cio_usbdev_sense
-    cio_usbdev_se0_d2p, // DIO6
-    cio_usbdev_pullup_d2p, // DIO5
+    1'b0, // DIO14: cio_spi_device_sck
+    1'b0, // DIO13: cio_spi_device_csb
+    1'b0, // DIO12: cio_spi_device_mosi
+    cio_spi_device_miso_d2p, // DIO11
+    1'b0, // DIO10: cio_uart_rx
+    cio_uart_tx_d2p, // DIO9
+    1'b0, // DIO8: cio_usbdev_sense
+    cio_usbdev_se0_d2p, // DIO7
+    cio_usbdev_dp_pullup_d2p, // DIO6
+    cio_usbdev_dn_pullup_d2p, // DIO5
     cio_usbdev_tx_mode_se_d2p, // DIO4
     cio_usbdev_suspend_d2p, // DIO3
     cio_usbdev_d_d2p, // DIO2
@@ -966,15 +971,16 @@
   };
 
   assign dio_d2p_en = {
-    1'b0, // DIO13: cio_spi_device_sck
-    1'b0, // DIO12: cio_spi_device_csb
-    1'b0, // DIO11: cio_spi_device_mosi
-    cio_spi_device_miso_en_d2p, // DIO10
-    1'b0, // DIO9: cio_uart_rx
-    cio_uart_tx_en_d2p, // DIO8
-    1'b0, // DIO7: cio_usbdev_sense
-    cio_usbdev_se0_en_d2p, // DIO6
-    cio_usbdev_pullup_en_d2p, // DIO5
+    1'b0, // DIO14: cio_spi_device_sck
+    1'b0, // DIO13: cio_spi_device_csb
+    1'b0, // DIO12: cio_spi_device_mosi
+    cio_spi_device_miso_en_d2p, // DIO11
+    1'b0, // DIO10: cio_uart_rx
+    cio_uart_tx_en_d2p, // DIO9
+    1'b0, // DIO8: cio_usbdev_sense
+    cio_usbdev_se0_en_d2p, // DIO7
+    cio_usbdev_dp_pullup_en_d2p, // DIO6
+    cio_usbdev_dn_pullup_en_d2p, // DIO5
     cio_usbdev_tx_mode_se_en_d2p, // DIO4
     cio_usbdev_suspend_en_d2p, // DIO3
     cio_usbdev_d_en_d2p, // DIO2
@@ -983,15 +989,16 @@
   };
 
   // Output-only DIOs have no p2d signal
-  assign cio_spi_device_sck_p2d    = dio_p2d[13]; // DIO13
-  assign cio_spi_device_csb_p2d    = dio_p2d[12]; // DIO12
-  assign cio_spi_device_mosi_p2d   = dio_p2d[11]; // DIO11
-  // DIO10: cio_spi_device_miso
-  assign cio_uart_rx_p2d           = dio_p2d[9]; // DIO9
-  // DIO8: cio_uart_tx
-  assign cio_usbdev_sense_p2d      = dio_p2d[7]; // DIO7
-  // DIO6: cio_usbdev_se0
-  // DIO5: cio_usbdev_pullup
+  assign cio_spi_device_sck_p2d    = dio_p2d[14]; // DIO14
+  assign cio_spi_device_csb_p2d    = dio_p2d[13]; // DIO13
+  assign cio_spi_device_mosi_p2d   = dio_p2d[12]; // DIO12
+  // DIO11: cio_spi_device_miso
+  assign cio_uart_rx_p2d           = dio_p2d[10]; // DIO10
+  // DIO9: cio_uart_tx
+  assign cio_usbdev_sense_p2d      = dio_p2d[8]; // DIO8
+  // DIO7: cio_usbdev_se0
+  // DIO6: cio_usbdev_dp_pullup
+  // DIO5: cio_usbdev_dn_pullup
   // DIO4: cio_usbdev_tx_mode_se
   // DIO3: cio_usbdev_suspend
   assign cio_usbdev_d_p2d          = dio_p2d[2]; // DIO2
diff --git a/hw/top_earlgrey/rtl/top_earlgrey_artys7.sv b/hw/top_earlgrey/rtl/top_earlgrey_artys7.sv
index fc666e2..16ab392 100644
--- a/hw/top_earlgrey/rtl/top_earlgrey_artys7.sv
+++ b/hw/top_earlgrey/rtl/top_earlgrey_artys7.sv
@@ -22,7 +22,8 @@
   inout               IO_USB_DP0,
   inout               IO_USB_DN0,
   inout               IO_USB_SENSE0,
-  inout               IO_USB_PULLUP0,
+  inout               IO_USB_DNPULLUP0,
+  inout               IO_USB_DPPULLUP0,
   // GPIO x 16 interface
   inout               IO_GP0,
   inout               IO_GP1,
@@ -65,10 +66,10 @@
     // 2: usbdev_d
     // 3: usbdev_suspend
     // 4: usbdev_tx_mode
-    // 6: usbdev_se
-    // 10-13: SPI / JTAG
-    .ConnectDioIn  ( 14'h03A3 ),
-    .ConnectDioOut ( 14'h03A3 )
+    // 7: usbdev_se
+    // 11-14: SPI / JTAG
+    .ConnectDioIn  ( 15'h0763 ),
+    .ConnectDioOut ( 15'h0763 )
   ) padring (
     // Clk / Rst
     .clk_pad_i           ( 1'b0 ),
@@ -101,7 +102,8 @@
                              IO_UTX,
                              IO_USB_SENSE0,
                              1'bz,    // usbdev_se0
-                             IO_USB_PULLUP0,
+                             IO_USB_DPPULLUP0,
+                             IO_USB_DNPULLUP0,
                              1'bz,    // usbdev_tx_mode
                              1'bz,    // usbdev_suspend
                              1'bz,    // usbdev_d
diff --git a/hw/top_earlgrey/rtl/top_earlgrey_asic.sv b/hw/top_earlgrey/rtl/top_earlgrey_asic.sv
index 77244eb..253f6c1 100644
--- a/hw/top_earlgrey/rtl/top_earlgrey_asic.sv
+++ b/hw/top_earlgrey/rtl/top_earlgrey_asic.sv
@@ -23,7 +23,8 @@
   inout               IO_USB_DP0,
   inout               IO_USB_DN0,
   inout               IO_USB_SENSE0,
-  inout               IO_USB_PULLUP0,
+  inout               IO_USB_DNPULLUP0,
+  inout               IO_USB_DPPULLUP0,
   // GPIO x 16 interface
   inout               IO_GP0,
   inout               IO_GP1,
@@ -66,9 +67,9 @@
     // 2: usbdev_d
     // 3: usbdev_suspend
     // 4: usbdev_tx_mode
-    // 6: usbdev_se
-    .ConnectDioIn  ( 14'h3FA3 ),
-    .ConnectDioOut ( 14'h3FA3 )
+    // 7: usbdev_se
+    .ConnectDioIn  ( 15'h7F63 ),
+    .ConnectDioOut ( 15'h7F63 )
   ) padring (
     // Clk / Rst
     .clk_pad_i           ( IO_CLK           ),
@@ -108,7 +109,8 @@
                              IO_UTX,
                              IO_USB_SENSE0,
                              1'bz,    // usbdev_se0
-                             IO_USB_PULLUP0,
+                             IO_USB_DPPULLUP0,
+                             IO_USB_DNPULLUP0,
                              1'bz,    // usbdev_tx_mode
                              1'bz,    // usbdev_suspend
                              1'bz,    // usbdev_d
diff --git a/hw/top_earlgrey/rtl/top_earlgrey_nexysvideo.sv b/hw/top_earlgrey/rtl/top_earlgrey_nexysvideo.sv
index 8c12213..5cc53f6 100644
--- a/hw/top_earlgrey/rtl/top_earlgrey_nexysvideo.sv
+++ b/hw/top_earlgrey/rtl/top_earlgrey_nexysvideo.sv
@@ -22,7 +22,8 @@
   inout               IO_USB_DP0,
   inout               IO_USB_DN0,
   inout               IO_USB_SENSE0,
-  inout               IO_USB_PULLUP0,
+  inout               IO_USB_DNPULLUP0,
+  inout               IO_USB_DPPULLUP0,
   // GPIO x 16 interface
   inout               IO_GP0,
   inout               IO_GP1,
@@ -67,9 +68,9 @@
     // 2: usbdev_d
     // 3: usbdev_suspend
     // 4: usbdev_tx_mode
-    // 6: usbdev_se
-    .ConnectDioIn  ( 14'h3FA3 ),
-    .ConnectDioOut ( 14'h3FA3 )
+    // 7: usbdev_se
+    .ConnectDioIn  ( 15'h7F63 ),
+    .ConnectDioOut ( 15'h7F63 )
   ) padring (
     // Clk / Rst
     .clk_pad_i           ( 1'b0 ),
@@ -109,7 +110,8 @@
                              IO_UTX,
                              IO_USB_SENSE0,
                              1'bz,    // usbdev_se0
-                             IO_USB_PULLUP0,
+                             IO_USB_DPPULLUP0,
+                             IO_USB_DNPULLUP0,
                              1'bz,    // usbdev_tx_mode
                              1'bz,    // usbdev_suspend
                              1'bz,    // usbdev_d
diff --git a/hw/top_earlgrey/rtl/top_earlgrey_verilator.sv b/hw/top_earlgrey/rtl/top_earlgrey_verilator.sv
index 8e2c9e8..8b29856 100644
--- a/hw/top_earlgrey/rtl/top_earlgrey_verilator.sv
+++ b/hw/top_earlgrey/rtl/top_earlgrey_verilator.sv
@@ -20,9 +20,10 @@
 
   logic cio_usbdev_sense_p2d;
   logic cio_usbdev_se0_d2p, cio_usbdev_se0_en_d2p;
-  logic cio_usbdev_pullup_d2p, cio_usbdev_pullup_en_d2p;
+  logic cio_usbdev_dp_pullup_d2p, cio_usbdev_dp_pullup_en_d2p;
+  logic cio_usbdev_dn_pullup_d2p, cio_usbdev_dn_pullup_en_d2p;
   logic cio_usbdev_tx_mode_se_d2p, cio_usbdev_tx_mode_se_en_d2p;
-  logic cio_usbdev_supsend_d2p, cio_usbdev_supsend_en_d2p;
+  logic cio_usbdev_suspend_d2p, cio_usbdev_suspend_en_d2p;
   logic cio_usbdev_d_p2d, cio_usbdev_d_d2p, cio_usbdev_d_en_d2p;
   logic cio_usbdev_dp_p2d, cio_usbdev_dp_d2p, cio_usbdev_dp_en_d2p;
   logic cio_usbdev_dn_p2d, cio_usbdev_dn_d2p, cio_usbdev_dn_en_d2p;
@@ -30,9 +31,9 @@
   logic IO_JTCK, IO_JTMS, IO_JTRST_N, IO_JTDI, IO_JTDO;
 
   // TODO: instantiate padring and route these signals through that module
-  logic [13:0] dio_in;
-  logic [13:0] dio_out;
-  logic [13:0] dio_oe;
+  logic [14:0] dio_in;
+  logic [14:0] dio_out;
+  logic [14:0] dio_oe;
 
   assign dio_in = {cio_spi_device_sck_p2d,
                    cio_spi_device_csb_p2d,
@@ -45,6 +46,7 @@
                    1'b0,
                    1'b0,
                    1'b0,
+                   1'b0,
                    cio_usbdev_d_p2d,
                    cio_usbdev_dp_p2d,
                    cio_usbdev_dn_p2d};
@@ -54,20 +56,22 @@
   assign cio_usbdev_d_d2p  = dio_out[2];
   assign cio_usbdev_suspend_d2p = dio_out[3];
   assign cio_usbdev_tx_mode_se_d2p = dio_out[4];
-  assign cio_usbdev_pullup_d2p = dio_out[5];
-  assign cio_usbdev_se0_d2p = dio_out[6];
-  assign cio_uart_tx_d2p = dio_out[8];
-  assign cio_spi_device_miso_d2p = dio_out[10];
+  assign cio_usbdev_dn_pullup_d2p = dio_out[5];
+  assign cio_usbdev_dp_pullup_d2p = dio_out[6];
+  assign cio_usbdev_se0_d2p = dio_out[7];
+  assign cio_uart_tx_d2p = dio_out[9];
+  assign cio_spi_device_miso_d2p = dio_out[11];
 
   assign cio_usbdev_dn_en_d2p = dio_oe[0];
   assign cio_usbdev_dp_en_d2p = dio_oe[1];
   assign cio_usbdev_d_en_d2p  = dio_oe[2];
   assign cio_usbdev_suspend_en_d2p = dio_oe[3];
   assign cio_usbdev_tx_mode_se_en_d2p = dio_oe[4];
-  assign cio_usbdev_pullup_en_d2p = dio_oe[5];
-  assign cio_usbdev_se0_en_d2p = dio_oe[6];
-  assign cio_uart_tx_en_d2p = dio_oe[8];
-  assign cio_spi_device_miso_en_d2p = dio_oe[10];
+  assign cio_usbdev_dn_pullup_en_d2p = dio_oe[5];
+  assign cio_usbdev_dp_pullup_en_d2p = dio_oe[6];
+  assign cio_usbdev_se0_en_d2p = dio_oe[7];
+  assign cio_uart_tx_en_d2p = dio_oe[9];
+  assign cio_spi_device_miso_en_d2p = dio_oe[11];
 
   // Top-level design
   top_earlgrey top_earlgrey (
@@ -172,8 +176,8 @@
     .rst_ni        (rst_ni),
     .clk_48MHz_i   (clk_i),
     .sense_p2d     (cio_usbdev_sense_p2d),
-    .pullup_d2p    (cio_usbdev_pullup_d2p),
-    .pullup_en_d2p (cio_usbdev_pullup_en_d2p),
+    .pullup_d2p    (cio_usbdev_dp_pullup_d2p),
+    .pullup_en_d2p (cio_usbdev_dp_pullup_en_d2p),
     .dp_p2d        (cio_usbdev_dp_p2d),
     .dp_d2p        (cio_usbdev_dp_d2p),
     .dp_en_d2p     (cio_usbdev_dp_en_d2p),
@@ -184,11 +188,14 @@
 
   // Tie off unused signals.
   logic unused_cio_usbdev_se0_d2p, unused_cio_usbdev_se0_en_d2p;
+  logic unused_cio_usbdev_dn_pullup_d2p, unused_cio_usbdev_dn_pullup_en_d2p;
   logic unused_cio_usbdev_tx_mode_se_d2p, unused_cio_usbdev_tx_mode_se_en_d2p;
-  logic unused_cio_usbdev_supsend_d2p, unused_cio_usbdev_supsend_en_d2p;
+  logic unused_cio_usbdev_suspend_d2p, unused_cio_usbdev_suspend_en_d2p;
   logic unused_cio_usbdev_d_d2p, unused_cio_usbdev_d_en_d2p;
   assign unused_cio_usbdev_se0_d2p = cio_usbdev_se0_d2p;
   assign unused_cio_usbdev_se0_en_d2p = cio_usbdev_se0_en_d2p;
+  assign unused_cio_usbdev_dn_pullup_d2p = cio_usbdev_dn_pullup_d2p;
+  assign unused_cio_usbdev_dn_pullup_en_d2p = cio_usbdev_dn_pullup_en_d2p;
   assign unused_cio_usbdev_tx_mode_se_d2p = cio_usbdev_tx_mode_se_d2p;
   assign unused_cio_usbdev_tx_mode_se_en_d2p = cio_usbdev_tx_mode_se_en_d2p;
   assign unused_cio_usbdev_suspend_d2p = cio_usbdev_suspend_d2p;
diff --git a/hw/top_earlgrey/sw/autogen/top_earlgrey.h b/hw/top_earlgrey/sw/autogen/top_earlgrey.h
index 6315923..3a82787 100644
--- a/hw/top_earlgrey/sw/autogen/top_earlgrey.h
+++ b/hw/top_earlgrey/sw/autogen/top_earlgrey.h
@@ -10,7 +10,7 @@
 // PERIPH_INSEL ranges from 0 to NUM_MIO + 2 -1}
 //  0 and 1 are tied to value 0 and 1
 #define NUM_MIO 32
-#define NUM_DIO 14
+#define NUM_DIO 15
 
 #define PINMUX_GPIO_GPIO_0_IN 0
 #define PINMUX_GPIO_GPIO_1_IN 1
diff --git a/hw/top_earlgrey/syn/constraints.sdc b/hw/top_earlgrey/syn/constraints.sdc
index 4891634..4d6bdea 100644
--- a/hw/top_earlgrey/syn/constraints.sdc
+++ b/hw/top_earlgrey/syn/constraints.sdc
@@ -55,12 +55,14 @@
 set_input_delay ${IN_DEL} [get_ports dio_usbdev_dp_i]          -clock ${USB_CLK_PIN}
 set_input_delay ${IN_DEL} [get_ports dio_usbdev_dn_i]          -clock ${USB_CLK_PIN}
 
-set_output_delay ${OUT_DEL} [get_ports dio_usbdev_pullup_o]    -clock ${USB_CLK_PIN}
-set_output_delay ${OUT_DEL} [get_ports dio_usbdev_pullup_en_o] -clock ${USB_CLK_PIN}
-set_output_delay ${OUT_DEL} [get_ports dio_usbdev_dp_o]        -clock ${USB_CLK_PIN}
-set_output_delay ${OUT_DEL} [get_ports dio_usbdev_dp_en_o]     -clock ${USB_CLK_PIN}
-set_output_delay ${OUT_DEL} [get_ports dio_usbdev_dn_o]        -clock ${USB_CLK_PIN}
-set_output_delay ${OUT_DEL} [get_ports dio_usbdev_dn_en_o]     -clock ${USB_CLK_PIN}
+set_output_delay ${OUT_DEL} [get_ports dio_usbdev_dp_pullup_o]    -clock ${USB_CLK_PIN}
+set_output_delay ${OUT_DEL} [get_ports dio_usbdev_dp_pullup_en_o] -clock ${USB_CLK_PIN}
+set_output_delay ${OUT_DEL} [get_ports dio_usbdev_dn_pullup_o]    -clock ${USB_CLK_PIN}
+set_output_delay ${OUT_DEL} [get_ports dio_usbdev_dn_pullup_en_o] -clock ${USB_CLK_PIN}
+set_output_delay ${OUT_DEL} [get_ports dio_usbdev_dp_o]           -clock ${USB_CLK_PIN}
+set_output_delay ${OUT_DEL} [get_ports dio_usbdev_dp_en_o]        -clock ${USB_CLK_PIN}
+set_output_delay ${OUT_DEL} [get_ports dio_usbdev_dn_o]           -clock ${USB_CLK_PIN}
+set_output_delay ${OUT_DEL} [get_ports dio_usbdev_dn_en_o]        -clock ${USB_CLK_PIN}
 
 #####################
 # JTAG clock        #