[usbdev] Move pinflip and dp_o/dn_o to usb_fs_nb_pe

Handle the interface changes and alternate TX interface in logic, before
the final register. Prior to this change, the pinflip was sometimes
handled in clock muxes, on the I/O side of the first/final registers,
and the dp_o/dn_o interface was only done in behavioral logic. Move this
all inside the USB clock domain, and perform only the pin overrides with
clock muxes.

Add override for rx_enable and remove the redundant one for
tx_use_d_se0.

Signed-off-by: Alexander Williams <awill@google.com>
diff --git a/hw/ip/usb_fs_nb_pe/rtl/usb_fs_nb_pe.sv b/hw/ip/usb_fs_nb_pe/rtl/usb_fs_nb_pe.sv
index 82c6070..38b1210 100644
--- a/hw/ip/usb_fs_nb_pe/rtl/usb_fs_nb_pe.sv
+++ b/hw/ip/usb_fs_nb_pe/rtl/usb_fs_nb_pe.sv
@@ -32,6 +32,8 @@
 
   input  logic                   cfg_eop_single_bit_i, // 1: detect a single SE0 bit as EOP
   input  logic                   cfg_use_diff_rcvr_i, // 1: use usb_d_i from a differential receiver
+  input  logic                   cfg_pinflip_i, // 1: USB-side D+ and D- pins are flipped.
+                                                // Change values in logic to accommodate.
   input  logic                   tx_osc_test_mode_i, // Oscillator test mode (constantly output JK)
   input  logic [NumOutEps-1:0]   data_toggle_clear_i, // Clear the data toggles for an EP
   input  logic                   diff_rx_ok_i, // 1: received differential data symbols are valid.
@@ -100,6 +102,8 @@
   ///////////////////////////////////////
   output logic                   usb_d_o,
   output logic                   usb_se0_o,
+  output logic                   usb_dp_o,
+  output logic                   usb_dn_o,
   output logic                   usb_oe_o
 );
 
@@ -238,6 +242,7 @@
     .link_reset_i           (link_reset_i),
     .cfg_eop_single_bit_i   (cfg_eop_single_bit_i),
     .cfg_use_diff_rcvr_i    (cfg_use_diff_rcvr_i),
+    .cfg_pinflip_i          (cfg_pinflip_i),
     .diff_rx_ok_i           (diff_rx_ok_i),
     .usb_d_i                (usb_d_i),
     .usb_dp_i               (usb_dp_i),
@@ -278,10 +283,13 @@
     .clk_i                  (clk_48mhz_i),
     .rst_ni                 (rst_ni),
     .link_reset_i           (link_reset_i),
+    .cfg_pinflip_i          (cfg_pinflip_i),
     .tx_osc_test_mode_i     (tx_osc_test_mode_i),
     .bit_strobe_i           (bit_strobe),
     .usb_d_o                (usb_d_o),
     .usb_se0_o              (usb_se0_o),
+    .usb_dp_o               (usb_dp_o),
+    .usb_dn_o               (usb_dn_o),
     .usb_oe_o               (usb_oe),
     .pkt_start_i            (tx_pkt_start),
     .pkt_end_o              (tx_pkt_end),
diff --git a/hw/ip/usb_fs_nb_pe/rtl/usb_fs_rx.sv b/hw/ip/usb_fs_nb_pe/rtl/usb_fs_rx.sv
index b63d915..20f00fc 100644
--- a/hw/ip/usb_fs_nb_pe/rtl/usb_fs_rx.sv
+++ b/hw/ip/usb_fs_nb_pe/rtl/usb_fs_rx.sv
@@ -13,6 +13,7 @@
   // configuration
   input  logic cfg_eop_single_bit_i,
   input  logic cfg_use_diff_rcvr_i,
+  input  logic cfg_pinflip_i,
   input  logic diff_rx_ok_i,
 
   // USB data+ and data- lines (synchronous)
@@ -63,7 +64,11 @@
   //////////////////////
   // usb receive path //
   //////////////////////
-
+  // Adjust inputs when D+/D- are flipped on the USB side
+  logic usb_dp_flipped, usb_dn_flipped, usb_d_flipped;
+  assign usb_dp_flipped = usb_dp_i ^ cfg_pinflip_i;
+  assign usb_dn_flipped = usb_dn_i ^ cfg_pinflip_i;
+  assign usb_d_flipped = usb_d_i ^ cfg_pinflip_i;
 
   ///////////////////////////////////////
   // line state recovery state machine //
@@ -117,8 +122,8 @@
       dpair = DJ[1:0]; // J
       ddiff = DJ[1:0]; // J
     end else begin
-      dpair = {usb_dp_i, usb_dn_i};
-      ddiff = usb_d_i ? DJ[1:0] : DK[1:0]; // equiv to {usb_d_i, ~usb_d_i}
+      dpair = {usb_dp_flipped, usb_dn_flipped};
+      ddiff = usb_d_flipped ? DJ[1:0] : DK[1:0]; // equiv to {usb_d_i, ~usb_d_i}
     end
   end
 
diff --git a/hw/ip/usb_fs_nb_pe/rtl/usb_fs_tx.sv b/hw/ip/usb_fs_nb_pe/rtl/usb_fs_tx.sv
index 7735845..9a8cd22 100644
--- a/hw/ip/usb_fs_nb_pe/rtl/usb_fs_tx.sv
+++ b/hw/ip/usb_fs_nb_pe/rtl/usb_fs_tx.sv
@@ -10,6 +10,7 @@
   input  logic clk_i,
   input  logic rst_ni,  // asyc reset
   input  logic link_reset_i, // USB reset, sync to 48 MHz, active high
+  input  logic cfg_pinflip_i,
 
   // Oscillator test mode (constantly output JK)
   input  logic tx_osc_test_mode_i,
@@ -21,6 +22,8 @@
   output logic usb_oe_o,
   output logic usb_d_o,
   output logic usb_se0_o,
+  output logic usb_dp_o,
+  output logic usb_dn_o,
 
   // pulse to initiate new packet transmission
   input  logic pkt_start_i,
@@ -449,8 +452,61 @@
     .q_o(usb_se0_q)
   );
 
+  // Handle the D+ / D- pin flip on the USB side, and provide both the
+  // dp/dn and d/se0 interfaces, for compatibility with multiple driver types.
+  logic usb_d_flipped, usb_se0_flipped, usb_dp_flipped, usb_dn_flipped;
+
+  always_comb begin
+    if (link_reset_i) begin
+      usb_d_flipped = 1'b0 ^ cfg_pinflip_i;
+      usb_se0_flipped = 1'b0;
+      usb_dp_flipped = 1'b0 ^ cfg_pinflip_i;
+      usb_dn_flipped = 1'b1 ^ cfg_pinflip_i;
+    end else begin
+      usb_d_flipped = usb_d_d ^ cfg_pinflip_i;
+      usb_se0_flipped = usb_se0_d;
+      usb_dp_flipped = (usb_d_d & ~usb_se0_d) ^ cfg_pinflip_i;
+      usb_dn_flipped = (~usb_d_d & ~usb_se0_d) ^ cfg_pinflip_i;
+    end
+  end
+
+  // Use registered outputs for the I/Os
+  prim_flop #(
+    .ResetValue(1) // J state = idle state
+  ) u_usb_d_o_flop (
+    .clk_i,
+    .rst_ni,
+    .d_i(usb_d_flipped),
+    .q_o(usb_d_o)
+  );
+
+  prim_flop #(
+    .ResetValue(0) // J state = idle state
+  ) u_usb_se0_o_flop (
+    .clk_i,
+    .rst_ni,
+    .d_i(usb_se0_flipped),
+    .q_o(usb_se0_o)
+  );
+
+  prim_flop #(
+    .ResetValue(1) // J state = idle state
+  ) u_usb_dp_o_flop (
+    .clk_i,
+    .rst_ni,
+    .d_i(usb_dp_flipped),
+    .q_o(usb_dp_o)
+  );
+
+  prim_flop #(
+    .ResetValue(0) // J state = idle state
+  ) u_usb_dn_o_flop (
+    .clk_i,
+    .rst_ni,
+    .d_i(usb_dn_flipped),
+    .q_o(usb_dn_o)
+  );
+
   assign usb_oe_o  = oe_q;
-  assign usb_d_o   = usb_d_q;
-  assign usb_se0_o = usb_se0_q;
 
 endmodule
diff --git a/hw/ip/usbdev/data/usbdev.hjson b/hw/ip/usbdev/data/usbdev.hjson
index 8970fe1..a8364f9 100644
--- a/hw/ip/usbdev/data/usbdev.hjson
+++ b/hw/ip/usbdev/data/usbdev.hjson
@@ -859,8 +859,8 @@
         }
         {
           bits: "5",
-          name: "tx_use_d_se0_o",
-          desc: "USB TX mode, intended to enable a variety of transceivers. 0: use dp/dn interface, 1: use d/se0 interface"
+          name: "rx_enable_o",
+          desc: "Enable differential receiver."
         }
         {
           bits: "6",
diff --git a/hw/ip/usbdev/rtl/usbdev.sv b/hw/ip/usbdev/rtl/usbdev.sv
index 6d0bfe4..30108c1 100644
--- a/hw/ip/usbdev/rtl/usbdev.sv
+++ b/hw/ip/usbdev/rtl/usbdev.sv
@@ -175,12 +175,16 @@
   /////////////////////////////////
   logic usb_tx_d;
   logic usb_tx_se0;
+  logic usb_tx_dp;
+  logic usb_tx_dn;
   logic usb_tx_oe;
   /////////////////////////////////
   // USB contol pins after CDC   //
   /////////////////////////////////
   logic usb_pwr_sense;
   logic usb_pullup_en;
+  logic usb_dp_pullup_en;
+  logic usb_dn_pullup_en;
 
   //////////////////////////////////
   // Microsecond timing reference //
@@ -562,6 +566,10 @@
   ////////////////////////////////////////////////////////
   // USB interface -- everything is in USB clock domain //
   ////////////////////////////////////////////////////////
+  wire cfg_pinflip = reg2hw.phy_config.pinflip.q; // cdc ok: quasi-static
+  assign usb_dp_pullup_en = cfg_pinflip ? 1'b0 : usb_pullup_en;
+  assign usb_dn_pullup_en = !cfg_pinflip ? 1'b0 : usb_pullup_en;
+
 
   usbdev_usbif #(
     .NEndpoints     (NEndpoints),
@@ -581,6 +589,8 @@
     .usb_oe_o             (usb_tx_oe),
     .usb_d_o              (usb_tx_d),
     .usb_se0_o            (usb_tx_se0),
+    .usb_dp_o             (usb_tx_dp),
+    .usb_dn_o             (usb_tx_dn),
     .usb_sense_i          (usb_pwr_sense),
     .usb_pullup_en_o      (usb_pullup_en),
 
@@ -631,7 +641,8 @@
     .diff_rx_ok_i         (usb_diff_rx_ok),
     .cfg_eop_single_bit_i (reg2hw.phy_config.eop_single_bit.q), // cdc ok: quasi-static
     .tx_osc_test_mode_i   (reg2hw.phy_config.tx_osc_test_mode.q), // cdc ok: quasi-static
-    .cfg_use_diff_rcvr_i  (reg2hw.phy_config.use_diff_rcvr.q), // cdc ok: quasi-static
+    .cfg_use_diff_rcvr_i  (usb_rx_enable_o),
+    .cfg_pinflip_i        (cfg_pinflip),
     .data_toggle_clear_i  (usb_data_toggle_clear),
     .resume_link_active_i (usb_resume_link_active),
 
@@ -1069,7 +1080,11 @@
   /////////////////////////////////
   // USB IO Muxing               //
   /////////////////////////////////
-  assign cio_usb_dn_en_o = cio_usb_dp_en_o;
+  logic cio_usb_oe;
+  logic usb_rx_enable;
+  assign cio_usb_dp_en_o = cio_usb_oe;
+  assign cio_usb_dn_en_o = cio_usb_oe;
+  assign usb_tx_use_d_se0_o = reg2hw.phy_config.tx_use_d_se0.q; // cdc ok: quasi-static
 
   usbdev_iomux i_usbdev_iomux (
     .clk_i                  (clk_i),
@@ -1080,7 +1095,6 @@
     // Register interface
     .sys_hw2reg_sense_o     (hw2reg.phy_pins_sense),
     .sys_reg2hw_drive_i     (reg2hw.phy_pins_drive),
-    .sys_reg2hw_config_i    (reg2hw.phy_config),
     .sys_usb_sense_o        (hw2reg.usbstat.sense.d),
 
     // Chip IO
@@ -1091,12 +1105,12 @@
     .usb_tx_se0_o           (usb_tx_se0_o),
     .usb_tx_dp_o            (cio_usb_dp_o),
     .usb_tx_dn_o            (cio_usb_dn_o),
-    .usb_tx_oe_o            (cio_usb_dp_en_o),
-    .usb_tx_use_d_se0_o     (usb_tx_use_d_se0_o),
+    .usb_tx_oe_o            (cio_usb_oe),
     .cio_usb_sense_i        (cio_sense_i),
     .usb_dp_pullup_en_o     (usb_dp_pullup_o),
     .usb_dn_pullup_en_o     (usb_dn_pullup_o),
     .usb_suspend_o          (usb_suspend_o),
+    .usb_rx_enable_o        (usb_rx_enable_o),
 
     // Internal interface
     .usb_rx_d_o             (usb_rx_d),
@@ -1104,10 +1118,14 @@
     .usb_rx_dn_o            (usb_rx_dn),
     .usb_tx_d_i             (usb_tx_d),
     .usb_tx_se0_i           (usb_tx_se0),
+    .usb_tx_dp_i            (usb_tx_dp),
+    .usb_tx_dn_i            (usb_tx_dn),
     .usb_tx_oe_i            (usb_tx_oe),
     .usb_pwr_sense_o        (usb_pwr_sense),
-    .usb_pullup_en_i        (usb_pullup_en),
-    .usb_suspend_i          (usb_event_link_suspend)
+    .usb_dp_pullup_en_i     (usb_dp_pullup_en),
+    .usb_dn_pullup_en_i     (usb_dn_pullup_en),
+    .usb_suspend_i          (usb_event_link_suspend),
+    .usb_rx_enable_i        (usb_rx_enable)
   );
 
   // Differential receiver enable
@@ -1120,8 +1138,8 @@
     .q_o    (usb_use_diff_rcvr)
   );
   // enable rx only when the single-ended input is enabled and the device is
-  // not suspended.
-  assign usb_rx_enable_o = usb_use_diff_rcvr & ~usb_suspend_o;
+  // not suspended (unless it is forced on in the I/O mux).
+  assign usb_rx_enable = usb_use_diff_rcvr & ~usb_suspend_o;
 
   // Symbols from the differential receiver are invalid until it has finished
   // waking up / powering on
diff --git a/hw/ip/usbdev/rtl/usbdev_iomux.sv b/hw/ip/usbdev/rtl/usbdev_iomux.sv
index 3e8c1a6..f6859a3 100644
--- a/hw/ip/usbdev/rtl/usbdev_iomux.sv
+++ b/hw/ip/usbdev/rtl/usbdev_iomux.sv
@@ -5,9 +5,8 @@
 //
 // USB IO Mux
 //
-// 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.
+// Muxes the USB IO signals between the override CSRs and the USB engine. The
+// incoming signals are also synchronized to the corresponding clock domain.
 
 module usbdev_iomux
   import usbdev_reg_pkg::*;
@@ -20,7 +19,6 @@
   // Register interface (system clk)
   output usbdev_hw2reg_phy_pins_sense_reg_t sys_hw2reg_sense_o,
   input  usbdev_reg2hw_phy_pins_drive_reg_t sys_reg2hw_drive_i,
-  input  usbdev_reg2hw_phy_config_reg_t     sys_reg2hw_config_i,
   output logic                              sys_usb_sense_o,
 
   // External USB Interface(s) (async)
@@ -33,12 +31,12 @@
   output logic                          usb_tx_dp_o,
   output logic                          usb_tx_dn_o,
   output logic                          usb_tx_oe_o,
-  output logic                          usb_tx_use_d_se0_o,
 
   input  logic                          cio_usb_sense_i,
   output logic                          usb_dp_pullup_en_o,
   output logic                          usb_dn_pullup_en_o,
   output logic                          usb_suspend_o,
+  output logic                          usb_rx_enable_o,
 
   // Internal USB Interface (usb clk)
   output logic                          usb_rx_d_o,
@@ -46,28 +44,17 @@
   output logic                          usb_rx_dn_o,
   input  logic                          usb_tx_d_i,
   input  logic                          usb_tx_se0_i,
+  input  logic                          usb_tx_dp_i,
+  input  logic                          usb_tx_dn_i,
   input  logic                          usb_tx_oe_i,
-  output logic                          usb_pwr_sense_o,
-  input  logic                          usb_pullup_en_i,
-  input  logic                          usb_suspend_i
+  input  logic                          usb_dp_pullup_en_i,
+  input  logic                          usb_dn_pullup_en_i,
+  input  logic                          usb_suspend_i,
+  input  logic                          usb_rx_enable_i,
+  output logic                          usb_pwr_sense_o
 );
 
-  logic usb_tx_d_flipped;
-  logic usb_dp_pullup_en, usb_dn_pullup_en;
-
   logic sys_usb_sense;
-  logic usb_rx_dp, usb_rx_dn, usb_rx_d;
-  logic pinflip;
-  logic unused_eop_single_bit;
-  logic unused_use_diff_rcvr;
-  logic unused_usb_ref_disable;
-  logic unused_tx_osc_test_mode;
-
-  assign unused_eop_single_bit       = sys_reg2hw_config_i.eop_single_bit.q;
-  assign unused_usb_ref_disable      = sys_reg2hw_config_i.usb_ref_disable.q;
-  assign unused_tx_osc_test_mode     = sys_reg2hw_config_i.tx_osc_test_mode.q;
-  assign unused_use_diff_rcvr        = sys_reg2hw_config_i.use_diff_rcvr.q;
-
   //////////
   // CDCs //
   //////////
@@ -81,8 +68,8 @@
     .d_i    ({usb_rx_dp_i,
               usb_rx_dn_i,
               usb_rx_d_i,
-              usb_tx_dp_o,
-              usb_tx_dn_o,
+              usb_tx_dp_i,
+              usb_tx_dn_i,
               usb_tx_d_i,
               usb_tx_se0_i,
               usb_tx_oe_i,
@@ -113,79 +100,28 @@
               usb_rx_dn_i,
               usb_rx_d_i,
               cio_usb_sense_i}),
-    .q_o    ({usb_rx_dp,
-              usb_rx_dn,
-              usb_rx_d,
+    .q_o    ({usb_rx_dp_o,
+              usb_rx_dn_o,
+              usb_rx_d_o,
               usb_pwr_sense_o})
   );
 
   ////////////////////////
   // USB output pin mux //
   ////////////////////////
-
-  // D+/D- can be swapped based on a config register.
-  assign pinflip = sys_reg2hw_config_i.pinflip.q;
-
-  prim_clock_mux2 #(
-    .NoFpgaBufG(1)
-  ) i_mux_tx_d_flip (
-    .clk0_i (usb_tx_d_i),
-    .clk1_i (~usb_tx_d_i),
-    .sel_i  (pinflip),
-    .clk_o  (usb_tx_d_flipped)
-  );
-  prim_clock_mux2 #(
-    .NoFpgaBufG(1)
-  ) i_mux_dp_pull_flip (
-    .clk0_i (usb_pullup_en_i),
-    .clk1_i (1'b0),
-    .sel_i  (pinflip),
-    .clk_o  (usb_dp_pullup_en)
-  );
-  prim_clock_mux2 #(
-    .NoFpgaBufG(1)
-  ) i_mux_dn_pull_flip (
-    .clk0_i (1'b0),
-    .clk1_i (usb_pullup_en_i),
-    .sel_i  (pinflip),
-    .clk_o  (usb_dn_pullup_en)
-  );
-
   always_comb begin : proc_drive_out
-    // Defaults
-    usb_tx_dn_o           = 1'b0;
-    usb_tx_dp_o           = 1'b0;
-
     if (sys_reg2hw_drive_i.en.q) begin
       // Override from registers
-      usb_tx_dp_o       = sys_reg2hw_drive_i.dp_o.q;
-      usb_tx_dn_o       = sys_reg2hw_drive_i.dn_o.q;
       usb_dp_pullup_en_o = sys_reg2hw_drive_i.dp_pullup_en_o.q;
       usb_dn_pullup_en_o = sys_reg2hw_drive_i.dn_pullup_en_o.q;
-      usb_tx_use_d_se0_o = sys_reg2hw_drive_i.tx_use_d_se0_o.q;
       usb_suspend_o      = sys_reg2hw_drive_i.suspend_o.q;
-
+      usb_rx_enable_o    = sys_reg2hw_drive_i.rx_enable_o.q;
     end else begin
       // Signals from the peripheral core
-      usb_dp_pullup_en_o = usb_dp_pullup_en;
-      usb_dn_pullup_en_o = usb_dn_pullup_en;
+      usb_dp_pullup_en_o = usb_dp_pullup_en_i;
+      usb_dn_pullup_en_o = usb_dn_pullup_en_i;
       usb_suspend_o      = usb_suspend_i;
-
-      if(sys_reg2hw_config_i.tx_use_d_se0.q) begin
-        // Single-ended TX interface (physical IO takes d and se0)
-        usb_tx_use_d_se0_o = 1'b1;
-      end else begin
-        // Differential TX interface (physical IO takes dp and dn)
-        // i.e. expect the "else" logic to be in the physical interface
-        usb_tx_use_d_se0_o = 1'b0;
-        if (usb_tx_se0_i) begin
-          usb_tx_dp_o = 1'b0;
-          usb_tx_dn_o = 1'b0;
-        end else begin
-          usb_tx_dp_o = usb_tx_d_flipped;
-          usb_tx_dn_o = ~usb_tx_d_flipped;
-        end
-      end
+      usb_rx_enable_o    = usb_rx_enable_i;
     end
   end
 
@@ -196,8 +132,24 @@
   // degrades performance in the JK-KJ jitter test.
   prim_clock_mux2 #(
     .NoFpgaBufG(1)
+  ) i_mux_tx_dp (
+    .clk0_i (usb_tx_dp_i),
+    .clk1_i (sys_reg2hw_drive_i.dp_o.q),
+    .sel_i  (sys_reg2hw_drive_i.en.q),
+    .clk_o  (usb_tx_dp_o)
+  );
+  prim_clock_mux2 #(
+    .NoFpgaBufG(1)
+  ) i_mux_tx_dn (
+    .clk0_i (usb_tx_dn_i),
+    .clk1_i (sys_reg2hw_drive_i.dn_o.q),
+    .sel_i  (sys_reg2hw_drive_i.en.q),
+    .clk_o  (usb_tx_dn_o)
+  );
+  prim_clock_mux2 #(
+    .NoFpgaBufG(1)
   ) i_mux_tx_d (
-    .clk0_i (usb_tx_d_flipped),
+    .clk0_i (usb_tx_d_i),
     .clk1_i (sys_reg2hw_drive_i.d_o.q),
     .sel_i  (sys_reg2hw_drive_i.en.q),
     .clk_o  (usb_tx_d_o)
@@ -219,13 +171,4 @@
     .clk_o  (usb_tx_oe_o)
   );
 
-  ///////////////////////
-  // USB input pin mux //
-  ///////////////////////
-
-  // D+/D- can be swapped based on a config register.
-  assign usb_rx_dp_o = pinflip ?  usb_rx_dn : usb_rx_dp;
-  assign usb_rx_dn_o = pinflip ?  usb_rx_dp : usb_rx_dn;
-  assign usb_rx_d_o  = pinflip ? ~usb_rx_d  : usb_rx_d;
-
 endmodule
diff --git a/hw/ip/usbdev/rtl/usbdev_reg_pkg.sv b/hw/ip/usbdev/rtl/usbdev_reg_pkg.sv
index 15ac6cd..fb5eb28 100644
--- a/hw/ip/usbdev/rtl/usbdev_reg_pkg.sv
+++ b/hw/ip/usbdev/rtl/usbdev_reg_pkg.sv
@@ -312,7 +312,7 @@
     } oe_o;
     struct packed {
       logic        q;
-    } tx_use_d_se0_o;
+    } rx_enable_o;
     struct packed {
       logic        q;
     } dp_pullup_en_o;
diff --git a/hw/ip/usbdev/rtl/usbdev_reg_top.sv b/hw/ip/usbdev/rtl/usbdev_reg_top.sv
index 0cfb2b9..50e1226 100644
--- a/hw/ip/usbdev/rtl/usbdev_reg_top.sv
+++ b/hw/ip/usbdev/rtl/usbdev_reg_top.sv
@@ -670,8 +670,8 @@
   logic phy_pins_drive_se0_o_wd;
   logic phy_pins_drive_oe_o_qs;
   logic phy_pins_drive_oe_o_wd;
-  logic phy_pins_drive_tx_use_d_se0_o_qs;
-  logic phy_pins_drive_tx_use_d_se0_o_wd;
+  logic phy_pins_drive_rx_enable_o_qs;
+  logic phy_pins_drive_rx_enable_o_wd;
   logic phy_pins_drive_dp_pullup_en_o_qs;
   logic phy_pins_drive_dp_pullup_en_o_wd;
   logic phy_pins_drive_dn_pullup_en_o_qs;
@@ -7161,18 +7161,18 @@
     .qs     (phy_pins_drive_oe_o_qs)
   );
 
-  //   F[tx_use_d_se0_o]: 5:5
+  //   F[rx_enable_o]: 5:5
   prim_subreg #(
     .DW      (1),
     .SwAccess(prim_subreg_pkg::SwAccessRW),
     .RESVAL  (1'h0)
-  ) u_phy_pins_drive_tx_use_d_se0_o (
+  ) u_phy_pins_drive_rx_enable_o (
     .clk_i   (clk_i),
     .rst_ni  (rst_ni),
 
     // from register interface
     .we     (phy_pins_drive_we),
-    .wd     (phy_pins_drive_tx_use_d_se0_o_wd),
+    .wd     (phy_pins_drive_rx_enable_o_wd),
 
     // from internal hardware
     .de     (1'b0),
@@ -7180,10 +7180,10 @@
 
     // to internal hardware
     .qe     (),
-    .q      (reg2hw.phy_pins_drive.tx_use_d_se0_o.q),
+    .q      (reg2hw.phy_pins_drive.rx_enable_o.q),
 
     // to register interface (read)
-    .qs     (phy_pins_drive_tx_use_d_se0_o_qs)
+    .qs     (phy_pins_drive_rx_enable_o_qs)
   );
 
   //   F[dp_pullup_en_o]: 6:6
@@ -8165,7 +8165,7 @@
 
   assign phy_pins_drive_oe_o_wd = reg_wdata[4];
 
-  assign phy_pins_drive_tx_use_d_se0_o_wd = reg_wdata[5];
+  assign phy_pins_drive_rx_enable_o_wd = reg_wdata[5];
 
   assign phy_pins_drive_dp_pullup_en_o_wd = reg_wdata[6];
 
@@ -8540,7 +8540,7 @@
         reg_rdata_next[2] = phy_pins_drive_d_o_qs;
         reg_rdata_next[3] = phy_pins_drive_se0_o_qs;
         reg_rdata_next[4] = phy_pins_drive_oe_o_qs;
-        reg_rdata_next[5] = phy_pins_drive_tx_use_d_se0_o_qs;
+        reg_rdata_next[5] = phy_pins_drive_rx_enable_o_qs;
         reg_rdata_next[6] = phy_pins_drive_dp_pullup_en_o_qs;
         reg_rdata_next[7] = phy_pins_drive_dn_pullup_en_o_qs;
         reg_rdata_next[8] = phy_pins_drive_suspend_o_qs;
diff --git a/hw/ip/usbdev/rtl/usbdev_usbif.sv b/hw/ip/usbdev/rtl/usbdev_usbif.sv
index d1ef16d..057a7c2 100644
--- a/hw/ip/usbdev/rtl/usbdev_usbif.sv
+++ b/hw/ip/usbdev/rtl/usbdev_usbif.sv
@@ -29,6 +29,8 @@
 
   output logic                     usb_d_o,
   output logic                     usb_se0_o,
+  output logic                     usb_dp_o,
+  output logic                     usb_dn_o,
   output logic                     usb_oe_o,
 
   output logic                     usb_pullup_en_o,
@@ -81,6 +83,8 @@
   input  logic                     diff_rx_ok_i, // 1: differential symbols (K/J) are valid
   input  logic                     cfg_eop_single_bit_i, // 1: detect a single SE0 bit as EOP
   input  logic                     cfg_use_diff_rcvr_i, // 1: use single-ended rx data on usb_d_i
+  input  logic                     cfg_pinflip_i, // 1: Treat outputs and inputs as though D+/D-
+                                                  // are flipped
   input  logic                     tx_osc_test_mode_i, // Oscillator test mode: constant JK output
   input  logic [NEndpoints-1:0]    data_toggle_clear_i, // Clear the data toggles for an EP
   input  logic                     resume_link_active_i, // Jump from LinkPowered to LinkResuming
@@ -282,6 +286,7 @@
 
     .cfg_eop_single_bit_i  (cfg_eop_single_bit_i),
     .cfg_use_diff_rcvr_i   (cfg_use_diff_rcvr_i),
+    .cfg_pinflip_i         (cfg_pinflip_i),
     .tx_osc_test_mode_i    (tx_osc_test_mode_i),
     .data_toggle_clear_i   (data_toggle_clear_i),
     .diff_rx_ok_i          (diff_rx_ok_i),
@@ -291,6 +296,8 @@
     .usb_dn_i              (usb_dn_i),
     .usb_d_o               (usb_d_o),
     .usb_se0_o             (usb_se0_o),
+    .usb_dp_o              (usb_dp_o),
+    .usb_dn_o              (usb_dn_o),
     .usb_oe_o              (usb_oe_o),
 
     .dev_addr_i            (devaddr_i),